1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_ppc_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2013 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 /* TODO 18/Nov/05: 37 38 Spot rld... cases which are simply left/right shifts and emit 39 Shl64/Shr64 accordingly. 40 41 Altivec 42 - datastream insns 43 - lvxl,stvxl: load/store with 'least recently used' hint 44 - vexptefp, vlogefp 45 46 LIMITATIONS: 47 48 Various, including: 49 50 - Some invalid forms of lswi and lswx are accepted when they should 51 not be. 52 53 - Floating Point: 54 - All exceptions disabled in FPSCR 55 - condition codes not set in FPSCR 56 57 - Altivec floating point: 58 - vmaddfp, vnmsubfp 59 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the 60 system default of Non-Java mode, we get some small errors 61 (lowest bit only). 62 This is because Non-Java mode brutally hacks denormalised results 63 to zero, whereas we keep maximum accuracy. However, using 64 Non-Java mode would give us more inaccuracy, as our intermediate 65 results would then be zeroed, too. 66 67 - AbiHints for the stack red zone are only emitted for 68 unconditional calls and returns (bl, blr). They should also be 69 emitted for conditional calls and returns, but we don't have a 70 way to express that right now. Ah well. 71 72 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c) 73 ignores the rounding mode, and generates code that assumes 74 round-to-nearest. This means V will compute incorrect results 75 for uses of these IROps when the rounding mode (first) arg is 76 not mkU32(Irrm_NEAREST). 77 */ 78 79 /* "Special" instructions. 80 81 This instruction decoder can decode four special instructions 82 which mean nothing natively (are no-ops as far as regs/mem are 83 concerned) but have meaning for supporting Valgrind. A special 84 instruction is flagged by a 16-byte preamble: 85 86 32-bit mode: 5400183E 5400683E 5400E83E 5400983E 87 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31; 88 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31) 89 90 64-bit mode: 78001800 78006800 7800E802 78009802 91 (rotldi 0,0,3; rotldi 0,0,13; 92 rotldi 0,0,61; rotldi 0,0,51) 93 94 Following that, one of the following 3 are allowed 95 (standard interpretation in parentheses): 96 97 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 98 7C421378 (or 2,2,2) %R3 = guest_NRADDR 99 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian 100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian 101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 102 7CA52B78 (or 5,5,5) IR injection 103 104 Any other bytes following the 16-byte preamble are illegal and 105 constitute a failure in instruction decoding. This all assumes 106 that the preamble will never occur except in specific code 107 fragments designed for Valgrind to catch. 108 */ 109 110 /* Little Endian notes */ 111 /* 112 * Vector operations in little Endian mode behave in non-obvious ways at times. 113 * Below is an attempt at explaining this. 114 * 115 * LE/BE vector example 116 * With a vector of unsigned ints declared as follows: 117 * vector unsigned int vec_inA = 118 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; 119 * The '0x11111111' word is word zero in both LE and BE format. But the 120 * loaded vector register will have word zero on the far left in BE mode and 121 * on the far right in LE mode. The lvx and stvx instructions work naturally 122 * for whatever endianness is in effect. For example, in LE mode, the stvx 123 * stores word zero (far right word) of the vector at the lowest memory 124 * address of the EA; in BE mode, stvx still stores word zero at the lowest 125 * memory address, but with word zero interpreted as the one at the far left 126 * of the register. 127 * 128 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode. 129 * When the compiler generates an lxvd2x instruction to load the 130 * above-declared vector of unsigned integers, it loads the vector as two 131 * double words, but they are in BE word-wise format. To put the vector in 132 * the right order for LE, the compiler also generates an xxswapd after the 133 * load, which puts it in proper LE format. Similarly, the stxvd2x 134 * instruction has a BE bias, storing the vector in BE word-wise format. But 135 * the compiler also generates an xxswapd prior to the store, thus ensuring 136 * the vector is stored in memory in the correct LE order. 137 * 138 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts 139 * of a double words and words within a vector. Because of the reverse order 140 * of numbering for LE as described above, the high part refers to word 1 in 141 * LE format. When input data is saved to a guest state vector register 142 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the 143 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction. 144 * The saving of the data to memory must be done in proper LE order. For the 145 * inverse operation of extracting data from a vector register (e.g., 146 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting 147 * in stvx), and then integer registers are loaded from the memory location 148 * from where the vector register was saved. Again, this must be done in 149 * proper LE order. So for these various vector Iops, we have LE-specific 150 * code in host_ppc_isel.c 151 * 152 * Another unique behavior of vectors in LE mode is with the vector scalar 153 * (VSX) operations that operate on "double word 0" of the source register, 154 * storing the result in "double word 0" of the output vector register. For 155 * these operations, "double word 0" is interpreted as "high half of the 156 * register" (i.e, the part on the left side). 157 * 158 */ 159 /* Translates PPC32/64 code to IR. */ 160 161 /* References 162 163 #define PPC32 164 "PowerPC Microprocessor Family: 165 The Programming Environments Manual for 32-Bit Microprocessors" 166 02/21/2000 167 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 168 169 #define PPC64 170 "PowerPC Microprocessor Family: 171 Programming Environments Manual for 64-Bit Microprocessors" 172 06/10/2003 173 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 174 175 #define AV 176 "PowerPC Microprocessor Family: 177 AltiVec(TM) Technology Programming Environments Manual" 178 07/10/2003 179 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 180 */ 181 182 #include "libvex_basictypes.h" 183 #include "libvex_ir.h" 184 #include "libvex.h" 185 #include "libvex_emnote.h" 186 #include "libvex_guest_ppc32.h" 187 #include "libvex_guest_ppc64.h" 188 189 #include "main_util.h" 190 #include "main_globals.h" 191 #include "guest_generic_bb_to_IR.h" 192 #include "guest_ppc_defs.h" 193 194 /*------------------------------------------------------------*/ 195 /*--- Globals ---*/ 196 /*------------------------------------------------------------*/ 197 198 /* These are set at the start of the translation of an insn, right 199 down in disInstr_PPC, so that we don't have to pass them around 200 endlessly. They are all constant during the translation of any 201 given insn. */ 202 203 /* We need to know this to do sub-register accesses correctly. */ 204 static VexEndness host_endness; 205 206 /* Pointer to the guest code area. */ 207 static const UChar* guest_code; 208 209 /* The guest address corresponding to guest_code[0]. */ 210 static Addr64 guest_CIA_bbstart; 211 212 /* The guest address for the instruction currently being 213 translated. */ 214 static Addr64 guest_CIA_curr_instr; 215 216 /* The IRSB* into which we're generating code. */ 217 static IRSB* irsb; 218 219 /* Is our guest binary 32 or 64bit? Set at each call to 220 disInstr_PPC below. */ 221 static Bool mode64 = False; 222 223 // Given a pointer to a function as obtained by "& functionname" in C, 224 // produce a pointer to the actual entry point for the function. For 225 // most platforms it's the identity function. Unfortunately, on 226 // ppc64-linux it isn't (sigh) 227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f ) 228 { 229 if (vbi->host_ppc_calls_use_fndescrs) { 230 /* f is a pointer to a 3-word function descriptor, of which the 231 first word is the entry address. */ 232 /* note, this is correct even with cross-jitting, since this is 233 purely a host issue, not a guest one. */ 234 HWord* fdescr = (HWord*)f; 235 return (void*)(fdescr[0]); 236 } else { 237 /* Simple; "& f" points directly at the code for f. */ 238 return f; 239 } 240 } 241 242 #define SIGN_BIT 0x8000000000000000ULL 243 #define SIGN_MASK 0x7fffffffffffffffULL 244 #define SIGN_BIT32 0x80000000 245 #define SIGN_MASK32 0x7fffffff 246 247 248 /*------------------------------------------------------------*/ 249 /*--- Debugging output ---*/ 250 /*------------------------------------------------------------*/ 251 252 #define DIP(format, args...) \ 253 if (vex_traceflags & VEX_TRACE_FE) \ 254 vex_printf(format, ## args) 255 256 #define DIS(buf, format, args...) \ 257 if (vex_traceflags & VEX_TRACE_FE) \ 258 vex_sprintf(buf, format, ## args) 259 260 261 /*------------------------------------------------------------*/ 262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 263 /*------------------------------------------------------------*/ 264 265 #define offsetofPPCGuestState(_x) \ 266 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 267 offsetof(VexGuestPPC32State, _x)) 268 269 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 271 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 272 #define OFFB_LR offsetofPPCGuestState(guest_LR) 273 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 274 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 275 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 276 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 277 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 278 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 279 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 280 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 281 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 282 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 283 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 284 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 285 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 287 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 288 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 289 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU) 290 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 291 292 293 /*------------------------------------------------------------*/ 294 /*--- Extract instruction fields --- */ 295 /*------------------------------------------------------------*/ 296 297 /* Extract field from insn, given idx (zero = lsb) and field length */ 298 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 299 300 /* Extract primary opcode, instr[31:26] */ 301 static UChar ifieldOPC( UInt instr ) { 302 return toUChar( IFIELD( instr, 26, 6 ) ); 303 } 304 305 /* Extract 10-bit secondary opcode, instr[10:1] */ 306 static UInt ifieldOPClo10 ( UInt instr) { 307 return IFIELD( instr, 1, 10 ); 308 } 309 310 /* Extract 9-bit secondary opcode, instr[9:1] */ 311 static UInt ifieldOPClo9 ( UInt instr) { 312 return IFIELD( instr, 1, 9 ); 313 } 314 315 /* Extract 8-bit secondary opcode, instr[8:1] */ 316 static UInt ifieldOPClo8 ( UInt instr) { 317 return IFIELD( instr, 1, 8 ); 318 } 319 320 /* Extract 5-bit secondary opcode, instr[5:1] */ 321 static UInt ifieldOPClo5 ( UInt instr) { 322 return IFIELD( instr, 1, 5 ); 323 } 324 325 /* Extract RD (destination register) field, instr[25:21] */ 326 static UChar ifieldRegDS( UInt instr ) { 327 return toUChar( IFIELD( instr, 21, 5 ) ); 328 } 329 330 /* Extract XT (destination register) field, instr[0,25:21] */ 331 static UChar ifieldRegXT ( UInt instr ) 332 { 333 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 334 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 335 return (upper_bit << 5) | lower_bits; 336 } 337 338 /* Extract XS (store source register) field, instr[0,25:21] */ 339 static inline UChar ifieldRegXS ( UInt instr ) 340 { 341 return ifieldRegXT ( instr ); 342 } 343 344 /* Extract RA (1st source register) field, instr[20:16] */ 345 static UChar ifieldRegA ( UInt instr ) { 346 return toUChar( IFIELD( instr, 16, 5 ) ); 347 } 348 349 /* Extract XA (1st source register) field, instr[2,20:16] */ 350 static UChar ifieldRegXA ( UInt instr ) 351 { 352 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 353 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 354 return (upper_bit << 5) | lower_bits; 355 } 356 357 /* Extract RB (2nd source register) field, instr[15:11] */ 358 static UChar ifieldRegB ( UInt instr ) { 359 return toUChar( IFIELD( instr, 11, 5 ) ); 360 } 361 362 /* Extract XB (2nd source register) field, instr[1,15:11] */ 363 static UChar ifieldRegXB ( UInt instr ) 364 { 365 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 366 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 367 return (upper_bit << 5) | lower_bits; 368 } 369 370 /* Extract RC (3rd source register) field, instr[10:6] */ 371 static UChar ifieldRegC ( UInt instr ) { 372 return toUChar( IFIELD( instr, 6, 5 ) ); 373 } 374 375 /* Extract XC (3rd source register) field, instr[3,10:6] */ 376 static UChar ifieldRegXC ( UInt instr ) 377 { 378 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 379 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 380 return (upper_bit << 5) | lower_bits; 381 } 382 383 /* Extract bit 10, instr[10] */ 384 static UChar ifieldBIT10 ( UInt instr ) { 385 return toUChar( IFIELD( instr, 10, 1 ) ); 386 } 387 388 /* Extract 2nd lowest bit, instr[1] */ 389 static UChar ifieldBIT1 ( UInt instr ) { 390 return toUChar( IFIELD( instr, 1, 1 ) ); 391 } 392 393 /* Extract lowest bit, instr[0] */ 394 static UChar ifieldBIT0 ( UInt instr ) { 395 return toUChar( instr & 0x1 ); 396 } 397 398 /* Extract unsigned bottom half, instr[15:0] */ 399 static UInt ifieldUIMM16 ( UInt instr ) { 400 return instr & 0xFFFF; 401 } 402 403 /* Extract unsigned bottom 26 bits, instr[25:0] */ 404 static UInt ifieldUIMM26 ( UInt instr ) { 405 return instr & 0x3FFFFFF; 406 } 407 408 /* Extract DM field, instr[9:8] */ 409 static UChar ifieldDM ( UInt instr ) { 410 return toUChar( IFIELD( instr, 8, 2 ) ); 411 } 412 413 /* Extract SHW field, instr[9:8] */ 414 static inline UChar ifieldSHW ( UInt instr ) 415 { 416 return ifieldDM ( instr ); 417 } 418 419 /*------------------------------------------------------------*/ 420 /*--- Guest-state identifiers ---*/ 421 /*------------------------------------------------------------*/ 422 423 typedef enum { 424 PPC_GST_CIA, // Current Instruction Address 425 PPC_GST_LR, // Link Register 426 PPC_GST_CTR, // Count Register 427 PPC_GST_XER, // Overflow, carry flags, byte count 428 PPC_GST_CR, // Condition Register 429 PPC_GST_FPSCR, // Floating Point Status/Control Register 430 PPC_GST_VRSAVE, // Vector Save/Restore Register 431 PPC_GST_VSCR, // Vector Status and Control Register 432 PPC_GST_EMWARN, // Emulation warnings 433 PPC_GST_CMSTART,// For icbi: start of area to invalidate 434 PPC_GST_CMLEN, // For icbi: length of area to invalidate 435 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 436 PPC_GST_SPRG3_RO, // SPRG3 437 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 438 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 439 PPC_GST_TEXASR, // Transactional EXception And Summary Register 440 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 441 PPC_GST_MAX 442 } PPC_GST; 443 444 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 445 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 446 #define MASK_VSCR_VALID 0x00010001 447 448 449 /*------------------------------------------------------------*/ 450 /*--- FP Helpers ---*/ 451 /*------------------------------------------------------------*/ 452 453 /* Produce the 32-bit pattern corresponding to the supplied 454 float. */ 455 static UInt float_to_bits ( Float f ) 456 { 457 union { UInt i; Float f; } u; 458 vassert(4 == sizeof(UInt)); 459 vassert(4 == sizeof(Float)); 460 vassert(4 == sizeof(u)); 461 u.f = f; 462 return u.i; 463 } 464 465 466 /*------------------------------------------------------------*/ 467 /*--- Misc Helpers ---*/ 468 /*------------------------------------------------------------*/ 469 470 /* Generate mask with 1's from 'begin' through 'end', 471 wrapping if begin > end. 472 begin->end works from right to left, 0=lsb 473 */ 474 static UInt MASK32( UInt begin, UInt end ) 475 { 476 UInt m1, m2, mask; 477 vassert(begin < 32); 478 vassert(end < 32); 479 m1 = ((UInt)(-1)) << begin; 480 m2 = ((UInt)(-1)) << end << 1; 481 mask = m1 ^ m2; 482 if (begin > end) mask = ~mask; // wrap mask 483 return mask; 484 } 485 486 static ULong MASK64( UInt begin, UInt end ) 487 { 488 ULong m1, m2, mask; 489 vassert(begin < 64); 490 vassert(end < 64); 491 m1 = ((ULong)(-1)) << begin; 492 m2 = ((ULong)(-1)) << end << 1; 493 mask = m1 ^ m2; 494 if (begin > end) mask = ~mask; // wrap mask 495 return mask; 496 } 497 498 static Addr64 nextInsnAddr( void ) 499 { 500 return guest_CIA_curr_instr + 4; 501 } 502 503 504 /*------------------------------------------------------------*/ 505 /*--- Helper bits and pieces for deconstructing the ---*/ 506 /*--- ppc32/64 insn stream. ---*/ 507 /*------------------------------------------------------------*/ 508 509 /* Add a statement to the list held by "irsb". */ 510 static void stmt ( IRStmt* st ) 511 { 512 addStmtToIRSB( irsb, st ); 513 } 514 515 /* Generate a new temporary of the given type. */ 516 static IRTemp newTemp ( IRType ty ) 517 { 518 vassert(isPlausibleIRType(ty)); 519 return newIRTemp( irsb->tyenv, ty ); 520 } 521 522 /* Various simple conversions */ 523 524 static UChar extend_s_5to8 ( UChar x ) 525 { 526 return toUChar((((Int)x) << 27) >> 27); 527 } 528 529 static UInt extend_s_8to32( UChar x ) 530 { 531 return (UInt)((((Int)x) << 24) >> 24); 532 } 533 534 static UInt extend_s_16to32 ( UInt x ) 535 { 536 return (UInt)((((Int)x) << 16) >> 16); 537 } 538 539 static ULong extend_s_16to64 ( UInt x ) 540 { 541 return (ULong)((((Long)x) << 48) >> 48); 542 } 543 544 static ULong extend_s_26to64 ( UInt x ) 545 { 546 return (ULong)((((Long)x) << 38) >> 38); 547 } 548 549 static ULong extend_s_32to64 ( UInt x ) 550 { 551 return (ULong)((((Long)x) << 32) >> 32); 552 } 553 554 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 555 of the underlying host. */ 556 static UInt getUIntPPCendianly ( const UChar* p ) 557 { 558 UInt w = 0; 559 if (host_endness == VexEndnessBE) { 560 w = (w << 8) | p[0]; 561 w = (w << 8) | p[1]; 562 w = (w << 8) | p[2]; 563 w = (w << 8) | p[3]; 564 } else { 565 w = (w << 8) | p[3]; 566 w = (w << 8) | p[2]; 567 w = (w << 8) | p[1]; 568 w = (w << 8) | p[0]; 569 } 570 return w; 571 } 572 573 574 /*------------------------------------------------------------*/ 575 /*--- Helpers for constructing IR. ---*/ 576 /*------------------------------------------------------------*/ 577 578 static void assign ( IRTemp dst, IRExpr* e ) 579 { 580 stmt( IRStmt_WrTmp(dst, e) ); 581 } 582 583 /* This generates a normal (non store-conditional) store. */ 584 static void store ( IRExpr* addr, IRExpr* data ) 585 { 586 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 587 vassert(tyA == Ity_I32 || tyA == Ity_I64); 588 589 if (host_endness == VexEndnessBE) 590 stmt( IRStmt_Store(Iend_BE, addr, data) ); 591 else 592 stmt( IRStmt_Store(Iend_LE, addr, data) ); 593 } 594 595 static IRExpr* unop ( IROp op, IRExpr* a ) 596 { 597 return IRExpr_Unop(op, a); 598 } 599 600 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 601 { 602 return IRExpr_Binop(op, a1, a2); 603 } 604 605 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 606 { 607 return IRExpr_Triop(op, a1, a2, a3); 608 } 609 610 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 611 IRExpr* a3, IRExpr* a4 ) 612 { 613 return IRExpr_Qop(op, a1, a2, a3, a4); 614 } 615 616 static IRExpr* mkexpr ( IRTemp tmp ) 617 { 618 return IRExpr_RdTmp(tmp); 619 } 620 621 static IRExpr* mkU8 ( UChar i ) 622 { 623 return IRExpr_Const(IRConst_U8(i)); 624 } 625 626 static IRExpr* mkU16 ( UInt i ) 627 { 628 return IRExpr_Const(IRConst_U16(i)); 629 } 630 631 static IRExpr* mkU32 ( UInt i ) 632 { 633 return IRExpr_Const(IRConst_U32(i)); 634 } 635 636 static IRExpr* mkU64 ( ULong i ) 637 { 638 return IRExpr_Const(IRConst_U64(i)); 639 } 640 641 static IRExpr* mkV128 ( UShort i ) 642 { 643 vassert(i == 0 || i == 0xffff); 644 return IRExpr_Const(IRConst_V128(i)); 645 } 646 647 /* This generates a normal (non load-linked) load. */ 648 static IRExpr* load ( IRType ty, IRExpr* addr ) 649 { 650 if (host_endness == VexEndnessBE) 651 return IRExpr_Load(Iend_BE, ty, addr); 652 else 653 return IRExpr_Load(Iend_LE, ty, addr); 654 } 655 656 static IRStmt* stmt_load ( IRTemp result, 657 IRExpr* addr, IRExpr* storedata ) 658 { 659 if (host_endness == VexEndnessBE) 660 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 661 else 662 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 663 } 664 665 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 666 { 667 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 668 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 669 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 670 unop(Iop_1Uto32, arg2))); 671 } 672 673 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 674 { 675 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 676 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 677 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 678 unop(Iop_1Uto32, arg2))); 679 } 680 681 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 682 static void expand8Ux16( IRExpr* vIn, 683 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 684 { 685 IRTemp ones8x16 = newTemp(Ity_V128); 686 687 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 688 vassert(vEvn && *vEvn == IRTemp_INVALID); 689 vassert(vOdd && *vOdd == IRTemp_INVALID); 690 *vEvn = newTemp(Ity_V128); 691 *vOdd = newTemp(Ity_V128); 692 693 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 694 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 695 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 696 binop(Iop_ShrV128, vIn, mkU8(8))) ); 697 } 698 699 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 700 static void expand8Sx16( IRExpr* vIn, 701 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 702 { 703 IRTemp ones8x16 = newTemp(Ity_V128); 704 705 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 706 vassert(vEvn && *vEvn == IRTemp_INVALID); 707 vassert(vOdd && *vOdd == IRTemp_INVALID); 708 *vEvn = newTemp(Ity_V128); 709 *vOdd = newTemp(Ity_V128); 710 711 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 712 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 713 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 714 binop(Iop_ShrV128, vIn, mkU8(8))) ); 715 } 716 717 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 718 static void expand16Ux8( IRExpr* vIn, 719 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 720 { 721 IRTemp ones16x8 = newTemp(Ity_V128); 722 723 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 724 vassert(vEvn && *vEvn == IRTemp_INVALID); 725 vassert(vOdd && *vOdd == IRTemp_INVALID); 726 *vEvn = newTemp(Ity_V128); 727 *vOdd = newTemp(Ity_V128); 728 729 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 730 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 731 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 732 binop(Iop_ShrV128, vIn, mkU8(16))) ); 733 } 734 735 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 736 static void expand16Sx8( IRExpr* vIn, 737 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 738 { 739 IRTemp ones16x8 = newTemp(Ity_V128); 740 741 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 742 vassert(vEvn && *vEvn == IRTemp_INVALID); 743 vassert(vOdd && *vOdd == IRTemp_INVALID); 744 *vEvn = newTemp(Ity_V128); 745 *vOdd = newTemp(Ity_V128); 746 747 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 748 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 749 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 750 binop(Iop_ShrV128, vIn, mkU8(16))) ); 751 } 752 753 /* break V128 to 4xF64's*/ 754 static void breakV128to4xF64( IRExpr* t128, 755 /*OUTs*/ 756 IRTemp* t3, IRTemp* t2, 757 IRTemp* t1, IRTemp* t0 ) 758 { 759 IRTemp hi64 = newTemp(Ity_I64); 760 IRTemp lo64 = newTemp(Ity_I64); 761 762 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 763 vassert(t0 && *t0 == IRTemp_INVALID); 764 vassert(t1 && *t1 == IRTemp_INVALID); 765 vassert(t2 && *t2 == IRTemp_INVALID); 766 vassert(t3 && *t3 == IRTemp_INVALID); 767 *t0 = newTemp(Ity_F64); 768 *t1 = newTemp(Ity_F64); 769 *t2 = newTemp(Ity_F64); 770 *t3 = newTemp(Ity_F64); 771 772 assign( hi64, unop(Iop_V128HIto64, t128) ); 773 assign( lo64, unop(Iop_V128to64, t128) ); 774 assign( *t3, 775 unop( Iop_F32toF64, 776 unop( Iop_ReinterpI32asF32, 777 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 778 assign( *t2, 779 unop( Iop_F32toF64, 780 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 781 assign( *t1, 782 unop( Iop_F32toF64, 783 unop( Iop_ReinterpI32asF32, 784 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 785 assign( *t0, 786 unop( Iop_F32toF64, 787 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 788 } 789 790 791 /* break V128 to 4xI32's, then sign-extend to I64's */ 792 static void breakV128to4x64S( IRExpr* t128, 793 /*OUTs*/ 794 IRTemp* t3, IRTemp* t2, 795 IRTemp* t1, IRTemp* t0 ) 796 { 797 IRTemp hi64 = newTemp(Ity_I64); 798 IRTemp lo64 = newTemp(Ity_I64); 799 800 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 801 vassert(t0 && *t0 == IRTemp_INVALID); 802 vassert(t1 && *t1 == IRTemp_INVALID); 803 vassert(t2 && *t2 == IRTemp_INVALID); 804 vassert(t3 && *t3 == IRTemp_INVALID); 805 *t0 = newTemp(Ity_I64); 806 *t1 = newTemp(Ity_I64); 807 *t2 = newTemp(Ity_I64); 808 *t3 = newTemp(Ity_I64); 809 810 assign( hi64, unop(Iop_V128HIto64, t128) ); 811 assign( lo64, unop(Iop_V128to64, t128) ); 812 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 813 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 814 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 815 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 816 } 817 818 /* break V128 to 4xI32's, then zero-extend to I64's */ 819 static void breakV128to4x64U ( IRExpr* t128, 820 /*OUTs*/ 821 IRTemp* t3, IRTemp* t2, 822 IRTemp* t1, IRTemp* t0 ) 823 { 824 IRTemp hi64 = newTemp(Ity_I64); 825 IRTemp lo64 = newTemp(Ity_I64); 826 827 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 828 vassert(t0 && *t0 == IRTemp_INVALID); 829 vassert(t1 && *t1 == IRTemp_INVALID); 830 vassert(t2 && *t2 == IRTemp_INVALID); 831 vassert(t3 && *t3 == IRTemp_INVALID); 832 *t0 = newTemp(Ity_I64); 833 *t1 = newTemp(Ity_I64); 834 *t2 = newTemp(Ity_I64); 835 *t3 = newTemp(Ity_I64); 836 837 assign( hi64, unop(Iop_V128HIto64, t128) ); 838 assign( lo64, unop(Iop_V128to64, t128) ); 839 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 840 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 841 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 842 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 843 } 844 845 static void breakV128to4x32( IRExpr* t128, 846 /*OUTs*/ 847 IRTemp* t3, IRTemp* t2, 848 IRTemp* t1, IRTemp* t0 ) 849 { 850 IRTemp hi64 = newTemp(Ity_I64); 851 IRTemp lo64 = newTemp(Ity_I64); 852 853 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 854 vassert(t0 && *t0 == IRTemp_INVALID); 855 vassert(t1 && *t1 == IRTemp_INVALID); 856 vassert(t2 && *t2 == IRTemp_INVALID); 857 vassert(t3 && *t3 == IRTemp_INVALID); 858 *t0 = newTemp(Ity_I32); 859 *t1 = newTemp(Ity_I32); 860 *t2 = newTemp(Ity_I32); 861 *t3 = newTemp(Ity_I32); 862 863 assign( hi64, unop(Iop_V128HIto64, t128) ); 864 assign( lo64, unop(Iop_V128to64, t128) ); 865 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 866 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 867 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 868 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 869 } 870 871 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 872 IRTemp t1, IRTemp t0 ) 873 { 874 return 875 binop( Iop_64HLtoV128, 876 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 877 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 878 ); 879 } 880 881 882 /* Signed saturating narrow 64S to 32 */ 883 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 884 { 885 IRTemp hi32 = newTemp(Ity_I32); 886 IRTemp lo32 = newTemp(Ity_I32); 887 888 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 889 890 assign( hi32, unop(Iop_64HIto32, t64)); 891 assign( lo32, unop(Iop_64to32, t64)); 892 893 return IRExpr_ITE( 894 /* if (hi32 == (lo32 >>s 31)) */ 895 binop(Iop_CmpEQ32, mkexpr(hi32), 896 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 897 /* then: within signed-32 range: lo half good enough */ 898 mkexpr(lo32), 899 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 900 binop(Iop_Add32, mkU32(0x7FFFFFFF), 901 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 902 } 903 904 /* Unsigned saturating narrow 64S to 32 */ 905 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 906 { 907 IRTemp hi32 = newTemp(Ity_I32); 908 IRTemp lo32 = newTemp(Ity_I32); 909 910 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 911 912 assign( hi32, unop(Iop_64HIto32, t64)); 913 assign( lo32, unop(Iop_64to32, t64)); 914 915 return IRExpr_ITE( 916 /* if (top 32 bits of t64 are 0) */ 917 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 918 /* then: within unsigned-32 range: lo half good enough */ 919 mkexpr(lo32), 920 /* else: positive saturate -> 0xFFFFFFFF */ 921 mkU32(0xFFFFFFFF)); 922 } 923 924 /* Signed saturate narrow 64->32, combining to V128 */ 925 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 926 IRExpr* t1, IRExpr* t0 ) 927 { 928 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 929 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 930 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 931 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 932 return binop(Iop_64HLtoV128, 933 binop(Iop_32HLto64, 934 mkQNarrow64Sto32( t3 ), 935 mkQNarrow64Sto32( t2 )), 936 binop(Iop_32HLto64, 937 mkQNarrow64Sto32( t1 ), 938 mkQNarrow64Sto32( t0 ))); 939 } 940 941 /* Unsigned saturate narrow 64->32, combining to V128 */ 942 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 943 IRExpr* t1, IRExpr* t0 ) 944 { 945 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 946 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 947 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 948 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 949 return binop(Iop_64HLtoV128, 950 binop(Iop_32HLto64, 951 mkQNarrow64Uto32( t3 ), 952 mkQNarrow64Uto32( t2 )), 953 binop(Iop_32HLto64, 954 mkQNarrow64Uto32( t1 ), 955 mkQNarrow64Uto32( t0 ))); 956 } 957 958 /* Simulate irops Iop_MullOdd*, since we don't have them */ 959 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 960 binop(Iop_MullEven8Ux16, \ 961 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 962 binop(Iop_ShrV128, expr_vB, mkU8(8))) 963 964 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 965 binop(Iop_MullEven8Sx16, \ 966 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 967 binop(Iop_ShrV128, expr_vB, mkU8(8))) 968 969 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 970 binop(Iop_MullEven16Ux8, \ 971 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 972 binop(Iop_ShrV128, expr_vB, mkU8(16))) 973 974 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 975 binop(Iop_MullEven32Ux4, \ 976 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 977 binop(Iop_ShrV128, expr_vB, mkU8(32))) 978 979 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 980 binop(Iop_MullEven16Sx8, \ 981 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 982 binop(Iop_ShrV128, expr_vB, mkU8(16))) 983 984 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 985 binop(Iop_MullEven32Sx4, \ 986 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 987 binop(Iop_ShrV128, expr_vB, mkU8(32))) 988 989 990 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 991 { 992 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 993 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 994 } 995 996 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 997 { 998 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 999 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1000 } 1001 1002 static IROp mkSzOp ( IRType ty, IROp op8 ) 1003 { 1004 Int adj; 1005 vassert(ty == Ity_I8 || ty == Ity_I16 || 1006 ty == Ity_I32 || ty == Ity_I64); 1007 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1008 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1009 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1010 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1011 op8 == Iop_Not8 ); 1012 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1013 return adj + op8; 1014 } 1015 1016 /* Make sure we get valid 32 and 64bit addresses */ 1017 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1018 { 1019 vassert(ty == Ity_I32 || ty == Ity_I64); 1020 return ( ty == Ity_I64 ? 1021 (Addr64)addr : 1022 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1023 } 1024 1025 /* sz, ULong -> IRExpr */ 1026 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1027 { 1028 vassert(ty == Ity_I32 || ty == Ity_I64); 1029 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1030 } 1031 1032 /* sz, ULong -> IRConst */ 1033 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1034 { 1035 vassert(ty == Ity_I32 || ty == Ity_I64); 1036 return ( ty == Ity_I64 ? 1037 IRConst_U64(imm64) : 1038 IRConst_U32((UInt)imm64) ); 1039 } 1040 1041 /* Sign extend imm16 -> IRExpr* */ 1042 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1043 { 1044 vassert(ty == Ity_I32 || ty == Ity_I64); 1045 return ( ty == Ity_I64 ? 1046 mkU64(extend_s_16to64(imm16)) : 1047 mkU32(extend_s_16to32(imm16)) ); 1048 } 1049 1050 /* Sign extend imm32 -> IRExpr* */ 1051 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1052 { 1053 vassert(ty == Ity_I32 || ty == Ity_I64); 1054 return ( ty == Ity_I64 ? 1055 mkU64(extend_s_32to64(imm32)) : 1056 mkU32(imm32) ); 1057 } 1058 1059 /* IR narrows I32/I64 -> I8/I16/I32 */ 1060 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1061 { 1062 vassert(ty == Ity_I32 || ty == Ity_I64); 1063 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1064 } 1065 1066 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1067 { 1068 vassert(ty == Ity_I32 || ty == Ity_I64); 1069 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1070 } 1071 1072 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1073 { 1074 vassert(ty == Ity_I32 || ty == Ity_I64); 1075 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1076 } 1077 1078 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1079 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1080 { 1081 IROp op; 1082 vassert(ty == Ity_I32 || ty == Ity_I64); 1083 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1084 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1085 return unop(op, src); 1086 } 1087 1088 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1089 { 1090 IROp op; 1091 vassert(ty == Ity_I32 || ty == Ity_I64); 1092 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1093 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1094 return unop(op, src); 1095 } 1096 1097 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1098 { 1099 vassert(ty == Ity_I32 || ty == Ity_I64); 1100 if (ty == Ity_I32) 1101 return src; 1102 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1103 } 1104 1105 1106 static Int integerGuestRegOffset ( UInt archreg ) 1107 { 1108 vassert(archreg < 32); 1109 1110 // jrs: probably not necessary; only matters if we reference sub-parts 1111 // of the ppc registers, but that isn't the case 1112 // later: this might affect Altivec though? 1113 1114 switch (archreg) { 1115 case 0: return offsetofPPCGuestState(guest_GPR0); 1116 case 1: return offsetofPPCGuestState(guest_GPR1); 1117 case 2: return offsetofPPCGuestState(guest_GPR2); 1118 case 3: return offsetofPPCGuestState(guest_GPR3); 1119 case 4: return offsetofPPCGuestState(guest_GPR4); 1120 case 5: return offsetofPPCGuestState(guest_GPR5); 1121 case 6: return offsetofPPCGuestState(guest_GPR6); 1122 case 7: return offsetofPPCGuestState(guest_GPR7); 1123 case 8: return offsetofPPCGuestState(guest_GPR8); 1124 case 9: return offsetofPPCGuestState(guest_GPR9); 1125 case 10: return offsetofPPCGuestState(guest_GPR10); 1126 case 11: return offsetofPPCGuestState(guest_GPR11); 1127 case 12: return offsetofPPCGuestState(guest_GPR12); 1128 case 13: return offsetofPPCGuestState(guest_GPR13); 1129 case 14: return offsetofPPCGuestState(guest_GPR14); 1130 case 15: return offsetofPPCGuestState(guest_GPR15); 1131 case 16: return offsetofPPCGuestState(guest_GPR16); 1132 case 17: return offsetofPPCGuestState(guest_GPR17); 1133 case 18: return offsetofPPCGuestState(guest_GPR18); 1134 case 19: return offsetofPPCGuestState(guest_GPR19); 1135 case 20: return offsetofPPCGuestState(guest_GPR20); 1136 case 21: return offsetofPPCGuestState(guest_GPR21); 1137 case 22: return offsetofPPCGuestState(guest_GPR22); 1138 case 23: return offsetofPPCGuestState(guest_GPR23); 1139 case 24: return offsetofPPCGuestState(guest_GPR24); 1140 case 25: return offsetofPPCGuestState(guest_GPR25); 1141 case 26: return offsetofPPCGuestState(guest_GPR26); 1142 case 27: return offsetofPPCGuestState(guest_GPR27); 1143 case 28: return offsetofPPCGuestState(guest_GPR28); 1144 case 29: return offsetofPPCGuestState(guest_GPR29); 1145 case 30: return offsetofPPCGuestState(guest_GPR30); 1146 case 31: return offsetofPPCGuestState(guest_GPR31); 1147 default: break; 1148 } 1149 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1150 } 1151 1152 static IRExpr* getIReg ( UInt archreg ) 1153 { 1154 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1155 vassert(archreg < 32); 1156 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1157 } 1158 1159 /* Ditto, but write to a reg instead. */ 1160 static void putIReg ( UInt archreg, IRExpr* e ) 1161 { 1162 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1163 vassert(archreg < 32); 1164 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1165 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1166 } 1167 1168 1169 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1170 static Int floatGuestRegOffset ( UInt archreg ) 1171 { 1172 vassert(archreg < 32); 1173 1174 if (host_endness == VexEndnessLE) { 1175 switch (archreg) { 1176 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1177 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1178 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1179 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1180 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1181 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1182 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1183 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1184 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1185 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1186 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1187 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1188 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1189 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1190 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1191 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1192 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1193 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1194 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1195 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1196 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1197 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1198 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1199 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1200 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1201 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1202 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1203 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1204 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1205 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1206 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1207 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1208 default: break; 1209 } 1210 } else { 1211 switch (archreg) { 1212 case 0: return offsetofPPCGuestState(guest_VSR0); 1213 case 1: return offsetofPPCGuestState(guest_VSR1); 1214 case 2: return offsetofPPCGuestState(guest_VSR2); 1215 case 3: return offsetofPPCGuestState(guest_VSR3); 1216 case 4: return offsetofPPCGuestState(guest_VSR4); 1217 case 5: return offsetofPPCGuestState(guest_VSR5); 1218 case 6: return offsetofPPCGuestState(guest_VSR6); 1219 case 7: return offsetofPPCGuestState(guest_VSR7); 1220 case 8: return offsetofPPCGuestState(guest_VSR8); 1221 case 9: return offsetofPPCGuestState(guest_VSR9); 1222 case 10: return offsetofPPCGuestState(guest_VSR10); 1223 case 11: return offsetofPPCGuestState(guest_VSR11); 1224 case 12: return offsetofPPCGuestState(guest_VSR12); 1225 case 13: return offsetofPPCGuestState(guest_VSR13); 1226 case 14: return offsetofPPCGuestState(guest_VSR14); 1227 case 15: return offsetofPPCGuestState(guest_VSR15); 1228 case 16: return offsetofPPCGuestState(guest_VSR16); 1229 case 17: return offsetofPPCGuestState(guest_VSR17); 1230 case 18: return offsetofPPCGuestState(guest_VSR18); 1231 case 19: return offsetofPPCGuestState(guest_VSR19); 1232 case 20: return offsetofPPCGuestState(guest_VSR20); 1233 case 21: return offsetofPPCGuestState(guest_VSR21); 1234 case 22: return offsetofPPCGuestState(guest_VSR22); 1235 case 23: return offsetofPPCGuestState(guest_VSR23); 1236 case 24: return offsetofPPCGuestState(guest_VSR24); 1237 case 25: return offsetofPPCGuestState(guest_VSR25); 1238 case 26: return offsetofPPCGuestState(guest_VSR26); 1239 case 27: return offsetofPPCGuestState(guest_VSR27); 1240 case 28: return offsetofPPCGuestState(guest_VSR28); 1241 case 29: return offsetofPPCGuestState(guest_VSR29); 1242 case 30: return offsetofPPCGuestState(guest_VSR30); 1243 case 31: return offsetofPPCGuestState(guest_VSR31); 1244 default: break; 1245 } 1246 } 1247 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1248 } 1249 1250 static IRExpr* getFReg ( UInt archreg ) 1251 { 1252 vassert(archreg < 32); 1253 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1254 } 1255 1256 /* Ditto, but write to a reg instead. */ 1257 static void putFReg ( UInt archreg, IRExpr* e ) 1258 { 1259 vassert(archreg < 32); 1260 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1261 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1262 } 1263 1264 /* get Decimal float value. Note, they share floating point register file. */ 1265 static IRExpr* getDReg(UInt archreg) { 1266 IRExpr *e; 1267 vassert( archreg < 32 ); 1268 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1269 return e; 1270 } 1271 static IRExpr* getDReg32(UInt archreg) { 1272 IRExpr *e; 1273 vassert( archreg < 32 ); 1274 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1275 return e; 1276 } 1277 1278 /* Read a floating point register pair and combine their contents into a 1279 128-bit value */ 1280 static IRExpr *getDReg_pair(UInt archreg) { 1281 IRExpr *high = getDReg( archreg ); 1282 IRExpr *low = getDReg( archreg + 1 ); 1283 1284 return binop( Iop_D64HLtoD128, high, low ); 1285 } 1286 1287 /* Ditto, but write to a reg instead. */ 1288 static void putDReg32(UInt archreg, IRExpr* e) { 1289 vassert( archreg < 32 ); 1290 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1291 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1292 } 1293 1294 static void putDReg(UInt archreg, IRExpr* e) { 1295 vassert( archreg < 32 ); 1296 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1297 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1298 } 1299 1300 /* Write a 128-bit floating point value into a register pair. */ 1301 static void putDReg_pair(UInt archreg, IRExpr *e) { 1302 IRTemp low = newTemp( Ity_D64 ); 1303 IRTemp high = newTemp( Ity_D64 ); 1304 1305 vassert( archreg < 32 ); 1306 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1307 1308 assign( low, unop( Iop_D128LOtoD64, e ) ); 1309 assign( high, unop( Iop_D128HItoD64, e ) ); 1310 1311 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1312 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1313 } 1314 1315 static Int vsxGuestRegOffset ( UInt archreg ) 1316 { 1317 vassert(archreg < 64); 1318 switch (archreg) { 1319 case 0: return offsetofPPCGuestState(guest_VSR0); 1320 case 1: return offsetofPPCGuestState(guest_VSR1); 1321 case 2: return offsetofPPCGuestState(guest_VSR2); 1322 case 3: return offsetofPPCGuestState(guest_VSR3); 1323 case 4: return offsetofPPCGuestState(guest_VSR4); 1324 case 5: return offsetofPPCGuestState(guest_VSR5); 1325 case 6: return offsetofPPCGuestState(guest_VSR6); 1326 case 7: return offsetofPPCGuestState(guest_VSR7); 1327 case 8: return offsetofPPCGuestState(guest_VSR8); 1328 case 9: return offsetofPPCGuestState(guest_VSR9); 1329 case 10: return offsetofPPCGuestState(guest_VSR10); 1330 case 11: return offsetofPPCGuestState(guest_VSR11); 1331 case 12: return offsetofPPCGuestState(guest_VSR12); 1332 case 13: return offsetofPPCGuestState(guest_VSR13); 1333 case 14: return offsetofPPCGuestState(guest_VSR14); 1334 case 15: return offsetofPPCGuestState(guest_VSR15); 1335 case 16: return offsetofPPCGuestState(guest_VSR16); 1336 case 17: return offsetofPPCGuestState(guest_VSR17); 1337 case 18: return offsetofPPCGuestState(guest_VSR18); 1338 case 19: return offsetofPPCGuestState(guest_VSR19); 1339 case 20: return offsetofPPCGuestState(guest_VSR20); 1340 case 21: return offsetofPPCGuestState(guest_VSR21); 1341 case 22: return offsetofPPCGuestState(guest_VSR22); 1342 case 23: return offsetofPPCGuestState(guest_VSR23); 1343 case 24: return offsetofPPCGuestState(guest_VSR24); 1344 case 25: return offsetofPPCGuestState(guest_VSR25); 1345 case 26: return offsetofPPCGuestState(guest_VSR26); 1346 case 27: return offsetofPPCGuestState(guest_VSR27); 1347 case 28: return offsetofPPCGuestState(guest_VSR28); 1348 case 29: return offsetofPPCGuestState(guest_VSR29); 1349 case 30: return offsetofPPCGuestState(guest_VSR30); 1350 case 31: return offsetofPPCGuestState(guest_VSR31); 1351 case 32: return offsetofPPCGuestState(guest_VSR32); 1352 case 33: return offsetofPPCGuestState(guest_VSR33); 1353 case 34: return offsetofPPCGuestState(guest_VSR34); 1354 case 35: return offsetofPPCGuestState(guest_VSR35); 1355 case 36: return offsetofPPCGuestState(guest_VSR36); 1356 case 37: return offsetofPPCGuestState(guest_VSR37); 1357 case 38: return offsetofPPCGuestState(guest_VSR38); 1358 case 39: return offsetofPPCGuestState(guest_VSR39); 1359 case 40: return offsetofPPCGuestState(guest_VSR40); 1360 case 41: return offsetofPPCGuestState(guest_VSR41); 1361 case 42: return offsetofPPCGuestState(guest_VSR42); 1362 case 43: return offsetofPPCGuestState(guest_VSR43); 1363 case 44: return offsetofPPCGuestState(guest_VSR44); 1364 case 45: return offsetofPPCGuestState(guest_VSR45); 1365 case 46: return offsetofPPCGuestState(guest_VSR46); 1366 case 47: return offsetofPPCGuestState(guest_VSR47); 1367 case 48: return offsetofPPCGuestState(guest_VSR48); 1368 case 49: return offsetofPPCGuestState(guest_VSR49); 1369 case 50: return offsetofPPCGuestState(guest_VSR50); 1370 case 51: return offsetofPPCGuestState(guest_VSR51); 1371 case 52: return offsetofPPCGuestState(guest_VSR52); 1372 case 53: return offsetofPPCGuestState(guest_VSR53); 1373 case 54: return offsetofPPCGuestState(guest_VSR54); 1374 case 55: return offsetofPPCGuestState(guest_VSR55); 1375 case 56: return offsetofPPCGuestState(guest_VSR56); 1376 case 57: return offsetofPPCGuestState(guest_VSR57); 1377 case 58: return offsetofPPCGuestState(guest_VSR58); 1378 case 59: return offsetofPPCGuestState(guest_VSR59); 1379 case 60: return offsetofPPCGuestState(guest_VSR60); 1380 case 61: return offsetofPPCGuestState(guest_VSR61); 1381 case 62: return offsetofPPCGuestState(guest_VSR62); 1382 case 63: return offsetofPPCGuestState(guest_VSR63); 1383 default: break; 1384 } 1385 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1386 } 1387 1388 /* Vector registers are mapped to VSX registers[32..63]. */ 1389 static Int vectorGuestRegOffset ( UInt archreg ) 1390 { 1391 vassert(archreg < 32); 1392 1393 switch (archreg) { 1394 case 0: return offsetofPPCGuestState(guest_VSR32); 1395 case 1: return offsetofPPCGuestState(guest_VSR33); 1396 case 2: return offsetofPPCGuestState(guest_VSR34); 1397 case 3: return offsetofPPCGuestState(guest_VSR35); 1398 case 4: return offsetofPPCGuestState(guest_VSR36); 1399 case 5: return offsetofPPCGuestState(guest_VSR37); 1400 case 6: return offsetofPPCGuestState(guest_VSR38); 1401 case 7: return offsetofPPCGuestState(guest_VSR39); 1402 case 8: return offsetofPPCGuestState(guest_VSR40); 1403 case 9: return offsetofPPCGuestState(guest_VSR41); 1404 case 10: return offsetofPPCGuestState(guest_VSR42); 1405 case 11: return offsetofPPCGuestState(guest_VSR43); 1406 case 12: return offsetofPPCGuestState(guest_VSR44); 1407 case 13: return offsetofPPCGuestState(guest_VSR45); 1408 case 14: return offsetofPPCGuestState(guest_VSR46); 1409 case 15: return offsetofPPCGuestState(guest_VSR47); 1410 case 16: return offsetofPPCGuestState(guest_VSR48); 1411 case 17: return offsetofPPCGuestState(guest_VSR49); 1412 case 18: return offsetofPPCGuestState(guest_VSR50); 1413 case 19: return offsetofPPCGuestState(guest_VSR51); 1414 case 20: return offsetofPPCGuestState(guest_VSR52); 1415 case 21: return offsetofPPCGuestState(guest_VSR53); 1416 case 22: return offsetofPPCGuestState(guest_VSR54); 1417 case 23: return offsetofPPCGuestState(guest_VSR55); 1418 case 24: return offsetofPPCGuestState(guest_VSR56); 1419 case 25: return offsetofPPCGuestState(guest_VSR57); 1420 case 26: return offsetofPPCGuestState(guest_VSR58); 1421 case 27: return offsetofPPCGuestState(guest_VSR59); 1422 case 28: return offsetofPPCGuestState(guest_VSR60); 1423 case 29: return offsetofPPCGuestState(guest_VSR61); 1424 case 30: return offsetofPPCGuestState(guest_VSR62); 1425 case 31: return offsetofPPCGuestState(guest_VSR63); 1426 default: break; 1427 } 1428 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1429 } 1430 1431 static IRExpr* getVReg ( UInt archreg ) 1432 { 1433 vassert(archreg < 32); 1434 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1435 } 1436 1437 /* Ditto, but write to a reg instead. */ 1438 static void putVReg ( UInt archreg, IRExpr* e ) 1439 { 1440 vassert(archreg < 32); 1441 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1442 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1443 } 1444 1445 /* Get contents of VSX guest register */ 1446 static IRExpr* getVSReg ( UInt archreg ) 1447 { 1448 vassert(archreg < 64); 1449 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1450 } 1451 1452 /* Ditto, but write to a VSX reg instead. */ 1453 static void putVSReg ( UInt archreg, IRExpr* e ) 1454 { 1455 vassert(archreg < 64); 1456 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1457 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1458 } 1459 1460 1461 static Int guestCR321offset ( UInt cr ) 1462 { 1463 switch (cr) { 1464 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1465 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1466 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1467 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1468 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1469 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1470 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1471 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1472 default: vpanic("guestCR321offset(ppc)"); 1473 } 1474 } 1475 1476 static Int guestCR0offset ( UInt cr ) 1477 { 1478 switch (cr) { 1479 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1480 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1481 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1482 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1483 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1484 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1485 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1486 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1487 default: vpanic("guestCR3offset(ppc)"); 1488 } 1489 } 1490 1491 typedef enum { 1492 _placeholder0, 1493 _placeholder1, 1494 _placeholder2, 1495 BYTE, 1496 HWORD, 1497 WORD, 1498 DWORD 1499 } _popcount_data_type; 1500 1501 /* Generate an IR sequence to do a popcount operation on the supplied 1502 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1503 Ity_I32 or Ity_I64 only. */ 1504 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1505 { 1506 /* Do count across 2^data_type bits, 1507 byte: data_type = 3 1508 half word: data_type = 4 1509 word: data_type = 5 1510 double word: data_type = 6 (not supported for 32-bit type) 1511 */ 1512 Int shift[6]; 1513 _popcount_data_type idx, i; 1514 IRTemp mask[6]; 1515 IRTemp old = IRTemp_INVALID; 1516 IRTemp nyu = IRTemp_INVALID; 1517 1518 vassert(ty == Ity_I64 || ty == Ity_I32); 1519 1520 if (ty == Ity_I32) { 1521 1522 for (idx = 0; idx < WORD; idx++) { 1523 mask[idx] = newTemp(ty); 1524 shift[idx] = 1 << idx; 1525 } 1526 assign(mask[0], mkU32(0x55555555)); 1527 assign(mask[1], mkU32(0x33333333)); 1528 assign(mask[2], mkU32(0x0F0F0F0F)); 1529 assign(mask[3], mkU32(0x00FF00FF)); 1530 assign(mask[4], mkU32(0x0000FFFF)); 1531 old = src; 1532 for (i = 0; i < data_type; i++) { 1533 nyu = newTemp(ty); 1534 assign(nyu, 1535 binop(Iop_Add32, 1536 binop(Iop_And32, 1537 mkexpr(old), 1538 mkexpr(mask[i])), 1539 binop(Iop_And32, 1540 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1541 mkexpr(mask[i])))); 1542 old = nyu; 1543 } 1544 return nyu; 1545 } 1546 1547 // else, ty == Ity_I64 1548 vassert(mode64); 1549 1550 for (i = 0; i < DWORD; i++) { 1551 mask[i] = newTemp( Ity_I64 ); 1552 shift[i] = 1 << i; 1553 } 1554 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1555 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1556 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1557 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1558 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1559 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1560 old = src; 1561 for (i = 0; i < data_type; i++) { 1562 nyu = newTemp( Ity_I64 ); 1563 assign( nyu, 1564 binop( Iop_Add64, 1565 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1566 binop( Iop_And64, 1567 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1568 mkexpr( mask[i] ) ) ) ); 1569 old = nyu; 1570 } 1571 return nyu; 1572 } 1573 1574 /* Special purpose population count function for 1575 * vpopcntd in 32-bit mode. 1576 */ 1577 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1578 { 1579 Int i, shift[6]; 1580 IRTemp mask[6]; 1581 IRTemp old = IRTemp_INVALID; 1582 IRTemp nyu1 = IRTemp_INVALID; 1583 IRTemp nyu2 = IRTemp_INVALID; 1584 IRTemp retval = newTemp(Ity_I64); 1585 1586 vassert(!mode64); 1587 1588 for (i = 0; i < WORD; i++) { 1589 mask[i] = newTemp(Ity_I32); 1590 shift[i] = 1 << i; 1591 } 1592 assign(mask[0], mkU32(0x55555555)); 1593 assign(mask[1], mkU32(0x33333333)); 1594 assign(mask[2], mkU32(0x0F0F0F0F)); 1595 assign(mask[3], mkU32(0x00FF00FF)); 1596 assign(mask[4], mkU32(0x0000FFFF)); 1597 old = src1; 1598 for (i = 0; i < WORD; i++) { 1599 nyu1 = newTemp(Ity_I32); 1600 assign(nyu1, 1601 binop(Iop_Add32, 1602 binop(Iop_And32, 1603 mkexpr(old), 1604 mkexpr(mask[i])), 1605 binop(Iop_And32, 1606 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1607 mkexpr(mask[i])))); 1608 old = nyu1; 1609 } 1610 1611 old = src2; 1612 for (i = 0; i < WORD; i++) { 1613 nyu2 = newTemp(Ity_I32); 1614 assign(nyu2, 1615 binop(Iop_Add32, 1616 binop(Iop_And32, 1617 mkexpr(old), 1618 mkexpr(mask[i])), 1619 binop(Iop_And32, 1620 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1621 mkexpr(mask[i])))); 1622 old = nyu2; 1623 } 1624 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1625 return retval; 1626 } 1627 1628 1629 // ROTL(src32/64, rot_amt5/6) 1630 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1631 IRExpr* rot_amt ) 1632 { 1633 IRExpr *mask, *rot; 1634 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1635 1636 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1637 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1638 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1639 rot = binop(Iop_Or64, 1640 binop(Iop_Shl64, src, mask), 1641 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1642 } else { 1643 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1644 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1645 rot = binop(Iop_Or32, 1646 binop(Iop_Shl32, src, mask), 1647 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1648 } 1649 /* Note: the ITE not merely an optimisation; it's needed 1650 because otherwise the Shr is a shift by the word size when 1651 mask denotes zero. For rotates by immediates, a lot of 1652 this junk gets folded out. */ 1653 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1654 /* non-zero rotate */ rot, 1655 /* zero rotate */ src); 1656 } 1657 1658 /* Standard effective address calc: (rA + rB) */ 1659 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1660 { 1661 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1662 vassert(rA < 32); 1663 vassert(rB < 32); 1664 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1665 } 1666 1667 /* Standard effective address calc: (rA + simm) */ 1668 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1669 { 1670 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1671 vassert(rA < 32); 1672 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1673 mkSzExtendS16(ty, simm16)); 1674 } 1675 1676 /* Standard effective address calc: (rA|0) */ 1677 static IRExpr* ea_rAor0 ( UInt rA ) 1678 { 1679 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1680 vassert(rA < 32); 1681 if (rA == 0) { 1682 return mkSzImm(ty, 0); 1683 } else { 1684 return getIReg(rA); 1685 } 1686 } 1687 1688 /* Standard effective address calc: (rA|0) + rB */ 1689 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1690 { 1691 vassert(rA < 32); 1692 vassert(rB < 32); 1693 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1694 } 1695 1696 /* Standard effective address calc: (rA|0) + simm16 */ 1697 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1698 { 1699 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1700 vassert(rA < 32); 1701 if (rA == 0) { 1702 return mkSzExtendS16(ty, simm16); 1703 } else { 1704 return ea_rA_simm( rA, simm16 ); 1705 } 1706 } 1707 1708 1709 /* Align effective address */ 1710 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1711 { 1712 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1713 Long mask; 1714 switch (align) { 1715 case 1: return addr; // byte aligned 1716 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1717 case 4: mask = ((Long)-1) << 2; break; // word aligned 1718 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1719 default: 1720 vex_printf("addr_align: align = %u\n", align); 1721 vpanic("addr_align(ppc)"); 1722 } 1723 1724 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1725 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1726 } 1727 1728 1729 /* Exit the trace if ADDR (intended to be a guest memory address) is 1730 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1731 restart of the current insn. */ 1732 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1733 { 1734 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1735 if (mode64) { 1736 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1737 stmt( 1738 IRStmt_Exit( 1739 binop(Iop_CmpNE64, 1740 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1741 mkU64(0)), 1742 Ijk_SigBUS, 1743 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1744 ) 1745 ); 1746 } else { 1747 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1748 stmt( 1749 IRStmt_Exit( 1750 binop(Iop_CmpNE32, 1751 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1752 mkU32(0)), 1753 Ijk_SigBUS, 1754 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1755 ) 1756 ); 1757 } 1758 } 1759 1760 1761 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1762 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1763 N) becomes undefined. That is at function calls and returns. ELF 1764 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1765 the address of the next instruction to be executed. 1766 */ 1767 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1768 IRTemp nia, const HChar* who ) 1769 { 1770 Int szB = vbi->guest_stack_redzone_size; 1771 if (0) vex_printf("AbiHint: %s\n", who); 1772 vassert(szB >= 0); 1773 if (szB > 0) { 1774 if (mode64) { 1775 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1776 stmt( IRStmt_AbiHint( 1777 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1778 szB, 1779 mkexpr(nia) 1780 )); 1781 } else { 1782 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1783 stmt( IRStmt_AbiHint( 1784 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1785 szB, 1786 mkexpr(nia) 1787 )); 1788 } 1789 } 1790 } 1791 1792 1793 /*------------------------------------------------------------*/ 1794 /*--- Helpers for condition codes. ---*/ 1795 /*------------------------------------------------------------*/ 1796 1797 /* Condition register layout. 1798 1799 In the hardware, CR is laid out like this. The leftmost end is the 1800 most significant bit in the register; however the IBM documentation 1801 numbers the bits backwards for some reason. 1802 1803 CR0 CR1 .......... CR6 CR7 1804 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1805 31 28 3 0 (normal bit numbering) 1806 1807 Each CR field is 4 bits: [<,>,==,SO] 1808 1809 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1810 1811 Indexing from BI to guest state: 1812 1813 let n = BI / 4 1814 off = BI % 4 1815 this references CR n: 1816 1817 off==0 -> guest_CRn_321 >> 3 1818 off==1 -> guest_CRn_321 >> 2 1819 off==2 -> guest_CRn_321 >> 1 1820 off==3 -> guest_CRn_SO 1821 1822 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1823 (normal notation) and in guest_CRn_321 the significant bits are 1824 3, 2 and 1 (normal notation). 1825 */ 1826 1827 static void putCR321 ( UInt cr, IRExpr* e ) 1828 { 1829 vassert(cr < 8); 1830 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1831 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1832 } 1833 1834 static void putCR0 ( UInt cr, IRExpr* e ) 1835 { 1836 vassert(cr < 8); 1837 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1838 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1839 } 1840 1841 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1842 { 1843 vassert(cr < 8); 1844 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1845 } 1846 1847 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1848 { 1849 vassert(cr < 8); 1850 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1851 } 1852 1853 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1854 return it at the bottom of an I32; the top 31 bits are guaranteed 1855 to be zero. */ 1856 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1857 { 1858 UInt n = bi / 4; 1859 UInt off = bi % 4; 1860 vassert(bi < 32); 1861 if (off == 3) { 1862 /* Fetch the SO bit for this CR field */ 1863 /* Note: And32 is redundant paranoia iff guest state only has 0 1864 or 1 in that slot. */ 1865 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1866 } else { 1867 /* Fetch the <, > or == bit for this CR field */ 1868 return binop( Iop_And32, 1869 binop( Iop_Shr32, 1870 unop(Iop_8Uto32, getCR321(n)), 1871 mkU8(toUChar(3-off)) ), 1872 mkU32(1) ); 1873 } 1874 } 1875 1876 /* Dually, write the least significant bit of BIT to the specified CR 1877 bit. Indexing as per getCRbit. */ 1878 static void putCRbit ( UInt bi, IRExpr* bit ) 1879 { 1880 UInt n, off; 1881 IRExpr* safe; 1882 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1883 safe = binop(Iop_And32, bit, mkU32(1)); 1884 n = bi / 4; 1885 off = bi % 4; 1886 vassert(bi < 32); 1887 if (off == 3) { 1888 /* This is the SO bit for this CR field */ 1889 putCR0(n, unop(Iop_32to8, safe)); 1890 } else { 1891 off = 3 - off; 1892 vassert(off == 1 || off == 2 || off == 3); 1893 putCR321( 1894 n, 1895 unop( Iop_32to8, 1896 binop( Iop_Or32, 1897 /* old value with field masked out */ 1898 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1899 mkU32(~(1 << off))), 1900 /* new value in the right place */ 1901 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1902 ) 1903 ) 1904 ); 1905 } 1906 } 1907 1908 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1909 return it somewhere in an I32; it does not matter where, but 1910 whichever bit it is, all other bits are guaranteed to be zero. In 1911 other words, the I32-typed expression will be zero if the bit is 1912 zero and nonzero if the bit is 1. Write into *where the index 1913 of where the bit will be. */ 1914 1915 static 1916 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1917 { 1918 UInt n = bi / 4; 1919 UInt off = bi % 4; 1920 vassert(bi < 32); 1921 if (off == 3) { 1922 /* Fetch the SO bit for this CR field */ 1923 /* Note: And32 is redundant paranoia iff guest state only has 0 1924 or 1 in that slot. */ 1925 *where = 0; 1926 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1927 } else { 1928 /* Fetch the <, > or == bit for this CR field */ 1929 *where = 3-off; 1930 return binop( Iop_And32, 1931 unop(Iop_8Uto32, getCR321(n)), 1932 mkU32(1 << (3-off)) ); 1933 } 1934 } 1935 1936 /* Set the CR0 flags following an arithmetic operation. 1937 (Condition Register CR0 Field Definition, PPC32 p60) 1938 */ 1939 static IRExpr* getXER_SO ( void ); 1940 static void set_CR0 ( IRExpr* result ) 1941 { 1942 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1943 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1944 if (mode64) { 1945 putCR321( 0, unop(Iop_64to8, 1946 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1947 } else { 1948 putCR321( 0, unop(Iop_32to8, 1949 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1950 } 1951 putCR0( 0, getXER_SO() ); 1952 } 1953 1954 1955 /* Set the CR6 flags following an AltiVec compare operation. 1956 * NOTE: This also works for VSX single-precision compares. 1957 * */ 1958 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1959 { 1960 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1961 all_ones = (v[0] && v[1] && v[2] && v[3]) 1962 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1963 */ 1964 IRTemp v0 = newTemp(Ity_V128); 1965 IRTemp v1 = newTemp(Ity_V128); 1966 IRTemp v2 = newTemp(Ity_V128); 1967 IRTemp v3 = newTemp(Ity_V128); 1968 IRTemp rOnes = newTemp(Ity_I8); 1969 IRTemp rZeros = newTemp(Ity_I8); 1970 1971 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1972 1973 assign( v0, result ); 1974 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1975 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1976 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1977 1978 assign( rZeros, unop(Iop_1Uto8, 1979 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1980 unop(Iop_Not32, 1981 unop(Iop_V128to32, 1982 binop(Iop_OrV128, 1983 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1984 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1985 ))) ); 1986 1987 if (test_all_ones) { 1988 assign( rOnes, unop(Iop_1Uto8, 1989 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1990 unop(Iop_V128to32, 1991 binop(Iop_AndV128, 1992 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1993 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1994 ))) ); 1995 putCR321( 6, binop(Iop_Or8, 1996 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1997 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1998 } else { 1999 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2000 } 2001 putCR0( 6, mkU8(0) ); 2002 } 2003 2004 2005 2006 /*------------------------------------------------------------*/ 2007 /*--- Helpers for XER flags. ---*/ 2008 /*------------------------------------------------------------*/ 2009 2010 static void putXER_SO ( IRExpr* e ) 2011 { 2012 IRExpr* so; 2013 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2014 so = binop(Iop_And8, e, mkU8(1)); 2015 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2016 } 2017 2018 static void putXER_OV ( IRExpr* e ) 2019 { 2020 IRExpr* ov; 2021 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2022 ov = binop(Iop_And8, e, mkU8(1)); 2023 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2024 } 2025 2026 static void putXER_CA ( IRExpr* e ) 2027 { 2028 IRExpr* ca; 2029 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2030 ca = binop(Iop_And8, e, mkU8(1)); 2031 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2032 } 2033 2034 static void putXER_BC ( IRExpr* e ) 2035 { 2036 IRExpr* bc; 2037 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2038 bc = binop(Iop_And8, e, mkU8(0x7F)); 2039 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2040 } 2041 2042 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2043 { 2044 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2045 } 2046 2047 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 2048 { 2049 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2050 } 2051 2052 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2053 { 2054 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2055 } 2056 2057 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 2058 { 2059 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2060 } 2061 2062 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 2063 { 2064 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2065 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2066 } 2067 2068 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2069 { 2070 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2071 } 2072 2073 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 2074 { 2075 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2076 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2077 } 2078 2079 2080 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2081 %XER.SO accordingly. */ 2082 2083 static void set_XER_OV_32( UInt op, IRExpr* res, 2084 IRExpr* argL, IRExpr* argR ) 2085 { 2086 IRTemp t64; 2087 IRExpr* xer_ov; 2088 vassert(op < PPCG_FLAG_OP_NUMBER); 2089 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2090 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2091 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2092 2093 # define INT32_MIN 0x80000000 2094 2095 # define XOR2(_aa,_bb) \ 2096 binop(Iop_Xor32,(_aa),(_bb)) 2097 2098 # define XOR3(_cc,_dd,_ee) \ 2099 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2100 2101 # define AND3(_ff,_gg,_hh) \ 2102 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2103 2104 #define NOT(_jj) \ 2105 unop(Iop_Not32, (_jj)) 2106 2107 switch (op) { 2108 case /* 0 */ PPCG_FLAG_OP_ADD: 2109 case /* 1 */ PPCG_FLAG_OP_ADDE: 2110 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2111 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2112 xer_ov 2113 = AND3( XOR3(argL,argR,mkU32(-1)), 2114 XOR2(argL,res), 2115 mkU32(INT32_MIN) ); 2116 /* xer_ov can only be 0 or 1<<31 */ 2117 xer_ov 2118 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2119 break; 2120 2121 case /* 2 */ PPCG_FLAG_OP_DIVW: 2122 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2123 xer_ov 2124 = mkOR1( 2125 mkAND1( 2126 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2127 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2128 ), 2129 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2130 ); 2131 xer_ov 2132 = unop(Iop_1Uto32, xer_ov); 2133 break; 2134 2135 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2136 /* argR == 0 */ 2137 xer_ov 2138 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2139 break; 2140 2141 case /* 4 */ PPCG_FLAG_OP_MULLW: 2142 /* OV true if result can't be represented in 32 bits 2143 i.e sHi != sign extension of sLo */ 2144 t64 = newTemp(Ity_I64); 2145 assign( t64, binop(Iop_MullS32, argL, argR) ); 2146 xer_ov 2147 = binop( Iop_CmpNE32, 2148 unop(Iop_64HIto32, mkexpr(t64)), 2149 binop( Iop_Sar32, 2150 unop(Iop_64to32, mkexpr(t64)), 2151 mkU8(31)) 2152 ); 2153 xer_ov 2154 = unop(Iop_1Uto32, xer_ov); 2155 break; 2156 2157 case /* 5 */ PPCG_FLAG_OP_NEG: 2158 /* argL == INT32_MIN */ 2159 xer_ov 2160 = unop( Iop_1Uto32, 2161 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2162 break; 2163 2164 case /* 6 */ PPCG_FLAG_OP_SUBF: 2165 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2166 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2167 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2168 xer_ov 2169 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2170 XOR2(NOT(argL),res), 2171 mkU32(INT32_MIN) ); 2172 /* xer_ov can only be 0 or 1<<31 */ 2173 xer_ov 2174 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2175 break; 2176 2177 case PPCG_FLAG_OP_DIVWEU: 2178 xer_ov 2179 = binop( Iop_Or32, 2180 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2181 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2182 break; 2183 2184 case PPCG_FLAG_OP_DIVWE: 2185 2186 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2187 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2188 * an overflow is implied. 2189 */ 2190 xer_ov = binop( Iop_Or32, 2191 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2192 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2193 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2194 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2195 break; 2196 2197 2198 2199 default: 2200 vex_printf("set_XER_OV: op = %u\n", op); 2201 vpanic("set_XER_OV(ppc)"); 2202 } 2203 2204 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2205 putXER_OV( unop(Iop_32to8, xer_ov) ); 2206 2207 /* Update the summary overflow */ 2208 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2209 2210 # undef INT32_MIN 2211 # undef AND3 2212 # undef XOR3 2213 # undef XOR2 2214 # undef NOT 2215 } 2216 2217 static void set_XER_OV_64( UInt op, IRExpr* res, 2218 IRExpr* argL, IRExpr* argR ) 2219 { 2220 IRExpr* xer_ov; 2221 vassert(op < PPCG_FLAG_OP_NUMBER); 2222 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2223 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2224 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2225 2226 # define INT64_MIN 0x8000000000000000ULL 2227 2228 # define XOR2(_aa,_bb) \ 2229 binop(Iop_Xor64,(_aa),(_bb)) 2230 2231 # define XOR3(_cc,_dd,_ee) \ 2232 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2233 2234 # define AND3(_ff,_gg,_hh) \ 2235 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2236 2237 #define NOT(_jj) \ 2238 unop(Iop_Not64, (_jj)) 2239 2240 switch (op) { 2241 case /* 0 */ PPCG_FLAG_OP_ADD: 2242 case /* 1 */ PPCG_FLAG_OP_ADDE: 2243 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2244 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2245 xer_ov 2246 = AND3( XOR3(argL,argR,mkU64(-1)), 2247 XOR2(argL,res), 2248 mkU64(INT64_MIN) ); 2249 /* xer_ov can only be 0 or 1<<63 */ 2250 xer_ov 2251 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2252 break; 2253 2254 case /* 2 */ PPCG_FLAG_OP_DIVW: 2255 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2256 xer_ov 2257 = mkOR1( 2258 mkAND1( 2259 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2260 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2261 ), 2262 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2263 ); 2264 break; 2265 2266 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2267 /* argR == 0 */ 2268 xer_ov 2269 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2270 break; 2271 2272 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2273 /* OV true if result can't be represented in 64 bits 2274 i.e sHi != sign extension of sLo */ 2275 xer_ov 2276 = binop( Iop_CmpNE32, 2277 unop(Iop_64HIto32, res), 2278 binop( Iop_Sar32, 2279 unop(Iop_64to32, res), 2280 mkU8(31)) 2281 ); 2282 break; 2283 } 2284 2285 case /* 5 */ PPCG_FLAG_OP_NEG: 2286 /* argL == INT64_MIN */ 2287 xer_ov 2288 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2289 break; 2290 2291 case /* 6 */ PPCG_FLAG_OP_SUBF: 2292 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2293 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2294 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2295 xer_ov 2296 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2297 XOR2(NOT(argL),res), 2298 mkU64(INT64_MIN) ); 2299 /* xer_ov can only be 0 or 1<<63 */ 2300 xer_ov 2301 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2302 break; 2303 2304 case PPCG_FLAG_OP_DIVDE: 2305 2306 /* If argR == 0, we must set the OV bit. But there's another condition 2307 * where we can get overflow set for divde . . . when the 2308 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2309 * both dividend and divisor are non-zero, it implies an overflow. 2310 */ 2311 xer_ov 2312 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2313 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2314 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2315 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2316 break; 2317 2318 case PPCG_FLAG_OP_DIVDEU: 2319 /* If argR == 0 or if argL >= argR, set OV. */ 2320 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2321 binop( Iop_CmpLE64U, argR, argL ) ); 2322 break; 2323 2324 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2325 IRTemp t128; 2326 /* OV true if result can't be represented in 64 bits 2327 i.e sHi != sign extension of sLo */ 2328 t128 = newTemp(Ity_I128); 2329 assign( t128, binop(Iop_MullS64, argL, argR) ); 2330 xer_ov 2331 = binop( Iop_CmpNE64, 2332 unop(Iop_128HIto64, mkexpr(t128)), 2333 binop( Iop_Sar64, 2334 unop(Iop_128to64, mkexpr(t128)), 2335 mkU8(63)) 2336 ); 2337 break; 2338 } 2339 2340 default: 2341 vex_printf("set_XER_OV: op = %u\n", op); 2342 vpanic("set_XER_OV(ppc64)"); 2343 } 2344 2345 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2346 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2347 2348 /* Update the summary overflow */ 2349 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2350 2351 # undef INT64_MIN 2352 # undef AND3 2353 # undef XOR3 2354 # undef XOR2 2355 # undef NOT 2356 } 2357 2358 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2359 IRExpr* argL, IRExpr* argR ) 2360 { 2361 if (ty == Ity_I32) 2362 set_XER_OV_32( op, res, argL, argR ); 2363 else 2364 set_XER_OV_64( op, res, argL, argR ); 2365 } 2366 2367 2368 2369 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2370 value being OLDCA. Set %XER.CA accordingly. */ 2371 2372 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2373 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2374 { 2375 IRExpr* xer_ca; 2376 vassert(op < PPCG_FLAG_OP_NUMBER); 2377 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2378 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2379 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2380 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2381 2382 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2383 seems reasonable given that it's always generated by 2384 getXER_CA32(), which masks it accordingly. In any case it being 2385 0 or 1 is an invariant of the ppc guest state representation; 2386 if it has any other value, that invariant has been violated. */ 2387 2388 switch (op) { 2389 case /* 0 */ PPCG_FLAG_OP_ADD: 2390 /* res <u argL */ 2391 xer_ca 2392 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2393 break; 2394 2395 case /* 1 */ PPCG_FLAG_OP_ADDE: 2396 /* res <u argL || (old_ca==1 && res==argL) */ 2397 xer_ca 2398 = mkOR1( 2399 binop(Iop_CmpLT32U, res, argL), 2400 mkAND1( 2401 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2402 binop(Iop_CmpEQ32, res, argL) 2403 ) 2404 ); 2405 xer_ca 2406 = unop(Iop_1Uto32, xer_ca); 2407 break; 2408 2409 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2410 /* res <u argR || (old_ca==1 && res==argR) */ 2411 xer_ca 2412 = mkOR1( 2413 binop(Iop_CmpLT32U, res, argR), 2414 mkAND1( 2415 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2416 binop(Iop_CmpEQ32, res, argR) 2417 ) 2418 ); 2419 xer_ca 2420 = unop(Iop_1Uto32, xer_ca); 2421 break; 2422 2423 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2424 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2425 /* res <=u argR */ 2426 xer_ca 2427 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2428 break; 2429 2430 case /* 10 */ PPCG_FLAG_OP_SRAW: 2431 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2432 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2433 bit of argL. */ 2434 /* This term valid for shift amount < 32 only */ 2435 xer_ca 2436 = binop( 2437 Iop_And32, 2438 binop(Iop_Sar32, argL, mkU8(31)), 2439 binop( Iop_And32, 2440 argL, 2441 binop( Iop_Sub32, 2442 binop(Iop_Shl32, mkU32(1), 2443 unop(Iop_32to8,argR)), 2444 mkU32(1) ) 2445 ) 2446 ); 2447 xer_ca 2448 = IRExpr_ITE( 2449 /* shift amt > 31 ? */ 2450 binop(Iop_CmpLT32U, mkU32(31), argR), 2451 /* yes -- get sign bit of argL */ 2452 binop(Iop_Shr32, argL, mkU8(31)), 2453 /* no -- be like srawi */ 2454 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2455 ); 2456 break; 2457 2458 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2459 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2460 0. Since the shift amount is known to be in the range 2461 0 .. 31 inclusive the following seems viable: 2462 xer.ca == 1 iff the following is nonzero: 2463 (argL >>s 31) -- either all 0s or all 1s 2464 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2465 xer_ca 2466 = binop( 2467 Iop_And32, 2468 binop(Iop_Sar32, argL, mkU8(31)), 2469 binop( Iop_And32, 2470 argL, 2471 binop( Iop_Sub32, 2472 binop(Iop_Shl32, mkU32(1), 2473 unop(Iop_32to8,argR)), 2474 mkU32(1) ) 2475 ) 2476 ); 2477 xer_ca 2478 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2479 break; 2480 2481 default: 2482 vex_printf("set_XER_CA: op = %u\n", op); 2483 vpanic("set_XER_CA(ppc)"); 2484 } 2485 2486 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2487 putXER_CA( unop(Iop_32to8, xer_ca) ); 2488 } 2489 2490 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2491 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2492 { 2493 IRExpr* xer_ca; 2494 vassert(op < PPCG_FLAG_OP_NUMBER); 2495 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2496 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2497 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2498 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2499 2500 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2501 seems reasonable given that it's always generated by 2502 getXER_CA32(), which masks it accordingly. In any case it being 2503 0 or 1 is an invariant of the ppc guest state representation; 2504 if it has any other value, that invariant has been violated. */ 2505 2506 switch (op) { 2507 case /* 0 */ PPCG_FLAG_OP_ADD: 2508 /* res <u argL */ 2509 xer_ca 2510 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2511 break; 2512 2513 case /* 1 */ PPCG_FLAG_OP_ADDE: 2514 /* res <u argL || (old_ca==1 && res==argL) */ 2515 xer_ca 2516 = mkOR1( 2517 binop(Iop_CmpLT64U, res, argL), 2518 mkAND1( 2519 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2520 binop(Iop_CmpEQ64, res, argL) 2521 ) 2522 ); 2523 xer_ca 2524 = unop(Iop_1Uto32, xer_ca); 2525 break; 2526 2527 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2528 /* res <u argR || (old_ca==1 && res==argR) */ 2529 xer_ca 2530 = mkOR1( 2531 binop(Iop_CmpLT64U, res, argR), 2532 mkAND1( 2533 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2534 binop(Iop_CmpEQ64, res, argR) 2535 ) 2536 ); 2537 xer_ca 2538 = unop(Iop_1Uto32, xer_ca); 2539 break; 2540 2541 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2542 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2543 /* res <=u argR */ 2544 xer_ca 2545 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2546 break; 2547 2548 2549 case /* 10 */ PPCG_FLAG_OP_SRAW: 2550 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2551 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2552 bit of argL. */ 2553 /* This term valid for shift amount < 31 only */ 2554 2555 xer_ca 2556 = binop( 2557 Iop_And64, 2558 binop(Iop_Sar64, argL, mkU8(31)), 2559 binop( Iop_And64, 2560 argL, 2561 binop( Iop_Sub64, 2562 binop(Iop_Shl64, mkU64(1), 2563 unop(Iop_64to8,argR)), 2564 mkU64(1) ) 2565 ) 2566 ); 2567 xer_ca 2568 = IRExpr_ITE( 2569 /* shift amt > 31 ? */ 2570 binop(Iop_CmpLT64U, mkU64(31), argR), 2571 /* yes -- get sign bit of argL */ 2572 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2573 /* no -- be like srawi */ 2574 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2575 ); 2576 break; 2577 2578 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2579 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2580 Since the shift amount is known to be in the range 0 .. 31 2581 inclusive the following seems viable: 2582 xer.ca == 1 iff the following is nonzero: 2583 (argL >>s 31) -- either all 0s or all 1s 2584 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2585 2586 xer_ca 2587 = binop( 2588 Iop_And64, 2589 binop(Iop_Sar64, argL, mkU8(31)), 2590 binop( Iop_And64, 2591 argL, 2592 binop( Iop_Sub64, 2593 binop(Iop_Shl64, mkU64(1), 2594 unop(Iop_64to8,argR)), 2595 mkU64(1) ) 2596 ) 2597 ); 2598 xer_ca 2599 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2600 break; 2601 2602 2603 case /* 12 */ PPCG_FLAG_OP_SRAD: 2604 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2605 If it is <= 63, behave like SRADI; else XER.CA is the sign 2606 bit of argL. */ 2607 /* This term valid for shift amount < 63 only */ 2608 2609 xer_ca 2610 = binop( 2611 Iop_And64, 2612 binop(Iop_Sar64, argL, mkU8(63)), 2613 binop( Iop_And64, 2614 argL, 2615 binop( Iop_Sub64, 2616 binop(Iop_Shl64, mkU64(1), 2617 unop(Iop_64to8,argR)), 2618 mkU64(1) ) 2619 ) 2620 ); 2621 xer_ca 2622 = IRExpr_ITE( 2623 /* shift amt > 63 ? */ 2624 binop(Iop_CmpLT64U, mkU64(63), argR), 2625 /* yes -- get sign bit of argL */ 2626 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2627 /* no -- be like sradi */ 2628 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2629 ); 2630 break; 2631 2632 2633 case /* 13 */ PPCG_FLAG_OP_SRADI: 2634 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2635 Since the shift amount is known to be in the range 0 .. 63 2636 inclusive, the following seems viable: 2637 xer.ca == 1 iff the following is nonzero: 2638 (argL >>s 63) -- either all 0s or all 1s 2639 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2640 2641 xer_ca 2642 = binop( 2643 Iop_And64, 2644 binop(Iop_Sar64, argL, mkU8(63)), 2645 binop( Iop_And64, 2646 argL, 2647 binop( Iop_Sub64, 2648 binop(Iop_Shl64, mkU64(1), 2649 unop(Iop_64to8,argR)), 2650 mkU64(1) ) 2651 ) 2652 ); 2653 xer_ca 2654 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2655 break; 2656 2657 default: 2658 vex_printf("set_XER_CA: op = %u\n", op); 2659 vpanic("set_XER_CA(ppc64)"); 2660 } 2661 2662 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2663 putXER_CA( unop(Iop_32to8, xer_ca) ); 2664 } 2665 2666 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2667 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2668 { 2669 if (ty == Ity_I32) 2670 set_XER_CA_32( op, res, argL, argR, oldca ); 2671 else 2672 set_XER_CA_64( op, res, argL, argR, oldca ); 2673 } 2674 2675 2676 2677 /*------------------------------------------------------------*/ 2678 /*--- Read/write to guest-state --- */ 2679 /*------------------------------------------------------------*/ 2680 2681 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2682 { 2683 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2684 switch (reg) { 2685 case PPC_GST_SPRG3_RO: 2686 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2687 2688 case PPC_GST_CIA: 2689 return IRExpr_Get( OFFB_CIA, ty ); 2690 2691 case PPC_GST_LR: 2692 return IRExpr_Get( OFFB_LR, ty ); 2693 2694 case PPC_GST_CTR: 2695 return IRExpr_Get( OFFB_CTR, ty ); 2696 2697 case PPC_GST_VRSAVE: 2698 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2699 2700 case PPC_GST_VSCR: 2701 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2702 mkU32(MASK_VSCR_VALID)); 2703 2704 case PPC_GST_CR: { 2705 /* Synthesise the entire CR into a single word. Expensive. */ 2706 # define FIELD(_n) \ 2707 binop(Iop_Shl32, \ 2708 unop(Iop_8Uto32, \ 2709 binop(Iop_Or8, \ 2710 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2711 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2712 ) \ 2713 ), \ 2714 mkU8(4 * (7-(_n))) \ 2715 ) 2716 return binop(Iop_Or32, 2717 binop(Iop_Or32, 2718 binop(Iop_Or32, FIELD(0), FIELD(1)), 2719 binop(Iop_Or32, FIELD(2), FIELD(3)) 2720 ), 2721 binop(Iop_Or32, 2722 binop(Iop_Or32, FIELD(4), FIELD(5)), 2723 binop(Iop_Or32, FIELD(6), FIELD(7)) 2724 ) 2725 ); 2726 # undef FIELD 2727 } 2728 2729 case PPC_GST_XER: 2730 return binop(Iop_Or32, 2731 binop(Iop_Or32, 2732 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2733 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2734 binop(Iop_Or32, 2735 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2736 getXER_BC32())); 2737 2738 case PPC_GST_TFHAR: 2739 return IRExpr_Get( OFFB_TFHAR, ty ); 2740 2741 case PPC_GST_TEXASR: 2742 return IRExpr_Get( OFFB_TEXASR, ty ); 2743 2744 case PPC_GST_TEXASRU: 2745 return IRExpr_Get( OFFB_TEXASRU, ty ); 2746 2747 case PPC_GST_TFIAR: 2748 return IRExpr_Get( OFFB_TFIAR, ty ); 2749 2750 default: 2751 vex_printf("getGST(ppc): reg = %u", reg); 2752 vpanic("getGST(ppc)"); 2753 } 2754 } 2755 2756 /* Get a masked word from the given reg */ 2757 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2758 { 2759 IRTemp val = newTemp(Ity_I32); 2760 vassert( reg < PPC_GST_MAX ); 2761 2762 switch (reg) { 2763 2764 case PPC_GST_FPSCR: { 2765 /* Vex-generated code expects the FPSCR to be set as follows: 2766 all exceptions masked, round-to-nearest. 2767 This corresponds to a FPSCR value of 0x0. */ 2768 2769 /* In the lower 32 bits of FPSCR, we're only keeping track of 2770 * the binary floating point rounding mode, so if the mask isn't 2771 * asking for this, just return 0x0. 2772 */ 2773 if (mask & MASK_FPSCR_RN) { 2774 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2775 } else { 2776 assign( val, mkU32(0x0) ); 2777 } 2778 break; 2779 } 2780 2781 default: 2782 vex_printf("getGST_masked(ppc): reg = %u", reg); 2783 vpanic("getGST_masked(ppc)"); 2784 } 2785 2786 if (mask != 0xFFFFFFFF) { 2787 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2788 } else { 2789 return mkexpr(val); 2790 } 2791 } 2792 2793 /* Get a masked word from the given reg */ 2794 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2795 IRExpr * val; 2796 vassert( reg < PPC_GST_MAX ); 2797 2798 switch (reg) { 2799 2800 case PPC_GST_FPSCR: { 2801 /* In the upper 32 bits of FPSCR, we're only keeping track 2802 * of the decimal floating point rounding mode, so if the mask 2803 * isn't asking for this, just return 0x0. 2804 */ 2805 if (mask & MASK_FPSCR_DRN) { 2806 val = binop( Iop_And32, 2807 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2808 unop( Iop_64HIto32, mkU64( mask ) ) ); 2809 } else { 2810 val = mkU32( 0x0ULL ); 2811 } 2812 break; 2813 } 2814 2815 default: 2816 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2817 vpanic( "getGST_masked_upper(ppc)" ); 2818 } 2819 return val; 2820 } 2821 2822 2823 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2824 and return it at the bottom of an I32; the top 27 bits are 2825 guaranteed to be zero. */ 2826 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2827 { 2828 UInt shft, mask; 2829 2830 vassert( fld < 8 ); 2831 vassert( reg < PPC_GST_MAX ); 2832 2833 shft = 4*(7-fld); 2834 mask = 0xF<<shft; 2835 2836 switch (reg) { 2837 case PPC_GST_XER: 2838 vassert(fld ==7); 2839 return binop(Iop_Or32, 2840 binop(Iop_Or32, 2841 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2842 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2843 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2844 break; 2845 2846 default: 2847 if (shft == 0) 2848 return getGST_masked( reg, mask ); 2849 else 2850 return binop(Iop_Shr32, 2851 getGST_masked( reg, mask ), 2852 mkU8(toUChar( shft ))); 2853 } 2854 } 2855 2856 static void putGST ( PPC_GST reg, IRExpr* src ) 2857 { 2858 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2859 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2860 vassert( reg < PPC_GST_MAX ); 2861 switch (reg) { 2862 case PPC_GST_IP_AT_SYSCALL: 2863 vassert( ty_src == ty ); 2864 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2865 break; 2866 case PPC_GST_CIA: 2867 vassert( ty_src == ty ); 2868 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2869 break; 2870 case PPC_GST_LR: 2871 vassert( ty_src == ty ); 2872 stmt( IRStmt_Put( OFFB_LR, src ) ); 2873 break; 2874 case PPC_GST_CTR: 2875 vassert( ty_src == ty ); 2876 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2877 break; 2878 case PPC_GST_VRSAVE: 2879 vassert( ty_src == Ity_I32 ); 2880 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2881 break; 2882 case PPC_GST_VSCR: 2883 vassert( ty_src == Ity_I32 ); 2884 stmt( IRStmt_Put( OFFB_VSCR, 2885 binop(Iop_And32, src, 2886 mkU32(MASK_VSCR_VALID)) ) ); 2887 break; 2888 case PPC_GST_XER: 2889 vassert( ty_src == Ity_I32 ); 2890 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2891 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2892 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2893 putXER_BC( unop(Iop_32to8, src) ); 2894 break; 2895 2896 case PPC_GST_EMWARN: 2897 vassert( ty_src == Ity_I32 ); 2898 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 2899 break; 2900 2901 case PPC_GST_CMSTART: 2902 vassert( ty_src == ty ); 2903 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 2904 break; 2905 2906 case PPC_GST_CMLEN: 2907 vassert( ty_src == ty ); 2908 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 2909 break; 2910 2911 case PPC_GST_TEXASR: 2912 vassert( ty_src == Ity_I64 ); 2913 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 2914 break; 2915 2916 case PPC_GST_TEXASRU: 2917 vassert( ty_src == Ity_I32 ); 2918 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 2919 break; 2920 2921 case PPC_GST_TFIAR: 2922 vassert( ty_src == Ity_I64 ); 2923 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 2924 break; 2925 case PPC_GST_TFHAR: 2926 vassert( ty_src == Ity_I64 ); 2927 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 2928 break; 2929 default: 2930 vex_printf("putGST(ppc): reg = %u", reg); 2931 vpanic("putGST(ppc)"); 2932 } 2933 } 2934 2935 /* Write masked src to the given reg */ 2936 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 2937 { 2938 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2939 vassert( reg < PPC_GST_MAX ); 2940 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 2941 2942 switch (reg) { 2943 case PPC_GST_FPSCR: { 2944 /* Allow writes to either binary or decimal floating point 2945 Rounding Mode. 2946 */ 2947 /* If any part of |mask| covers FPSCR.RN, update the bits of 2948 FPSCR.RN by copying in |src| for locations where the 2949 corresponding bit in |mask| is 1, and leaving it unchanged 2950 for corresponding |mask| zero bits. */ 2951 if (mask & MASK_FPSCR_RN) { 2952 stmt( 2953 IRStmt_Put( 2954 OFFB_FPROUND, 2955 unop( 2956 Iop_32to8, 2957 binop( 2958 Iop_Or32, 2959 binop( 2960 Iop_And32, 2961 unop(Iop_64to32, src), 2962 mkU32(MASK_FPSCR_RN & mask) 2963 ), 2964 binop( 2965 Iop_And32, 2966 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 2967 mkU32(MASK_FPSCR_RN & ~mask) 2968 ) 2969 ) 2970 ) 2971 ) 2972 ); 2973 } 2974 /* Similarly, update FPSCR.DRN if any bits of |mask| 2975 corresponding to FPSCR.DRN are set. */ 2976 if (mask & MASK_FPSCR_DRN) { 2977 stmt( 2978 IRStmt_Put( 2979 OFFB_DFPROUND, 2980 unop( 2981 Iop_32to8, 2982 binop( 2983 Iop_Or32, 2984 binop( 2985 Iop_And32, 2986 unop(Iop_64HIto32, src), 2987 mkU32((MASK_FPSCR_DRN & mask) >> 32) 2988 ), 2989 binop( 2990 Iop_And32, 2991 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 2992 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 2993 ) 2994 ) 2995 ) 2996 ) 2997 ); 2998 } 2999 3000 /* Give EmNote for attempted writes to: 3001 - Exception Controls 3002 - Non-IEEE Mode 3003 */ 3004 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3005 VexEmNote ew = EmWarn_PPCexns; 3006 3007 /* If any of the src::exception_control bits are actually set, 3008 side-exit to the next insn, reporting the warning, 3009 so that Valgrind's dispatcher sees the warning. */ 3010 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3011 stmt( 3012 IRStmt_Exit( 3013 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3014 Ijk_EmWarn, 3015 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3016 } 3017 3018 /* Ignore all other writes */ 3019 break; 3020 } 3021 3022 default: 3023 vex_printf("putGST_masked(ppc): reg = %u", reg); 3024 vpanic("putGST_masked(ppc)"); 3025 } 3026 } 3027 3028 /* Write the least significant nibble of src to the specified 3029 REG[FLD] (as per IBM/hardware notation). */ 3030 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3031 { 3032 UInt shft; 3033 ULong mask; 3034 3035 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3036 vassert( fld < 16 ); 3037 vassert( reg < PPC_GST_MAX ); 3038 3039 if (fld < 8) 3040 shft = 4*(7-fld); 3041 else 3042 shft = 4*(15-fld); 3043 mask = 0xF; 3044 mask = mask << shft; 3045 3046 switch (reg) { 3047 case PPC_GST_CR: 3048 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3049 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3050 break; 3051 3052 default: 3053 { 3054 IRExpr * src64 = unop( Iop_32Uto64, src ); 3055 3056 if (shft == 0) { 3057 putGST_masked( reg, src64, mask ); 3058 } else { 3059 putGST_masked( reg, 3060 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3061 mask ); 3062 } 3063 } 3064 } 3065 } 3066 3067 /*------------------------------------------------------------*/ 3068 /* Helpers for VSX instructions that do floating point 3069 * operations and need to determine if a src contains a 3070 * special FP value. 3071 * 3072 *------------------------------------------------------------*/ 3073 3074 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3075 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3076 mkexpr( x ), \ 3077 mkU64( NONZERO_FRAC_MASK ) ) 3078 3079 // Returns exponent part of a single precision floating point as I32 3080 static IRExpr * fp_exp_part_sp(IRTemp src) 3081 { 3082 return binop( Iop_And32, 3083 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3084 mkU32( 0xff ) ); 3085 } 3086 3087 // Returns exponent part of floating point as I32 3088 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 3089 { 3090 IRExpr * exp; 3091 if (sp) 3092 return fp_exp_part_sp(src); 3093 3094 if (!mode64) 3095 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 3096 mkexpr( src ) ), 3097 mkU8( 20 ) ), mkU32( 0x7ff ) ); 3098 else 3099 exp = unop( Iop_64to32, 3100 binop( Iop_And64, 3101 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 3102 mkU64( 0x7ff ) ) ); 3103 return exp; 3104 } 3105 3106 static IRExpr * is_Inf_sp(IRTemp src) 3107 { 3108 IRTemp frac_part = newTemp(Ity_I32); 3109 IRExpr * Inf_exp; 3110 3111 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 3112 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 3113 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 3114 } 3115 3116 3117 // Infinity: exp = 7ff and fraction is zero; s = 0/1 3118 static IRExpr * is_Inf(IRTemp src, Bool sp) 3119 { 3120 IRExpr * Inf_exp, * hi32, * low32; 3121 IRTemp frac_part; 3122 3123 if (sp) 3124 return is_Inf_sp(src); 3125 3126 frac_part = newTemp(Ity_I64); 3127 assign( frac_part, FP_FRAC_PART(src) ); 3128 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 3129 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3130 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3131 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3132 mkU32( 0 ) ) ); 3133 } 3134 3135 static IRExpr * is_Zero_sp(IRTemp src) 3136 { 3137 IRTemp sign_less_part = newTemp(Ity_I32); 3138 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 3139 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 3140 } 3141 3142 // Zero: exp is zero and fraction is zero; s = 0/1 3143 static IRExpr * is_Zero(IRTemp src, Bool sp) 3144 { 3145 IRExpr * hi32, * low32; 3146 IRTemp sign_less_part; 3147 if (sp) 3148 return is_Zero_sp(src); 3149 3150 sign_less_part = newTemp(Ity_I64); 3151 3152 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 3153 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 3154 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 3155 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3156 mkU32( 0 ) ); 3157 } 3158 3159 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 3160 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 3161 * This function returns an IRExpr value of '1' for any type of NaN. 3162 */ 3163 static IRExpr * is_NaN(IRTemp src) 3164 { 3165 IRExpr * NaN_exp, * hi32, * low32; 3166 IRTemp frac_part = newTemp(Ity_I64); 3167 3168 assign( frac_part, FP_FRAC_PART(src) ); 3169 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3170 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3171 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 3172 mkU32( 0x7ff ) ); 3173 3174 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 3175 mkU32( 0 ) ) ); 3176 } 3177 3178 /* This function returns an IRExpr value of '1' for any type of NaN. 3179 * The passed 'src' argument is assumed to be Ity_I32. 3180 */ 3181 static IRExpr * is_NaN_32(IRTemp src) 3182 { 3183 #define NONZERO_FRAC_MASK32 0x007fffffULL 3184 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3185 mkexpr( x ), \ 3186 mkU32( NONZERO_FRAC_MASK32 ) ) 3187 3188 IRExpr * frac_part = FP_FRAC_PART32(src); 3189 IRExpr * exp_part = binop( Iop_And32, 3190 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3191 mkU32( 0x0ff ) ); 3192 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 3193 3194 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 3195 } 3196 3197 /* This function takes an Ity_I32 input argument interpreted 3198 * as a single-precision floating point value. If src is a 3199 * SNaN, it is changed to a QNaN and returned; otherwise, 3200 * the original value is returned. 3201 */ 3202 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 3203 { 3204 #define SNAN_MASK32 0x00400000 3205 IRTemp tmp = newTemp(Ity_I32); 3206 IRTemp mask = newTemp(Ity_I32); 3207 IRTemp is_SNAN = newTemp(Ity_I1); 3208 3209 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 3210 assign(tmp, src); 3211 3212 /* check if input is SNaN, if it is convert to QNaN */ 3213 assign( is_SNAN, 3214 mkAND1( is_NaN_32( tmp ), 3215 binop( Iop_CmpEQ32, 3216 binop( Iop_And32, mkexpr( tmp ), 3217 mkU32( SNAN_MASK32 ) ), 3218 mkU32( 0 ) ) ) ); 3219 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 3220 assign ( mask, binop( Iop_And32, 3221 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 3222 mkU32( SNAN_MASK32 ) ) ); 3223 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 3224 } 3225 3226 3227 /* This helper function performs the negation part of operations of the form: 3228 * "Negate Multiply-<op>" 3229 * where "<op>" is either "Add" or "Sub". 3230 * 3231 * This function takes one argument -- the floating point intermediate result (converted to 3232 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 3233 * the operation described above. 3234 */ 3235 static IRTemp getNegatedResult(IRTemp intermediateResult) 3236 { 3237 ULong signbit_mask = 0x8000000000000000ULL; 3238 IRTemp signbit_32 = newTemp(Ity_I32); 3239 IRTemp resultantSignbit = newTemp(Ity_I1); 3240 IRTemp negatedResult = newTemp(Ity_I64); 3241 assign( signbit_32, binop( Iop_Shr32, 3242 unop( Iop_64HIto32, 3243 binop( Iop_And64, mkexpr( intermediateResult ), 3244 mkU64( signbit_mask ) ) ), 3245 mkU8( 31 ) ) ); 3246 /* We negate the signbit if and only if the intermediate result from the 3247 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3248 */ 3249 assign( resultantSignbit, 3250 unop( Iop_Not1, 3251 binop( Iop_CmpEQ32, 3252 binop( Iop_Xor32, 3253 mkexpr( signbit_32 ), 3254 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 3255 mkU32( 1 ) ) ) ); 3256 3257 assign( negatedResult, 3258 binop( Iop_Or64, 3259 binop( Iop_And64, 3260 mkexpr( intermediateResult ), 3261 mkU64( ~signbit_mask ) ), 3262 binop( Iop_32HLto64, 3263 binop( Iop_Shl32, 3264 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3265 mkU8( 31 ) ), 3266 mkU32( 0 ) ) ) ); 3267 3268 return negatedResult; 3269 } 3270 3271 /* This helper function performs the negation part of operations of the form: 3272 * "Negate Multiply-<op>" 3273 * where "<op>" is either "Add" or "Sub". 3274 * 3275 * This function takes one argument -- the floating point intermediate result (converted to 3276 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 3277 * the operation described above. 3278 */ 3279 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 3280 { 3281 UInt signbit_mask = 0x80000000; 3282 IRTemp signbit_32 = newTemp(Ity_I32); 3283 IRTemp resultantSignbit = newTemp(Ity_I1); 3284 IRTemp negatedResult = newTemp(Ity_I32); 3285 assign( signbit_32, binop( Iop_Shr32, 3286 binop( Iop_And32, mkexpr( intermediateResult ), 3287 mkU32( signbit_mask ) ), 3288 mkU8( 31 ) ) ); 3289 /* We negate the signbit if and only if the intermediate result from the 3290 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3291 */ 3292 assign( resultantSignbit, 3293 unop( Iop_Not1, 3294 binop( Iop_CmpEQ32, 3295 binop( Iop_Xor32, 3296 mkexpr( signbit_32 ), 3297 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 3298 mkU32( 1 ) ) ) ); 3299 3300 assign( negatedResult, 3301 binop( Iop_Or32, 3302 binop( Iop_And32, 3303 mkexpr( intermediateResult ), 3304 mkU32( ~signbit_mask ) ), 3305 binop( Iop_Shl32, 3306 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3307 mkU8( 31 ) ) ) ); 3308 3309 return negatedResult; 3310 } 3311 3312 /*------------------------------------------------------------*/ 3313 /* Transactional memory helpers 3314 * 3315 *------------------------------------------------------------*/ 3316 3317 static ULong generate_TMreason( UInt failure_code, 3318 UInt persistant, 3319 UInt nest_overflow, 3320 UInt tm_exact ) 3321 { 3322 ULong tm_err_code = 3323 ( (ULong) 0) << (63-6) /* Failure code */ 3324 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 3325 | ( (ULong) 0) << (63-8) /* Disallowed */ 3326 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 3327 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 3328 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 3329 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 3330 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 3331 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 3332 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 3333 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 3334 | ( (ULong) 0) << (63-30) /* Reserved */ 3335 | ( (ULong) 0) << (63-31) /* Abort */ 3336 | ( (ULong) 0) << (63-32) /* Suspend */ 3337 | ( (ULong) 0) << (63-33) /* Reserved */ 3338 | ( (ULong) 0) << (63-35) /* Privilege */ 3339 | ( (ULong) 0) << (63-36) /* Failure Summary */ 3340 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 3341 | ( (ULong) 0) << (63-38) /* ROT */ 3342 | ( (ULong) 0) << (63-51) /* Reserved */ 3343 | ( (ULong) 0) << (63-63); /* Transaction Level */ 3344 3345 return tm_err_code; 3346 } 3347 3348 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 3349 Addr64 handler_address ) 3350 { 3351 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 3352 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 3353 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 3354 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 3355 } 3356 3357 /*------------------------------------------------------------*/ 3358 /*--- Integer Instruction Translation --- */ 3359 /*------------------------------------------------------------*/ 3360 3361 /* 3362 Integer Arithmetic Instructions 3363 */ 3364 static Bool dis_int_arith ( UInt theInstr ) 3365 { 3366 /* D-Form, XO-Form */ 3367 UChar opc1 = ifieldOPC(theInstr); 3368 UChar rD_addr = ifieldRegDS(theInstr); 3369 UChar rA_addr = ifieldRegA(theInstr); 3370 UInt uimm16 = ifieldUIMM16(theInstr); 3371 UChar rB_addr = ifieldRegB(theInstr); 3372 UChar flag_OE = ifieldBIT10(theInstr); 3373 UInt opc2 = ifieldOPClo9(theInstr); 3374 UChar flag_rC = ifieldBIT0(theInstr); 3375 3376 Long simm16 = extend_s_16to64(uimm16); 3377 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3378 IRTemp rA = newTemp(ty); 3379 IRTemp rB = newTemp(ty); 3380 IRTemp rD = newTemp(ty); 3381 3382 Bool do_rc = False; 3383 3384 assign( rA, getIReg(rA_addr) ); 3385 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3386 3387 switch (opc1) { 3388 /* D-Form */ 3389 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3390 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3391 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3392 mkSzExtendS16(ty, uimm16) ) ); 3393 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3394 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3395 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3396 break; 3397 3398 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3399 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3400 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3401 mkSzExtendS16(ty, uimm16) ) ); 3402 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3403 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3404 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3405 do_rc = True; // Always record to CR 3406 flag_rC = 1; 3407 break; 3408 3409 case 0x0E: // addi (Add Immediate, PPC32 p350) 3410 // li rD,val == addi rD,0,val 3411 // la disp(rA) == addi rD,rA,disp 3412 if ( rA_addr == 0 ) { 3413 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3414 assign( rD, mkSzExtendS16(ty, uimm16) ); 3415 } else { 3416 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3417 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3418 mkSzExtendS16(ty, uimm16) ) ); 3419 } 3420 break; 3421 3422 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3423 // lis rD,val == addis rD,0,val 3424 if ( rA_addr == 0 ) { 3425 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3426 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3427 } else { 3428 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 3429 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3430 mkSzExtendS32(ty, uimm16 << 16) ) ); 3431 } 3432 break; 3433 3434 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3435 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3436 if (mode64) 3437 assign( rD, unop(Iop_128to64, 3438 binop(Iop_MullS64, mkexpr(rA), 3439 mkSzExtendS16(ty, uimm16))) ); 3440 else 3441 assign( rD, unop(Iop_64to32, 3442 binop(Iop_MullS32, mkexpr(rA), 3443 mkSzExtendS16(ty, uimm16))) ); 3444 break; 3445 3446 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3447 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3448 // rD = simm16 - rA 3449 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3450 mkSzExtendS16(ty, uimm16), 3451 mkexpr(rA)) ); 3452 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3453 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3454 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3455 break; 3456 3457 /* XO-Form */ 3458 case 0x1F: 3459 do_rc = True; // All below record to CR 3460 3461 switch (opc2) { 3462 case 0x10A: // add (Add, PPC32 p347) 3463 DIP("add%s%s r%u,r%u,r%u\n", 3464 flag_OE ? "o" : "", flag_rC ? ".":"", 3465 rD_addr, rA_addr, rB_addr); 3466 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3467 mkexpr(rA), mkexpr(rB) ) ); 3468 if (flag_OE) { 3469 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3470 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3471 } 3472 break; 3473 3474 case 0x00A: // addc (Add Carrying, PPC32 p348) 3475 DIP("addc%s%s r%u,r%u,r%u\n", 3476 flag_OE ? "o" : "", flag_rC ? ".":"", 3477 rD_addr, rA_addr, rB_addr); 3478 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3479 mkexpr(rA), mkexpr(rB)) ); 3480 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3481 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3482 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3483 if (flag_OE) { 3484 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3485 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3486 } 3487 break; 3488 3489 case 0x08A: { // adde (Add Extended, PPC32 p349) 3490 IRTemp old_xer_ca = newTemp(ty); 3491 DIP("adde%s%s r%u,r%u,r%u\n", 3492 flag_OE ? "o" : "", flag_rC ? ".":"", 3493 rD_addr, rA_addr, rB_addr); 3494 // rD = rA + rB + XER[CA] 3495 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3496 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3497 binop( mkSzOp(ty, Iop_Add8), 3498 mkexpr(rB), mkexpr(old_xer_ca))) ); 3499 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3500 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3501 mkexpr(old_xer_ca) ); 3502 if (flag_OE) { 3503 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3504 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3505 } 3506 break; 3507 } 3508 3509 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3510 IRTemp old_xer_ca = newTemp(ty); 3511 IRExpr *min_one; 3512 if (rB_addr != 0) { 3513 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3514 return False; 3515 } 3516 DIP("addme%s%s r%u,r%u,r%u\n", 3517 flag_OE ? "o" : "", flag_rC ? ".":"", 3518 rD_addr, rA_addr, rB_addr); 3519 // rD = rA + (-1) + XER[CA] 3520 // => Just another form of adde 3521 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3522 min_one = mkSzImm(ty, (Long)-1); 3523 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3524 binop( mkSzOp(ty, Iop_Add8), 3525 min_one, mkexpr(old_xer_ca)) )); 3526 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3527 mkexpr(rD), mkexpr(rA), min_one, 3528 mkexpr(old_xer_ca) ); 3529 if (flag_OE) { 3530 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3531 mkexpr(rD), mkexpr(rA), min_one ); 3532 } 3533 break; 3534 } 3535 3536 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3537 IRTemp old_xer_ca = newTemp(ty); 3538 if (rB_addr != 0) { 3539 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3540 return False; 3541 } 3542 DIP("addze%s%s r%u,r%u,r%u\n", 3543 flag_OE ? "o" : "", flag_rC ? ".":"", 3544 rD_addr, rA_addr, rB_addr); 3545 // rD = rA + (0) + XER[CA] 3546 // => Just another form of adde 3547 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3548 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3549 mkexpr(rA), mkexpr(old_xer_ca)) ); 3550 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3551 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3552 mkexpr(old_xer_ca) ); 3553 if (flag_OE) { 3554 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3555 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3556 } 3557 break; 3558 } 3559 3560 case 0x1EB: // divw (Divide Word, PPC32 p388) 3561 DIP("divw%s%s r%u,r%u,r%u\n", 3562 flag_OE ? "o" : "", flag_rC ? ".":"", 3563 rD_addr, rA_addr, rB_addr); 3564 if (mode64) { 3565 /* Note: 3566 XER settings are mode independent, and reflect the 3567 overflow of the low-order 32bit result 3568 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3569 */ 3570 /* rD[hi32] are undefined: setting them to sign of lo32 3571 - makes set_CR0 happy */ 3572 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3573 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3574 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3575 divisor) ) ); 3576 if (flag_OE) { 3577 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3578 mkexpr(rD), dividend, divisor ); 3579 } 3580 } else { 3581 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3582 if (flag_OE) { 3583 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3584 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3585 } 3586 } 3587 /* Note: 3588 if (0x8000_0000 / -1) or (x / 0) 3589 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3590 => But _no_ exception raised. */ 3591 break; 3592 3593 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3594 DIP("divwu%s%s r%u,r%u,r%u\n", 3595 flag_OE ? "o" : "", flag_rC ? ".":"", 3596 rD_addr, rA_addr, rB_addr); 3597 if (mode64) { 3598 /* Note: 3599 XER settings are mode independent, and reflect the 3600 overflow of the low-order 32bit result 3601 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3602 */ 3603 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3604 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3605 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3606 divisor) ) ); 3607 if (flag_OE) { 3608 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3609 mkexpr(rD), dividend, divisor ); 3610 } 3611 } else { 3612 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3613 if (flag_OE) { 3614 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3615 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3616 } 3617 } 3618 /* Note: ditto comment divw, for (x / 0) */ 3619 break; 3620 3621 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3622 if (flag_OE != 0) { 3623 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3624 return False; 3625 } 3626 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3627 rD_addr, rA_addr, rB_addr); 3628 if (mode64) { 3629 /* rD[hi32] are undefined: setting them to sign of lo32 3630 - makes set_CR0 happy */ 3631 assign( rD, binop(Iop_Sar64, 3632 binop(Iop_Mul64, 3633 mk64lo32Sto64( mkexpr(rA) ), 3634 mk64lo32Sto64( mkexpr(rB) )), 3635 mkU8(32)) ); 3636 } else { 3637 assign( rD, unop(Iop_64HIto32, 3638 binop(Iop_MullS32, 3639 mkexpr(rA), mkexpr(rB))) ); 3640 } 3641 break; 3642 3643 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3644 if (flag_OE != 0) { 3645 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3646 return False; 3647 } 3648 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3649 rD_addr, rA_addr, rB_addr); 3650 if (mode64) { 3651 /* rD[hi32] are undefined: setting them to sign of lo32 3652 - makes set_CR0 happy */ 3653 assign( rD, binop(Iop_Sar64, 3654 binop(Iop_Mul64, 3655 mk64lo32Uto64( mkexpr(rA) ), 3656 mk64lo32Uto64( mkexpr(rB) ) ), 3657 mkU8(32)) ); 3658 } else { 3659 assign( rD, unop(Iop_64HIto32, 3660 binop(Iop_MullU32, 3661 mkexpr(rA), mkexpr(rB))) ); 3662 } 3663 break; 3664 3665 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3666 DIP("mullw%s%s r%u,r%u,r%u\n", 3667 flag_OE ? "o" : "", flag_rC ? ".":"", 3668 rD_addr, rA_addr, rB_addr); 3669 if (mode64) { 3670 /* rD[hi32] are undefined: setting them to sign of lo32 3671 - set_XER_OV() and set_CR0() depend on this */ 3672 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3673 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3674 assign( rD, binop(Iop_MullS32, a, b) ); 3675 if (flag_OE) { 3676 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3677 mkexpr(rD), 3678 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3679 } 3680 } else { 3681 assign( rD, unop(Iop_64to32, 3682 binop(Iop_MullU32, 3683 mkexpr(rA), mkexpr(rB))) ); 3684 if (flag_OE) { 3685 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3686 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3687 } 3688 } 3689 break; 3690 3691 case 0x068: // neg (Negate, PPC32 p493) 3692 if (rB_addr != 0) { 3693 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3694 return False; 3695 } 3696 DIP("neg%s%s r%u,r%u\n", 3697 flag_OE ? "o" : "", flag_rC ? ".":"", 3698 rD_addr, rA_addr); 3699 // rD = (~rA) + 1 3700 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3701 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3702 mkSzImm(ty, 1)) ); 3703 if (flag_OE) { 3704 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3705 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3706 } 3707 break; 3708 3709 case 0x028: // subf (Subtract From, PPC32 p537) 3710 DIP("subf%s%s r%u,r%u,r%u\n", 3711 flag_OE ? "o" : "", flag_rC ? ".":"", 3712 rD_addr, rA_addr, rB_addr); 3713 // rD = rB - rA 3714 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3715 mkexpr(rB), mkexpr(rA)) ); 3716 if (flag_OE) { 3717 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3718 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3719 } 3720 break; 3721 3722 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3723 DIP("subfc%s%s r%u,r%u,r%u\n", 3724 flag_OE ? "o" : "", flag_rC ? ".":"", 3725 rD_addr, rA_addr, rB_addr); 3726 // rD = rB - rA 3727 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3728 mkexpr(rB), mkexpr(rA)) ); 3729 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3730 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3731 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3732 if (flag_OE) { 3733 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3734 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3735 } 3736 break; 3737 3738 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3739 IRTemp old_xer_ca = newTemp(ty); 3740 DIP("subfe%s%s r%u,r%u,r%u\n", 3741 flag_OE ? "o" : "", flag_rC ? ".":"", 3742 rD_addr, rA_addr, rB_addr); 3743 // rD = (log not)rA + rB + XER[CA] 3744 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3745 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3746 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3747 binop( mkSzOp(ty, Iop_Add8), 3748 mkexpr(rB), mkexpr(old_xer_ca))) ); 3749 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3750 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3751 mkexpr(old_xer_ca) ); 3752 if (flag_OE) { 3753 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3754 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3755 } 3756 break; 3757 } 3758 3759 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3760 IRTemp old_xer_ca = newTemp(ty); 3761 IRExpr *min_one; 3762 if (rB_addr != 0) { 3763 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3764 return False; 3765 } 3766 DIP("subfme%s%s r%u,r%u\n", 3767 flag_OE ? "o" : "", flag_rC ? ".":"", 3768 rD_addr, rA_addr); 3769 // rD = (log not)rA + (-1) + XER[CA] 3770 // => Just another form of subfe 3771 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3772 min_one = mkSzImm(ty, (Long)-1); 3773 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3774 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3775 binop( mkSzOp(ty, Iop_Add8), 3776 min_one, mkexpr(old_xer_ca))) ); 3777 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3778 mkexpr(rD), mkexpr(rA), min_one, 3779 mkexpr(old_xer_ca) ); 3780 if (flag_OE) { 3781 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3782 mkexpr(rD), mkexpr(rA), min_one ); 3783 } 3784 break; 3785 } 3786 3787 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3788 IRTemp old_xer_ca = newTemp(ty); 3789 if (rB_addr != 0) { 3790 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3791 return False; 3792 } 3793 DIP("subfze%s%s r%u,r%u\n", 3794 flag_OE ? "o" : "", flag_rC ? ".":"", 3795 rD_addr, rA_addr); 3796 // rD = (log not)rA + (0) + XER[CA] 3797 // => Just another form of subfe 3798 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3799 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3800 unop( mkSzOp(ty, Iop_Not8), 3801 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3802 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3803 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3804 mkexpr(old_xer_ca) ); 3805 if (flag_OE) { 3806 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3807 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3808 } 3809 break; 3810 } 3811 3812 3813 /* 64bit Arithmetic */ 3814 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3815 if (flag_OE != 0) { 3816 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3817 return False; 3818 } 3819 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3820 rD_addr, rA_addr, rB_addr); 3821 assign( rD, unop(Iop_128HIto64, 3822 binop(Iop_MullS64, 3823 mkexpr(rA), mkexpr(rB))) ); 3824 3825 break; 3826 3827 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3828 if (flag_OE != 0) { 3829 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3830 return False; 3831 } 3832 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3833 rD_addr, rA_addr, rB_addr); 3834 assign( rD, unop(Iop_128HIto64, 3835 binop(Iop_MullU64, 3836 mkexpr(rA), mkexpr(rB))) ); 3837 break; 3838 3839 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3840 DIP("mulld%s%s r%u,r%u,r%u\n", 3841 flag_OE ? "o" : "", flag_rC ? ".":"", 3842 rD_addr, rA_addr, rB_addr); 3843 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3844 if (flag_OE) { 3845 set_XER_OV( ty, PPCG_FLAG_OP_MULLD, 3846 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3847 } 3848 break; 3849 3850 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3851 DIP("divd%s%s r%u,r%u,r%u\n", 3852 flag_OE ? "o" : "", flag_rC ? ".":"", 3853 rD_addr, rA_addr, rB_addr); 3854 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3855 if (flag_OE) { 3856 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3857 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3858 } 3859 break; 3860 /* Note: 3861 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3862 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3863 => But _no_ exception raised. */ 3864 3865 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3866 DIP("divdu%s%s r%u,r%u,r%u\n", 3867 flag_OE ? "o" : "", flag_rC ? ".":"", 3868 rD_addr, rA_addr, rB_addr); 3869 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3870 if (flag_OE) { 3871 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3872 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3873 } 3874 break; 3875 /* Note: ditto comment divd, for (x / 0) */ 3876 3877 case 0x18B: // divweu (Divide Word Extended Unsigned) 3878 { 3879 /* 3880 * If (RA) >= (RB), or if an attempt is made to perform the division 3881 * <anything> / 0 3882 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3883 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3884 * to 1. 3885 */ 3886 IRTemp res = newTemp(Ity_I32); 3887 IRExpr * dividend, * divisor; 3888 DIP("divweu%s%s r%u,r%u,r%u\n", 3889 flag_OE ? "o" : "", flag_rC ? ".":"", 3890 rD_addr, rA_addr, rB_addr); 3891 if (mode64) { 3892 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3893 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3894 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3895 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3896 } else { 3897 dividend = mkexpr( rA ); 3898 divisor = mkexpr( rB ); 3899 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3900 assign( rD, mkexpr( res) ); 3901 } 3902 3903 if (flag_OE) { 3904 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 3905 mkexpr(res), dividend, divisor ); 3906 } 3907 break; 3908 } 3909 3910 case 0x1AB: // divwe (Divide Word Extended) 3911 { 3912 /* 3913 * If the quotient cannot be represented in 32 bits, or if an 3914 * attempt is made to perform the division 3915 * <anything> / 0 3916 * then the contents of register RD are undefined as are (if 3917 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3918 * Field 0. In these cases, if OE=1 then OV is set to 1. 3919 */ 3920 3921 IRTemp res = newTemp(Ity_I32); 3922 IRExpr * dividend, * divisor; 3923 DIP("divwe%s%s r%u,r%u,r%u\n", 3924 flag_OE ? "o" : "", flag_rC ? ".":"", 3925 rD_addr, rA_addr, rB_addr); 3926 if (mode64) { 3927 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3928 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3929 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3930 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3931 } else { 3932 dividend = mkexpr( rA ); 3933 divisor = mkexpr( rB ); 3934 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3935 assign( rD, mkexpr( res) ); 3936 } 3937 3938 if (flag_OE) { 3939 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 3940 mkexpr(res), dividend, divisor ); 3941 } 3942 break; 3943 } 3944 3945 3946 case 0x1A9: // divde (Divide Doubleword Extended) 3947 /* 3948 * If the quotient cannot be represented in 64 bits, or if an 3949 * attempt is made to perform the division 3950 * <anything> / 0 3951 * then the contents of register RD are undefined as are (if 3952 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3953 * Field 0. In these cases, if OE=1 then OV is set to 1. 3954 */ 3955 DIP("divde%s%s r%u,r%u,r%u\n", 3956 flag_OE ? "o" : "", flag_rC ? ".":"", 3957 rD_addr, rA_addr, rB_addr); 3958 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 3959 if (flag_OE) { 3960 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 3961 mkexpr( rA ), mkexpr( rB ) ); 3962 } 3963 break; 3964 3965 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 3966 // Same CR and OV rules as given for divweu above 3967 DIP("divdeu%s%s r%u,r%u,r%u\n", 3968 flag_OE ? "o" : "", flag_rC ? ".":"", 3969 rD_addr, rA_addr, rB_addr); 3970 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 3971 if (flag_OE) { 3972 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 3973 mkexpr( rA ), mkexpr( rB ) ); 3974 } 3975 break; 3976 3977 default: 3978 vex_printf("dis_int_arith(ppc)(opc2)\n"); 3979 return False; 3980 } 3981 break; 3982 3983 default: 3984 vex_printf("dis_int_arith(ppc)(opc1)\n"); 3985 return False; 3986 } 3987 3988 putIReg( rD_addr, mkexpr(rD) ); 3989 3990 if (do_rc && flag_rC) { 3991 set_CR0( mkexpr(rD) ); 3992 } 3993 return True; 3994 } 3995 3996 3997 3998 /* 3999 Integer Compare Instructions 4000 */ 4001 static Bool dis_int_cmp ( UInt theInstr ) 4002 { 4003 /* D-Form, X-Form */ 4004 UChar opc1 = ifieldOPC(theInstr); 4005 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 4006 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 4007 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 4008 UChar rA_addr = ifieldRegA(theInstr); 4009 UInt uimm16 = ifieldUIMM16(theInstr); 4010 UChar rB_addr = ifieldRegB(theInstr); 4011 UInt opc2 = ifieldOPClo10(theInstr); 4012 UChar b0 = ifieldBIT0(theInstr); 4013 4014 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4015 IRExpr *a = getIReg(rA_addr); 4016 IRExpr *b; 4017 4018 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 4019 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 4020 return False; 4021 } 4022 4023 if (b22 != 0) { 4024 vex_printf("dis_int_cmp(ppc)(b22)\n"); 4025 return False; 4026 } 4027 4028 switch (opc1) { 4029 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 4030 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 4031 (Int)extend_s_16to32(uimm16)); 4032 b = mkSzExtendS16( ty, uimm16 ); 4033 if (flag_L == 1) { 4034 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4035 } else { 4036 a = mkNarrowTo32( ty, a ); 4037 b = mkNarrowTo32( ty, b ); 4038 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 4039 } 4040 putCR0( crfD, getXER_SO() ); 4041 break; 4042 4043 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 4044 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 4045 b = mkSzImm( ty, uimm16 ); 4046 if (flag_L == 1) { 4047 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4048 } else { 4049 a = mkNarrowTo32( ty, a ); 4050 b = mkNarrowTo32( ty, b ); 4051 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4052 } 4053 putCR0( crfD, getXER_SO() ); 4054 break; 4055 4056 /* X Form */ 4057 case 0x1F: 4058 if (b0 != 0) { 4059 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 4060 return False; 4061 } 4062 b = getIReg(rB_addr); 4063 4064 switch (opc2) { 4065 case 0x000: // cmp (Compare, PPC32 p367) 4066 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4067 /* Comparing a reg with itself produces a result which 4068 doesn't depend on the contents of the reg. Therefore 4069 remove the false dependency, which has been known to cause 4070 memcheck to produce false errors. */ 4071 if (rA_addr == rB_addr) 4072 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4073 ? mkU64(0) : mkU32(0); 4074 if (flag_L == 1) { 4075 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4076 } else { 4077 a = mkNarrowTo32( ty, a ); 4078 b = mkNarrowTo32( ty, b ); 4079 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 4080 } 4081 putCR0( crfD, getXER_SO() ); 4082 break; 4083 4084 case 0x020: // cmpl (Compare Logical, PPC32 p369) 4085 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4086 /* Comparing a reg with itself produces a result which 4087 doesn't depend on the contents of the reg. Therefore 4088 remove the false dependency, which has been known to cause 4089 memcheck to produce false errors. */ 4090 if (rA_addr == rB_addr) 4091 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4092 ? mkU64(0) : mkU32(0); 4093 if (flag_L == 1) { 4094 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4095 } else { 4096 a = mkNarrowTo32( ty, a ); 4097 b = mkNarrowTo32( ty, b ); 4098 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4099 } 4100 putCR0( crfD, getXER_SO() ); 4101 break; 4102 4103 default: 4104 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 4105 return False; 4106 } 4107 break; 4108 4109 default: 4110 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 4111 return False; 4112 } 4113 4114 return True; 4115 } 4116 4117 4118 /* 4119 Integer Logical Instructions 4120 */ 4121 static Bool dis_int_logic ( UInt theInstr ) 4122 { 4123 /* D-Form, X-Form */ 4124 UChar opc1 = ifieldOPC(theInstr); 4125 UChar rS_addr = ifieldRegDS(theInstr); 4126 UChar rA_addr = ifieldRegA(theInstr); 4127 UInt uimm16 = ifieldUIMM16(theInstr); 4128 UChar rB_addr = ifieldRegB(theInstr); 4129 UInt opc2 = ifieldOPClo10(theInstr); 4130 UChar flag_rC = ifieldBIT0(theInstr); 4131 4132 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4133 IRTemp rS = newTemp(ty); 4134 IRTemp rA = newTemp(ty); 4135 IRTemp rB = newTemp(ty); 4136 IRExpr* irx; 4137 Bool do_rc = False; 4138 4139 assign( rS, getIReg(rS_addr) ); 4140 assign( rB, getIReg(rB_addr) ); 4141 4142 switch (opc1) { 4143 case 0x1C: // andi. (AND Immediate, PPC32 p358) 4144 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4145 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4146 mkSzImm(ty, uimm16)) ); 4147 do_rc = True; // Always record to CR 4148 flag_rC = 1; 4149 break; 4150 4151 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 4152 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4153 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4154 mkSzImm(ty, uimm16 << 16)) ); 4155 do_rc = True; // Always record to CR 4156 flag_rC = 1; 4157 break; 4158 4159 case 0x18: // ori (OR Immediate, PPC32 p497) 4160 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4161 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4162 mkSzImm(ty, uimm16)) ); 4163 break; 4164 4165 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 4166 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4167 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4168 mkSzImm(ty, uimm16 << 16)) ); 4169 break; 4170 4171 case 0x1A: // xori (XOR Immediate, PPC32 p550) 4172 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4173 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4174 mkSzImm(ty, uimm16)) ); 4175 break; 4176 4177 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 4178 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4179 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4180 mkSzImm(ty, uimm16 << 16)) ); 4181 break; 4182 4183 /* X Form */ 4184 case 0x1F: 4185 do_rc = True; // All below record to CR, except for where we return at case end. 4186 4187 switch (opc2) { 4188 case 0x01C: // and (AND, PPC32 p356) 4189 DIP("and%s r%u,r%u,r%u\n", 4190 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4191 assign(rA, binop( mkSzOp(ty, Iop_And8), 4192 mkexpr(rS), mkexpr(rB))); 4193 break; 4194 4195 case 0x03C: // andc (AND with Complement, PPC32 p357) 4196 DIP("andc%s r%u,r%u,r%u\n", 4197 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4198 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4199 unop( mkSzOp(ty, Iop_Not8), 4200 mkexpr(rB)))); 4201 break; 4202 4203 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 4204 IRExpr* lo32; 4205 if (rB_addr!=0) { 4206 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 4207 return False; 4208 } 4209 DIP("cntlzw%s r%u,r%u\n", 4210 flag_rC ? ".":"", rA_addr, rS_addr); 4211 4212 // mode64: count in low word only 4213 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 4214 4215 // Iop_Clz32 undefined for arg==0, so deal with that case: 4216 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 4217 assign(rA, mkWidenFrom32(ty, 4218 IRExpr_ITE( irx, 4219 unop(Iop_Clz32, lo32), 4220 mkU32(32)), 4221 False)); 4222 4223 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 4224 break; 4225 } 4226 4227 case 0x11C: // eqv (Equivalent, PPC32 p396) 4228 DIP("eqv%s r%u,r%u,r%u\n", 4229 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4230 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4231 binop( mkSzOp(ty, Iop_Xor8), 4232 mkexpr(rS), mkexpr(rB))) ); 4233 break; 4234 4235 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 4236 if (rB_addr!=0) { 4237 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 4238 return False; 4239 } 4240 DIP("extsb%s r%u,r%u\n", 4241 flag_rC ? ".":"", rA_addr, rS_addr); 4242 if (mode64) 4243 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 4244 else 4245 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 4246 break; 4247 4248 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 4249 if (rB_addr!=0) { 4250 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 4251 return False; 4252 } 4253 DIP("extsh%s r%u,r%u\n", 4254 flag_rC ? ".":"", rA_addr, rS_addr); 4255 if (mode64) 4256 assign( rA, unop(Iop_16Sto64, 4257 unop(Iop_64to16, mkexpr(rS))) ); 4258 else 4259 assign( rA, unop(Iop_16Sto32, 4260 unop(Iop_32to16, mkexpr(rS))) ); 4261 break; 4262 4263 case 0x1DC: // nand (NAND, PPC32 p492) 4264 DIP("nand%s r%u,r%u,r%u\n", 4265 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4266 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4267 binop( mkSzOp(ty, Iop_And8), 4268 mkexpr(rS), mkexpr(rB))) ); 4269 break; 4270 4271 case 0x07C: // nor (NOR, PPC32 p494) 4272 DIP("nor%s r%u,r%u,r%u\n", 4273 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4274 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4275 binop( mkSzOp(ty, Iop_Or8), 4276 mkexpr(rS), mkexpr(rB))) ); 4277 break; 4278 4279 case 0x1BC: // or (OR, PPC32 p495) 4280 if ((!flag_rC) && rS_addr == rB_addr) { 4281 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 4282 assign( rA, mkexpr(rS) ); 4283 } else { 4284 DIP("or%s r%u,r%u,r%u\n", 4285 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4286 assign( rA, binop( mkSzOp(ty, Iop_Or8), 4287 mkexpr(rS), mkexpr(rB)) ); 4288 } 4289 break; 4290 4291 case 0x19C: // orc (OR with Complement, PPC32 p496) 4292 DIP("orc%s r%u,r%u,r%u\n", 4293 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4294 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4295 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 4296 break; 4297 4298 case 0x13C: // xor (XOR, PPC32 p549) 4299 DIP("xor%s r%u,r%u,r%u\n", 4300 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4301 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 4302 mkexpr(rS), mkexpr(rB)) ); 4303 break; 4304 4305 4306 /* 64bit Integer Logical Instructions */ 4307 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 4308 if (rB_addr!=0) { 4309 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 4310 return False; 4311 } 4312 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 4313 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 4314 break; 4315 4316 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 4317 if (rB_addr!=0) { 4318 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 4319 return False; 4320 } 4321 DIP("cntlzd%s r%u,r%u\n", 4322 flag_rC ? ".":"", rA_addr, rS_addr); 4323 // Iop_Clz64 undefined for arg==0, so deal with that case: 4324 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 4325 assign(rA, IRExpr_ITE( irx, 4326 unop(Iop_Clz64, mkexpr(rS)), 4327 mkU64(64) )); 4328 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 4329 break; 4330 4331 case 0x1FC: // cmpb (Power6: compare bytes) 4332 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4333 4334 if (mode64) 4335 assign( rA, unop( Iop_V128to64, 4336 binop( Iop_CmpEQ8x16, 4337 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 4338 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 4339 )) ); 4340 else 4341 assign( rA, unop( Iop_V128to32, 4342 binop( Iop_CmpEQ8x16, 4343 unop( Iop_32UtoV128, mkexpr(rS) ), 4344 unop( Iop_32UtoV128, mkexpr(rB) ) 4345 )) ); 4346 break; 4347 4348 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 4349 IRTemp frB = newTemp(Ity_F64); 4350 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 4351 4352 assign( frB, getFReg(rB_addr)); // always F64 4353 if (mode64) 4354 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 4355 else 4356 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 4357 4358 putIReg( rS_addr, mkexpr(rA)); 4359 return True; 4360 } 4361 4362 case 0x25F: { // mffgpr (move floating-point from general purpose register) 4363 IRTemp frA = newTemp(Ity_F64); 4364 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 4365 4366 if (mode64) 4367 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 4368 else 4369 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 4370 4371 putFReg( rS_addr, mkexpr(frA)); 4372 return True; 4373 } 4374 case 0x1FA: // popcntd (population count doubleword 4375 { 4376 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4377 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 4378 putIReg( rA_addr, mkexpr(result) ); 4379 return True; 4380 } 4381 case 0x17A: // popcntw (Population Count Words) 4382 { 4383 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4384 if (mode64) { 4385 IRTemp resultHi, resultLo; 4386 IRTemp argLo = newTemp(Ity_I32); 4387 IRTemp argHi = newTemp(Ity_I32); 4388 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4389 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4390 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 4391 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 4392 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4393 } else { 4394 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 4395 putIReg( rA_addr, mkexpr(result) ); 4396 } 4397 return True; 4398 } 4399 case 0x7A: // popcntb (Population Count Byte) 4400 { 4401 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4402 4403 if (mode64) { 4404 IRTemp resultHi, resultLo; 4405 IRTemp argLo = newTemp(Ity_I32); 4406 IRTemp argHi = newTemp(Ity_I32); 4407 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4408 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4409 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 4410 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 4411 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4412 mkexpr(resultLo))); 4413 } else { 4414 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 4415 putIReg( rA_addr, mkexpr(result) ); 4416 } 4417 return True; 4418 } 4419 case 0x0FC: // bpermd (Bit Permute Doubleword) 4420 { 4421 /* This is a lot of rigmarole to emulate bpermd like this, as it 4422 * could be done much faster by implementing a call to the native 4423 * instruction. However, where possible I want to avoid using new 4424 * native instructions so that we can use valgrind to emulate those 4425 * instructions on older PPC64 hardware. 4426 */ 4427 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4428 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4429 int i; 4430 IRExpr * rS_expr = mkexpr(rS); 4431 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4432 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4433 for (i = 0; i < 8; i++) { 4434 IRTemp idx_tmp = newTemp( Ity_I64 ); 4435 IRTemp perm_bit = newTemp( Ity_I64 ); 4436 IRTemp idx = newTemp( Ity_I8 ); 4437 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4438 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4439 4440 assign( idx_tmp, 4441 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4442 assign( idx_LT64, 4443 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4444 assign( idx, 4445 binop( Iop_And8, 4446 unop( Iop_1Sto8, 4447 mkexpr(idx_LT64) ), 4448 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4449 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4450 * to determine which bit of rB to use for the perm bit, and then we shift 4451 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4452 * to set the final perm bit. 4453 */ 4454 assign( idx_LT64_ity64, 4455 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4456 assign( perm_bit, 4457 binop( Iop_And64, 4458 mkexpr( idx_LT64_ity64 ), 4459 binop( Iop_Shr64, 4460 binop( Iop_And64, 4461 mkU64( BPERMD_BIT_MASK ), 4462 binop( Iop_Shl64, 4463 mkexpr( rB ), 4464 mkexpr( idx ) ) ), 4465 mkU8( 63 ) ) ) ); 4466 res = binop( Iop_Or64, 4467 res, 4468 binop( Iop_Shl64, 4469 mkexpr( perm_bit ), 4470 mkU8( i ) ) ); 4471 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4472 } 4473 putIReg(rA_addr, res); 4474 return True; 4475 } 4476 4477 default: 4478 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4479 return False; 4480 } 4481 break; 4482 4483 default: 4484 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4485 return False; 4486 } 4487 4488 putIReg( rA_addr, mkexpr(rA) ); 4489 4490 if (do_rc && flag_rC) { 4491 set_CR0( mkexpr(rA) ); 4492 } 4493 return True; 4494 } 4495 4496 /* 4497 Integer Parity Instructions 4498 */ 4499 static Bool dis_int_parity ( UInt theInstr ) 4500 { 4501 /* X-Form */ 4502 UChar opc1 = ifieldOPC(theInstr); 4503 UChar rS_addr = ifieldRegDS(theInstr); 4504 UChar rA_addr = ifieldRegA(theInstr); 4505 UChar rB_addr = ifieldRegB(theInstr); 4506 UInt opc2 = ifieldOPClo10(theInstr); 4507 UChar b0 = ifieldBIT0(theInstr); 4508 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4509 4510 IRTemp rS = newTemp(ty); 4511 IRTemp rA = newTemp(ty); 4512 IRTemp iTot1 = newTemp(Ity_I32); 4513 IRTemp iTot2 = newTemp(Ity_I32); 4514 IRTemp iTot3 = newTemp(Ity_I32); 4515 IRTemp iTot4 = newTemp(Ity_I32); 4516 IRTemp iTot5 = newTemp(Ity_I32); 4517 IRTemp iTot6 = newTemp(Ity_I32); 4518 IRTemp iTot7 = newTemp(Ity_I32); 4519 IRTemp iTot8 = newTemp(Ity_I32); 4520 IRTemp rS1 = newTemp(ty); 4521 IRTemp rS2 = newTemp(ty); 4522 IRTemp rS3 = newTemp(ty); 4523 IRTemp rS4 = newTemp(ty); 4524 IRTemp rS5 = newTemp(ty); 4525 IRTemp rS6 = newTemp(ty); 4526 IRTemp rS7 = newTemp(ty); 4527 IRTemp iHi = newTemp(Ity_I32); 4528 IRTemp iLo = newTemp(Ity_I32); 4529 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4530 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4531 4532 if (opc1 != 0x1f || rB_addr || b0) { 4533 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4534 return False; 4535 } 4536 4537 assign( rS, getIReg(rS_addr) ); 4538 4539 switch (opc2) { 4540 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4541 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4542 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4543 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4544 assign( iTot2, binop(Iop_Add32, 4545 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4546 mkexpr(iTot1)) ); 4547 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4548 assign( iTot3, binop(Iop_Add32, 4549 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4550 mkexpr(iTot2)) ); 4551 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4552 assign( iTot4, binop(Iop_Add32, 4553 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4554 mkexpr(iTot3)) ); 4555 if (mode64) { 4556 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4557 assign( iTot5, binop(Iop_Add32, 4558 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4559 mkexpr(iTot4)) ); 4560 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4561 assign( iTot6, binop(Iop_Add32, 4562 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4563 mkexpr(iTot5)) ); 4564 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4565 assign( iTot7, binop(Iop_Add32, 4566 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4567 mkexpr(iTot6)) ); 4568 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4569 assign( iTot8, binop(Iop_Add32, 4570 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4571 mkexpr(iTot7)) ); 4572 assign( rA, unop(Iop_32Uto64, 4573 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4574 } else 4575 assign( rA, mkexpr(iTot4) ); 4576 4577 break; 4578 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4579 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4580 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4581 assign( iTot2, binop(Iop_Add32, 4582 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4583 mkexpr(iTot1)) ); 4584 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4585 assign( iTot3, binop(Iop_Add32, 4586 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4587 mkexpr(iTot2)) ); 4588 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4589 assign( iTot4, binop(Iop_Add32, 4590 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4591 mkexpr(iTot3)) ); 4592 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4593 4594 if (mode64) { 4595 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4596 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4597 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4598 assign( iTot6, binop(Iop_Add32, 4599 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4600 mkexpr(iTot5)) ); 4601 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4602 assign( iTot7, binop(Iop_Add32, 4603 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4604 mkexpr(iTot6)) ); 4605 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4606 assign( iTot8, binop(Iop_Add32, 4607 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4608 mkexpr(iTot7)) ); 4609 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4610 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4611 } else 4612 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4613 break; 4614 default: 4615 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4616 return False; 4617 } 4618 4619 putIReg( rA_addr, mkexpr(rA) ); 4620 4621 return True; 4622 } 4623 4624 4625 /* 4626 Integer Rotate Instructions 4627 */ 4628 static Bool dis_int_rot ( UInt theInstr ) 4629 { 4630 /* M-Form, MDS-Form */ 4631 UChar opc1 = ifieldOPC(theInstr); 4632 UChar rS_addr = ifieldRegDS(theInstr); 4633 UChar rA_addr = ifieldRegA(theInstr); 4634 UChar rB_addr = ifieldRegB(theInstr); 4635 UChar sh_imm = rB_addr; 4636 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4637 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4638 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4639 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4640 UChar b1 = ifieldBIT1(theInstr); 4641 UChar flag_rC = ifieldBIT0(theInstr); 4642 4643 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4644 IRTemp rS = newTemp(ty); 4645 IRTemp rA = newTemp(ty); 4646 IRTemp rB = newTemp(ty); 4647 IRTemp rot = newTemp(ty); 4648 IRExpr *r; 4649 UInt mask32; 4650 ULong mask64; 4651 4652 assign( rS, getIReg(rS_addr) ); 4653 assign( rB, getIReg(rB_addr) ); 4654 4655 switch (opc1) { 4656 case 0x14: { 4657 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4658 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4659 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4660 if (mode64) { 4661 // tmp32 = (ROTL(rS_Lo32, Imm) 4662 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4663 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4664 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4665 r = unop(Iop_32Uto64, r); 4666 assign( rot, binop(Iop_Or64, r, 4667 binop(Iop_Shl64, r, mkU8(32))) ); 4668 assign( rA, 4669 binop(Iop_Or64, 4670 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4671 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4672 } 4673 else { 4674 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4675 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4676 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4677 assign( rA, 4678 binop(Iop_Or32, 4679 binop(Iop_And32, mkU32(mask32), r), 4680 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4681 } 4682 break; 4683 } 4684 4685 case 0x15: { 4686 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4687 vassert(MaskBeg < 32); 4688 vassert(MaskEnd < 32); 4689 vassert(sh_imm < 32); 4690 4691 if (mode64) { 4692 IRTemp rTmp = newTemp(Ity_I64); 4693 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4694 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4695 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4696 // tmp32 = (ROTL(rS_Lo32, Imm) 4697 // rA = ((tmp32 || tmp32) & mask64) 4698 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4699 r = unop(Iop_32Uto64, r); 4700 assign( rTmp, r ); 4701 r = NULL; 4702 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4703 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4704 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4705 } 4706 else { 4707 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4708 /* Special-case the ,n,0,31-n form as that is just n-bit 4709 shift left, PPC32 p501 */ 4710 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4711 rA_addr, rS_addr, sh_imm); 4712 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4713 } 4714 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4715 /* Special-case the ,32-n,n,31 form as that is just n-bit 4716 unsigned shift right, PPC32 p501 */ 4717 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4718 rA_addr, rS_addr, MaskBeg); 4719 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4720 } 4721 else { 4722 /* General case. */ 4723 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4724 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4725 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4726 // rA = ROTL(rS, Imm) & mask 4727 assign( rA, binop(Iop_And32, 4728 ROTL(mkexpr(rS), mkU8(sh_imm)), 4729 mkU32(mask32)) ); 4730 } 4731 } 4732 break; 4733 } 4734 4735 case 0x17: { 4736 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4737 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4738 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4739 if (mode64) { 4740 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4741 /* weird insn alert! 4742 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4743 rA = ((tmp32 || tmp32) & mask64) 4744 */ 4745 // note, ROTL does the masking, so we don't do it here 4746 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4747 unop(Iop_64to8, mkexpr(rB)) ); 4748 r = unop(Iop_32Uto64, r); 4749 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4750 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4751 } else { 4752 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4753 // rA = ROTL(rS, rB[0-4]) & mask 4754 // note, ROTL does the masking, so we don't do it here 4755 assign( rA, binop(Iop_And32, 4756 ROTL(mkexpr(rS), 4757 unop(Iop_32to8, mkexpr(rB))), 4758 mkU32(mask32)) ); 4759 } 4760 break; 4761 } 4762 4763 /* 64bit Integer Rotates */ 4764 case 0x1E: { 4765 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4766 sh_imm |= b1 << 5; 4767 4768 vassert( msk_imm < 64 ); 4769 vassert( sh_imm < 64 ); 4770 4771 switch (opc2) { 4772 case 0x4: { 4773 /* r = ROTL64( rS, rB_lo6) */ 4774 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4775 4776 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4777 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4778 rA_addr, rS_addr, rB_addr, msk_imm); 4779 // note, ROTL does the masking, so we don't do it here 4780 mask64 = MASK64(0, 63-msk_imm); 4781 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4782 break; 4783 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4784 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4785 rA_addr, rS_addr, rB_addr, msk_imm); 4786 mask64 = MASK64(63-msk_imm, 63); 4787 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4788 break; 4789 } 4790 break; 4791 } 4792 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4793 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4794 rA_addr, rS_addr, sh_imm, msk_imm); 4795 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4796 mask64 = MASK64(sh_imm, 63-msk_imm); 4797 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4798 break; 4799 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4800 /* 4801 Hmm... looks like this'll do the job more simply: 4802 r = SHL(rS, sh_imm) 4803 m = ~(1 << (63-msk_imm)) 4804 assign(rA, r & m); 4805 */ 4806 4807 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4808 if (mode64 4809 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4810 /* special-case the ,64-n,n form as that is just 4811 unsigned shift-right by n */ 4812 DIP("srdi%s r%u,r%u,%u\n", 4813 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4814 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4815 } else { 4816 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4817 rA_addr, rS_addr, sh_imm, msk_imm); 4818 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4819 mask64 = MASK64(0, 63-msk_imm); 4820 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4821 } 4822 break; 4823 4824 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4825 if (mode64 4826 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4827 /* special-case the ,n,63-n form as that is just 4828 shift-left by n */ 4829 DIP("sldi%s r%u,r%u,%u\n", 4830 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4831 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4832 } else { 4833 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4834 rA_addr, rS_addr, sh_imm, msk_imm); 4835 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4836 mask64 = MASK64(63-msk_imm, 63); 4837 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4838 } 4839 break; 4840 4841 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4842 IRTemp rA_orig = newTemp(ty); 4843 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4844 rA_addr, rS_addr, sh_imm, msk_imm); 4845 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4846 mask64 = MASK64(sh_imm, 63-msk_imm); 4847 assign( rA_orig, getIReg(rA_addr) ); 4848 assign( rA, binop(Iop_Or64, 4849 binop(Iop_And64, mkU64(mask64), r), 4850 binop(Iop_And64, mkU64(~mask64), 4851 mkexpr(rA_orig))) ); 4852 break; 4853 } 4854 default: 4855 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4856 return False; 4857 } 4858 break; 4859 } 4860 4861 default: 4862 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4863 return False; 4864 } 4865 4866 putIReg( rA_addr, mkexpr(rA) ); 4867 4868 if (flag_rC) { 4869 set_CR0( mkexpr(rA) ); 4870 } 4871 return True; 4872 } 4873 4874 4875 /* 4876 Integer Load Instructions 4877 */ 4878 static Bool dis_int_load ( UInt theInstr ) 4879 { 4880 /* D-Form, X-Form, DS-Form */ 4881 UChar opc1 = ifieldOPC(theInstr); 4882 UChar rD_addr = ifieldRegDS(theInstr); 4883 UChar rA_addr = ifieldRegA(theInstr); 4884 UInt uimm16 = ifieldUIMM16(theInstr); 4885 UChar rB_addr = ifieldRegB(theInstr); 4886 UInt opc2 = ifieldOPClo10(theInstr); 4887 UChar b1 = ifieldBIT1(theInstr); 4888 UChar b0 = ifieldBIT0(theInstr); 4889 4890 Int simm16 = extend_s_16to32(uimm16); 4891 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4892 IRTemp EA = newTemp(ty); 4893 IRExpr* val; 4894 4895 switch (opc1) { 4896 case 0x1F: // register offset 4897 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4898 break; 4899 case 0x38: // immediate offset: 64bit: lq: maskoff 4900 // lowest 4 bits of immediate before forming EA 4901 simm16 = simm16 & 0xFFFFFFF0; 4902 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4903 break; 4904 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 4905 // lowest 2 bits of immediate before forming EA 4906 simm16 = simm16 & 0xFFFFFFFC; 4907 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4908 break; 4909 default: // immediate offset 4910 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4911 break; 4912 } 4913 4914 switch (opc1) { 4915 case 0x22: // lbz (Load B & Zero, PPC32 p433) 4916 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4917 val = load(Ity_I8, mkexpr(EA)); 4918 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4919 break; 4920 4921 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 4922 if (rA_addr == 0 || rA_addr == rD_addr) { 4923 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 4924 return False; 4925 } 4926 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4927 val = load(Ity_I8, mkexpr(EA)); 4928 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4929 putIReg( rA_addr, mkexpr(EA) ); 4930 break; 4931 4932 case 0x2A: // lha (Load HW Alg, PPC32 p445) 4933 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4934 val = load(Ity_I16, mkexpr(EA)); 4935 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4936 break; 4937 4938 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 4939 if (rA_addr == 0 || rA_addr == rD_addr) { 4940 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 4941 return False; 4942 } 4943 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4944 val = load(Ity_I16, mkexpr(EA)); 4945 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4946 putIReg( rA_addr, mkexpr(EA) ); 4947 break; 4948 4949 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 4950 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4951 val = load(Ity_I16, mkexpr(EA)); 4952 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4953 break; 4954 4955 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 4956 if (rA_addr == 0 || rA_addr == rD_addr) { 4957 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 4958 return False; 4959 } 4960 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4961 val = load(Ity_I16, mkexpr(EA)); 4962 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4963 putIReg( rA_addr, mkexpr(EA) ); 4964 break; 4965 4966 case 0x20: // lwz (Load W & Zero, PPC32 p460) 4967 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4968 val = load(Ity_I32, mkexpr(EA)); 4969 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4970 break; 4971 4972 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 4973 if (rA_addr == 0 || rA_addr == rD_addr) { 4974 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 4975 return False; 4976 } 4977 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4978 val = load(Ity_I32, mkexpr(EA)); 4979 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4980 putIReg( rA_addr, mkexpr(EA) ); 4981 break; 4982 4983 /* X Form */ 4984 case 0x1F: 4985 if (b0 != 0) { 4986 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 4987 return False; 4988 } 4989 4990 switch (opc2) { 4991 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 4992 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4993 if (rA_addr == 0 || rA_addr == rD_addr) { 4994 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4995 return False; 4996 } 4997 val = load(Ity_I8, mkexpr(EA)); 4998 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4999 putIReg( rA_addr, mkexpr(EA) ); 5000 break; 5001 5002 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 5003 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5004 val = load(Ity_I8, mkexpr(EA)); 5005 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5006 break; 5007 5008 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 5009 if (rA_addr == 0 || rA_addr == rD_addr) { 5010 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 5011 return False; 5012 } 5013 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5014 val = load(Ity_I16, mkexpr(EA)); 5015 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5016 putIReg( rA_addr, mkexpr(EA) ); 5017 break; 5018 5019 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 5020 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5021 val = load(Ity_I16, mkexpr(EA)); 5022 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5023 break; 5024 5025 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 5026 if (rA_addr == 0 || rA_addr == rD_addr) { 5027 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 5028 return False; 5029 } 5030 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5031 val = load(Ity_I16, mkexpr(EA)); 5032 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5033 putIReg( rA_addr, mkexpr(EA) ); 5034 break; 5035 5036 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 5037 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5038 val = load(Ity_I16, mkexpr(EA)); 5039 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5040 break; 5041 5042 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 5043 if (rA_addr == 0 || rA_addr == rD_addr) { 5044 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5045 return False; 5046 } 5047 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5048 val = load(Ity_I32, mkexpr(EA)); 5049 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5050 putIReg( rA_addr, mkexpr(EA) ); 5051 break; 5052 5053 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 5054 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5055 val = load(Ity_I32, mkexpr(EA)); 5056 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5057 break; 5058 5059 5060 /* 64bit Loads */ 5061 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 5062 if (rA_addr == 0 || rA_addr == rD_addr) { 5063 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 5064 return False; 5065 } 5066 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5067 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5068 putIReg( rA_addr, mkexpr(EA) ); 5069 break; 5070 5071 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 5072 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5073 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5074 break; 5075 5076 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 5077 if (rA_addr == 0 || rA_addr == rD_addr) { 5078 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 5079 return False; 5080 } 5081 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5082 putIReg( rD_addr, 5083 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5084 putIReg( rA_addr, mkexpr(EA) ); 5085 break; 5086 5087 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 5088 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5089 putIReg( rD_addr, 5090 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5091 break; 5092 5093 default: 5094 vex_printf("dis_int_load(ppc)(opc2)\n"); 5095 return False; 5096 } 5097 break; 5098 5099 /* DS Form - 64bit Loads. In each case EA will have been formed 5100 with the lowest 2 bits masked off the immediate offset. */ 5101 case 0x3A: 5102 switch ((b1<<1) | b0) { 5103 case 0x0: // ld (Load DWord, PPC64 p472) 5104 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5105 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5106 break; 5107 5108 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 5109 if (rA_addr == 0 || rA_addr == rD_addr) { 5110 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 5111 return False; 5112 } 5113 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5114 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5115 putIReg( rA_addr, mkexpr(EA) ); 5116 break; 5117 5118 case 0x2: // lwa (Load Word Alg, PPC64 p499) 5119 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5120 putIReg( rD_addr, 5121 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5122 break; 5123 5124 default: 5125 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5126 return False; 5127 } 5128 break; 5129 5130 case 0x38: { 5131 IRTemp high = newTemp(ty); 5132 IRTemp low = newTemp(ty); 5133 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 5134 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5135 /* NOTE: there are some changes to XER[41:42] that have not been 5136 * implemented. 5137 */ 5138 // trap if EA misaligned on 16 byte address 5139 if (mode64) { 5140 if (host_endness == VexEndnessBE) { 5141 assign(high, load(ty, mkexpr( EA ) ) ); 5142 assign(low, load(ty, binop( Iop_Add64, 5143 mkexpr( EA ), 5144 mkU64( 8 ) ) ) ); 5145 } else { 5146 assign(low, load(ty, mkexpr( EA ) ) ); 5147 assign(high, load(ty, binop( Iop_Add64, 5148 mkexpr( EA ), 5149 mkU64( 8 ) ) ) ); 5150 } 5151 } else { 5152 assign(high, load(ty, binop( Iop_Add32, 5153 mkexpr( EA ), 5154 mkU32( 4 ) ) ) ); 5155 assign(low, load(ty, binop( Iop_Add32, 5156 mkexpr( EA ), 5157 mkU32( 12 ) ) ) ); 5158 } 5159 gen_SIGBUS_if_misaligned( EA, 16 ); 5160 putIReg( rD_addr, mkexpr( high) ); 5161 putIReg( rD_addr+1, mkexpr( low) ); 5162 break; 5163 } 5164 default: 5165 vex_printf("dis_int_load(ppc)(opc1)\n"); 5166 return False; 5167 } 5168 return True; 5169 } 5170 5171 5172 5173 /* 5174 Integer Store Instructions 5175 */ 5176 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 5177 { 5178 /* D-Form, X-Form, DS-Form */ 5179 UChar opc1 = ifieldOPC(theInstr); 5180 UInt rS_addr = ifieldRegDS(theInstr); 5181 UInt rA_addr = ifieldRegA(theInstr); 5182 UInt uimm16 = ifieldUIMM16(theInstr); 5183 UInt rB_addr = ifieldRegB(theInstr); 5184 UInt opc2 = ifieldOPClo10(theInstr); 5185 UChar b1 = ifieldBIT1(theInstr); 5186 UChar b0 = ifieldBIT0(theInstr); 5187 5188 Int simm16 = extend_s_16to32(uimm16); 5189 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5190 IRTemp rS = newTemp(ty); 5191 IRTemp rB = newTemp(ty); 5192 IRTemp EA = newTemp(ty); 5193 5194 assign( rB, getIReg(rB_addr) ); 5195 assign( rS, getIReg(rS_addr) ); 5196 5197 switch (opc1) { 5198 case 0x1F: // register offset 5199 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5200 break; 5201 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 5202 // lowest 2 bits of immediate before forming EA 5203 simm16 = simm16 & 0xFFFFFFFC; 5204 default: // immediate offset 5205 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5206 break; 5207 } 5208 5209 switch (opc1) { 5210 case 0x26: // stb (Store B, PPC32 p509) 5211 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5212 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5213 break; 5214 5215 case 0x27: // stbu (Store B, Update, PPC32 p510) 5216 if (rA_addr == 0 ) { 5217 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 5218 return False; 5219 } 5220 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5221 putIReg( rA_addr, mkexpr(EA) ); 5222 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5223 break; 5224 5225 case 0x2C: // sth (Store HW, PPC32 p522) 5226 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5227 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5228 break; 5229 5230 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 5231 if (rA_addr == 0) { 5232 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 5233 return False; 5234 } 5235 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5236 putIReg( rA_addr, mkexpr(EA) ); 5237 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5238 break; 5239 5240 case 0x24: // stw (Store W, PPC32 p530) 5241 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5242 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5243 break; 5244 5245 case 0x25: // stwu (Store W, Update, PPC32 p534) 5246 if (rA_addr == 0) { 5247 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 5248 return False; 5249 } 5250 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5251 putIReg( rA_addr, mkexpr(EA) ); 5252 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5253 break; 5254 5255 /* X Form : all these use EA_indexed */ 5256 case 0x1F: 5257 if (b0 != 0) { 5258 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 5259 return False; 5260 } 5261 5262 switch (opc2) { 5263 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 5264 if (rA_addr == 0) { 5265 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 5266 return False; 5267 } 5268 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5269 putIReg( rA_addr, mkexpr(EA) ); 5270 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5271 break; 5272 5273 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 5274 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5275 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5276 break; 5277 5278 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 5279 if (rA_addr == 0) { 5280 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 5281 return False; 5282 } 5283 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5284 putIReg( rA_addr, mkexpr(EA) ); 5285 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5286 break; 5287 5288 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 5289 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5290 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5291 break; 5292 5293 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 5294 if (rA_addr == 0) { 5295 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 5296 return False; 5297 } 5298 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5299 putIReg( rA_addr, mkexpr(EA) ); 5300 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5301 break; 5302 5303 case 0x097: // stwx (Store W Indexed, PPC32 p536) 5304 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5305 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5306 break; 5307 5308 5309 /* 64bit Stores */ 5310 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 5311 if (rA_addr == 0) { 5312 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 5313 return False; 5314 } 5315 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5316 putIReg( rA_addr, mkexpr(EA) ); 5317 store( mkexpr(EA), mkexpr(rS) ); 5318 break; 5319 5320 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 5321 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5322 store( mkexpr(EA), mkexpr(rS) ); 5323 break; 5324 5325 default: 5326 vex_printf("dis_int_store(ppc)(opc2)\n"); 5327 return False; 5328 } 5329 break; 5330 5331 /* DS Form - 64bit Stores. In each case EA will have been formed 5332 with the lowest 2 bits masked off the immediate offset. */ 5333 case 0x3E: 5334 switch ((b1<<1) | b0) { 5335 case 0x0: // std (Store DWord, PPC64 p580) 5336 if (!mode64) 5337 return False; 5338 5339 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5340 store( mkexpr(EA), mkexpr(rS) ); 5341 break; 5342 5343 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 5344 if (!mode64) 5345 return False; 5346 5347 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5348 putIReg( rA_addr, mkexpr(EA) ); 5349 store( mkexpr(EA), mkexpr(rS) ); 5350 break; 5351 5352 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 5353 IRTemp EA_hi = newTemp(ty); 5354 IRTemp EA_lo = newTemp(ty); 5355 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5356 5357 if (mode64) { 5358 if (host_endness == VexEndnessBE) { 5359 5360 /* upper 64-bits */ 5361 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 5362 5363 /* lower 64-bits */ 5364 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5365 } else { 5366 /* upper 64-bits */ 5367 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5368 5369 /* lower 64-bits */ 5370 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 5371 } 5372 } else { 5373 /* upper half of upper 64-bits */ 5374 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 5375 5376 /* lower half of upper 64-bits */ 5377 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 5378 } 5379 store( mkexpr(EA_hi), mkexpr(rS) ); 5380 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 5381 break; 5382 } 5383 default: 5384 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5385 return False; 5386 } 5387 break; 5388 5389 default: 5390 vex_printf("dis_int_store(ppc)(opc1)\n"); 5391 return False; 5392 } 5393 return True; 5394 } 5395 5396 5397 5398 /* 5399 Integer Load/Store Multiple Instructions 5400 */ 5401 static Bool dis_int_ldst_mult ( UInt theInstr ) 5402 { 5403 /* D-Form */ 5404 UChar opc1 = ifieldOPC(theInstr); 5405 UChar rD_addr = ifieldRegDS(theInstr); 5406 UChar rS_addr = rD_addr; 5407 UChar rA_addr = ifieldRegA(theInstr); 5408 UInt uimm16 = ifieldUIMM16(theInstr); 5409 5410 Int simm16 = extend_s_16to32(uimm16); 5411 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5412 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 5413 IRTemp EA = newTemp(ty); 5414 UInt r = 0; 5415 UInt ea_off = 0; 5416 IRExpr* irx_addr; 5417 5418 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5419 5420 switch (opc1) { 5421 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 5422 if (rA_addr >= rD_addr) { 5423 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 5424 return False; 5425 } 5426 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5427 for (r = rD_addr; r <= 31; r++) { 5428 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5429 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 5430 False) ); 5431 ea_off += 4; 5432 } 5433 break; 5434 5435 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 5436 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5437 for (r = rS_addr; r <= 31; r++) { 5438 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5439 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 5440 ea_off += 4; 5441 } 5442 break; 5443 5444 default: 5445 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 5446 return False; 5447 } 5448 return True; 5449 } 5450 5451 5452 5453 /* 5454 Integer Load/Store String Instructions 5455 */ 5456 static 5457 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5458 IRTemp EA, // EA 5459 Int rD, // first dst register 5460 Int maxBytes ) // 32 or 128 5461 { 5462 Int i, shift = 24; 5463 IRExpr* e_nbytes = mkexpr(tNBytes); 5464 IRExpr* e_EA = mkexpr(EA); 5465 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5466 5467 vassert(rD >= 0 && rD < 32); 5468 rD--; if (rD < 0) rD = 31; 5469 5470 for (i = 0; i < maxBytes; i++) { 5471 /* if (nBytes < (i+1)) goto NIA; */ 5472 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5473 Ijk_Boring, 5474 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5475 /* when crossing into a new dest register, set it to zero. */ 5476 if ((i % 4) == 0) { 5477 rD++; if (rD == 32) rD = 0; 5478 putIReg(rD, mkSzImm(ty, 0)); 5479 shift = 24; 5480 } 5481 /* rD |= (8Uto32(*(EA+i))) << shift */ 5482 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5483 putIReg( 5484 rD, 5485 mkWidenFrom32( 5486 ty, 5487 binop( 5488 Iop_Or32, 5489 mkNarrowTo32(ty, getIReg(rD)), 5490 binop( 5491 Iop_Shl32, 5492 unop( 5493 Iop_8Uto32, 5494 load( Ity_I8, 5495 binop( mkSzOp(ty,Iop_Add8), 5496 e_EA, mkSzImm(ty,i))) 5497 ), 5498 mkU8(toUChar(shift)) 5499 ) 5500 ), 5501 /*Signed*/False 5502 ) 5503 ); 5504 shift -= 8; 5505 } 5506 } 5507 5508 static 5509 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5510 IRTemp EA, // EA 5511 Int rS, // first src register 5512 Int maxBytes ) // 32 or 128 5513 { 5514 Int i, shift = 24; 5515 IRExpr* e_nbytes = mkexpr(tNBytes); 5516 IRExpr* e_EA = mkexpr(EA); 5517 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5518 5519 vassert(rS >= 0 && rS < 32); 5520 rS--; if (rS < 0) rS = 31; 5521 5522 for (i = 0; i < maxBytes; i++) { 5523 /* if (nBytes < (i+1)) goto NIA; */ 5524 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5525 Ijk_Boring, 5526 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5527 /* check for crossing into a new src register. */ 5528 if ((i % 4) == 0) { 5529 rS++; if (rS == 32) rS = 0; 5530 shift = 24; 5531 } 5532 /* *(EA+i) = 32to8(rS >> shift) */ 5533 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5534 store( 5535 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5536 unop( Iop_32to8, 5537 binop( Iop_Shr32, 5538 mkNarrowTo32( ty, getIReg(rS) ), 5539 mkU8( toUChar(shift) ))) 5540 ); 5541 shift -= 8; 5542 } 5543 } 5544 5545 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5546 { 5547 /* X-Form */ 5548 UChar opc1 = ifieldOPC(theInstr); 5549 UChar rD_addr = ifieldRegDS(theInstr); 5550 UChar rS_addr = rD_addr; 5551 UChar rA_addr = ifieldRegA(theInstr); 5552 UChar rB_addr = ifieldRegB(theInstr); 5553 UChar NumBytes = rB_addr; 5554 UInt opc2 = ifieldOPClo10(theInstr); 5555 UChar b0 = ifieldBIT0(theInstr); 5556 5557 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5558 IRTemp t_EA = newTemp(ty); 5559 IRTemp t_nbytes = IRTemp_INVALID; 5560 5561 *stopHere = False; 5562 5563 if (opc1 != 0x1F || b0 != 0) { 5564 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5565 return False; 5566 } 5567 5568 switch (opc2) { 5569 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5570 /* NB: does not reject the case where RA is in the range of 5571 registers to be loaded. It should. */ 5572 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5573 assign( t_EA, ea_rAor0(rA_addr) ); 5574 if (NumBytes == 8 && !mode64) { 5575 /* Special case hack */ 5576 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5577 putIReg( rD_addr, 5578 load(Ity_I32, mkexpr(t_EA)) ); 5579 putIReg( (rD_addr+1) % 32, 5580 load(Ity_I32, 5581 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5582 } else { 5583 t_nbytes = newTemp(Ity_I32); 5584 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5585 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5586 *stopHere = True; 5587 } 5588 return True; 5589 5590 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5591 /* NB: does not reject the case where RA is in the range of 5592 registers to be loaded. It should. Although considering 5593 that that can only be detected at run time, it's not easy to 5594 do so. */ 5595 if (rD_addr == rA_addr || rD_addr == rB_addr) 5596 return False; 5597 if (rD_addr == 0 && rA_addr == 0) 5598 return False; 5599 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5600 t_nbytes = newTemp(Ity_I32); 5601 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5602 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5603 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5604 *stopHere = True; 5605 return True; 5606 5607 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5608 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5609 assign( t_EA, ea_rAor0(rA_addr) ); 5610 if (NumBytes == 8 && !mode64) { 5611 /* Special case hack */ 5612 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5613 store( mkexpr(t_EA), 5614 getIReg(rD_addr) ); 5615 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5616 getIReg((rD_addr+1) % 32) ); 5617 } else { 5618 t_nbytes = newTemp(Ity_I32); 5619 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5620 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5621 *stopHere = True; 5622 } 5623 return True; 5624 5625 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5626 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5627 t_nbytes = newTemp(Ity_I32); 5628 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5629 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5630 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5631 *stopHere = True; 5632 return True; 5633 5634 default: 5635 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5636 return False; 5637 } 5638 return True; 5639 } 5640 5641 5642 /* ------------------------------------------------------------------ 5643 Integer Branch Instructions 5644 ------------------------------------------------------------------ */ 5645 5646 /* 5647 Branch helper function 5648 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5649 Returns an I32 which is 0x00000000 if the ctr condition failed 5650 and 0xFFFFFFFF otherwise. 5651 */ 5652 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5653 { 5654 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5655 IRTemp ok = newTemp(Ity_I32); 5656 5657 if ((BO >> 2) & 1) { // independent of ctr 5658 assign( ok, mkU32(0xFFFFFFFF) ); 5659 } else { 5660 if ((BO >> 1) & 1) { // ctr == 0 ? 5661 assign( ok, unop( Iop_1Sto32, 5662 binop( mkSzOp(ty, Iop_CmpEQ8), 5663 getGST( PPC_GST_CTR ), 5664 mkSzImm(ty,0))) ); 5665 } else { // ctr != 0 ? 5666 assign( ok, unop( Iop_1Sto32, 5667 binop( mkSzOp(ty, Iop_CmpNE8), 5668 getGST( PPC_GST_CTR ), 5669 mkSzImm(ty,0))) ); 5670 } 5671 } 5672 return mkexpr(ok); 5673 } 5674 5675 5676 /* 5677 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5678 Returns an I32 which is either 0 if the condition failed or 5679 some arbitrary nonzero value otherwise. */ 5680 5681 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5682 { 5683 Int where; 5684 IRTemp res = newTemp(Ity_I32); 5685 IRTemp cr_bi = newTemp(Ity_I32); 5686 5687 if ((BO >> 4) & 1) { 5688 assign( res, mkU32(1) ); 5689 } else { 5690 // ok = (CR[BI] == BO[3]) Note, the following relies on 5691 // getCRbit_anywhere returning a value which 5692 // is either zero or has exactly 1 bit set. 5693 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5694 5695 if ((BO >> 3) & 1) { 5696 /* We can use cr_bi as-is. */ 5697 assign( res, mkexpr(cr_bi) ); 5698 } else { 5699 /* We have to invert the sense of the information held in 5700 cr_bi. For that we need to know which bit 5701 getCRbit_anywhere regards as significant. */ 5702 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5703 mkU32(1<<where)) ); 5704 } 5705 } 5706 return mkexpr(res); 5707 } 5708 5709 5710 /* 5711 Integer Branch Instructions 5712 */ 5713 static Bool dis_branch ( UInt theInstr, 5714 const VexAbiInfo* vbi, 5715 /*OUT*/DisResult* dres, 5716 Bool (*resteerOkFn)(void*,Addr), 5717 void* callback_opaque ) 5718 { 5719 UChar opc1 = ifieldOPC(theInstr); 5720 UChar BO = ifieldRegDS(theInstr); 5721 UChar BI = ifieldRegA(theInstr); 5722 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5723 UChar b11to15 = ifieldRegB(theInstr); 5724 UInt opc2 = ifieldOPClo10(theInstr); 5725 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5726 UChar flag_AA = ifieldBIT1(theInstr); 5727 UChar flag_LK = ifieldBIT0(theInstr); 5728 5729 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5730 Addr64 tgt = 0; 5731 Int BD = extend_s_16to32(BD_u16); 5732 IRTemp do_branch = newTemp(Ity_I32); 5733 IRTemp ctr_ok = newTemp(Ity_I32); 5734 IRTemp cond_ok = newTemp(Ity_I32); 5735 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5736 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5737 IRTemp lr_old = newTemp(ty); 5738 5739 /* Hack to pass through code that just wants to read the PC */ 5740 if (theInstr == 0x429F0005) { 5741 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5742 putGST( PPC_GST_LR, e_nia ); 5743 return True; 5744 } 5745 5746 /* The default what-next. Individual cases can override it. */ 5747 dres->whatNext = Dis_StopHere; 5748 vassert(dres->jk_StopHere == Ijk_INVALID); 5749 5750 switch (opc1) { 5751 case 0x12: // b (Branch, PPC32 p360) 5752 if (flag_AA) { 5753 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5754 } else { 5755 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5756 (Long)extend_s_26to64(LI_u26) ); 5757 } 5758 if (mode64) { 5759 DIP("b%s%s 0x%llx\n", 5760 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5761 } else { 5762 DIP("b%s%s 0x%x\n", 5763 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5764 } 5765 5766 if (flag_LK) { 5767 putGST( PPC_GST_LR, e_nia ); 5768 if (vbi->guest_ppc_zap_RZ_at_bl 5769 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5770 IRTemp t_tgt = newTemp(ty); 5771 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5772 make_redzone_AbiHint( vbi, t_tgt, 5773 "branch-and-link (unconditional call)" ); 5774 } 5775 } 5776 5777 if (resteerOkFn( callback_opaque, tgt )) { 5778 dres->whatNext = Dis_ResteerU; 5779 dres->continueAt = tgt; 5780 } else { 5781 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5782 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5783 } 5784 break; 5785 5786 case 0x10: // bc (Branch Conditional, PPC32 p361) 5787 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5788 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5789 5790 if (!(BO & 0x4)) { 5791 putGST( PPC_GST_CTR, 5792 binop(mkSzOp(ty, Iop_Sub8), 5793 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5794 } 5795 5796 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5797 cond_ok is either zero or nonzero, since that's the cheapest 5798 way to compute it. Anding them together gives a value which 5799 is either zero or non zero and so that's what we must test 5800 for in the IRStmt_Exit. */ 5801 assign( ctr_ok, branch_ctr_ok( BO ) ); 5802 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5803 assign( do_branch, 5804 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5805 5806 if (flag_AA) { 5807 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5808 } else { 5809 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5810 (Long)extend_s_16to64(BD_u16)); 5811 } 5812 if (flag_LK) 5813 putGST( PPC_GST_LR, e_nia ); 5814 5815 stmt( IRStmt_Exit( 5816 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5817 flag_LK ? Ijk_Call : Ijk_Boring, 5818 mkSzConst(ty, tgt), OFFB_CIA ) ); 5819 5820 dres->jk_StopHere = Ijk_Boring; 5821 putGST( PPC_GST_CIA, e_nia ); 5822 break; 5823 5824 case 0x13: 5825 /* For bclr and bcctr, it appears that the lowest two bits of 5826 b11to15 are a branch hint, and so we only need to ensure it's 5827 of the form 000XX. */ 5828 if ((b11to15 & ~3) != 0) { 5829 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 5830 return False; 5831 } 5832 5833 switch (opc2) { 5834 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5835 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5836 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5837 return False; 5838 } 5839 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5840 5841 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5842 5843 /* FIXME: this is confusing. lr_old holds the old value 5844 of ctr, not lr :-) */ 5845 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5846 5847 if (flag_LK) 5848 putGST( PPC_GST_LR, e_nia ); 5849 5850 stmt( IRStmt_Exit( 5851 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5852 Ijk_Boring, 5853 c_nia, OFFB_CIA )); 5854 5855 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5856 make_redzone_AbiHint( vbi, lr_old, 5857 "b-ctr-l (indirect call)" ); 5858 } 5859 5860 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5861 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5862 break; 5863 5864 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5865 Bool vanilla_return = False; 5866 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5867 DIP("blr\n"); 5868 vanilla_return = True; 5869 } else { 5870 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5871 } 5872 5873 if (!(BO & 0x4)) { 5874 putGST( PPC_GST_CTR, 5875 binop(mkSzOp(ty, Iop_Sub8), 5876 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5877 } 5878 5879 /* See comments above for 'bc' about this */ 5880 assign( ctr_ok, branch_ctr_ok( BO ) ); 5881 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5882 assign( do_branch, 5883 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5884 5885 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5886 5887 if (flag_LK) 5888 putGST( PPC_GST_LR, e_nia ); 5889 5890 stmt( IRStmt_Exit( 5891 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 5892 Ijk_Boring, 5893 c_nia, OFFB_CIA )); 5894 5895 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 5896 make_redzone_AbiHint( vbi, lr_old, 5897 "branch-to-lr (unconditional return)" ); 5898 } 5899 5900 /* blrl is pretty strange; it's like a return that sets the 5901 return address of its caller to the insn following this 5902 one. Mark it as a return. */ 5903 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 5904 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5905 break; 5906 } 5907 default: 5908 vex_printf("dis_int_branch(ppc)(opc2)\n"); 5909 return False; 5910 } 5911 break; 5912 5913 default: 5914 vex_printf("dis_int_branch(ppc)(opc1)\n"); 5915 return False; 5916 } 5917 5918 return True; 5919 } 5920 5921 5922 5923 /* 5924 Condition Register Logical Instructions 5925 */ 5926 static Bool dis_cond_logic ( UInt theInstr ) 5927 { 5928 /* XL-Form */ 5929 UChar opc1 = ifieldOPC(theInstr); 5930 UChar crbD_addr = ifieldRegDS(theInstr); 5931 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 5932 UChar crbA_addr = ifieldRegA(theInstr); 5933 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 5934 UChar crbB_addr = ifieldRegB(theInstr); 5935 UInt opc2 = ifieldOPClo10(theInstr); 5936 UChar b0 = ifieldBIT0(theInstr); 5937 5938 IRTemp crbD = newTemp(Ity_I32); 5939 IRTemp crbA = newTemp(Ity_I32); 5940 IRTemp crbB = newTemp(Ity_I32); 5941 5942 if (opc1 != 19 || b0 != 0) { 5943 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 5944 return False; 5945 } 5946 5947 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 5948 if (((crbD_addr & 0x3) != 0) || 5949 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 5950 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 5951 return False; 5952 } 5953 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 5954 putCR0( crfD_addr, getCR0( crfS_addr) ); 5955 putCR321( crfD_addr, getCR321(crfS_addr) ); 5956 } else { 5957 assign( crbA, getCRbit(crbA_addr) ); 5958 if (crbA_addr == crbB_addr) 5959 crbB = crbA; 5960 else 5961 assign( crbB, getCRbit(crbB_addr) ); 5962 5963 switch (opc2) { 5964 case 0x101: // crand (Cond Reg AND, PPC32 p372) 5965 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5966 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 5967 break; 5968 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 5969 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5970 assign( crbD, binop(Iop_And32, 5971 mkexpr(crbA), 5972 unop(Iop_Not32, mkexpr(crbB))) ); 5973 break; 5974 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 5975 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5976 assign( crbD, unop(Iop_Not32, 5977 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 5978 break; 5979 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 5980 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5981 assign( crbD, unop(Iop_Not32, 5982 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 5983 break; 5984 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 5985 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5986 assign( crbD, unop(Iop_Not32, 5987 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 5988 break; 5989 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 5990 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5991 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 5992 break; 5993 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 5994 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5995 assign( crbD, binop(Iop_Or32, 5996 mkexpr(crbA), 5997 unop(Iop_Not32, mkexpr(crbB))) ); 5998 break; 5999 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 6000 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6001 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 6002 break; 6003 default: 6004 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 6005 return False; 6006 } 6007 6008 putCRbit( crbD_addr, mkexpr(crbD) ); 6009 } 6010 return True; 6011 } 6012 6013 6014 /* 6015 Trap instructions 6016 */ 6017 6018 /* Do the code generation for a trap. Returned Bool is true iff 6019 this is an unconditional trap. If the two arg IRExpr*s are 6020 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 6021 then they are 64-bit, and we must be disassembling 64-bit 6022 instructions. */ 6023 static Bool do_trap ( UChar TO, 6024 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 6025 { 6026 IRTemp argL, argR; 6027 IRExpr *argLe, *argRe, *cond, *tmp; 6028 6029 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 6030 6031 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 6032 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 6033 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 6034 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 6035 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 6036 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 6037 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 6038 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 6039 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 6040 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 6041 6042 const UChar b11100 = 0x1C; 6043 const UChar b00111 = 0x07; 6044 6045 if (is32bit) { 6046 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 6047 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 6048 } else { 6049 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 6050 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 6051 vassert( mode64 ); 6052 } 6053 6054 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 6055 /* Unconditional trap. Just do the exit without 6056 testing the arguments. */ 6057 stmt( IRStmt_Exit( 6058 binop(opCMPEQ, const0, const0), 6059 Ijk_SigTRAP, 6060 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6061 OFFB_CIA 6062 )); 6063 return True; /* unconditional trap */ 6064 } 6065 6066 if (is32bit) { 6067 argL = newTemp(Ity_I32); 6068 argR = newTemp(Ity_I32); 6069 } else { 6070 argL = newTemp(Ity_I64); 6071 argR = newTemp(Ity_I64); 6072 } 6073 6074 assign( argL, argL0 ); 6075 assign( argR, argR0 ); 6076 6077 argLe = mkexpr(argL); 6078 argRe = mkexpr(argR); 6079 6080 cond = const0; 6081 if (TO & 16) { // L <s R 6082 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 6083 cond = binop(opOR, tmp, cond); 6084 } 6085 if (TO & 8) { // L >s R 6086 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 6087 cond = binop(opOR, tmp, cond); 6088 } 6089 if (TO & 4) { // L == R 6090 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 6091 cond = binop(opOR, tmp, cond); 6092 } 6093 if (TO & 2) { // L <u R 6094 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 6095 cond = binop(opOR, tmp, cond); 6096 } 6097 if (TO & 1) { // L >u R 6098 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 6099 cond = binop(opOR, tmp, cond); 6100 } 6101 stmt( IRStmt_Exit( 6102 binop(opCMPNE, cond, const0), 6103 Ijk_SigTRAP, 6104 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6105 OFFB_CIA 6106 )); 6107 return False; /* not an unconditional trap */ 6108 } 6109 6110 static Bool dis_trapi ( UInt theInstr, 6111 /*OUT*/DisResult* dres ) 6112 { 6113 /* D-Form */ 6114 UChar opc1 = ifieldOPC(theInstr); 6115 UChar TO = ifieldRegDS(theInstr); 6116 UChar rA_addr = ifieldRegA(theInstr); 6117 UInt uimm16 = ifieldUIMM16(theInstr); 6118 ULong simm16 = extend_s_16to64(uimm16); 6119 Addr64 cia = guest_CIA_curr_instr; 6120 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6121 Bool uncond = False; 6122 6123 switch (opc1) { 6124 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 6125 uncond = do_trap( TO, 6126 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6127 : getIReg(rA_addr), 6128 mkU32( (UInt)simm16 ), 6129 cia ); 6130 if (TO == 4) { 6131 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 6132 } else { 6133 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 6134 } 6135 break; 6136 case 0x02: // tdi 6137 if (!mode64) 6138 return False; 6139 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 6140 if (TO == 4) { 6141 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 6142 } else { 6143 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 6144 } 6145 break; 6146 default: 6147 return False; 6148 } 6149 6150 if (uncond) { 6151 /* If the trap shows signs of being unconditional, don't 6152 continue decoding past it. */ 6153 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6154 dres->jk_StopHere = Ijk_Boring; 6155 dres->whatNext = Dis_StopHere; 6156 } 6157 6158 return True; 6159 } 6160 6161 static Bool dis_trap ( UInt theInstr, 6162 /*OUT*/DisResult* dres ) 6163 { 6164 /* X-Form */ 6165 UInt opc2 = ifieldOPClo10(theInstr); 6166 UChar TO = ifieldRegDS(theInstr); 6167 UChar rA_addr = ifieldRegA(theInstr); 6168 UChar rB_addr = ifieldRegB(theInstr); 6169 Addr64 cia = guest_CIA_curr_instr; 6170 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6171 Bool uncond = False; 6172 6173 if (ifieldBIT0(theInstr) != 0) 6174 return False; 6175 6176 switch (opc2) { 6177 case 0x004: // tw (Trap Word, PPC64 p540) 6178 uncond = do_trap( TO, 6179 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6180 : getIReg(rA_addr), 6181 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 6182 : getIReg(rB_addr), 6183 cia ); 6184 if (TO == 4) { 6185 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6186 } else { 6187 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6188 } 6189 break; 6190 case 0x044: // td (Trap Doubleword, PPC64 p534) 6191 if (!mode64) 6192 return False; 6193 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 6194 if (TO == 4) { 6195 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6196 } else { 6197 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6198 } 6199 break; 6200 default: 6201 return False; 6202 } 6203 6204 if (uncond) { 6205 /* If the trap shows signs of being unconditional, don't 6206 continue decoding past it. */ 6207 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6208 dres->jk_StopHere = Ijk_Boring; 6209 dres->whatNext = Dis_StopHere; 6210 } 6211 6212 return True; 6213 } 6214 6215 6216 /* 6217 System Linkage Instructions 6218 */ 6219 static Bool dis_syslink ( UInt theInstr, 6220 const VexAbiInfo* abiinfo, DisResult* dres ) 6221 { 6222 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6223 6224 if (theInstr != 0x44000002) { 6225 vex_printf("dis_syslink(ppc)(theInstr)\n"); 6226 return False; 6227 } 6228 6229 // sc (System Call, PPC32 p504) 6230 DIP("sc\n"); 6231 6232 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 6233 Valgrind can back the guest up to this instruction if it needs 6234 to restart the syscall. */ 6235 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 6236 6237 /* It's important that all ArchRegs carry their up-to-date value 6238 at this point. So we declare an end-of-block here, which 6239 forces any TempRegs caching ArchRegs to be flushed. */ 6240 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6241 6242 dres->whatNext = Dis_StopHere; 6243 dres->jk_StopHere = Ijk_Sys_syscall; 6244 return True; 6245 } 6246 6247 6248 /* 6249 Memory Synchronization Instructions 6250 6251 Note on Reservations: 6252 We rely on the assumption that V will in fact only allow one thread at 6253 once to run. In effect, a thread can make a reservation, but we don't 6254 check any stores it does. Instead, the reservation is cancelled when 6255 the scheduler switches to another thread (run_thread_for_a_while()). 6256 */ 6257 static Bool dis_memsync ( UInt theInstr ) 6258 { 6259 /* X-Form, XL-Form */ 6260 UChar opc1 = ifieldOPC(theInstr); 6261 UInt b11to25 = IFIELD(theInstr, 11, 15); 6262 UChar flag_L = ifieldRegDS(theInstr); 6263 UInt b11to20 = IFIELD(theInstr, 11, 10); 6264 UChar rD_addr = ifieldRegDS(theInstr); 6265 UChar rS_addr = rD_addr; 6266 UChar rA_addr = ifieldRegA(theInstr); 6267 UChar rB_addr = ifieldRegB(theInstr); 6268 UInt opc2 = ifieldOPClo10(theInstr); 6269 UChar b0 = ifieldBIT0(theInstr); 6270 6271 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6272 IRTemp EA = newTemp(ty); 6273 6274 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6275 6276 switch (opc1) { 6277 /* XL-Form */ 6278 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 6279 if (opc2 != 0x096) { 6280 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 6281 return False; 6282 } 6283 if (b11to25 != 0 || b0 != 0) { 6284 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 6285 return False; 6286 } 6287 DIP("isync\n"); 6288 stmt( IRStmt_MBE(Imbe_Fence) ); 6289 break; 6290 6291 /* X-Form */ 6292 case 0x1F: 6293 switch (opc2) { 6294 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 6295 if (b11to25 != 0 || b0 != 0) { 6296 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 6297 return False; 6298 } 6299 DIP("eieio\n"); 6300 /* Insert a memory fence, just to be on the safe side. */ 6301 stmt( IRStmt_MBE(Imbe_Fence) ); 6302 break; 6303 6304 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 6305 IRTemp res; 6306 /* According to the PowerPC ISA version 2.05, b0 (called EH 6307 in the documentation) is merely a hint bit to the 6308 hardware, I think as to whether or not contention is 6309 likely. So we can just ignore it. */ 6310 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6311 6312 // trap if misaligned 6313 gen_SIGBUS_if_misaligned( EA, 4 ); 6314 6315 // and actually do the load 6316 res = newTemp(Ity_I32); 6317 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6318 6319 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 6320 break; 6321 } 6322 6323 case 0x034: { // lbarx (Load Word and Reserve Indexed) 6324 IRTemp res; 6325 /* According to the PowerPC ISA version 2.05, b0 (called EH 6326 in the documentation) is merely a hint bit to the 6327 hardware, I think as to whether or not contention is 6328 likely. So we can just ignore it. */ 6329 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6330 6331 // and actually do the load 6332 res = newTemp(Ity_I8); 6333 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6334 6335 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 6336 break; 6337 } 6338 6339 case 0x074: { // lharx (Load Word and Reserve Indexed) 6340 IRTemp res; 6341 /* According to the PowerPC ISA version 2.05, b0 (called EH 6342 in the documentation) is merely a hint bit to the 6343 hardware, I think as to whether or not contention is 6344 likely. So we can just ignore it. */ 6345 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6346 6347 // trap if misaligned 6348 gen_SIGBUS_if_misaligned( EA, 2 ); 6349 6350 // and actually do the load 6351 res = newTemp(Ity_I16); 6352 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6353 6354 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 6355 break; 6356 } 6357 6358 case 0x096: { 6359 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 6360 // Note this has to handle stwcx. in both 32- and 64-bit modes, 6361 // so isn't quite as straightforward as it might otherwise be. 6362 IRTemp rS = newTemp(Ity_I32); 6363 IRTemp resSC; 6364 if (b0 != 1) { 6365 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6366 return False; 6367 } 6368 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6369 6370 // trap if misaligned 6371 gen_SIGBUS_if_misaligned( EA, 4 ); 6372 6373 // Get the data to be stored, and narrow to 32 bits if necessary 6374 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6375 6376 // Do the store, and get success/failure bit into resSC 6377 resSC = newTemp(Ity_I1); 6378 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6379 6380 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6381 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6382 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6383 putCR0(0, getXER_SO()); 6384 6385 /* Note: 6386 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6387 whether rS is stored is dependent on that value. */ 6388 /* So I guess we can just ignore this case? */ 6389 break; 6390 } 6391 6392 case 0x2B6: { 6393 // stbcx. (Store Byte Conditional Indexed) 6394 // Note this has to handle stbcx. in both 32- and 64-bit modes, 6395 // so isn't quite as straightforward as it might otherwise be. 6396 IRTemp rS = newTemp(Ity_I8); 6397 IRTemp resSC; 6398 if (b0 != 1) { 6399 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 6400 return False; 6401 } 6402 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6403 6404 // Get the data to be stored, and narrow to 32 bits if necessary 6405 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 6406 6407 // Do the store, and get success/failure bit into resSC 6408 resSC = newTemp(Ity_I1); 6409 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6410 6411 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6412 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6413 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6414 putCR0(0, getXER_SO()); 6415 6416 /* Note: 6417 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 6418 whether rS is stored is dependent on that value. */ 6419 /* So I guess we can just ignore this case? */ 6420 break; 6421 } 6422 6423 case 0x2D6: { 6424 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 6425 // Note this has to handle sthcx. in both 32- and 64-bit modes, 6426 // so isn't quite as straightforward as it might otherwise be. 6427 IRTemp rS = newTemp(Ity_I16); 6428 IRTemp resSC; 6429 if (b0 != 1) { 6430 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6431 return False; 6432 } 6433 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6434 6435 // trap if misaligned 6436 gen_SIGBUS_if_misaligned( EA, 2 ); 6437 6438 // Get the data to be stored, and narrow to 16 bits if necessary 6439 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 6440 6441 // Do the store, and get success/failure bit into resSC 6442 resSC = newTemp(Ity_I1); 6443 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6444 6445 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6446 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6447 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6448 putCR0(0, getXER_SO()); 6449 6450 /* Note: 6451 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 6452 whether rS is stored is dependent on that value. */ 6453 /* So I guess we can just ignore this case? */ 6454 break; 6455 } 6456 6457 case 0x256: // sync (Synchronize, PPC32 p543), 6458 // also lwsync (L==1), ptesync (L==2) 6459 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 6460 6461 The PowerPC architecture used in IBM chips has expanded 6462 the sync instruction into two variants: lightweight sync 6463 and heavyweight sync. The original sync instruction is 6464 the new heavyweight sync and lightweight sync is a strict 6465 subset of the heavyweight sync functionality. This allows 6466 the programmer to specify a less expensive operation on 6467 high-end systems when the full sync functionality is not 6468 necessary. 6469 6470 The basic "sync" mnemonic now utilizes an operand. "sync" 6471 without an operand now becomes a extended mnemonic for 6472 heavyweight sync. Processors without the lwsync 6473 instruction will not decode the L field and will perform a 6474 heavyweight sync. Everything is backward compatible. 6475 6476 sync = sync 0 6477 lwsync = sync 1 6478 ptesync = sync 2 *** TODO - not implemented *** 6479 */ 6480 if (b11to20 != 0 || b0 != 0) { 6481 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 6482 return False; 6483 } 6484 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 6485 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 6486 return False; 6487 } 6488 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 6489 /* Insert a memory fence. It's sometimes important that these 6490 are carried through to the generated code. */ 6491 stmt( IRStmt_MBE(Imbe_Fence) ); 6492 break; 6493 6494 /* 64bit Memsync */ 6495 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 6496 IRTemp res; 6497 /* According to the PowerPC ISA version 2.05, b0 (called EH 6498 in the documentation) is merely a hint bit to the 6499 hardware, I think as to whether or not contention is 6500 likely. So we can just ignore it. */ 6501 if (!mode64) 6502 return False; 6503 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6504 6505 // trap if misaligned 6506 gen_SIGBUS_if_misaligned( EA, 8 ); 6507 6508 // and actually do the load 6509 res = newTemp(Ity_I64); 6510 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 6511 6512 putIReg( rD_addr, mkexpr(res) ); 6513 break; 6514 } 6515 6516 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 6517 // A marginally simplified version of the stwcx. case 6518 IRTemp rS = newTemp(Ity_I64); 6519 IRTemp resSC; 6520 if (b0 != 1) { 6521 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 6522 return False; 6523 } 6524 if (!mode64) 6525 return False; 6526 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6527 6528 // trap if misaligned 6529 gen_SIGBUS_if_misaligned( EA, 8 ); 6530 6531 // Get the data to be stored 6532 assign( rS, getIReg(rS_addr) ); 6533 6534 // Do the store, and get success/failure bit into resSC 6535 resSC = newTemp(Ity_I1); 6536 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6537 6538 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6539 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6540 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6541 putCR0(0, getXER_SO()); 6542 6543 /* Note: 6544 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6545 whether rS is stored is dependent on that value. */ 6546 /* So I guess we can just ignore this case? */ 6547 break; 6548 } 6549 6550 /* 128bit Memsync */ 6551 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 6552 IRTemp res_hi = newTemp(ty); 6553 IRTemp res_lo = newTemp(ty); 6554 6555 /* According to the PowerPC ISA version 2.07, b0 (called EH 6556 in the documentation) is merely a hint bit to the 6557 hardware, I think as to whether or not contention is 6558 likely. So we can just ignore it. */ 6559 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6560 6561 // trap if misaligned 6562 gen_SIGBUS_if_misaligned( EA, 16 ); 6563 6564 // and actually do the load 6565 if (mode64) { 6566 if (host_endness == VexEndnessBE) { 6567 stmt( stmt_load( res_hi, 6568 mkexpr(EA), NULL/*this is a load*/) ); 6569 stmt( stmt_load( res_lo, 6570 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6571 NULL/*this is a load*/) ); 6572 } else { 6573 stmt( stmt_load( res_lo, 6574 mkexpr(EA), NULL/*this is a load*/) ); 6575 stmt( stmt_load( res_hi, 6576 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6577 NULL/*this is a load*/) ); 6578 } 6579 } else { 6580 stmt( stmt_load( res_hi, 6581 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 6582 NULL/*this is a load*/) ); 6583 stmt( stmt_load( res_lo, 6584 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 6585 NULL/*this is a load*/) ); 6586 } 6587 putIReg( rD_addr, mkexpr(res_hi) ); 6588 putIReg( rD_addr+1, mkexpr(res_lo) ); 6589 break; 6590 } 6591 6592 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 6593 // A marginally simplified version of the stwcx. case 6594 IRTemp rS_hi = newTemp(ty); 6595 IRTemp rS_lo = newTemp(ty); 6596 IRTemp resSC; 6597 if (b0 != 1) { 6598 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 6599 return False; 6600 } 6601 6602 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6603 6604 // trap if misaligned 6605 gen_SIGBUS_if_misaligned( EA, 16 ); 6606 // Get the data to be stored 6607 assign( rS_hi, getIReg(rS_addr) ); 6608 assign( rS_lo, getIReg(rS_addr+1) ); 6609 6610 // Do the store, and get success/failure bit into resSC 6611 resSC = newTemp(Ity_I1); 6612 6613 if (mode64) { 6614 if (host_endness == VexEndnessBE) { 6615 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 6616 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6617 mkexpr(rS_lo) ); 6618 } else { 6619 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 6620 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6621 mkexpr(rS_hi) ); 6622 } 6623 } else { 6624 stmt( stmt_load( resSC, binop( Iop_Add32, 6625 mkexpr(EA), 6626 mkU32(4) ), 6627 mkexpr(rS_hi) ) ); 6628 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 6629 } 6630 6631 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6632 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6633 putCR321(0, binop( Iop_Shl8, 6634 unop(Iop_1Uto8, mkexpr(resSC) ), 6635 mkU8(1))); 6636 putCR0(0, getXER_SO()); 6637 break; 6638 } 6639 6640 default: 6641 vex_printf("dis_memsync(ppc)(opc2)\n"); 6642 return False; 6643 } 6644 break; 6645 6646 default: 6647 vex_printf("dis_memsync(ppc)(opc1)\n"); 6648 return False; 6649 } 6650 return True; 6651 } 6652 6653 6654 6655 /* 6656 Integer Shift Instructions 6657 */ 6658 static Bool dis_int_shift ( UInt theInstr ) 6659 { 6660 /* X-Form, XS-Form */ 6661 UChar opc1 = ifieldOPC(theInstr); 6662 UChar rS_addr = ifieldRegDS(theInstr); 6663 UChar rA_addr = ifieldRegA(theInstr); 6664 UChar rB_addr = ifieldRegB(theInstr); 6665 UChar sh_imm = rB_addr; 6666 UInt opc2 = ifieldOPClo10(theInstr); 6667 UChar b1 = ifieldBIT1(theInstr); 6668 UChar flag_rC = ifieldBIT0(theInstr); 6669 6670 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6671 IRTemp rA = newTemp(ty); 6672 IRTemp rS = newTemp(ty); 6673 IRTemp rB = newTemp(ty); 6674 IRTemp outofrange = newTemp(Ity_I1); 6675 IRTemp rS_lo32 = newTemp(Ity_I32); 6676 IRTemp rB_lo32 = newTemp(Ity_I32); 6677 IRExpr* e_tmp; 6678 6679 assign( rS, getIReg(rS_addr) ); 6680 assign( rB, getIReg(rB_addr) ); 6681 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6682 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6683 6684 if (opc1 == 0x1F) { 6685 switch (opc2) { 6686 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6687 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6688 rA_addr, rS_addr, rB_addr); 6689 /* rA = rS << rB */ 6690 /* ppc32 semantics are: 6691 slw(x,y) = (x << (y & 31)) -- primary result 6692 & ~((y << 26) >>s 31) -- make result 0 6693 for y in 32 .. 63 6694 */ 6695 e_tmp = 6696 binop( Iop_And32, 6697 binop( Iop_Shl32, 6698 mkexpr(rS_lo32), 6699 unop( Iop_32to8, 6700 binop(Iop_And32, 6701 mkexpr(rB_lo32), mkU32(31)))), 6702 unop( Iop_Not32, 6703 binop( Iop_Sar32, 6704 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6705 mkU8(31))) ); 6706 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6707 break; 6708 } 6709 6710 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6711 IRTemp sh_amt = newTemp(Ity_I32); 6712 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6713 rA_addr, rS_addr, rB_addr); 6714 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6715 amt = rB & 63 6716 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6717 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6718 */ 6719 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6720 mkexpr(rB_lo32)) ); 6721 assign( outofrange, 6722 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 6723 e_tmp = binop( Iop_Sar32, 6724 mkexpr(rS_lo32), 6725 unop( Iop_32to8, 6726 IRExpr_ITE( mkexpr(outofrange), 6727 mkU32(31), 6728 mkexpr(sh_amt)) ) ); 6729 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6730 6731 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6732 mkexpr(rA), 6733 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6734 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6735 mkWidenFrom32(ty, getXER_CA32(), True) ); 6736 break; 6737 } 6738 6739 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6740 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6741 rA_addr, rS_addr, sh_imm); 6742 vassert(sh_imm < 32); 6743 if (mode64) { 6744 assign( rA, binop(Iop_Sar64, 6745 binop(Iop_Shl64, getIReg(rS_addr), 6746 mkU8(32)), 6747 mkU8(32 + sh_imm)) ); 6748 } else { 6749 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6750 mkU8(sh_imm)) ); 6751 } 6752 6753 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6754 mkexpr(rA), 6755 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6756 mkSzImm(ty, sh_imm), 6757 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6758 break; 6759 6760 case 0x218: // srw (Shift Right Word, PPC32 p508) 6761 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6762 rA_addr, rS_addr, rB_addr); 6763 /* rA = rS >>u rB */ 6764 /* ppc32 semantics are: 6765 srw(x,y) = (x >>u (y & 31)) -- primary result 6766 & ~((y << 26) >>s 31) -- make result 0 6767 for y in 32 .. 63 6768 */ 6769 e_tmp = 6770 binop( 6771 Iop_And32, 6772 binop( Iop_Shr32, 6773 mkexpr(rS_lo32), 6774 unop( Iop_32to8, 6775 binop(Iop_And32, mkexpr(rB_lo32), 6776 mkU32(31)))), 6777 unop( Iop_Not32, 6778 binop( Iop_Sar32, 6779 binop(Iop_Shl32, mkexpr(rB_lo32), 6780 mkU8(26)), 6781 mkU8(31)))); 6782 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6783 break; 6784 6785 6786 /* 64bit Shifts */ 6787 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6788 DIP("sld%s r%u,r%u,r%u\n", 6789 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6790 /* rA = rS << rB */ 6791 /* ppc64 semantics are: 6792 slw(x,y) = (x << (y & 63)) -- primary result 6793 & ~((y << 57) >>s 63) -- make result 0 6794 for y in 64 .. 6795 */ 6796 assign( rA, 6797 binop( 6798 Iop_And64, 6799 binop( Iop_Shl64, 6800 mkexpr(rS), 6801 unop( Iop_64to8, 6802 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6803 unop( Iop_Not64, 6804 binop( Iop_Sar64, 6805 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6806 mkU8(63)))) ); 6807 break; 6808 6809 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6810 IRTemp sh_amt = newTemp(Ity_I64); 6811 DIP("srad%s r%u,r%u,r%u\n", 6812 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6813 /* amt = rB & 127 6814 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6815 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6816 */ 6817 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6818 assign( outofrange, 6819 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 6820 assign( rA, 6821 binop( Iop_Sar64, 6822 mkexpr(rS), 6823 unop( Iop_64to8, 6824 IRExpr_ITE( mkexpr(outofrange), 6825 mkU64(63), 6826 mkexpr(sh_amt)) )) 6827 ); 6828 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6829 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6830 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6831 break; 6832 } 6833 6834 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6835 sh_imm |= b1<<5; 6836 vassert(sh_imm < 64); 6837 DIP("sradi%s r%u,r%u,%u\n", 6838 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6839 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6840 6841 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6842 mkexpr(rA), 6843 getIReg(rS_addr), 6844 mkU64(sh_imm), 6845 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6846 break; 6847 6848 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6849 DIP("srd%s r%u,r%u,r%u\n", 6850 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6851 /* rA = rS >>u rB */ 6852 /* ppc semantics are: 6853 srw(x,y) = (x >>u (y & 63)) -- primary result 6854 & ~((y << 57) >>s 63) -- make result 0 6855 for y in 64 .. 127 6856 */ 6857 assign( rA, 6858 binop( 6859 Iop_And64, 6860 binop( Iop_Shr64, 6861 mkexpr(rS), 6862 unop( Iop_64to8, 6863 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6864 unop( Iop_Not64, 6865 binop( Iop_Sar64, 6866 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6867 mkU8(63)))) ); 6868 break; 6869 6870 default: 6871 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6872 return False; 6873 } 6874 } else { 6875 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6876 return False; 6877 } 6878 6879 putIReg( rA_addr, mkexpr(rA) ); 6880 6881 if (flag_rC) { 6882 set_CR0( mkexpr(rA) ); 6883 } 6884 return True; 6885 } 6886 6887 6888 6889 /* 6890 Integer Load/Store Reverse Instructions 6891 */ 6892 /* Generates code to swap the byte order in an Ity_I32. */ 6893 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 6894 { 6895 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6896 return 6897 binop(Iop_Or32, 6898 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 6899 binop(Iop_Or32, 6900 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6901 mkU32(0x00FF0000)), 6902 binop(Iop_Or32, 6903 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6904 mkU32(0x0000FF00)), 6905 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 6906 mkU32(0x000000FF) ) 6907 ))); 6908 } 6909 6910 /* Generates code to swap the byte order in the lower half of an Ity_I32, 6911 and zeroes the upper half. */ 6912 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 6913 { 6914 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6915 return 6916 binop(Iop_Or32, 6917 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6918 mkU32(0x0000FF00)), 6919 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6920 mkU32(0x000000FF)) 6921 ); 6922 } 6923 6924 static Bool dis_int_ldst_rev ( UInt theInstr ) 6925 { 6926 /* X-Form */ 6927 UChar opc1 = ifieldOPC(theInstr); 6928 UChar rD_addr = ifieldRegDS(theInstr); 6929 UChar rS_addr = rD_addr; 6930 UChar rA_addr = ifieldRegA(theInstr); 6931 UChar rB_addr = ifieldRegB(theInstr); 6932 UInt opc2 = ifieldOPClo10(theInstr); 6933 UChar b0 = ifieldBIT0(theInstr); 6934 6935 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6936 IRTemp EA = newTemp(ty); 6937 IRTemp w1 = newTemp(Ity_I32); 6938 IRTemp w2 = newTemp(Ity_I32); 6939 6940 if (opc1 != 0x1F || b0 != 0) { 6941 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 6942 return False; 6943 } 6944 6945 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6946 6947 switch (opc2) { 6948 6949 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 6950 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6951 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 6952 assign( w2, gen_byterev16(w1) ); 6953 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6954 /* Signed */False) ); 6955 break; 6956 6957 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 6958 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6959 assign( w1, load(Ity_I32, mkexpr(EA)) ); 6960 assign( w2, gen_byterev32(w1) ); 6961 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6962 /* Signed */False) ); 6963 break; 6964 6965 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 6966 { 6967 IRExpr * nextAddr; 6968 IRTemp w3 = newTemp( Ity_I32 ); 6969 IRTemp w4 = newTemp( Ity_I32 ); 6970 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6971 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 6972 assign( w2, gen_byterev32( w1 ) ); 6973 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 6974 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 6975 assign( w3, load( Ity_I32, nextAddr ) ); 6976 assign( w4, gen_byterev32( w3 ) ); 6977 if (host_endness == VexEndnessLE) 6978 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 6979 else 6980 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 6981 break; 6982 } 6983 6984 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 6985 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6986 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6987 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 6988 break; 6989 6990 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 6991 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6992 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6993 store( mkexpr(EA), gen_byterev32(w1) ); 6994 break; 6995 6996 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 6997 { 6998 IRTemp lo = newTemp(Ity_I32); 6999 IRTemp hi = newTemp(Ity_I32); 7000 IRTemp rS = newTemp(Ity_I64); 7001 assign( rS, getIReg( rS_addr ) ); 7002 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7003 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 7004 assign(hi, unop(Iop_64to32, mkexpr(rS))); 7005 store( mkexpr( EA ), 7006 binop( Iop_32HLto64, gen_byterev32( hi ), 7007 gen_byterev32( lo ) ) ); 7008 break; 7009 } 7010 7011 default: 7012 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 7013 return False; 7014 } 7015 return True; 7016 } 7017 7018 7019 7020 /* 7021 Processor Control Instructions 7022 */ 7023 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 7024 { 7025 UChar opc1 = ifieldOPC(theInstr); 7026 7027 /* X-Form */ 7028 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7029 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7030 UChar rD_addr = ifieldRegDS(theInstr); 7031 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 7032 7033 /* XFX-Form */ 7034 UChar rS_addr = rD_addr; 7035 UInt SPR = b11to20; 7036 UInt TBR = b11to20; 7037 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 7038 UInt CRM = IFIELD( theInstr, 12, 8 ); 7039 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 7040 7041 UInt opc2 = ifieldOPClo10(theInstr); 7042 UChar b0 = ifieldBIT0(theInstr); 7043 7044 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7045 IRTemp rS = newTemp(ty); 7046 assign( rS, getIReg(rS_addr) ); 7047 7048 /* Reorder SPR field as per PPC32 p470 */ 7049 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 7050 /* Reorder TBR field as per PPC32 p475 */ 7051 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 7052 7053 /* b0 = 0, inst is treated as floating point inst for reservation purposes 7054 * b0 = 1, inst is treated as vector inst for reservation purposes 7055 */ 7056 if (opc1 != 0x1F) { 7057 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 7058 return False; 7059 } 7060 7061 switch (opc2) { 7062 /* X-Form */ 7063 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 7064 if (b21to22 != 0 || b11to20 != 0) { 7065 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 7066 return False; 7067 } 7068 DIP("mcrxr crf%d\n", crfD); 7069 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 7070 putGST_field( PPC_GST_CR, 7071 getGST_field( PPC_GST_XER, 7 ), 7072 crfD ); 7073 7074 // Clear XER[0-3] 7075 putXER_SO( mkU8(0) ); 7076 putXER_OV( mkU8(0) ); 7077 putXER_CA( mkU8(0) ); 7078 break; 7079 } 7080 7081 case 0x013: 7082 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 7083 // b20==1 & b11==0: mfocrf (Move from One CR Field) 7084 // However it seems that the 'mfcr' behaviour is an acceptable 7085 // implementation of mfocr (from the 2.02 arch spec) 7086 if (b11to20 == 0) { 7087 DIP("mfcr r%u\n", rD_addr); 7088 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7089 /* Signed */False) ); 7090 break; 7091 } 7092 if (b20 == 1 && b11 == 0) { 7093 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 7094 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7095 /* Signed */False) ); 7096 break; 7097 } 7098 /* not decodable */ 7099 return False; 7100 7101 /* XFX-Form */ 7102 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 7103 7104 switch (SPR) { // Choose a register... 7105 case 0x1: 7106 DIP("mfxer r%u\n", rD_addr); 7107 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 7108 /* Signed */False) ); 7109 break; 7110 case 0x8: 7111 DIP("mflr r%u\n", rD_addr); 7112 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 7113 break; 7114 case 0x9: 7115 DIP("mfctr r%u\n", rD_addr); 7116 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 7117 break; 7118 case 0x80: // 128 7119 DIP("mfspr r%u (TFHAR)\n", rD_addr); 7120 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 7121 break; 7122 case 0x81: // 129 7123 DIP("mfspr r%u (TFIAR)\n", rD_addr); 7124 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 7125 break; 7126 case 0x82: // 130 7127 DIP("mfspr r%u (TEXASR)\n", rD_addr); 7128 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 7129 break; 7130 case 0x83: // 131 7131 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 7132 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 7133 break; 7134 case 0x100: 7135 DIP("mfvrsave r%u\n", rD_addr); 7136 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 7137 /* Signed */False) ); 7138 break; 7139 7140 case 0x103: 7141 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 7142 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 7143 break; 7144 7145 /* Even a lowly PPC7400 can run the associated helper, so no 7146 obvious need for feature testing at this point. */ 7147 case 268 /* 0x10C */: 7148 case 269 /* 0x10D */: { 7149 UInt arg = SPR==268 ? 0 : 1; 7150 IRTemp val = newTemp(Ity_I32); 7151 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 7152 IRDirty* d = unsafeIRDirty_1_N( 7153 val, 7154 0/*regparms*/, 7155 "ppc32g_dirtyhelper_MFSPR_268_269", 7156 fnptr_to_fnentry 7157 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 7158 args 7159 ); 7160 /* execute the dirty call, dumping the result in val. */ 7161 stmt( IRStmt_Dirty(d) ); 7162 putIReg( rD_addr, 7163 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7164 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 7165 break; 7166 } 7167 7168 /* Again, runs natively on PPC7400 (7447, really). Not 7169 bothering with a feature test. */ 7170 case 287: /* 0x11F */ { 7171 IRTemp val = newTemp(Ity_I32); 7172 IRExpr** args = mkIRExprVec_0(); 7173 IRDirty* d = unsafeIRDirty_1_N( 7174 val, 7175 0/*regparms*/, 7176 "ppc32g_dirtyhelper_MFSPR_287", 7177 fnptr_to_fnentry 7178 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 7179 args 7180 ); 7181 /* execute the dirty call, dumping the result in val. */ 7182 stmt( IRStmt_Dirty(d) ); 7183 putIReg( rD_addr, 7184 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7185 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 7186 break; 7187 } 7188 7189 default: 7190 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 7191 return False; 7192 } 7193 break; 7194 7195 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 7196 IRTemp val = newTemp(Ity_I64); 7197 IRExpr** args = mkIRExprVec_0(); 7198 IRDirty* d = unsafeIRDirty_1_N( 7199 val, 7200 0/*regparms*/, 7201 "ppcg_dirtyhelper_MFTB", 7202 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 7203 args ); 7204 /* execute the dirty call, dumping the result in val. */ 7205 stmt( IRStmt_Dirty(d) ); 7206 7207 switch (TBR) { 7208 case 269: 7209 DIP("mftbu r%u", rD_addr); 7210 putIReg( rD_addr, 7211 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 7212 /* Signed */False) ); 7213 break; 7214 case 268: 7215 DIP("mftb r%u", rD_addr); 7216 putIReg( rD_addr, (mode64) ? mkexpr(val) : 7217 unop(Iop_64to32, mkexpr(val)) ); 7218 break; 7219 default: 7220 return False; /* illegal instruction */ 7221 } 7222 break; 7223 } 7224 7225 case 0x090: { 7226 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 7227 // b20==1: mtocrf (Move to One Cond Reg Field) 7228 Int cr; 7229 UChar shft; 7230 if (b11 != 0) 7231 return False; 7232 if (b20 == 1) { 7233 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 7234 1 field is written. It seems more robust to decline to 7235 decode the insn if so. */ 7236 switch (CRM) { 7237 case 0x01: case 0x02: case 0x04: case 0x08: 7238 case 0x10: case 0x20: case 0x40: case 0x80: 7239 break; 7240 default: 7241 return False; 7242 } 7243 } 7244 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 7245 CRM, rS_addr); 7246 /* Write to each field specified by CRM */ 7247 for (cr = 0; cr < 8; cr++) { 7248 if ((CRM & (1 << (7-cr))) == 0) 7249 continue; 7250 shft = 4*(7-cr); 7251 putGST_field( PPC_GST_CR, 7252 binop(Iop_Shr32, 7253 mkNarrowTo32(ty, mkexpr(rS)), 7254 mkU8(shft)), cr ); 7255 } 7256 break; 7257 } 7258 7259 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 7260 7261 switch (SPR) { // Choose a register... 7262 case 0x1: 7263 DIP("mtxer r%u\n", rS_addr); 7264 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 7265 break; 7266 case 0x8: 7267 DIP("mtlr r%u\n", rS_addr); 7268 putGST( PPC_GST_LR, mkexpr(rS) ); 7269 break; 7270 case 0x9: 7271 DIP("mtctr r%u\n", rS_addr); 7272 putGST( PPC_GST_CTR, mkexpr(rS) ); 7273 break; 7274 case 0x100: 7275 DIP("mtvrsave r%u\n", rS_addr); 7276 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 7277 break; 7278 case 0x80: // 128 7279 DIP("mtspr r%u (TFHAR)\n", rS_addr); 7280 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 7281 break; 7282 case 0x81: // 129 7283 DIP("mtspr r%u (TFIAR)\n", rS_addr); 7284 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 7285 break; 7286 case 0x82: // 130 7287 DIP("mtspr r%u (TEXASR)\n", rS_addr); 7288 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 7289 break; 7290 default: 7291 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 7292 return False; 7293 } 7294 break; 7295 7296 case 0x33: // mfvsrd 7297 { 7298 UChar XS = ifieldRegXS( theInstr ); 7299 UChar rA_addr = ifieldRegA(theInstr); 7300 IRExpr * high64; 7301 IRTemp vS = newTemp( Ity_V128 ); 7302 DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS); 7303 7304 /* XS = SX || S 7305 * For SX=0, mfvsrd is treated as a Floating-Point 7306 * instruction in terms of resource availability. 7307 * For SX=1, mfvsrd is treated as a Vector instruction in 7308 * terms of resource availability. 7309 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7310 */ 7311 assign( vS, getVSReg( XS ) ); 7312 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7313 putIReg( rA_addr, (mode64) ? high64 : 7314 unop( Iop_64to32, high64 ) ); 7315 break; 7316 } 7317 7318 case 0x73: // mfvsrwz 7319 { 7320 UChar XS = ifieldRegXS( theInstr ); 7321 UChar rA_addr = ifieldRegA(theInstr); 7322 IRExpr * high64; 7323 IRTemp vS = newTemp( Ity_V128 ); 7324 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS); 7325 /* XS = SX || S 7326 * For SX=0, mfvsrwz is treated as a Floating-Point 7327 * instruction in terms of resource availability. 7328 * For SX=1, mfvsrwz is treated as a Vector instruction in 7329 * terms of resource availability. 7330 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7331 */ 7332 7333 assign( vS, getVSReg( XS ) ); 7334 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7335 /* move value to the destination setting the upper 32-bits to zero */ 7336 putIReg( rA_addr, (mode64) ? 7337 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 7338 unop( Iop_64to32, 7339 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 7340 break; 7341 } 7342 7343 case 0xB3: // mtvsrd 7344 { 7345 UChar XT = ifieldRegXT( theInstr ); 7346 UChar rA_addr = ifieldRegA(theInstr); 7347 IRTemp rA = newTemp(ty); 7348 DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr); 7349 /* XS = SX || S 7350 * For SX=0, mfvsrd is treated as a Floating-Point 7351 * instruction in terms of resource availability. 7352 * For SX=1, mfvsrd is treated as a Vector instruction in 7353 * terms of resource availability. 7354 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7355 */ 7356 assign( rA, getIReg(rA_addr) ); 7357 7358 if (mode64) 7359 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 7360 else 7361 putVSReg( XT, binop( Iop_64HLtoV128, 7362 binop( Iop_32HLto64, 7363 mkU32( 0 ), 7364 mkexpr( rA ) ), 7365 mkU64( 0 ) ) ); 7366 break; 7367 } 7368 7369 case 0xD3: // mtvsrwa 7370 { 7371 UChar XT = ifieldRegXT( theInstr ); 7372 UChar rA_addr = ifieldRegA(theInstr); 7373 IRTemp rA = newTemp( Ity_I32 ); 7374 DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr); 7375 /* XS = SX || S 7376 * For SX=0, mtvsrwa is treated as a Floating-Point 7377 * instruction in terms of resource availability. 7378 * For SX=1, mtvsrwa is treated as a Vector instruction in 7379 * terms of resource availability. 7380 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7381 */ 7382 if (mode64) 7383 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7384 else 7385 assign( rA, getIReg(rA_addr) ); 7386 7387 putVSReg( XT, binop( Iop_64HLtoV128, 7388 unop( Iop_32Sto64, mkexpr( rA ) ), 7389 mkU64( 0 ) ) ); 7390 break; 7391 } 7392 7393 case 0xF3: // mtvsrwz 7394 { 7395 UChar XT = ifieldRegXT( theInstr ); 7396 UChar rA_addr = ifieldRegA(theInstr); 7397 IRTemp rA = newTemp( Ity_I32 ); 7398 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT); 7399 /* XS = SX || S 7400 * For SX=0, mtvsrwz is treated as a Floating-Point 7401 * instruction in terms of resource availability. 7402 * For SX=1, mtvsrwz is treated as a Vector instruction in 7403 * terms of resource availability. 7404 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7405 */ 7406 if (mode64) 7407 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7408 else 7409 assign( rA, getIReg(rA_addr) ); 7410 7411 putVSReg( XT, binop( Iop_64HLtoV128, 7412 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 7413 mkU64( 0 ) ) ); 7414 break; 7415 } 7416 7417 default: 7418 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 7419 return False; 7420 } 7421 return True; 7422 } 7423 7424 7425 /* 7426 Cache Management Instructions 7427 */ 7428 static Bool dis_cache_manage ( UInt theInstr, 7429 DisResult* dres, 7430 const VexArchInfo* guest_archinfo ) 7431 { 7432 /* X-Form */ 7433 UChar opc1 = ifieldOPC(theInstr); 7434 UChar b21to25 = ifieldRegDS(theInstr); 7435 UChar rA_addr = ifieldRegA(theInstr); 7436 UChar rB_addr = ifieldRegB(theInstr); 7437 UInt opc2 = ifieldOPClo10(theInstr); 7438 UChar b0 = ifieldBIT0(theInstr); 7439 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 7440 Bool is_dcbzl = False; 7441 7442 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7443 7444 // Check for valid hint values for dcbt and dcbtst as currently described in 7445 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 7446 // means of modeling the hint anyway. 7447 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 7448 if (b21to25 == 0x10 || b21to25 < 0x10) 7449 b21to25 = 0; 7450 } 7451 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 7452 b21to25 = 0; 7453 7454 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 7455 if (b21to25 == 1) { 7456 is_dcbzl = True; 7457 b21to25 = 0; 7458 if (!(guest_archinfo->ppc_dcbzl_szB)) { 7459 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 7460 return False; 7461 } 7462 } 7463 } 7464 7465 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 7466 if (0) vex_printf("dis_cache_manage %d %d %d\n", 7467 (Int)opc1, (Int)b21to25, (Int)b0); 7468 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 7469 return False; 7470 } 7471 7472 /* stay sane .. */ 7473 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 7474 7475 switch (opc2) { 7476 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 7477 //zz vassert(0); /* AWAITING TEST CASE */ 7478 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 7479 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 7480 //zz break; 7481 7482 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 7483 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 7484 /* nop as far as vex is concerned */ 7485 break; 7486 7487 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 7488 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 7489 /* nop as far as vex is concerned */ 7490 break; 7491 7492 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 7493 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 7494 /* nop as far as vex is concerned */ 7495 break; 7496 7497 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 7498 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 7499 /* nop as far as vex is concerned */ 7500 break; 7501 7502 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 7503 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 7504 /* Clear all bytes in cache block at (rA|0) + rB. */ 7505 IRTemp EA = newTemp(ty); 7506 IRTemp addr = newTemp(ty); 7507 IRExpr* irx_addr; 7508 UInt i; 7509 UInt clearszB; 7510 if (is_dcbzl) { 7511 clearszB = guest_archinfo->ppc_dcbzl_szB; 7512 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 7513 } 7514 else { 7515 clearszB = guest_archinfo->ppc_dcbz_szB; 7516 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 7517 } 7518 7519 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7520 7521 if (mode64) { 7522 /* Round EA down to the start of the containing block. */ 7523 assign( addr, binop( Iop_And64, 7524 mkexpr(EA), 7525 mkU64( ~((ULong)clearszB-1) )) ); 7526 7527 for (i = 0; i < clearszB / 8; i++) { 7528 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 7529 store( irx_addr, mkU64(0) ); 7530 } 7531 } else { 7532 /* Round EA down to the start of the containing block. */ 7533 assign( addr, binop( Iop_And32, 7534 mkexpr(EA), 7535 mkU32( ~(clearszB-1) )) ); 7536 7537 for (i = 0; i < clearszB / 4; i++) { 7538 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 7539 store( irx_addr, mkU32(0) ); 7540 } 7541 } 7542 break; 7543 } 7544 7545 case 0x3D6: { 7546 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 7547 /* Invalidate all translations containing code from the cache 7548 block at (rA|0) + rB. */ 7549 IRTemp EA = newTemp(ty); 7550 IRTemp addr = newTemp(ty); 7551 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 7552 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7553 7554 /* Round EA down to the start of the containing block. */ 7555 assign( addr, binop( mkSzOp(ty, Iop_And8), 7556 mkexpr(EA), 7557 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 7558 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 7559 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 7560 7561 /* be paranoid ... */ 7562 stmt( IRStmt_MBE(Imbe_Fence) ); 7563 7564 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 7565 dres->jk_StopHere = Ijk_InvalICache; 7566 dres->whatNext = Dis_StopHere; 7567 break; 7568 } 7569 7570 default: 7571 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 7572 return False; 7573 } 7574 return True; 7575 } 7576 7577 7578 /*------------------------------------------------------------*/ 7579 /*--- Floating Point Helpers ---*/ 7580 /*------------------------------------------------------------*/ 7581 7582 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 7583 /* Produces a value in 0 .. 3, which is encoded as per the type 7584 IRRoundingMode. PPCRoundingMode encoding is different to 7585 IRRoundingMode, so need to map it. 7586 */ 7587 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 7588 { 7589 /* 7590 rounding mode | PPC | IR 7591 ------------------------ 7592 to nearest | 00 | 00 7593 to zero | 01 | 11 7594 to +infinity | 10 | 10 7595 to -infinity | 11 | 01 7596 */ 7597 IRTemp rm_PPC32 = newTemp(Ity_I32); 7598 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 7599 7600 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7601 return binop( Iop_Xor32, 7602 mkexpr(rm_PPC32), 7603 binop( Iop_And32, 7604 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 7605 mkU32(2) )); 7606 } 7607 7608 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 7609 * mapping would still work with the extended three bit DFP rounding 7610 * mode designator. 7611 7612 * rounding mode | PPC | IR 7613 * ----------------------------------------------- 7614 * to nearest, ties to even | 000 | 000 7615 * to zero | 001 | 011 7616 * to +infinity | 010 | 010 7617 * to -infinity | 011 | 001 7618 * to nearest, ties away from 0 | 100 | 100 7619 * to nearest, ties toward 0 | 101 | 111 7620 * to away from 0 | 110 | 110 7621 * to prepare for shorter precision | 111 | 101 7622 */ 7623 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 7624 { 7625 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 7626 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 7627 7628 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7629 return binop( Iop_Xor32, 7630 mkexpr( rm_PPC32 ), 7631 binop( Iop_And32, 7632 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 7633 mkU32( 2 ) ) ); 7634 } 7635 7636 #define NANmaskSingle 0x7F800000 7637 #define NANmaskDouble 0x7FF00000 7638 7639 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 7640 { 7641 IRTemp exp_zero = newTemp(Ity_I8); 7642 IRTemp frac_mask = newTemp(Ity_I32); 7643 IRTemp frac_not_zero = newTemp(Ity_I8); 7644 7645 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 7646 * The input value is always 64-bits, for single precision values, the 7647 * lower 32 bits must be zero. 7648 * 7649 * Single Pricision 7650 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 7651 * [53:32] fraction field is zero for Infinity and non-zero for NAN 7652 * [31:0] unused for single precision representation 7653 * 7654 * Double Pricision 7655 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 7656 * [50:0] fraction field is zero for Infinity and non-zero for NAN 7657 * 7658 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 7659 */ 7660 assign( frac_mask, unop( Iop_Not32, 7661 binop( Iop_Or32, 7662 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 7663 7664 assign( exp_zero, 7665 unop( Iop_1Sto8, 7666 binop( Iop_CmpEQ32, 7667 binop( Iop_And32, 7668 unop( Iop_64HIto32, 7669 unop( Iop_ReinterpF64asI64, 7670 value ) ), 7671 Hi32Mask ), 7672 Hi32Mask ) ) ); 7673 assign( frac_not_zero, 7674 binop( Iop_Or8, 7675 unop( Iop_1Sto8, 7676 binop( Iop_CmpNE32, 7677 binop( Iop_And32, 7678 unop( Iop_64HIto32, 7679 unop( Iop_ReinterpF64asI64, 7680 value ) ), 7681 mkexpr( frac_mask ) ), 7682 mkU32( 0x0 ) ) ), 7683 unop( Iop_1Sto8, 7684 binop( Iop_CmpNE32, 7685 binop( Iop_And32, 7686 unop( Iop_64to32, 7687 unop( Iop_ReinterpF64asI64, 7688 value ) ), 7689 mkU32( 0xFFFFFFFF ) ), 7690 mkU32( 0x0 ) ) ) ) ); 7691 return unop( Iop_8Sto32, 7692 binop( Iop_And8, 7693 mkexpr( exp_zero ), 7694 mkexpr( frac_not_zero ) ) ); 7695 } 7696 7697 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 7698 { 7699 /* This function will only complement the 64-bit floating point value if it 7700 * is not Nan. NaN is not a signed value. Need to do computations using 7701 * 32-bit operands to ensure it will run in 32-bit mode. 7702 */ 7703 return binop( Iop_32HLto64, 7704 binop( Iop_Or32, 7705 binop( Iop_And32, 7706 nan_mask, 7707 unop( Iop_64HIto32, 7708 unop( Iop_ReinterpF64asI64, 7709 value ) ) ), 7710 binop( Iop_And32, 7711 unop( Iop_Not32, 7712 nan_mask ), 7713 unop( Iop_64HIto32, 7714 unop( Iop_ReinterpF64asI64, 7715 unop( Iop_NegF64, 7716 value ) ) ) ) ), 7717 unop( Iop_64to32, 7718 unop( Iop_ReinterpF64asI64, value ) ) ); 7719 } 7720 7721 /*------------------------------------------------------------*/ 7722 /*--- Floating Point Instruction Translation ---*/ 7723 /*------------------------------------------------------------*/ 7724 7725 /* 7726 Floating Point Load Instructions 7727 */ 7728 static Bool dis_fp_load ( UInt theInstr ) 7729 { 7730 /* X-Form, D-Form */ 7731 UChar opc1 = ifieldOPC(theInstr); 7732 UChar frD_addr = ifieldRegDS(theInstr); 7733 UChar rA_addr = ifieldRegA(theInstr); 7734 UChar rB_addr = ifieldRegB(theInstr); 7735 UInt opc2 = ifieldOPClo10(theInstr); 7736 UChar b0 = ifieldBIT0(theInstr); 7737 UInt uimm16 = ifieldUIMM16(theInstr); 7738 7739 Int simm16 = extend_s_16to32(uimm16); 7740 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7741 IRTemp EA = newTemp(ty); 7742 IRTemp rA = newTemp(ty); 7743 IRTemp rB = newTemp(ty); 7744 IRTemp iHi = newTemp(Ity_I32); 7745 IRTemp iLo = newTemp(Ity_I32); 7746 7747 assign( rA, getIReg(rA_addr) ); 7748 assign( rB, getIReg(rB_addr) ); 7749 7750 /* These are completely straightforward from a rounding and status 7751 bits perspective: no rounding involved and no funny status or CR 7752 bits affected. */ 7753 7754 switch (opc1) { 7755 case 0x30: // lfs (Load Float Single, PPC32 p441) 7756 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7757 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7758 putFReg( frD_addr, 7759 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7760 break; 7761 7762 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 7763 if (rA_addr == 0) 7764 return False; 7765 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7766 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7767 putFReg( frD_addr, 7768 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7769 putIReg( rA_addr, mkexpr(EA) ); 7770 break; 7771 7772 case 0x32: // lfd (Load Float Double, PPC32 p437) 7773 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7774 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7775 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7776 break; 7777 7778 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 7779 if (rA_addr == 0) 7780 return False; 7781 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7782 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7783 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7784 putIReg( rA_addr, mkexpr(EA) ); 7785 break; 7786 7787 case 0x1F: 7788 if (b0 != 0) { 7789 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 7790 return False; 7791 } 7792 7793 switch(opc2) { 7794 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7795 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7796 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7797 putFReg( frD_addr, unop( Iop_F32toF64, 7798 load(Ity_F32, mkexpr(EA))) ); 7799 break; 7800 7801 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7802 if (rA_addr == 0) 7803 return False; 7804 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7805 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7806 putFReg( frD_addr, 7807 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7808 putIReg( rA_addr, mkexpr(EA) ); 7809 break; 7810 7811 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7812 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7813 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7814 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7815 break; 7816 7817 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7818 if (rA_addr == 0) 7819 return False; 7820 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7821 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7822 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7823 putIReg( rA_addr, mkexpr(EA) ); 7824 break; 7825 7826 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7827 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7828 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7829 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7830 assign( iHi, binop(Iop_Sub32, 7831 mkU32(0), 7832 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7833 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7834 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7835 break; 7836 7837 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7838 { 7839 IRTemp dw = newTemp( Ity_I64 ); 7840 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7841 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7842 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7843 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7844 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7845 break; 7846 } 7847 7848 default: 7849 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7850 return False; 7851 } 7852 break; 7853 7854 default: 7855 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7856 return False; 7857 } 7858 return True; 7859 } 7860 7861 7862 7863 /* 7864 Floating Point Store Instructions 7865 */ 7866 static Bool dis_fp_store ( UInt theInstr ) 7867 { 7868 /* X-Form, D-Form */ 7869 UChar opc1 = ifieldOPC(theInstr); 7870 UChar frS_addr = ifieldRegDS(theInstr); 7871 UChar rA_addr = ifieldRegA(theInstr); 7872 UChar rB_addr = ifieldRegB(theInstr); 7873 UInt opc2 = ifieldOPClo10(theInstr); 7874 UChar b0 = ifieldBIT0(theInstr); 7875 Int uimm16 = ifieldUIMM16(theInstr); 7876 7877 Int simm16 = extend_s_16to32(uimm16); 7878 IRTemp frS = newTemp(Ity_F64); 7879 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7880 IRTemp EA = newTemp(ty); 7881 IRTemp rA = newTemp(ty); 7882 IRTemp rB = newTemp(ty); 7883 7884 assign( frS, getFReg(frS_addr) ); 7885 assign( rA, getIReg(rA_addr) ); 7886 assign( rB, getIReg(rB_addr) ); 7887 7888 /* These are straightforward from a status bits perspective: no 7889 funny status or CR bits affected. For single precision stores, 7890 the values are truncated and denormalised (not rounded) to turn 7891 them into single precision values. */ 7892 7893 switch (opc1) { 7894 7895 case 0x34: // stfs (Store Float Single, PPC32 p518) 7896 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7897 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7898 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 7899 the value to be stored in the correct way, without any 7900 rounding. */ 7901 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7902 break; 7903 7904 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 7905 if (rA_addr == 0) 7906 return False; 7907 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7908 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7909 /* See comment for stfs */ 7910 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7911 putIReg( rA_addr, mkexpr(EA) ); 7912 break; 7913 7914 case 0x36: // stfd (Store Float Double, PPC32 p513) 7915 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7916 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7917 store( mkexpr(EA), mkexpr(frS) ); 7918 break; 7919 7920 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 7921 if (rA_addr == 0) 7922 return False; 7923 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7924 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7925 store( mkexpr(EA), mkexpr(frS) ); 7926 putIReg( rA_addr, mkexpr(EA) ); 7927 break; 7928 7929 case 0x1F: 7930 if (b0 != 0) { 7931 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 7932 return False; 7933 } 7934 switch(opc2) { 7935 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 7936 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7937 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7938 /* See note for stfs */ 7939 store( mkexpr(EA), 7940 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7941 break; 7942 7943 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 7944 if (rA_addr == 0) 7945 return False; 7946 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7947 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7948 /* See note for stfs */ 7949 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7950 putIReg( rA_addr, mkexpr(EA) ); 7951 break; 7952 7953 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 7954 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7955 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7956 store( mkexpr(EA), mkexpr(frS) ); 7957 break; 7958 7959 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 7960 if (rA_addr == 0) 7961 return False; 7962 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7963 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7964 store( mkexpr(EA), mkexpr(frS) ); 7965 putIReg( rA_addr, mkexpr(EA) ); 7966 break; 7967 7968 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 7969 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7970 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7971 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7972 store( mkexpr(EA), 7973 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 7974 break; 7975 7976 default: 7977 vex_printf("dis_fp_store(ppc)(opc2)\n"); 7978 return False; 7979 } 7980 break; 7981 7982 default: 7983 vex_printf("dis_fp_store(ppc)(opc1)\n"); 7984 return False; 7985 } 7986 return True; 7987 } 7988 7989 7990 7991 /* 7992 Floating Point Arith Instructions 7993 */ 7994 static Bool dis_fp_arith ( UInt theInstr ) 7995 { 7996 /* A-Form */ 7997 UChar opc1 = ifieldOPC(theInstr); 7998 UChar frD_addr = ifieldRegDS(theInstr); 7999 UChar frA_addr = ifieldRegA(theInstr); 8000 UChar frB_addr = ifieldRegB(theInstr); 8001 UChar frC_addr = ifieldRegC(theInstr); 8002 UChar opc2 = ifieldOPClo5(theInstr); 8003 UChar flag_rC = ifieldBIT0(theInstr); 8004 8005 IRTemp frD = newTemp(Ity_F64); 8006 IRTemp frA = newTemp(Ity_F64); 8007 IRTemp frB = newTemp(Ity_F64); 8008 IRTemp frC = newTemp(Ity_F64); 8009 IRExpr* rm = get_IR_roundingmode(); 8010 8011 /* By default, we will examine the results of the operation and set 8012 fpscr[FPRF] accordingly. */ 8013 Bool set_FPRF = True; 8014 8015 /* By default, if flag_RC is set, we will clear cr1 after the 8016 operation. In reality we should set cr1 to indicate the 8017 exception status of the operation, but since we're not 8018 simulating exceptions, the exception status will appear to be 8019 zero. Hence cr1 should be cleared if this is a . form insn. */ 8020 Bool clear_CR1 = True; 8021 8022 assign( frA, getFReg(frA_addr)); 8023 assign( frB, getFReg(frB_addr)); 8024 assign( frC, getFReg(frC_addr)); 8025 8026 switch (opc1) { 8027 case 0x3B: 8028 switch (opc2) { 8029 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 8030 if (frC_addr != 0) 8031 return False; 8032 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8033 frD_addr, frA_addr, frB_addr); 8034 assign( frD, triop( Iop_DivF64r32, 8035 rm, mkexpr(frA), mkexpr(frB) )); 8036 break; 8037 8038 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 8039 if (frC_addr != 0) 8040 return False; 8041 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8042 frD_addr, frA_addr, frB_addr); 8043 assign( frD, triop( Iop_SubF64r32, 8044 rm, mkexpr(frA), mkexpr(frB) )); 8045 break; 8046 8047 case 0x15: // fadds (Floating Add Single, PPC32 p401) 8048 if (frC_addr != 0) 8049 return False; 8050 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8051 frD_addr, frA_addr, frB_addr); 8052 assign( frD, triop( Iop_AddF64r32, 8053 rm, mkexpr(frA), mkexpr(frB) )); 8054 break; 8055 8056 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 8057 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8058 if (frA_addr != 0 || frC_addr != 0) 8059 return False; 8060 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 8061 frD_addr, frB_addr); 8062 // however illogically, on ppc970 this insn behaves identically 8063 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 8064 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 8065 break; 8066 8067 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 8068 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8069 if (frA_addr != 0 || frC_addr != 0) 8070 return False; 8071 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 8072 frD_addr, frB_addr); 8073 { IRExpr* ieee_one 8074 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8075 assign( frD, triop( Iop_DivF64r32, 8076 rm, 8077 ieee_one, mkexpr(frB) )); 8078 } 8079 break; 8080 8081 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 8082 if (frB_addr != 0) 8083 return False; 8084 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8085 frD_addr, frA_addr, frC_addr); 8086 assign( frD, triop( Iop_MulF64r32, 8087 rm, mkexpr(frA), mkexpr(frC) )); 8088 break; 8089 8090 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 8091 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8092 // Undocumented instruction? 8093 if (frA_addr != 0 || frC_addr != 0) 8094 return False; 8095 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 8096 frD_addr, frB_addr); 8097 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8098 break; 8099 8100 default: 8101 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 8102 return False; 8103 } 8104 break; 8105 8106 case 0x3F: 8107 switch (opc2) { 8108 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 8109 if (frC_addr != 0) 8110 return False; 8111 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8112 frD_addr, frA_addr, frB_addr); 8113 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 8114 break; 8115 8116 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 8117 if (frC_addr != 0) 8118 return False; 8119 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8120 frD_addr, frA_addr, frB_addr); 8121 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 8122 break; 8123 8124 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 8125 if (frC_addr != 0) 8126 return False; 8127 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8128 frD_addr, frA_addr, frB_addr); 8129 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 8130 break; 8131 8132 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 8133 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8134 if (frA_addr != 0 || frC_addr != 0) 8135 return False; 8136 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 8137 frD_addr, frB_addr); 8138 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 8139 break; 8140 8141 case 0x17: { // fsel (Floating Select, PPC32 p426) 8142 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8143 IRTemp cc = newTemp(Ity_I32); 8144 IRTemp cc_b0 = newTemp(Ity_I32); 8145 8146 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8147 frD_addr, frA_addr, frC_addr, frB_addr); 8148 8149 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 8150 // => GT|EQ == (cc & 0x1 == 0) 8151 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 8152 IRExpr_Const(IRConst_F64(0))) ); 8153 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 8154 8155 // frD = (frA >= 0.0) ? frC : frB 8156 // = (cc_b0 == 0) ? frC : frB 8157 assign( frD, 8158 IRExpr_ITE( 8159 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 8160 mkexpr(frC), 8161 mkexpr(frB) )); 8162 8163 /* One of the rare ones which don't mess with FPRF */ 8164 set_FPRF = False; 8165 break; 8166 } 8167 8168 case 0x18: // fre (Floating Reciprocal Estimate) 8169 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8170 // Note: unclear whether this insn really exists or not 8171 // ppc970 doesn't have it, but POWER5 does 8172 if (frA_addr != 0 || frC_addr != 0) 8173 return False; 8174 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 8175 frD_addr, frB_addr); 8176 { IRExpr* ieee_one 8177 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8178 assign( frD, triop( Iop_DivF64, 8179 rm, 8180 ieee_one, mkexpr(frB) )); 8181 } 8182 break; 8183 8184 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 8185 if (frB_addr != 0) 8186 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 8187 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8188 frD_addr, frA_addr, frC_addr); 8189 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 8190 break; 8191 8192 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 8193 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8194 if (frA_addr != 0 || frC_addr != 0) 8195 return False; 8196 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 8197 frD_addr, frB_addr); 8198 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8199 break; 8200 8201 default: 8202 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 8203 return False; 8204 } 8205 break; 8206 8207 default: 8208 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 8209 return False; 8210 } 8211 8212 putFReg( frD_addr, mkexpr(frD) ); 8213 8214 if (set_FPRF) { 8215 // XXX XXX XXX FIXME 8216 // set FPRF from frD 8217 } 8218 8219 if (flag_rC && clear_CR1) { 8220 putCR321( 1, mkU8(0) ); 8221 putCR0( 1, mkU8(0) ); 8222 } 8223 8224 return True; 8225 } 8226 8227 8228 8229 /* 8230 Floating Point Mult-Add Instructions 8231 */ 8232 static Bool dis_fp_multadd ( UInt theInstr ) 8233 { 8234 /* A-Form */ 8235 UChar opc1 = ifieldOPC(theInstr); 8236 UChar frD_addr = ifieldRegDS(theInstr); 8237 UChar frA_addr = ifieldRegA(theInstr); 8238 UChar frB_addr = ifieldRegB(theInstr); 8239 UChar frC_addr = ifieldRegC(theInstr); 8240 UChar opc2 = ifieldOPClo5(theInstr); 8241 UChar flag_rC = ifieldBIT0(theInstr); 8242 8243 IRTemp frD = newTemp(Ity_F64); 8244 IRTemp frA = newTemp(Ity_F64); 8245 IRTemp frB = newTemp(Ity_F64); 8246 IRTemp frC = newTemp(Ity_F64); 8247 IRTemp rmt = newTemp(Ity_I32); 8248 IRTemp tmp = newTemp(Ity_F64); 8249 IRTemp sign_tmp = newTemp(Ity_I64); 8250 IRTemp nan_mask = newTemp(Ity_I32); 8251 IRExpr* rm; 8252 8253 /* By default, we will examine the results of the operation and set 8254 fpscr[FPRF] accordingly. */ 8255 Bool set_FPRF = True; 8256 8257 /* By default, if flag_RC is set, we will clear cr1 after the 8258 operation. In reality we should set cr1 to indicate the 8259 exception status of the operation, but since we're not 8260 simulating exceptions, the exception status will appear to be 8261 zero. Hence cr1 should be cleared if this is a . form insn. */ 8262 Bool clear_CR1 = True; 8263 8264 /* Bind the rounding mode expression to a temp; there's no 8265 point in creating gratuitous CSEs, as we know we'll need 8266 to use it twice. */ 8267 assign( rmt, get_IR_roundingmode() ); 8268 rm = mkexpr(rmt); 8269 8270 assign( frA, getFReg(frA_addr)); 8271 assign( frB, getFReg(frB_addr)); 8272 assign( frC, getFReg(frC_addr)); 8273 8274 /* The rounding in this is all a bit dodgy. The idea is to only do 8275 one rounding. That clearly isn't achieveable without dedicated 8276 four-input IR primops, although in the single precision case we 8277 can sort-of simulate it by doing the inner multiply in double 8278 precision. 8279 8280 In the negated cases, the negation happens after rounding. */ 8281 8282 switch (opc1) { 8283 case 0x3B: 8284 switch (opc2) { 8285 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 8286 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8287 frD_addr, frA_addr, frC_addr, frB_addr); 8288 assign( frD, qop( Iop_MSubF64r32, rm, 8289 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8290 break; 8291 8292 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 8293 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8294 frD_addr, frA_addr, frC_addr, frB_addr); 8295 assign( frD, qop( Iop_MAddF64r32, rm, 8296 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8297 break; 8298 8299 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 8300 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 8301 8302 if (opc2 == 0x1E) { 8303 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8304 frD_addr, frA_addr, frC_addr, frB_addr); 8305 assign( tmp, qop( Iop_MSubF64r32, rm, 8306 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8307 } else { 8308 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8309 frD_addr, frA_addr, frC_addr, frB_addr); 8310 assign( tmp, qop( Iop_MAddF64r32, rm, 8311 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8312 } 8313 8314 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8315 mkU32( NANmaskSingle ) ) ); 8316 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8317 mkexpr( nan_mask ) ) ); 8318 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8319 break; 8320 8321 default: 8322 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 8323 return False; 8324 } 8325 break; 8326 8327 case 0x3F: 8328 switch (opc2) { 8329 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 8330 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8331 frD_addr, frA_addr, frC_addr, frB_addr); 8332 assign( frD, qop( Iop_MSubF64, rm, 8333 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8334 break; 8335 8336 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 8337 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8338 frD_addr, frA_addr, frC_addr, frB_addr); 8339 assign( frD, qop( Iop_MAddF64, rm, 8340 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8341 break; 8342 8343 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 8344 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 8345 8346 if (opc2 == 0x1E) { 8347 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8348 frD_addr, frA_addr, frC_addr, frB_addr); 8349 assign( tmp, qop( Iop_MSubF64, rm, 8350 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8351 } else { 8352 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8353 frD_addr, frA_addr, frC_addr, frB_addr); 8354 assign( tmp, qop( Iop_MAddF64, rm, 8355 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8356 } 8357 8358 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8359 mkU32( NANmaskDouble ) ) ); 8360 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8361 mkexpr( nan_mask ) ) ); 8362 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8363 break; 8364 8365 default: 8366 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 8367 return False; 8368 } 8369 break; 8370 8371 default: 8372 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 8373 return False; 8374 } 8375 8376 putFReg( frD_addr, mkexpr(frD) ); 8377 8378 if (set_FPRF) { 8379 // XXX XXX XXX FIXME 8380 // set FPRF from frD 8381 } 8382 8383 if (flag_rC && clear_CR1) { 8384 putCR321( 1, mkU8(0) ); 8385 putCR0( 1, mkU8(0) ); 8386 } 8387 8388 return True; 8389 } 8390 8391 /* 8392 * fe_flag is set to 1 if any of the following conditions occurs: 8393 * - The floating-point operand in register FRB is a Zero, a 8394 * NaN, an Infinity, or a negative value. 8395 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 8396 * Otherwise fe_flag is set to 0. 8397 * 8398 * fg_flag is set to 1 if either of the following conditions occurs. 8399 * - The floating-point operand in register FRB is a Zero, an 8400 * Infinity, or a denormalized value. 8401 * Otherwise fg_flag is set to 0. 8402 * 8403 */ 8404 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8405 { 8406 // The following temps are for holding intermediate results 8407 IRTemp e_b = newTemp(Ity_I32); 8408 IRExpr * fe_flag, * fg_flag; 8409 IRTemp frB_exp_shR = newTemp(Ity_I32); 8410 UInt bias = sp? 127 : 1023; 8411 IRExpr * frbNaN, * frbDenorm, * frBNeg; 8412 IRExpr * eb_LTE; 8413 IRTemp frbZero_tmp = newTemp(Ity_I1); 8414 IRTemp frbInf_tmp = newTemp(Ity_I1); 8415 *fe_flag_tmp = newTemp(Ity_I32); 8416 *fg_flag_tmp = newTemp(Ity_I32); 8417 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 8418 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8419 8420 ////////////////// fe_flag tests BEGIN ////////////////////// 8421 /* We first do all tests that may result in setting fe_flag to '1'. 8422 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 8423 * for details.) 8424 */ 8425 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 8426 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 8427 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 8428 { 8429 // Test_value = -970 for double precision 8430 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 8431 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 8432 } 8433 frBNeg = binop( Iop_CmpEQ32, 8434 binop( Iop_Shr32, 8435 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 8436 mkU8( 31 ) ), 8437 mkU32( 1 ) ); 8438 ////////////////// fe_flag tests END ////////////////////// 8439 8440 ////////////////// fg_flag tests BEGIN ////////////////////// 8441 /* 8442 * The following tests were already performed above in the fe_flag 8443 * tests. So these conditions will result in both fe_ and fg_ flags 8444 * being set. 8445 * - Test if FRB is Zero 8446 * - Test if FRB is an Infinity 8447 */ 8448 8449 /* 8450 * Test if FRB holds a denormalized value. A denormalized value is one where 8451 * the exp is 0 and the fraction is non-zero. 8452 */ 8453 if (sp) { 8454 IRTemp frac_part = newTemp(Ity_I32); 8455 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 8456 frbDenorm 8457 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8458 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 8459 } else { 8460 IRExpr * hi32, * low32, * fraction_is_nonzero; 8461 IRTemp frac_part = newTemp(Ity_I64); 8462 8463 assign( frac_part, FP_FRAC_PART(frB_Int) ); 8464 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8465 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8466 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8467 mkU32( 0 ) ); 8468 frbDenorm 8469 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8470 fraction_is_nonzero ); 8471 } 8472 ////////////////// fg_flag tests END ////////////////////// 8473 8474 ///////////////////////// 8475 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 8476 mkOR1( frbNaN, 8477 mkOR1( mkexpr( frbInf_tmp ), 8478 mkOR1( frBNeg, eb_LTE ) ) ) ); 8479 8480 fe_flag = unop(Iop_1Uto32, fe_flag); 8481 8482 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 8483 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 8484 fg_flag = unop(Iop_1Uto32, fg_flag); 8485 assign (*fg_flag_tmp, fg_flag); 8486 assign (*fe_flag_tmp, fe_flag); 8487 } 8488 /* 8489 * fe_flag is set to 1 if any of the following conditions occurs: 8490 * - The double-precision floating-point operand in register FRA is a NaN or an 8491 * Infinity. 8492 * - The double-precision floating-point operand in register FRB is a Zero, a 8493 * NaN, or an Infinity. 8494 * - e_b is less than or equal to -1022. 8495 * - e_b is greater than or equal to 1021. 8496 * - The double-precision floating-point operand in register FRA is not a zero 8497 * and the difference, e_a - e_b, is greater than or equal to 1023. 8498 * - The double-precision floating-point operand in register FRA is not a zero 8499 * and the difference, e_a - e_b, is less than or equal to -1021. 8500 * - The double-precision floating-point operand in register FRA is not a zero 8501 * and e_a is less than or equal to -970 8502 * Otherwise fe_flag is set to 0. 8503 * 8504 * fg_flag is set to 1 if either of the following conditions occurs. 8505 * - The double-precision floating-point operand in register FRA is an Infinity. 8506 * - The double-precision floating-point operand in register FRB is a Zero, an 8507 * Infinity, or a denormalized value. 8508 * Otherwise fg_flag is set to 0. 8509 * 8510 */ 8511 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8512 { 8513 // The following temps are for holding intermediate results 8514 IRTemp e_a = newTemp(Ity_I32); 8515 IRTemp e_b = newTemp(Ity_I32); 8516 IRTemp frA_exp_shR = newTemp(Ity_I32); 8517 IRTemp frB_exp_shR = newTemp(Ity_I32); 8518 8519 UInt bias = sp? 127 : 1023; 8520 *fe_flag_tmp = newTemp(Ity_I32); 8521 *fg_flag_tmp = newTemp(Ity_I32); 8522 8523 /* The following variables hold boolean results from tests 8524 * that are OR'ed together for setting the fe_ and fg_ flags. 8525 * For some cases, the booleans are used more than once, so 8526 * I make those IRTemp's instead of IRExpr's. 8527 */ 8528 IRExpr * fraNaN, * frbNaN, * frbDenorm; 8529 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 8530 IRTemp fraInf_tmp = newTemp(Ity_I1); 8531 IRTemp frbZero_tmp = newTemp(Ity_I1); 8532 IRTemp frbInf_tmp = newTemp(Ity_I1); 8533 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 8534 8535 /* The following are the flags that are set by OR'ing the results of 8536 * all the tests done for tdiv. These flags are the input to the specified CR. 8537 */ 8538 IRExpr * fe_flag, * fg_flag; 8539 8540 // Create temps that will be used throughout the following tests. 8541 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 8542 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 8543 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 8544 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 8545 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8546 8547 8548 ////////////////// fe_flag tests BEGIN ////////////////////// 8549 /* We first do all tests that may result in setting fe_flag to '1'. */ 8550 8551 /* 8552 * Test if the double-precision floating-point operand in register FRA is 8553 * a NaN: 8554 */ 8555 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 8556 /* 8557 * Test if the double-precision floating-point operand in register FRA is 8558 * an Infinity. 8559 */ 8560 assign(fraInf_tmp, is_Inf(frA_int, sp)); 8561 8562 /* 8563 * Test if the double-precision floating-point operand in register FRB is 8564 * a NaN: 8565 */ 8566 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 8567 /* 8568 * Test if the double-precision floating-point operand in register FRB is 8569 * an Infinity. 8570 */ 8571 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 8572 /* 8573 * Test if the double-precision floating-point operand in register FRB is 8574 * a Zero. 8575 */ 8576 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 8577 8578 /* 8579 * Test if e_b <= -1022 for double precision; 8580 * or e_b <= -126 for single precision 8581 */ 8582 { 8583 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 8584 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 8585 } 8586 8587 /* 8588 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 8589 * or e_b >= -125 (125 < e_b) for single precision 8590 */ 8591 { 8592 Int test_value = sp ? 125 : 1021; 8593 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 8594 } 8595 8596 /* 8597 * Test if FRA != Zero and (e_a - e_b) >= bias 8598 */ 8599 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 8600 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 8601 binop( Iop_CmpLT32S, mkU32( bias ), 8602 binop( Iop_Sub32, mkexpr( e_a ), 8603 mkexpr( e_b ) ) ) ); 8604 8605 /* 8606 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 8607 */ 8608 { 8609 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 8610 8611 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 8612 binop( Iop_CmpLE32S, 8613 binop( Iop_Sub32, 8614 mkexpr( e_a ), 8615 mkexpr( e_b ) ), 8616 mkU32( test_value ) ) ); 8617 } 8618 8619 /* 8620 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 8621 */ 8622 { 8623 UInt test_value = 0xfffffc36; //Int test_value = -970; 8624 8625 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 8626 mkexpr( e_a ), 8627 mkU32( test_value ) ) ); 8628 } 8629 ////////////////// fe_flag tests END ////////////////////// 8630 8631 ////////////////// fg_flag tests BEGIN ////////////////////// 8632 /* 8633 * The following tests were already performed above in the fe_flag 8634 * tests. So these conditions will result in both fe_ and fg_ flags 8635 * being set. 8636 * - Test if FRA is an Infinity 8637 * - Test if FRB ix Zero 8638 * - Test if FRB is an Infinity 8639 */ 8640 8641 /* 8642 * Test if FRB holds a denormalized value. A denormalized value is one where 8643 * the exp is 0 and the fraction is non-zero. 8644 */ 8645 { 8646 IRExpr * fraction_is_nonzero; 8647 8648 if (sp) { 8649 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 8650 mkU32( 0 ) ); 8651 } else { 8652 IRExpr * hi32, * low32; 8653 IRTemp frac_part = newTemp(Ity_I64); 8654 assign( frac_part, FP_FRAC_PART(frB_int) ); 8655 8656 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8657 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8658 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8659 mkU32( 0 ) ); 8660 } 8661 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 8662 mkU32( 0x0 ) ), fraction_is_nonzero ); 8663 8664 } 8665 ////////////////// fg_flag tests END ////////////////////// 8666 8667 fe_flag 8668 = mkOR1( 8669 fraNaN, 8670 mkOR1( 8671 mkexpr( fraInf_tmp ), 8672 mkOR1( 8673 mkexpr( frbZero_tmp ), 8674 mkOR1( 8675 frbNaN, 8676 mkOR1( 8677 mkexpr( frbInf_tmp ), 8678 mkOR1( eb_LTE, 8679 mkOR1( eb_GTE, 8680 mkOR1( ea_eb_GTE, 8681 mkOR1( ea_eb_LTE, 8682 ea_LTE ) ) ) ) ) ) ) ) ); 8683 8684 fe_flag = unop(Iop_1Uto32, fe_flag); 8685 8686 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 8687 mkOR1( mkexpr( frbInf_tmp ), 8688 frbDenorm ) ) ); 8689 fg_flag = unop(Iop_1Uto32, fg_flag); 8690 assign(*fe_flag_tmp, fe_flag); 8691 assign(*fg_flag_tmp, fg_flag); 8692 } 8693 8694 /* See description for _do_fp_tdiv() above. */ 8695 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 8696 { 8697 IRTemp fe_flag, fg_flag; 8698 ///////////////////////// 8699 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8700 * where fl_flag == 1 on ppc64. 8701 */ 8702 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 8703 fe_flag = fg_flag = IRTemp_INVALID; 8704 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 8705 return binop( Iop_Or32, 8706 binop( Iop_Or32, 8707 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 8708 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8709 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 8710 } 8711 8712 static Bool dis_fp_tests ( UInt theInstr ) 8713 { 8714 UChar opc1 = ifieldOPC(theInstr); 8715 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8716 UChar frB_addr = ifieldRegB(theInstr); 8717 UChar b0 = ifieldBIT0(theInstr); 8718 UInt opc2 = ifieldOPClo10(theInstr); 8719 IRTemp frB_I64 = newTemp(Ity_I64); 8720 8721 if (opc1 != 0x3F || b0 != 0 ){ 8722 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8723 return False; 8724 } 8725 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 8726 8727 switch (opc2) { 8728 case 0x080: // ftdiv 8729 { 8730 UChar frA_addr = ifieldRegA(theInstr); 8731 IRTemp frA_I64 = newTemp(Ity_I64); 8732 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8733 if (b21to22 != 0 ) { 8734 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8735 return False; 8736 } 8737 8738 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 8739 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 8740 8741 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8742 break; 8743 } 8744 case 0x0A0: // ftsqrt 8745 { 8746 IRTemp flags = newTemp(Ity_I32); 8747 IRTemp fe_flag, fg_flag; 8748 fe_flag = fg_flag = IRTemp_INVALID; 8749 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 8750 if ( b18to22 != 0) { 8751 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 8752 return False; 8753 } 8754 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 8755 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 8756 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8757 * where fl_flag == 1 on ppc64. 8758 */ 8759 assign( flags, 8760 binop( Iop_Or32, 8761 binop( Iop_Or32, mkU32( 8 ), // fl_flag 8762 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8763 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 8764 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 8765 break; 8766 } 8767 8768 default: 8769 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 8770 return False; 8771 8772 } 8773 return True; 8774 } 8775 8776 /* 8777 Floating Point Compare Instructions 8778 */ 8779 static Bool dis_fp_cmp ( UInt theInstr ) 8780 { 8781 /* X-Form */ 8782 UChar opc1 = ifieldOPC(theInstr); 8783 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8784 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8785 UChar frA_addr = ifieldRegA(theInstr); 8786 UChar frB_addr = ifieldRegB(theInstr); 8787 UInt opc2 = ifieldOPClo10(theInstr); 8788 UChar b0 = ifieldBIT0(theInstr); 8789 8790 IRTemp ccIR = newTemp(Ity_I32); 8791 IRTemp ccPPC32 = newTemp(Ity_I32); 8792 8793 IRTemp frA = newTemp(Ity_F64); 8794 IRTemp frB = newTemp(Ity_F64); 8795 8796 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 8797 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 8798 return False; 8799 } 8800 8801 assign( frA, getFReg(frA_addr)); 8802 assign( frB, getFReg(frB_addr)); 8803 8804 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 8805 8806 /* Map compare result from IR to PPC32 */ 8807 /* 8808 FP cmp result | PPC | IR 8809 -------------------------- 8810 UN | 0x1 | 0x45 8811 EQ | 0x2 | 0x40 8812 GT | 0x4 | 0x00 8813 LT | 0x8 | 0x01 8814 */ 8815 8816 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 8817 // | ((ccIR ^ (ccIR>>6)) & 1) 8818 assign( 8819 ccPPC32, 8820 binop( 8821 Iop_Shl32, 8822 mkU32(1), 8823 unop( 8824 Iop_32to8, 8825 binop( 8826 Iop_Or32, 8827 binop( 8828 Iop_And32, 8829 unop( 8830 Iop_Not32, 8831 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 8832 ), 8833 mkU32(2) 8834 ), 8835 binop( 8836 Iop_And32, 8837 binop( 8838 Iop_Xor32, 8839 mkexpr(ccIR), 8840 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 8841 ), 8842 mkU32(1) 8843 ) 8844 ) 8845 ) 8846 ) 8847 ); 8848 8849 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 8850 8851 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 8852 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 8853 */ 8854 // XXX XXX XXX FIXME 8855 // Also write the result into FPRF (it's not entirely clear how) 8856 8857 /* Note: Differences between fcmpu and fcmpo are only in exception 8858 flag settings, which aren't supported anyway. */ 8859 switch (opc2) { 8860 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 8861 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8862 break; 8863 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 8864 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8865 break; 8866 default: 8867 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 8868 return False; 8869 } 8870 return True; 8871 } 8872 8873 8874 8875 /* 8876 Floating Point Rounding/Conversion Instructions 8877 */ 8878 static Bool dis_fp_round ( UInt theInstr ) 8879 { 8880 /* X-Form */ 8881 UChar opc1 = ifieldOPC(theInstr); 8882 UChar b16to20 = ifieldRegA(theInstr); 8883 UChar frD_addr = ifieldRegDS(theInstr); 8884 UChar frB_addr = ifieldRegB(theInstr); 8885 UInt opc2 = ifieldOPClo10(theInstr); 8886 UChar flag_rC = ifieldBIT0(theInstr); 8887 8888 IRTemp frD = newTemp(Ity_F64); 8889 IRTemp frB = newTemp(Ity_F64); 8890 IRTemp r_tmp32 = newTemp(Ity_I32); 8891 IRTemp r_tmp64 = newTemp(Ity_I64); 8892 IRExpr* rm = get_IR_roundingmode(); 8893 8894 /* By default, we will examine the results of the operation and set 8895 fpscr[FPRF] accordingly. */ 8896 Bool set_FPRF = True; 8897 8898 /* By default, if flag_RC is set, we will clear cr1 after the 8899 operation. In reality we should set cr1 to indicate the 8900 exception status of the operation, but since we're not 8901 simulating exceptions, the exception status will appear to be 8902 zero. Hence cr1 should be cleared if this is a . form insn. */ 8903 Bool clear_CR1 = True; 8904 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 8905 vex_printf("dis_fp_round(ppc)(instr)\n"); 8906 return False; 8907 } 8908 8909 assign( frB, getFReg(frB_addr)); 8910 if (opc1 == 0x3B) { 8911 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 8912 * they're very similar to the other instructions handled here, but have 8913 * a different primary opcode. 8914 */ 8915 switch (opc2) { 8916 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 8917 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8918 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8919 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 8920 mkexpr( r_tmp64 ) ) ) ); 8921 goto putFR; 8922 8923 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 8924 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8925 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8926 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 8927 goto putFR; 8928 } 8929 } 8930 8931 8932 switch (opc2) { 8933 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 8934 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8935 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 8936 break; 8937 8938 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 8939 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8940 assign( r_tmp32, 8941 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 8942 assign( frD, unop( Iop_ReinterpI64asF64, 8943 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8944 /* FPRF is undefined after fctiw. Leave unchanged. */ 8945 set_FPRF = False; 8946 break; 8947 8948 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 8949 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8950 assign( r_tmp32, 8951 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 8952 assign( frD, unop( Iop_ReinterpI64asF64, 8953 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8954 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8955 set_FPRF = False; 8956 break; 8957 8958 case 0x08F: case 0x08E: // fctiwu[z] 8959 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 8960 flag_rC ? ".":"", frD_addr, frB_addr); 8961 assign( r_tmp32, 8962 binop( Iop_F64toI32U, 8963 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 8964 mkexpr( frB ) ) ); 8965 assign( frD, unop( Iop_ReinterpI64asF64, 8966 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8967 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8968 set_FPRF = False; 8969 break; 8970 8971 8972 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 8973 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8974 assign( r_tmp64, 8975 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 8976 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8977 /* FPRF is undefined after fctid. Leave unchanged. */ 8978 set_FPRF = False; 8979 break; 8980 8981 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 8982 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8983 assign( r_tmp64, 8984 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8985 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8986 /* FPRF is undefined after fctidz. Leave unchanged. */ 8987 set_FPRF = False; 8988 break; 8989 8990 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 8991 { 8992 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 8993 flag_rC ? ".":"", frD_addr, frB_addr); 8994 assign( r_tmp64, 8995 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 8996 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8997 /* FPRF is undefined after fctidz. Leave unchanged. */ 8998 set_FPRF = False; 8999 break; 9000 } 9001 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 9002 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9003 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9004 assign( frD, 9005 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 9006 break; 9007 9008 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 9009 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9010 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9011 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 9012 break; 9013 9014 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 9015 switch(opc2) { 9016 case 0x188: // frin (Floating Round to Integer Nearest) 9017 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9018 assign( r_tmp64, 9019 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 9020 break; 9021 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 9022 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9023 assign( r_tmp64, 9024 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 9025 break; 9026 case 0x1C8: // frip (Floating Round to Integer Plus) 9027 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9028 assign( r_tmp64, 9029 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 9030 break; 9031 case 0x1E8: // frim (Floating Round to Integer Minus) 9032 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9033 assign( r_tmp64, 9034 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 9035 break; 9036 } 9037 9038 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 9039 /* F64 has only log10(2**52) significant digits anyway */ 9040 /* need to preserve sign of zero */ 9041 /* frD = (fabs(frB) > 9e18) ? frB : 9042 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 9043 assign(frD, IRExpr_ITE( 9044 binop(Iop_CmpNE8, 9045 unop(Iop_32to8, 9046 binop(Iop_CmpF64, 9047 IRExpr_Const(IRConst_F64(9e18)), 9048 unop(Iop_AbsF64, mkexpr(frB)))), 9049 mkU8(0)), 9050 mkexpr(frB), 9051 IRExpr_ITE( 9052 binop(Iop_CmpNE32, 9053 binop(Iop_Shr32, 9054 unop(Iop_64HIto32, 9055 unop(Iop_ReinterpF64asI64, 9056 mkexpr(frB))), 9057 mkU8(31)), 9058 mkU32(0)), 9059 unop(Iop_NegF64, 9060 unop( Iop_AbsF64, 9061 binop(Iop_I64StoF64, mkU32(0), 9062 mkexpr(r_tmp64)) )), 9063 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 9064 ) 9065 )); 9066 break; 9067 9068 default: 9069 vex_printf("dis_fp_round(ppc)(opc2)\n"); 9070 return False; 9071 } 9072 putFR: 9073 putFReg( frD_addr, mkexpr(frD) ); 9074 9075 if (set_FPRF) { 9076 // XXX XXX XXX FIXME 9077 // set FPRF from frD 9078 } 9079 9080 if (flag_rC && clear_CR1) { 9081 putCR321( 1, mkU8(0) ); 9082 putCR0( 1, mkU8(0) ); 9083 } 9084 9085 return True; 9086 } 9087 9088 /* 9089 Floating Point Pair Instructions 9090 */ 9091 static Bool dis_fp_pair ( UInt theInstr ) 9092 { 9093 /* X-Form/DS-Form */ 9094 UChar opc1 = ifieldOPC(theInstr); 9095 UChar frT_hi_addr = ifieldRegDS(theInstr); 9096 UChar frT_lo_addr = frT_hi_addr + 1; 9097 UChar rA_addr = ifieldRegA(theInstr); 9098 UChar rB_addr = ifieldRegB(theInstr); 9099 UInt uimm16 = ifieldUIMM16(theInstr); 9100 Int simm16 = extend_s_16to32(uimm16); 9101 UInt opc2 = ifieldOPClo10(theInstr); 9102 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9103 IRTemp EA_hi = newTemp(ty); 9104 IRTemp EA_lo = newTemp(ty); 9105 IRTemp frT_hi = newTemp(Ity_F64); 9106 IRTemp frT_lo = newTemp(Ity_F64); 9107 UChar b0 = ifieldBIT0(theInstr); 9108 Bool is_load = 0; 9109 9110 if ((frT_hi_addr %2) != 0) { 9111 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 9112 return False; 9113 } 9114 9115 switch (opc1) { 9116 case 0x1F: // register offset 9117 switch(opc2) { 9118 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 9119 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9120 is_load = 1; 9121 break; 9122 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 9123 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9124 break; 9125 default: 9126 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 9127 return False; 9128 } 9129 9130 if (b0 != 0) { 9131 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 9132 return False; 9133 } 9134 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 9135 break; 9136 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 9137 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9138 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9139 is_load = 1; 9140 break; 9141 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 9142 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9143 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9144 break; 9145 default: // immediate offset 9146 vex_printf("dis_fp_pair(ppc)(instr)\n"); 9147 return False; 9148 } 9149 9150 if (mode64) 9151 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 9152 else 9153 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 9154 9155 assign( frT_hi, getFReg(frT_hi_addr) ); 9156 assign( frT_lo, getFReg(frT_lo_addr) ); 9157 9158 if (is_load) { 9159 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) ); 9160 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) ); 9161 } else { 9162 store( mkexpr(EA_hi), mkexpr(frT_hi) ); 9163 store( mkexpr(EA_lo), mkexpr(frT_lo) ); 9164 } 9165 9166 return True; 9167 } 9168 9169 9170 /* 9171 Floating Point Merge Instructions 9172 */ 9173 static Bool dis_fp_merge ( UInt theInstr ) 9174 { 9175 /* X-Form */ 9176 UInt opc2 = ifieldOPClo10(theInstr); 9177 UChar frD_addr = ifieldRegDS(theInstr); 9178 UChar frA_addr = ifieldRegA(theInstr); 9179 UChar frB_addr = ifieldRegB(theInstr); 9180 9181 IRTemp frD = newTemp(Ity_F64); 9182 IRTemp frA = newTemp(Ity_F64); 9183 IRTemp frB = newTemp(Ity_F64); 9184 9185 assign( frA, getFReg(frA_addr)); 9186 assign( frB, getFReg(frB_addr)); 9187 9188 switch (opc2) { 9189 case 0x3c6: // fmrgew floating merge even word 9190 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9191 9192 assign( frD, unop( Iop_ReinterpI64asF64, 9193 binop( Iop_32HLto64, 9194 unop( Iop_64HIto32, 9195 unop( Iop_ReinterpF64asI64, 9196 mkexpr(frA) ) ), 9197 unop( Iop_64HIto32, 9198 unop( Iop_ReinterpF64asI64, 9199 mkexpr(frB) ) ) ) ) ); 9200 break; 9201 9202 case 0x346: // fmrgow floating merge odd word 9203 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9204 9205 assign( frD, unop( Iop_ReinterpI64asF64, 9206 binop( Iop_32HLto64, 9207 unop( Iop_64to32, 9208 unop( Iop_ReinterpF64asI64, 9209 mkexpr(frA) ) ), 9210 unop( Iop_64to32, 9211 unop( Iop_ReinterpF64asI64, 9212 mkexpr(frB) ) ) ) ) ); 9213 break; 9214 9215 default: 9216 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 9217 return False; 9218 } 9219 9220 putFReg( frD_addr, mkexpr(frD) ); 9221 return True; 9222 } 9223 9224 /* 9225 Floating Point Move Instructions 9226 */ 9227 static Bool dis_fp_move ( UInt theInstr ) 9228 { 9229 /* X-Form */ 9230 UChar opc1 = ifieldOPC(theInstr); 9231 UChar frD_addr = ifieldRegDS(theInstr); 9232 UChar frA_addr = ifieldRegA(theInstr); 9233 UChar frB_addr = ifieldRegB(theInstr); 9234 UInt opc2 = ifieldOPClo10(theInstr); 9235 UChar flag_rC = ifieldBIT0(theInstr); 9236 9237 IRTemp frD = newTemp(Ity_F64); 9238 IRTemp frB = newTemp(Ity_F64); 9239 IRTemp itmpB = newTemp(Ity_F64); 9240 IRTemp frA; 9241 IRTemp signA; 9242 IRTemp hiD; 9243 9244 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 9245 vex_printf("dis_fp_move(ppc)(instr)\n"); 9246 return False; 9247 } 9248 9249 assign( frB, getFReg(frB_addr)); 9250 9251 switch (opc2) { 9252 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 9253 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 9254 frB_addr); 9255 signA = newTemp(Ity_I32); 9256 hiD = newTemp(Ity_I32); 9257 itmpB = newTemp(Ity_I64); 9258 frA = newTemp(Ity_F64); 9259 assign( frA, getFReg(frA_addr) ); 9260 9261 /* get A's sign bit */ 9262 assign(signA, binop(Iop_And32, 9263 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 9264 mkexpr(frA))), 9265 mkU32(0x80000000)) ); 9266 9267 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 9268 9269 /* mask off B's sign bit and or in A's sign bit */ 9270 assign(hiD, binop(Iop_Or32, 9271 binop(Iop_And32, 9272 unop(Iop_64HIto32, 9273 mkexpr(itmpB)), /* frB's high 32 bits */ 9274 mkU32(0x7fffffff)), 9275 mkexpr(signA)) ); 9276 9277 /* combine hiD/loB into frD */ 9278 assign( frD, unop(Iop_ReinterpI64asF64, 9279 binop(Iop_32HLto64, 9280 mkexpr(hiD), 9281 unop(Iop_64to32, 9282 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 9283 break; 9284 9285 case 0x028: // fneg (Floating Negate, PPC32 p416) 9286 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9287 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 9288 break; 9289 9290 case 0x048: // fmr (Floating Move Register, PPC32 p410) 9291 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9292 assign( frD, mkexpr(frB) ); 9293 break; 9294 9295 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 9296 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9297 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 9298 break; 9299 9300 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 9301 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9302 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 9303 break; 9304 9305 default: 9306 vex_printf("dis_fp_move(ppc)(opc2)\n"); 9307 return False; 9308 } 9309 9310 putFReg( frD_addr, mkexpr(frD) ); 9311 9312 /* None of these change FPRF. cr1 is set in the usual way though, 9313 if flag_rC is set. */ 9314 9315 if (flag_rC) { 9316 putCR321( 1, mkU8(0) ); 9317 putCR0( 1, mkU8(0) ); 9318 } 9319 9320 return True; 9321 } 9322 9323 9324 9325 /* 9326 Floating Point Status/Control Register Instructions 9327 */ 9328 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 9329 { 9330 /* Many forms - see each switch case */ 9331 UChar opc1 = ifieldOPC(theInstr); 9332 UInt opc2 = ifieldOPClo10(theInstr); 9333 UChar flag_rC = ifieldBIT0(theInstr); 9334 9335 if (opc1 != 0x3F) { 9336 vex_printf("dis_fp_scr(ppc)(instr)\n"); 9337 return False; 9338 } 9339 9340 switch (opc2) { 9341 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 9342 // Bit crbD of the FPSCR is set. 9343 UChar crbD = ifieldRegDS(theInstr); 9344 UInt b11to20 = IFIELD(theInstr, 11, 10); 9345 9346 if (b11to20 != 0) { 9347 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 9348 return False; 9349 } 9350 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 9351 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 9352 1ULL << ( 31 - crbD ) ); 9353 break; 9354 } 9355 9356 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 9357 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9358 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9359 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 9360 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 9361 IRTemp tmp = newTemp(Ity_I32); 9362 IRExpr* fpscr_all; 9363 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 9364 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 9365 return False; 9366 } 9367 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 9368 vassert(crfD < 8); 9369 vassert(crfS < 8); 9370 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9371 assign( tmp, binop(Iop_And32, 9372 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 9373 mkU32(0xF)) ); 9374 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 9375 break; 9376 } 9377 9378 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 9379 // Bit crbD of the FPSCR is cleared. 9380 UChar crbD = ifieldRegDS(theInstr); 9381 UInt b11to20 = IFIELD(theInstr, 11, 10); 9382 9383 if (b11to20 != 0) { 9384 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 9385 return False; 9386 } 9387 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 9388 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 9389 break; 9390 } 9391 9392 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 9393 UInt crfD = IFIELD( theInstr, 23, 3 ); 9394 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 9395 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 9396 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9397 UChar Wbit; 9398 9399 if (b16to22 != 0 || b11 != 0) { 9400 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 9401 return False; 9402 } 9403 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 9404 if (GX_level) { 9405 /* This implies that Decimal Floating Point is supported, and the 9406 * FPSCR must be managed as a 64-bit register. 9407 */ 9408 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9409 } else { 9410 Wbit = 0; 9411 } 9412 crfD = crfD + (8 * (1 - Wbit) ); 9413 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 9414 break; 9415 } 9416 9417 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 9418 UChar frD_addr = ifieldRegDS(theInstr); 9419 UInt b11to20 = IFIELD(theInstr, 11, 10); 9420 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9421 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, 9422 MASK_FPSCR_DRN ); 9423 9424 if (b11to20 != 0) { 9425 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 9426 return False; 9427 } 9428 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 9429 putFReg( frD_addr, 9430 unop( Iop_ReinterpI64asF64, 9431 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 9432 break; 9433 } 9434 9435 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 9436 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 9437 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 9438 UChar frB_addr = ifieldRegB(theInstr); 9439 IRTemp frB = newTemp(Ity_F64); 9440 IRTemp rB_64 = newTemp( Ity_I64 ); 9441 Int i; 9442 ULong mask; 9443 UChar Wbit; 9444 #define BFP_MASK_SEED 0x3000000000000000ULL 9445 #define DFP_MASK_SEED 0x7000000000000000ULL 9446 9447 if (GX_level) { 9448 /* This implies that Decimal Floating Point is supported, and the 9449 * FPSCR must be managed as a 64-bit register. 9450 */ 9451 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9452 } else { 9453 Wbit = 0; 9454 } 9455 9456 if (b25 == 1) { 9457 /* new 64 bit move variant for power 6. If L field (bit 25) is 9458 * a one do a full 64 bit move. Note, the FPSCR is not really 9459 * properly modeled. This instruciton only changes the value of 9460 * the rounding mode. The HW exception bits do not get set in 9461 * the simulator. 1/12/09 9462 */ 9463 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 9464 mask = 0xFF; 9465 9466 } else { 9467 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 9468 // Build 32bit mask from FM: 9469 mask = 0; 9470 for (i=0; i<8; i++) { 9471 if ((FM & (1<<(7-i))) == 1) { 9472 /* FPSCR field k is set to the contents of the corresponding 9473 * field of register FRB, where k = i+8x(1-W). In the Power 9474 * ISA, register field numbering is from left to right, so field 9475 * 15 is the least significant field in a 64-bit register. To 9476 * generate the mask, we set all the appropriate rounding mode 9477 * bits in the highest order nibble (field 0) and shift right 9478 * 'k x nibble length'. 9479 */ 9480 if (Wbit) 9481 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9482 else 9483 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9484 } 9485 } 9486 } 9487 assign( frB, getFReg(frB_addr)); 9488 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 9489 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 9490 break; 9491 } 9492 9493 default: 9494 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 9495 return False; 9496 } 9497 return True; 9498 } 9499 9500 /*------------------------------------------------------------*/ 9501 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 9502 /*------------------------------------------------------------*/ 9503 #define DFP_LONG 1 9504 #define DFP_EXTND 2 9505 #define DFP_LONG_BIAS 398 9506 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 9507 #define DFP_EXTND_BIAS 6176 9508 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 9509 #define DFP_LONG_EXP_MSK 0XFF 9510 #define DFP_EXTND_EXP_MSK 0XFFF 9511 9512 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 9513 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 9514 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 9515 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 9516 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 9517 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 9518 #define DFP_LONG_EXP_MAX 369 // biased max 9519 #define DFP_LONG_EXP_MIN 0 // biased min 9520 #define DFP_EXTND_EXP_MAX 6111 // biased max 9521 #define DFP_EXTND_EXP_MIN 0 // biased min 9522 #define DFP_LONG_MAX_SIG_DIGITS 16 9523 #define DFP_EXTND_MAX_SIG_DIGITS 34 9524 #define MAX_DIGITS_IN_STRING 8 9525 9526 9527 #define AND(x, y) binop( Iop_And32, x, y ) 9528 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 9529 #define OR(x, y) binop( Iop_Or32, x, y ) 9530 #define OR3(x, y, z) OR( x, OR( y, z ) ) 9531 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 9532 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 9533 9534 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 9535 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 9536 9537 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 9538 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 9539 ((_b1) << 1) | ((_b0) << 0)) 9540 9541 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 9542 { 9543 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9544 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 9545 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 9546 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 9547 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 9548 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 9549 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9550 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9551 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9552 9553 /* The encodig is as follows: 9554 * lmd - left most digit 9555 * lme - left most 2-bits of the exponent 9556 * 9557 * lmd 9558 * 0 - 7 (lmexp << 3) | lmd 9559 * 8 0b11000 (24 decimal) if lme=0b00; 9560 * 0b11010 (26 decimal) if lme=0b01; 9561 * 0b11100 (28 decimal) if lme=0b10; 9562 * 9 0b11001 (25 decimal) if lme=0b00; 9563 * 0b11011 (27 decimal) if lme=0b01; 9564 * 0b11101 (29 decimal) if lme=0b10; 9565 */ 9566 9567 /* Generate the masks for each condition */ 9568 assign( lmd_07_mask, 9569 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 9570 assign( lmd_8_mask, 9571 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 9572 assign( lmd_9_mask, 9573 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 9574 assign( lmexp_00_mask, 9575 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 9576 assign( lmexp_01_mask, 9577 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 9578 assign( lmexp_10_mask, 9579 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 9580 9581 /* Generate the values for each LMD condition, assuming the condition 9582 * is TRUE. 9583 */ 9584 assign( lmd_07_val, 9585 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 9586 assign( lmd_8_val, 9587 binop( Iop_Or32, 9588 binop( Iop_Or32, 9589 binop( Iop_And32, 9590 mkexpr( lmexp_00_mask ), 9591 mkU32( 24 ) ), 9592 binop( Iop_And32, 9593 mkexpr( lmexp_01_mask ), 9594 mkU32( 26 ) ) ), 9595 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 9596 assign( lmd_9_val, 9597 binop( Iop_Or32, 9598 binop( Iop_Or32, 9599 binop( Iop_And32, 9600 mkexpr( lmexp_00_mask ), 9601 mkU32( 25 ) ), 9602 binop( Iop_And32, 9603 mkexpr( lmexp_01_mask ), 9604 mkU32( 27 ) ) ), 9605 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 9606 9607 /* generate the result from the possible LMD values */ 9608 return binop( Iop_Or32, 9609 binop( Iop_Or32, 9610 binop( Iop_And32, 9611 mkexpr( lmd_07_mask ), 9612 mkexpr( lmd_07_val ) ), 9613 binop( Iop_And32, 9614 mkexpr( lmd_8_mask ), 9615 mkexpr( lmd_8_val ) ) ), 9616 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 9617 } 9618 9619 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 9620 { 9621 /* Extract the exponent and the left most digit of the mantissa 9622 * from the G field bits [0:4]. 9623 */ 9624 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9625 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 9626 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 9627 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 9628 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 9629 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 9630 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 9631 9632 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9633 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9634 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9635 9636 /* The left most digit (LMD) encoding is as follows: 9637 * lmd 9638 * 0 - 7 (lmexp << 3) | lmd 9639 * 8 0b11000 (24 decimal) if lme=0b00; 9640 * 0b11010 (26 decimal) if lme=0b01; 9641 * 0b11100 (28 decimal) if lme=0b10 9642 * 9 0b11001 (25 decimal) if lme=0b00; 9643 * 0b11011 (27 decimal) if lme=0b01; 9644 * 0b11101 (29 decimal) if lme=0b10; 9645 */ 9646 9647 /* Generate the masks for each condition of LMD and exponent bits */ 9648 assign( lmd_07_mask, 9649 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 9650 gfield_0_4, 9651 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 9652 assign( lmd_8_00_mask, 9653 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9654 gfield_0_4, 9655 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 9656 assign( lmd_8_01_mask, 9657 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9658 gfield_0_4, 9659 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 9660 assign( lmd_8_10_mask, 9661 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9662 gfield_0_4, 9663 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 9664 assign( lmd_9_00_mask, 9665 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9666 gfield_0_4, 9667 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 9668 assign( lmd_9_01_mask, 9669 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9670 gfield_0_4, 9671 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 9672 assign( lmd_9_10_mask, 9673 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9674 gfield_0_4, 9675 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 9676 9677 /* Generate the values for each LMD condition, assuming the condition 9678 * is TRUE. 9679 */ 9680 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 9681 assign( lmd_8_val, mkU32( 0x8 ) ); 9682 assign( lmd_9_val, mkU32( 0x9 ) ); 9683 9684 assign( *lmd, 9685 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 9686 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 9687 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 9688 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 9689 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 9690 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 9691 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 9692 ) ) ); 9693 } 9694 9695 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 9696 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 9697 #define DIGIT3_SHR 12 9698 #define DIGIT4_SHR 16 9699 #define DIGIT5_SHR 20 9700 #define DIGIT6_SHR 24 9701 #define DIGIT7_SHR 28 9702 9703 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 9704 { 9705 /* 60-bit BCD string stored in two 32-bit values. Check that each, 9706 * digit is a valid BCD number, i.e. less then 9. 9707 */ 9708 IRTemp valid = newTemp( Ity_I32 ); 9709 9710 assign( valid, 9711 AND4( AND4 ( unop( Iop_1Sto32, 9712 binop( Iop_CmpLE32U, 9713 binop( Iop_And32, 9714 bcd_l, 9715 mkU32 ( 0xF ) ), 9716 mkU32( 0x9 ) ) ), 9717 unop( Iop_1Sto32, 9718 binop( Iop_CmpLE32U, 9719 binop( Iop_And32, 9720 binop( Iop_Shr32, 9721 bcd_l, 9722 mkU8 ( DIGIT1_SHR ) ), 9723 mkU32 ( 0xF ) ), 9724 mkU32( 0x9 ) ) ), 9725 unop( Iop_1Sto32, 9726 binop( Iop_CmpLE32U, 9727 binop( Iop_And32, 9728 binop( Iop_Shr32, 9729 bcd_l, 9730 mkU8 ( DIGIT2_SHR ) ), 9731 mkU32 ( 0xF ) ), 9732 mkU32( 0x9 ) ) ), 9733 unop( Iop_1Sto32, 9734 binop( Iop_CmpLE32U, 9735 binop( Iop_And32, 9736 binop( Iop_Shr32, 9737 bcd_l, 9738 mkU8 ( DIGIT3_SHR ) ), 9739 mkU32 ( 0xF ) ), 9740 mkU32( 0x9 ) ) ) ), 9741 AND4 ( unop( Iop_1Sto32, 9742 binop( Iop_CmpLE32U, 9743 binop( Iop_And32, 9744 binop( Iop_Shr32, 9745 bcd_l, 9746 mkU8 ( DIGIT4_SHR ) ), 9747 mkU32 ( 0xF ) ), 9748 mkU32( 0x9 ) ) ), 9749 unop( Iop_1Sto32, 9750 binop( Iop_CmpLE32U, 9751 binop( Iop_And32, 9752 binop( Iop_Shr32, 9753 bcd_l, 9754 mkU8 ( DIGIT5_SHR ) ), 9755 mkU32 ( 0xF ) ), 9756 mkU32( 0x9 ) ) ), 9757 unop( Iop_1Sto32, 9758 binop( Iop_CmpLE32U, 9759 binop( Iop_And32, 9760 binop( Iop_Shr32, 9761 bcd_l, 9762 mkU8 ( DIGIT6_SHR ) ), 9763 mkU32 ( 0xF ) ), 9764 mkU32( 0x9 ) ) ), 9765 unop( Iop_1Sto32, 9766 binop( Iop_CmpLE32U, 9767 binop( Iop_And32, 9768 binop( Iop_Shr32, 9769 bcd_l, 9770 mkU8 ( DIGIT7_SHR ) ), 9771 mkU32 ( 0xF ) ), 9772 mkU32( 0x9 ) ) ) ), 9773 AND4( unop( Iop_1Sto32, 9774 binop( Iop_CmpLE32U, 9775 binop( Iop_And32, 9776 bcd_u, 9777 mkU32 ( 0xF ) ), 9778 mkU32( 0x9 ) ) ), 9779 unop( Iop_1Sto32, 9780 binop( Iop_CmpLE32U, 9781 binop( Iop_And32, 9782 binop( Iop_Shr32, 9783 bcd_u, 9784 mkU8 ( DIGIT1_SHR ) ), 9785 mkU32 ( 0xF ) ), 9786 mkU32( 0x9 ) ) ), 9787 unop( Iop_1Sto32, 9788 binop( Iop_CmpLE32U, 9789 binop( Iop_And32, 9790 binop( Iop_Shr32, 9791 bcd_u, 9792 mkU8 ( DIGIT2_SHR ) ), 9793 mkU32 ( 0xF ) ), 9794 mkU32( 0x9 ) ) ), 9795 unop( Iop_1Sto32, 9796 binop( Iop_CmpLE32U, 9797 binop( Iop_And32, 9798 binop( Iop_Shr32, 9799 bcd_u, 9800 mkU8 ( DIGIT3_SHR ) ), 9801 mkU32 ( 0xF ) ), 9802 mkU32( 0x9 ) ) ) ), 9803 AND4( unop( Iop_1Sto32, 9804 binop( Iop_CmpLE32U, 9805 binop( Iop_And32, 9806 binop( Iop_Shr32, 9807 bcd_u, 9808 mkU8 ( DIGIT4_SHR ) ), 9809 mkU32 ( 0xF ) ), 9810 mkU32( 0x9 ) ) ), 9811 unop( Iop_1Sto32, 9812 binop( Iop_CmpLE32U, 9813 binop( Iop_And32, 9814 binop( Iop_Shr32, 9815 bcd_u, 9816 mkU8 ( DIGIT5_SHR ) ), 9817 mkU32 ( 0xF ) ), 9818 mkU32( 0x9 ) ) ), 9819 unop( Iop_1Sto32, 9820 binop( Iop_CmpLE32U, 9821 binop( Iop_And32, 9822 binop( Iop_Shr32, 9823 bcd_u, 9824 mkU8 ( DIGIT6_SHR ) ), 9825 mkU32 ( 0xF ) ), 9826 mkU32( 0x9 ) ) ), 9827 unop( Iop_1Sto32, 9828 binop( Iop_CmpLE32U, 9829 binop( Iop_And32, 9830 binop( Iop_Shr32, 9831 bcd_u, 9832 mkU8 ( DIGIT7_SHR ) ), 9833 mkU32 ( 0xF ) ), 9834 mkU32( 0x9 ) ) ) ) ) ); 9835 9836 return unop( Iop_Not32, mkexpr( valid ) ); 9837 } 9838 #undef DIGIT1_SHR 9839 #undef DIGIT2_SHR 9840 #undef DIGIT3_SHR 9841 #undef DIGIT4_SHR 9842 #undef DIGIT5_SHR 9843 #undef DIGIT6_SHR 9844 #undef DIGIT7_SHR 9845 9846 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 9847 { 9848 return binop( Iop_Or32, 9849 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 9850 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 9851 ); 9852 } 9853 9854 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 9855 { 9856 return binop( Iop_Or32, 9857 binop( Iop_Or32, 9858 unop( Iop_1Sto32, 9859 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 9860 unop( Iop_1Sto32, 9861 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 9862 binop( Iop_Or32, 9863 unop( Iop_1Sto32, 9864 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 9865 unop( Iop_1Sto32, 9866 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 9867 } 9868 9869 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 9870 IRExpr * neg_sign_mask ) 9871 { 9872 return binop( Iop_Or32, 9873 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 9874 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 9875 } 9876 9877 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 9878 IRExpr * pos_sign_mask, 9879 IRExpr * neg_sign_mask ) 9880 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 9881 { 9882 return binop( Iop_Or32, 9883 invalid_bcd_mask, 9884 unop( Iop_1Sto32, 9885 binop( Iop_CmpEQ32, 9886 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 9887 mkU32( 0x0 ) ) ) ); 9888 } 9889 9890 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 9891 IRTemp * top_12_l, IRTemp * mid_60_u, 9892 IRTemp * mid_60_l, IRTemp * low_60_u, 9893 IRTemp * low_60_l) 9894 { 9895 IRTemp tmplow60 = newTemp( Ity_I64 ); 9896 IRTemp tmpmid60 = newTemp( Ity_I64 ); 9897 IRTemp tmptop12 = newTemp( Ity_I64 ); 9898 IRTemp low_50 = newTemp( Ity_I64 ); 9899 IRTemp mid_50 = newTemp( Ity_I64 ); 9900 IRTemp top_10 = newTemp( Ity_I64 ); 9901 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 9902 9903 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 9904 9905 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 9906 assign( low_50, 9907 binop( Iop_32HLto64, 9908 binop( Iop_And32, 9909 unop( Iop_64HIto32, frBI64_lo ), 9910 mkU32( 0x3FFFF ) ), 9911 unop( Iop_64to32, frBI64_lo ) ) ); 9912 9913 /* Convert the 50 bit densely packed BCD string to a 60 bit 9914 * BCD string. 9915 */ 9916 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 9917 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 9918 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 9919 9920 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 9921 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 9922 */ 9923 assign( mid_50, 9924 binop( Iop_32HLto64, 9925 binop( Iop_Or32, 9926 binop( Iop_Shl32, 9927 binop( Iop_And32, 9928 unop( Iop_64HIto32, frBI64_hi ), 9929 mkU32( 0xF ) ), 9930 mkU8( 14 ) ), 9931 binop( Iop_Shr32, 9932 unop( Iop_64to32, frBI64_hi ), 9933 mkU8( 18 ) ) ), 9934 binop( Iop_Or32, 9935 binop( Iop_Shl32, 9936 unop( Iop_64to32, frBI64_hi ), 9937 mkU8( 14 ) ), 9938 binop( Iop_Shr32, 9939 unop( Iop_64HIto32, frBI64_lo ), 9940 mkU8( 18 ) ) ) ) ); 9941 9942 /* Convert the 50 bit densely packed BCD string to a 60 bit 9943 * BCD string. 9944 */ 9945 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 9946 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 9947 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 9948 9949 /* top_10[49:0] = frBI64_hi[45:36]) | */ 9950 assign( top_10, 9951 binop( Iop_32HLto64, 9952 mkU32( 0 ), 9953 binop( Iop_And32, 9954 binop( Iop_Shr32, 9955 unop( Iop_64HIto32, frBI64_hi ), 9956 mkU8( 4 ) ), 9957 mkU32( 0x3FF ) ) ) ); 9958 9959 /* Convert the 10 bit densely packed BCD string to a 12 bit 9960 * BCD string. 9961 */ 9962 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 9963 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 9964 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 9965 } 9966 9967 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 9968 IRTemp * final_cnt, IRTemp * final_flag, 9969 IRExpr * string ) 9970 { 9971 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 9972 int digits = MAX_DIGITS_IN_STRING; 9973 int i; 9974 9975 cnt[start-1] = newTemp( Ity_I8 ); 9976 flag[start-1] = newTemp( Ity_I8 ); 9977 assign( cnt[start-1], init_cnt); 9978 assign( flag[start-1], init_flag); 9979 9980 for ( i = start; i <= digits; i++) { 9981 cnt[i] = newTemp( Ity_I8 ); 9982 flag[i] = newTemp( Ity_I8 ); 9983 assign( cnt[i], 9984 binop( Iop_Add8, 9985 mkexpr( cnt[i-1] ), 9986 binop(Iop_And8, 9987 unop( Iop_1Uto8, 9988 binop(Iop_CmpEQ32, 9989 binop(Iop_And32, 9990 string, 9991 mkU32( 0xF << 9992 ( ( digits - i ) * 4) ) ), 9993 mkU32( 0 ) ) ), 9994 binop( Iop_Xor8, /* complement flag */ 9995 mkexpr( flag[i - 1] ), 9996 mkU8( 0xFF ) ) ) ) ); 9997 9998 /* set flag to 1 if digit was not a zero */ 9999 assign( flag[i], 10000 binop(Iop_Or8, 10001 unop( Iop_1Sto8, 10002 binop(Iop_CmpNE32, 10003 binop(Iop_And32, 10004 string, 10005 mkU32( 0xF << 10006 ( (digits - i) * 4) ) ), 10007 mkU32( 0 ) ) ), 10008 mkexpr( flag[i - 1] ) ) ); 10009 } 10010 10011 *final_cnt = cnt[digits]; 10012 *final_flag = flag[digits]; 10013 } 10014 10015 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 10016 IRExpr * low_32 ) 10017 { 10018 IRTemp num_lmd = newTemp( Ity_I8 ); 10019 IRTemp num_upper = newTemp( Ity_I8 ); 10020 IRTemp num_low = newTemp( Ity_I8 ); 10021 IRTemp lmd_flag = newTemp( Ity_I8 ); 10022 IRTemp upper_flag = newTemp( Ity_I8 ); 10023 IRTemp low_flag = newTemp( Ity_I8 ); 10024 10025 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10026 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10027 10028 Count_zeros( 2, 10029 mkexpr( num_lmd ), 10030 mkexpr( lmd_flag ), 10031 &num_upper, 10032 &upper_flag, 10033 upper_28 ); 10034 10035 Count_zeros( 1, 10036 mkexpr( num_upper ), 10037 mkexpr( upper_flag ), 10038 &num_low, 10039 &low_flag, 10040 low_32 ); 10041 10042 return mkexpr( num_low ); 10043 } 10044 10045 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 10046 IRExpr * mid_60_u, IRExpr * mid_60_l, 10047 IRExpr * low_60_u, IRExpr * low_60_l) 10048 { 10049 IRTemp num_lmd = newTemp( Ity_I8 ); 10050 IRTemp num_top = newTemp( Ity_I8 ); 10051 IRTemp num_mid_u = newTemp( Ity_I8 ); 10052 IRTemp num_mid_l = newTemp( Ity_I8 ); 10053 IRTemp num_low_u = newTemp( Ity_I8 ); 10054 IRTemp num_low_l = newTemp( Ity_I8 ); 10055 10056 IRTemp lmd_flag = newTemp( Ity_I8 ); 10057 IRTemp top_flag = newTemp( Ity_I8 ); 10058 IRTemp mid_u_flag = newTemp( Ity_I8 ); 10059 IRTemp mid_l_flag = newTemp( Ity_I8 ); 10060 IRTemp low_u_flag = newTemp( Ity_I8 ); 10061 IRTemp low_l_flag = newTemp( Ity_I8 ); 10062 10063 /* Check the LMD, digit 16, to see if it is zero. */ 10064 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10065 10066 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10067 10068 Count_zeros( 6, 10069 mkexpr( num_lmd ), 10070 mkexpr( lmd_flag ), 10071 &num_top, 10072 &top_flag, 10073 top_12_l ); 10074 10075 Count_zeros( 1, 10076 mkexpr( num_top ), 10077 mkexpr( top_flag ), 10078 &num_mid_u, 10079 &mid_u_flag, 10080 binop( Iop_Or32, 10081 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 10082 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 10083 10084 Count_zeros( 2, 10085 mkexpr( num_mid_u ), 10086 mkexpr( mid_u_flag ), 10087 &num_mid_l, 10088 &mid_l_flag, 10089 mid_60_l ); 10090 10091 Count_zeros( 1, 10092 mkexpr( num_mid_l ), 10093 mkexpr( mid_l_flag ), 10094 &num_low_u, 10095 &low_u_flag, 10096 binop( Iop_Or32, 10097 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 10098 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 10099 10100 Count_zeros( 2, 10101 mkexpr( num_low_u ), 10102 mkexpr( low_u_flag ), 10103 &num_low_l, 10104 &low_l_flag, 10105 low_60_l ); 10106 10107 return mkexpr( num_low_l ); 10108 } 10109 10110 static IRExpr * Check_unordered(IRExpr * val) 10111 { 10112 IRTemp gfield0to5 = newTemp( Ity_I32 ); 10113 10114 /* Extract G[0:4] */ 10115 assign( gfield0to5, 10116 binop( Iop_And32, 10117 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 10118 mkU32( 0x1F ) ) ); 10119 10120 /* Check for unordered, return all 1'x if true */ 10121 return binop( Iop_Or32, /* QNaN check */ 10122 unop( Iop_1Sto32, 10123 binop( Iop_CmpEQ32, 10124 mkexpr( gfield0to5 ), 10125 mkU32( 0x1E ) ) ), 10126 unop( Iop_1Sto32, /* SNaN check */ 10127 binop( Iop_CmpEQ32, 10128 mkexpr( gfield0to5 ), 10129 mkU32( 0x1F ) ) ) ); 10130 } 10131 10132 #undef AND 10133 #undef AND4 10134 #undef OR 10135 #undef OR3 10136 #undef OR4 10137 #undef NOT 10138 #undef SHR 10139 #undef SHL 10140 #undef BITS5 10141 10142 /*------------------------------------------------------------*/ 10143 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 10144 /*------------------------------------------------------------*/ 10145 10146 /* DFP Arithmetic instructions */ 10147 static Bool dis_dfp_arith(UInt theInstr) 10148 { 10149 UInt opc2 = ifieldOPClo10( theInstr ); 10150 UChar frS_addr = ifieldRegDS( theInstr ); 10151 UChar frA_addr = ifieldRegA( theInstr ); 10152 UChar frB_addr = ifieldRegB( theInstr ); 10153 UChar flag_rC = ifieldBIT0( theInstr ); 10154 10155 IRTemp frA = newTemp( Ity_D64 ); 10156 IRTemp frB = newTemp( Ity_D64 ); 10157 IRTemp frS = newTemp( Ity_D64 ); 10158 IRExpr* round = get_IR_roundingmode_DFP(); 10159 10160 /* By default, if flag_RC is set, we will clear cr1 after the 10161 * operation. In reality we should set cr1 to indicate the 10162 * exception status of the operation, but since we're not 10163 * simulating exceptions, the exception status will appear to be 10164 * zero. Hence cr1 should be cleared if this is a . form insn. 10165 */ 10166 Bool clear_CR1 = True; 10167 10168 assign( frA, getDReg( frA_addr ) ); 10169 assign( frB, getDReg( frB_addr ) ); 10170 10171 switch (opc2) { 10172 case 0x2: // dadd 10173 DIP( "dadd%s fr%u,fr%u,fr%u\n", 10174 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10175 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10176 break; 10177 case 0x202: // dsub 10178 DIP( "dsub%s fr%u,fr%u,fr%u\n", 10179 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10180 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10181 break; 10182 case 0x22: // dmul 10183 DIP( "dmul%s fr%u,fr%u,fr%u\n", 10184 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10185 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10186 break; 10187 case 0x222: // ddiv 10188 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 10189 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10190 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10191 break; 10192 } 10193 10194 putDReg( frS_addr, mkexpr( frS ) ); 10195 10196 if (flag_rC && clear_CR1) { 10197 putCR321( 1, mkU8( 0 ) ); 10198 putCR0( 1, mkU8( 0 ) ); 10199 } 10200 10201 return True; 10202 } 10203 10204 /* Quad DFP Arithmetic instructions */ 10205 static Bool dis_dfp_arithq(UInt theInstr) 10206 { 10207 UInt opc2 = ifieldOPClo10( theInstr ); 10208 UChar frS_addr = ifieldRegDS( theInstr ); 10209 UChar frA_addr = ifieldRegA( theInstr ); 10210 UChar frB_addr = ifieldRegB( theInstr ); 10211 UChar flag_rC = ifieldBIT0( theInstr ); 10212 10213 IRTemp frA = newTemp( Ity_D128 ); 10214 IRTemp frB = newTemp( Ity_D128 ); 10215 IRTemp frS = newTemp( Ity_D128 ); 10216 IRExpr* round = get_IR_roundingmode_DFP(); 10217 10218 /* By default, if flag_RC is set, we will clear cr1 after the 10219 * operation. In reality we should set cr1 to indicate the 10220 * exception status of the operation, but since we're not 10221 * simulating exceptions, the exception status will appear to be 10222 * zero. Hence cr1 should be cleared if this is a . form insn. 10223 */ 10224 Bool clear_CR1 = True; 10225 10226 assign( frA, getDReg_pair( frA_addr ) ); 10227 assign( frB, getDReg_pair( frB_addr ) ); 10228 10229 switch (opc2) { 10230 case 0x2: // daddq 10231 DIP( "daddq%s fr%u,fr%u,fr%u\n", 10232 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10233 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10234 break; 10235 case 0x202: // dsubq 10236 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 10237 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10238 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10239 break; 10240 case 0x22: // dmulq 10241 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 10242 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10243 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10244 break; 10245 case 0x222: // ddivq 10246 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 10247 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10248 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10249 break; 10250 } 10251 10252 putDReg_pair( frS_addr, mkexpr( frS ) ); 10253 10254 if (flag_rC && clear_CR1) { 10255 putCR321( 1, mkU8( 0 ) ); 10256 putCR0( 1, mkU8( 0 ) ); 10257 } 10258 10259 return True; 10260 } 10261 10262 /* DFP 64-bit logical shift instructions */ 10263 static Bool dis_dfp_shift(UInt theInstr) { 10264 UInt opc2 = ifieldOPClo9( theInstr ); 10265 UChar frS_addr = ifieldRegDS( theInstr ); 10266 UChar frA_addr = ifieldRegA( theInstr ); 10267 UChar shift_val = IFIELD(theInstr, 10, 6); 10268 UChar flag_rC = ifieldBIT0( theInstr ); 10269 10270 IRTemp frA = newTemp( Ity_D64 ); 10271 IRTemp frS = newTemp( Ity_D64 ); 10272 Bool clear_CR1 = True; 10273 10274 assign( frA, getDReg( frA_addr ) ); 10275 10276 switch (opc2) { 10277 case 0x42: // dscli 10278 DIP( "dscli%s fr%u,fr%u,%u\n", 10279 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10280 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10281 break; 10282 case 0x62: // dscri 10283 DIP( "dscri%s fr%u,fr%u,%u\n", 10284 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10285 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10286 break; 10287 } 10288 10289 putDReg( frS_addr, mkexpr( frS ) ); 10290 10291 if (flag_rC && clear_CR1) { 10292 putCR321( 1, mkU8( 0 ) ); 10293 putCR0( 1, mkU8( 0 ) ); 10294 } 10295 10296 return True; 10297 } 10298 10299 /* Quad DFP logical shift instructions */ 10300 static Bool dis_dfp_shiftq(UInt theInstr) { 10301 UInt opc2 = ifieldOPClo9( theInstr ); 10302 UChar frS_addr = ifieldRegDS( theInstr ); 10303 UChar frA_addr = ifieldRegA( theInstr ); 10304 UChar shift_val = IFIELD(theInstr, 10, 6); 10305 UChar flag_rC = ifieldBIT0( theInstr ); 10306 10307 IRTemp frA = newTemp( Ity_D128 ); 10308 IRTemp frS = newTemp( Ity_D128 ); 10309 Bool clear_CR1 = True; 10310 10311 assign( frA, getDReg_pair( frA_addr ) ); 10312 10313 switch (opc2) { 10314 case 0x42: // dscliq 10315 DIP( "dscliq%s fr%u,fr%u,%u\n", 10316 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10317 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10318 break; 10319 case 0x62: // dscriq 10320 DIP( "dscriq%s fr%u,fr%u,%u\n", 10321 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10322 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10323 break; 10324 } 10325 10326 putDReg_pair( frS_addr, mkexpr( frS ) ); 10327 10328 if (flag_rC && clear_CR1) { 10329 putCR321( 1, mkU8( 0 ) ); 10330 putCR0( 1, mkU8( 0 ) ); 10331 } 10332 10333 return True; 10334 } 10335 10336 /* DFP 64-bit format conversion instructions */ 10337 static Bool dis_dfp_fmt_conv(UInt theInstr) { 10338 UInt opc2 = ifieldOPClo10( theInstr ); 10339 UChar frS_addr = ifieldRegDS( theInstr ); 10340 UChar frB_addr = ifieldRegB( theInstr ); 10341 IRExpr* round = get_IR_roundingmode_DFP(); 10342 UChar flag_rC = ifieldBIT0( theInstr ); 10343 IRTemp frB; 10344 IRTemp frS; 10345 Bool clear_CR1 = True; 10346 10347 switch (opc2) { 10348 case 0x102: //dctdp 10349 DIP( "dctdp%s fr%u,fr%u\n", 10350 flag_rC ? ".":"", frS_addr, frB_addr ); 10351 10352 frB = newTemp( Ity_D32 ); 10353 frS = newTemp( Ity_D64 ); 10354 assign( frB, getDReg32( frB_addr ) ); 10355 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 10356 putDReg( frS_addr, mkexpr( frS ) ); 10357 break; 10358 case 0x302: // drsp 10359 DIP( "drsp%s fr%u,fr%u\n", 10360 flag_rC ? ".":"", frS_addr, frB_addr ); 10361 frB = newTemp( Ity_D64 ); 10362 frS = newTemp( Ity_D32 ); 10363 assign( frB, getDReg( frB_addr ) ); 10364 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 10365 putDReg32( frS_addr, mkexpr( frS ) ); 10366 break; 10367 case 0x122: // dctfix 10368 { 10369 IRTemp tmp = newTemp( Ity_I64 ); 10370 10371 DIP( "dctfix%s fr%u,fr%u\n", 10372 flag_rC ? ".":"", frS_addr, frB_addr ); 10373 frB = newTemp( Ity_D64 ); 10374 frS = newTemp( Ity_D64 ); 10375 assign( frB, getDReg( frB_addr ) ); 10376 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 10377 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10378 putDReg( frS_addr, mkexpr( frS ) ); 10379 } 10380 break; 10381 case 0x322: // dcffix 10382 DIP( "dcffix%s fr%u,fr%u\n", 10383 flag_rC ? ".":"", frS_addr, frB_addr ); 10384 frB = newTemp( Ity_D64 ); 10385 frS = newTemp( Ity_D64 ); 10386 assign( frB, getDReg( frB_addr ) ); 10387 assign( frS, binop( Iop_I64StoD64, 10388 round, 10389 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 10390 putDReg( frS_addr, mkexpr( frS ) ); 10391 break; 10392 } 10393 10394 if (flag_rC && clear_CR1) { 10395 putCR321( 1, mkU8( 0 ) ); 10396 putCR0( 1, mkU8( 0 ) ); 10397 } 10398 10399 return True; 10400 } 10401 10402 /* Quad DFP format conversion instructions */ 10403 static Bool dis_dfp_fmt_convq(UInt theInstr) { 10404 UInt opc2 = ifieldOPClo10( theInstr ); 10405 UChar frS_addr = ifieldRegDS( theInstr ); 10406 UChar frB_addr = ifieldRegB( theInstr ); 10407 IRExpr* round = get_IR_roundingmode_DFP(); 10408 IRTemp frB64 = newTemp( Ity_D64 ); 10409 IRTemp frB128 = newTemp( Ity_D128 ); 10410 IRTemp frS64 = newTemp( Ity_D64 ); 10411 IRTemp frS128 = newTemp( Ity_D128 ); 10412 UChar flag_rC = ifieldBIT0( theInstr ); 10413 Bool clear_CR1 = True; 10414 10415 switch (opc2) { 10416 case 0x102: // dctqpq 10417 DIP( "dctqpq%s fr%u,fr%u\n", 10418 flag_rC ? ".":"", frS_addr, frB_addr ); 10419 assign( frB64, getDReg( frB_addr ) ); 10420 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 10421 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10422 break; 10423 case 0x122: // dctfixq 10424 { 10425 IRTemp tmp = newTemp( Ity_I64 ); 10426 10427 DIP( "dctfixq%s fr%u,fr%u\n", 10428 flag_rC ? ".":"", frS_addr, frB_addr ); 10429 assign( frB128, getDReg_pair( frB_addr ) ); 10430 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 10431 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10432 putDReg( frS_addr, mkexpr( frS64 ) ); 10433 } 10434 break; 10435 case 0x302: //drdpq 10436 DIP( "drdpq%s fr%u,fr%u\n", 10437 flag_rC ? ".":"", frS_addr, frB_addr ); 10438 assign( frB128, getDReg_pair( frB_addr ) ); 10439 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 10440 putDReg( frS_addr, mkexpr( frS64 ) ); 10441 break; 10442 case 0x322: // dcffixq 10443 { 10444 /* Have to introduce an IOP for this instruction so it will work 10445 * on POWER 6 because emulating the instruction requires a POWER 7 10446 * DFP instruction in the emulation code. 10447 */ 10448 DIP( "dcffixq%s fr%u,fr%u\n", 10449 flag_rC ? ".":"", frS_addr, frB_addr ); 10450 assign( frB64, getDReg( frB_addr ) ); 10451 assign( frS128, unop( Iop_I64StoD128, 10452 unop( Iop_ReinterpD64asI64, 10453 mkexpr( frB64 ) ) ) ); 10454 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10455 break; 10456 } 10457 } 10458 10459 if (flag_rC && clear_CR1) { 10460 putCR321( 1, mkU8( 0 ) ); 10461 putCR0( 1, mkU8( 0 ) ); 10462 } 10463 10464 return True; 10465 } 10466 10467 static Bool dis_dfp_round( UInt theInstr ) { 10468 UChar frS_addr = ifieldRegDS(theInstr); 10469 UChar R = IFIELD(theInstr, 16, 1); 10470 UChar RMC = IFIELD(theInstr, 9, 2); 10471 UChar frB_addr = ifieldRegB( theInstr ); 10472 UChar flag_rC = ifieldBIT0( theInstr ); 10473 IRTemp frB = newTemp( Ity_D64 ); 10474 IRTemp frS = newTemp( Ity_D64 ); 10475 UInt opc2 = ifieldOPClo8( theInstr ); 10476 Bool clear_CR1 = True; 10477 10478 switch (opc2) { 10479 /* drintn, is the same as drintx. The only difference is this 10480 * instruction does not generate an exception for an inexact operation. 10481 * Currently not supporting inexact exceptions. 10482 */ 10483 case 0x63: // drintx 10484 case 0xE3: // drintn 10485 DIP( "drintx/drintn%s fr%u,fr%u\n", 10486 flag_rC ? ".":"", frS_addr, frB_addr ); 10487 10488 /* NOTE, this instruction takes a DFP value and rounds to the 10489 * neares floating point integer value, i.e. fractional part 10490 * is zero. The result is a floating point number. 10491 */ 10492 /* pass the value of R and RMC in the same field */ 10493 assign( frB, getDReg( frB_addr ) ); 10494 assign( frS, binop( Iop_RoundD64toInt, 10495 mkU32( ( R << 3 ) | RMC ), 10496 mkexpr( frB ) ) ); 10497 putDReg( frS_addr, mkexpr( frS ) ); 10498 break; 10499 default: 10500 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 10501 return False; 10502 } 10503 10504 if (flag_rC && clear_CR1) { 10505 putCR321( 1, mkU8( 0 ) ); 10506 putCR0( 1, mkU8( 0 ) ); 10507 } 10508 10509 return True; 10510 } 10511 10512 static Bool dis_dfp_roundq(UInt theInstr) { 10513 UChar frS_addr = ifieldRegDS( theInstr ); 10514 UChar frB_addr = ifieldRegB( theInstr ); 10515 UChar R = IFIELD(theInstr, 16, 1); 10516 UChar RMC = IFIELD(theInstr, 9, 2); 10517 UChar flag_rC = ifieldBIT0( theInstr ); 10518 IRTemp frB = newTemp( Ity_D128 ); 10519 IRTemp frS = newTemp( Ity_D128 ); 10520 Bool clear_CR1 = True; 10521 UInt opc2 = ifieldOPClo8( theInstr ); 10522 10523 switch (opc2) { 10524 /* drintnq, is the same as drintxq. The only difference is this 10525 * instruction does not generate an exception for an inexact operation. 10526 * Currently not supporting inexact exceptions. 10527 */ 10528 case 0x63: // drintxq 10529 case 0xE3: // drintnq 10530 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 10531 flag_rC ? ".":"", frS_addr, frB_addr ); 10532 10533 /* pass the value of R and RMC in the same field */ 10534 assign( frB, getDReg_pair( frB_addr ) ); 10535 assign( frS, binop( Iop_RoundD128toInt, 10536 mkU32( ( R << 3 ) | RMC ), 10537 mkexpr( frB ) ) ); 10538 putDReg_pair( frS_addr, mkexpr( frS ) ); 10539 break; 10540 default: 10541 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 10542 return False; 10543 } 10544 10545 if (flag_rC && clear_CR1) { 10546 putCR321( 1, mkU8( 0 ) ); 10547 putCR0( 1, mkU8( 0 ) ); 10548 } 10549 10550 return True; 10551 } 10552 10553 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 10554 UInt opc2 = ifieldOPClo8( theInstr ); 10555 UChar frS_addr = ifieldRegDS( theInstr ); 10556 UChar frA_addr = ifieldRegA( theInstr ); 10557 UChar frB_addr = ifieldRegB( theInstr ); 10558 UChar flag_rC = ifieldBIT0( theInstr ); 10559 UInt TE_value = IFIELD(theInstr, 16, 4); 10560 UInt TE_sign = IFIELD(theInstr, 20, 1); 10561 UInt RMC = IFIELD(theInstr, 9, 2); 10562 IRTemp frA = newTemp( Ity_D64 ); 10563 IRTemp frB = newTemp( Ity_D64 ); 10564 IRTemp frS = newTemp( Ity_D64 ); 10565 Bool clear_CR1 = True; 10566 10567 assign( frB, getDReg( frB_addr ) ); 10568 10569 switch (opc2) { 10570 case 0x43: // dquai 10571 DIP( "dquai%s fr%u,fr%u,fr%u\n", 10572 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10573 IRTemp TE_I64 = newTemp( Ity_I64 ); 10574 10575 /* Generate a reference DFP value frA with the desired exponent 10576 * given by TE using significand from frB. Need to add the bias 10577 * 398 to TE. TE is stored as a 2's complement number. 10578 */ 10579 if (TE_sign == 1) { 10580 /* Take 2's complement of the 5-bit value and subtract from bias. 10581 * Bias is adjusted for the +1 required when taking 2's complement. 10582 */ 10583 assign( TE_I64, 10584 unop( Iop_32Uto64, 10585 binop( Iop_Sub32, mkU32( 397 ), 10586 binop( Iop_And32, mkU32( 0xF ), 10587 unop( Iop_Not32, mkU32( TE_value ) ) 10588 ) ) ) ); 10589 10590 } else { 10591 assign( TE_I64, 10592 unop( Iop_32Uto64, 10593 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 10594 ) ); 10595 } 10596 10597 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 10598 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 10599 10600 assign( frS, triop( Iop_QuantizeD64, 10601 mkU32( RMC ), 10602 mkexpr( frA ), 10603 mkexpr( frB ) ) ); 10604 break; 10605 10606 case 0x3: // dqua 10607 DIP( "dqua%s fr%u,fr%u,fr%u\n", 10608 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10609 assign( frA, getDReg( frA_addr ) ); 10610 assign( frS, triop( Iop_QuantizeD64, 10611 mkU32( RMC ), 10612 mkexpr( frA ), 10613 mkexpr( frB ) ) ); 10614 break; 10615 case 0x23: // drrnd 10616 { 10617 IRTemp tmp = newTemp( Ity_I8 ); 10618 10619 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 10620 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10621 assign( frA, getDReg( frA_addr ) ); 10622 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 10623 assign( tmp, unop( Iop_32to8, 10624 unop( Iop_64to32, 10625 unop( Iop_ReinterpD64asI64, 10626 mkexpr( frA ) ) ) ) ); 10627 assign( frS, triop( Iop_SignificanceRoundD64, 10628 mkU32( RMC ), 10629 mkexpr( tmp ), 10630 mkexpr( frB ) ) ); 10631 } 10632 break; 10633 default: 10634 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 10635 return False; 10636 } 10637 putDReg( frS_addr, mkexpr( frS ) ); 10638 10639 if (flag_rC && clear_CR1) { 10640 putCR321( 1, mkU8( 0 ) ); 10641 putCR0( 1, mkU8( 0 ) ); 10642 } 10643 10644 return True; 10645 } 10646 10647 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 10648 UInt opc2 = ifieldOPClo8( theInstr ); 10649 UChar frS_addr = ifieldRegDS( theInstr ); 10650 UChar frA_addr = ifieldRegA( theInstr ); 10651 UChar frB_addr = ifieldRegB( theInstr ); 10652 UChar flag_rC = ifieldBIT0( theInstr ); 10653 UInt TE_value = IFIELD(theInstr, 16, 4); 10654 UInt TE_sign = IFIELD(theInstr, 20, 1); 10655 UInt RMC = IFIELD(theInstr, 9, 2); 10656 IRTemp frA = newTemp( Ity_D128 ); 10657 IRTemp frB = newTemp( Ity_D128 ); 10658 IRTemp frS = newTemp( Ity_D128 ); 10659 Bool clear_CR1 = True; 10660 10661 assign( frB, getDReg_pair( frB_addr ) ); 10662 10663 switch (opc2) { 10664 case 0x43: // dquaiq 10665 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10666 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10667 IRTemp TE_I64 = newTemp( Ity_I64 ); 10668 10669 /* Generate a reference DFP value frA with the desired exponent 10670 * given by TE using significand of 1. Need to add the bias 10671 * 6176 to TE. 10672 */ 10673 if (TE_sign == 1) { 10674 /* Take 2's complement of the 5-bit value and subtract from bias. 10675 * Bias adjusted for the +1 required when taking 2's complement. 10676 */ 10677 assign( TE_I64, 10678 unop( Iop_32Uto64, 10679 binop( Iop_Sub32, mkU32( 6175 ), 10680 binop( Iop_And32, mkU32( 0xF ), 10681 unop( Iop_Not32, mkU32( TE_value ) ) 10682 ) ) ) ); 10683 10684 } else { 10685 assign( TE_I64, 10686 unop( Iop_32Uto64, 10687 binop( Iop_Add32, 10688 mkU32( 6176 ), 10689 mkU32( TE_value ) ) ) ); 10690 } 10691 10692 assign( frA, 10693 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 10694 unop( Iop_D64toD128, 10695 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 10696 assign( frS, triop( Iop_QuantizeD128, 10697 mkU32( RMC ), 10698 mkexpr( frA ), 10699 mkexpr( frB ) ) ); 10700 break; 10701 case 0x3: // dquaq 10702 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10703 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10704 assign( frA, getDReg_pair( frA_addr ) ); 10705 assign( frS, triop( Iop_QuantizeD128, 10706 mkU32( RMC ), 10707 mkexpr( frA ), 10708 mkexpr( frB ) ) ); 10709 break; 10710 case 0x23: // drrndq 10711 { 10712 IRTemp tmp = newTemp( Ity_I8 ); 10713 10714 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 10715 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10716 assign( frA, getDReg_pair( frA_addr ) ); 10717 assign( tmp, unop( Iop_32to8, 10718 unop( Iop_64to32, 10719 unop( Iop_ReinterpD64asI64, 10720 unop( Iop_D128HItoD64, 10721 mkexpr( frA ) ) ) ) ) ); 10722 assign( frS, triop( Iop_SignificanceRoundD128, 10723 mkU32( RMC ), 10724 mkexpr( tmp ), 10725 mkexpr( frB ) ) ); 10726 } 10727 break; 10728 default: 10729 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 10730 return False; 10731 } 10732 putDReg_pair( frS_addr, mkexpr( frS ) ); 10733 10734 if (flag_rC && clear_CR1) { 10735 putCR321( 1, mkU8( 0 ) ); 10736 putCR0( 1, mkU8( 0 ) ); 10737 } 10738 10739 return True; 10740 } 10741 10742 static Bool dis_dfp_extract_insert(UInt theInstr) { 10743 UInt opc2 = ifieldOPClo10( theInstr ); 10744 UChar frS_addr = ifieldRegDS( theInstr ); 10745 UChar frA_addr = ifieldRegA( theInstr ); 10746 UChar frB_addr = ifieldRegB( theInstr ); 10747 UChar flag_rC = ifieldBIT0( theInstr ); 10748 Bool clear_CR1 = True; 10749 10750 IRTemp frA = newTemp( Ity_D64 ); 10751 IRTemp frB = newTemp( Ity_D64 ); 10752 IRTemp frS = newTemp( Ity_D64 ); 10753 IRTemp tmp = newTemp( Ity_I64 ); 10754 10755 assign( frA, getDReg( frA_addr ) ); 10756 assign( frB, getDReg( frB_addr ) ); 10757 10758 switch (opc2) { 10759 case 0x162: // dxex 10760 DIP( "dxex%s fr%u,fr%u,fr%u\n", 10761 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10762 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 10763 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10764 break; 10765 case 0x362: // diex 10766 DIP( "diex%s fr%u,fr%u,fr%u\n", 10767 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10768 assign( frS, binop( Iop_InsertExpD64, 10769 unop( Iop_ReinterpD64asI64, 10770 mkexpr( frA ) ), 10771 mkexpr( frB ) ) ); 10772 break; 10773 default: 10774 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 10775 return False; 10776 } 10777 10778 putDReg( frS_addr, mkexpr( frS ) ); 10779 10780 if (flag_rC && clear_CR1) { 10781 putCR321( 1, mkU8( 0 ) ); 10782 putCR0( 1, mkU8( 0 ) ); 10783 } 10784 10785 return True; 10786 } 10787 10788 static Bool dis_dfp_extract_insertq(UInt theInstr) { 10789 UInt opc2 = ifieldOPClo10( theInstr ); 10790 UChar frS_addr = ifieldRegDS( theInstr ); 10791 UChar frA_addr = ifieldRegA( theInstr ); 10792 UChar frB_addr = ifieldRegB( theInstr ); 10793 UChar flag_rC = ifieldBIT0( theInstr ); 10794 10795 IRTemp frA = newTemp( Ity_D64 ); 10796 IRTemp frB = newTemp( Ity_D128 ); 10797 IRTemp frS64 = newTemp( Ity_D64 ); 10798 IRTemp frS = newTemp( Ity_D128 ); 10799 IRTemp tmp = newTemp( Ity_I64 ); 10800 Bool clear_CR1 = True; 10801 10802 assign( frB, getDReg_pair( frB_addr ) ); 10803 10804 switch (opc2) { 10805 case 0x162: // dxexq 10806 DIP( "dxexq%s fr%u,fr%u\n", 10807 flag_rC ? ".":"", frS_addr, frB_addr ); 10808 /* Instruction actually returns a 64-bit result. So as to be 10809 * consistent and not have to add a new struct, the emulation returns 10810 * the 64-bit result in the upper and lower register. 10811 */ 10812 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 10813 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10814 putDReg( frS_addr, mkexpr( frS64 ) ); 10815 break; 10816 case 0x362: // diexq 10817 DIP( "diexq%s fr%u,fr%u,fr%u\n", 10818 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10819 assign( frA, getDReg( frA_addr ) ); 10820 assign( frS, binop( Iop_InsertExpD128, 10821 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 10822 mkexpr( frB ) ) ); 10823 putDReg_pair( frS_addr, mkexpr( frS ) ); 10824 break; 10825 default: 10826 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 10827 return False; 10828 } 10829 10830 if (flag_rC && clear_CR1) { 10831 putCR321( 1, mkU8( 0 ) ); 10832 putCR0( 1, mkU8( 0 ) ); 10833 } 10834 10835 return True; 10836 } 10837 10838 /* DFP 64-bit comparison instructions */ 10839 static Bool dis_dfp_compare(UInt theInstr) { 10840 /* X-Form */ 10841 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10842 UChar frA_addr = ifieldRegA( theInstr ); 10843 UChar frB_addr = ifieldRegB( theInstr ); 10844 UInt opc1 = ifieldOPC( theInstr ); 10845 IRTemp frA; 10846 IRTemp frB; 10847 10848 IRTemp ccIR = newTemp( Ity_I32 ); 10849 IRTemp ccPPC32 = newTemp( Ity_I32 ); 10850 10851 10852 /* Note: Differences between dcmpu and dcmpo are only in exception 10853 flag settings, which aren't supported anyway. */ 10854 switch (opc1) { 10855 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 10856 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10857 frA = newTemp( Ity_D64 ); 10858 frB = newTemp( Ity_D64 ); 10859 10860 assign( frA, getDReg( frA_addr ) ); 10861 assign( frB, getDReg( frB_addr ) ); 10862 10863 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 10864 break; 10865 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 10866 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10867 frA = newTemp( Ity_D128 ); 10868 frB = newTemp( Ity_D128 ); 10869 10870 assign( frA, getDReg_pair( frA_addr ) ); 10871 assign( frB, getDReg_pair( frB_addr ) ); 10872 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 10873 break; 10874 default: 10875 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 10876 return False; 10877 } 10878 10879 /* Map compare result from IR to PPC32 */ 10880 /* 10881 FP cmp result | PPC | IR 10882 -------------------------- 10883 UN | 0x1 | 0x45 10884 EQ | 0x2 | 0x40 10885 GT | 0x4 | 0x00 10886 LT | 0x8 | 0x01 10887 */ 10888 10889 assign( ccPPC32, 10890 binop( Iop_Shl32, 10891 mkU32( 1 ), 10892 unop( Iop_32to8, 10893 binop( Iop_Or32, 10894 binop( Iop_And32, 10895 unop( Iop_Not32, 10896 binop( Iop_Shr32, 10897 mkexpr( ccIR ), 10898 mkU8( 5 ) ) ), 10899 mkU32( 2 ) ), 10900 binop( Iop_And32, 10901 binop( Iop_Xor32, 10902 mkexpr( ccIR ), 10903 binop( Iop_Shr32, 10904 mkexpr( ccIR ), 10905 mkU8( 6 ) ) ), 10906 mkU32( 1 ) ) ) ) ) ); 10907 10908 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 10909 return True; 10910 } 10911 10912 /* Test class/group/exponent/significance instructions. */ 10913 static Bool dis_dfp_exponent_test ( UInt theInstr ) 10914 { 10915 UChar frA_addr = ifieldRegA( theInstr ); 10916 UChar frB_addr = ifieldRegB( theInstr ); 10917 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10918 IRTemp frA = newTemp( Ity_D64 ); 10919 IRTemp frB = newTemp( Ity_D64 ); 10920 IRTemp frA128 = newTemp( Ity_D128 ); 10921 IRTemp frB128 = newTemp( Ity_D128 ); 10922 UInt opc1 = ifieldOPC( theInstr ); 10923 IRTemp gfield_A = newTemp( Ity_I32 ); 10924 IRTemp gfield_B = newTemp( Ity_I32 ); 10925 IRTemp gfield_mask = newTemp( Ity_I32 ); 10926 IRTemp exponent_A = newTemp( Ity_I32 ); 10927 IRTemp exponent_B = newTemp( Ity_I32 ); 10928 IRTemp A_NaN_true = newTemp( Ity_I32 ); 10929 IRTemp B_NaN_true = newTemp( Ity_I32 ); 10930 IRTemp A_inf_true = newTemp( Ity_I32 ); 10931 IRTemp B_inf_true = newTemp( Ity_I32 ); 10932 IRTemp A_equals_B = newTemp( Ity_I32 ); 10933 IRTemp finite_number = newTemp( Ity_I32 ); 10934 IRTemp cc0 = newTemp( Ity_I32 ); 10935 IRTemp cc1 = newTemp( Ity_I32 ); 10936 IRTemp cc2 = newTemp( Ity_I32 ); 10937 IRTemp cc3 = newTemp( Ity_I32 ); 10938 10939 /* The dtstex and dtstexg instructions only differ in the size of the 10940 * exponent field. The following switch statement takes care of the size 10941 * specific setup. Once the value of the exponents, the G-field shift 10942 * and mask is setup the remaining code is identical. 10943 */ 10944 switch (opc1) { 10945 case 0x3b: // dtstex Extended instruction setup 10946 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10947 assign( frA, getDReg( frA_addr ) ); 10948 assign( frB, getDReg( frB_addr ) ); 10949 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10950 assign(exponent_A, unop( Iop_64to32, 10951 unop( Iop_ExtractExpD64, 10952 mkexpr( frA ) ) ) ); 10953 assign(exponent_B, unop( Iop_64to32, 10954 unop( Iop_ExtractExpD64, 10955 mkexpr( frB ) ) ) ); 10956 break; 10957 10958 case 0x3F: // dtstexq Quad instruction setup 10959 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10960 assign( frA128, getDReg_pair( frA_addr ) ); 10961 assign( frB128, getDReg_pair( frB_addr ) ); 10962 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 10963 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 10964 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10965 assign( exponent_A, unop( Iop_64to32, 10966 unop( Iop_ExtractExpD128, 10967 mkexpr( frA128 ) ) ) ); 10968 assign( exponent_B, unop( Iop_64to32, 10969 unop( Iop_ExtractExpD128, 10970 mkexpr( frB128 ) ) ) ); 10971 break; 10972 default: 10973 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 10974 return False; 10975 } 10976 10977 /* Extract the Gfield */ 10978 assign( gfield_A, binop( Iop_And32, 10979 mkexpr( gfield_mask ), 10980 unop( Iop_64HIto32, 10981 unop( Iop_ReinterpD64asI64, 10982 mkexpr(frA) ) ) ) ); 10983 10984 assign( gfield_B, binop( Iop_And32, 10985 mkexpr( gfield_mask ), 10986 unop( Iop_64HIto32, 10987 unop( Iop_ReinterpD64asI64, 10988 mkexpr(frB) ) ) ) ); 10989 10990 /* check for NAN */ 10991 assign( A_NaN_true, binop(Iop_Or32, 10992 unop( Iop_1Sto32, 10993 binop( Iop_CmpEQ32, 10994 mkexpr( gfield_A ), 10995 mkU32( 0x7C000000 ) ) ), 10996 unop( Iop_1Sto32, 10997 binop( Iop_CmpEQ32, 10998 mkexpr( gfield_A ), 10999 mkU32( 0x7E000000 ) ) 11000 ) ) ); 11001 assign( B_NaN_true, binop(Iop_Or32, 11002 unop( Iop_1Sto32, 11003 binop( Iop_CmpEQ32, 11004 mkexpr( gfield_B ), 11005 mkU32( 0x7C000000 ) ) ), 11006 unop( Iop_1Sto32, 11007 binop( Iop_CmpEQ32, 11008 mkexpr( gfield_B ), 11009 mkU32( 0x7E000000 ) ) 11010 ) ) ); 11011 11012 /* check for infinity */ 11013 assign( A_inf_true, 11014 unop( Iop_1Sto32, 11015 binop( Iop_CmpEQ32, 11016 mkexpr( gfield_A ), 11017 mkU32( 0x78000000 ) ) ) ); 11018 11019 assign( B_inf_true, 11020 unop( Iop_1Sto32, 11021 binop( Iop_CmpEQ32, 11022 mkexpr( gfield_B ), 11023 mkU32( 0x78000000 ) ) ) ); 11024 11025 assign( finite_number, 11026 unop( Iop_Not32, 11027 binop( Iop_Or32, 11028 binop( Iop_Or32, 11029 mkexpr( A_NaN_true ), 11030 mkexpr( B_NaN_true ) ), 11031 binop( Iop_Or32, 11032 mkexpr( A_inf_true ), 11033 mkexpr( B_inf_true ) ) ) ) ); 11034 11035 /* Calculate the condition code bits 11036 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 11037 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 11038 * cc0, cc1 and cc0 reflect the results of the comparisons. 11039 */ 11040 assign( A_equals_B, 11041 binop( Iop_Or32, 11042 unop( Iop_1Uto32, 11043 binop( Iop_CmpEQ32, 11044 mkexpr( exponent_A ), 11045 mkexpr( exponent_B ) ) ), 11046 binop( Iop_Or32, 11047 binop( Iop_And32, 11048 mkexpr( A_inf_true ), 11049 mkexpr( B_inf_true ) ), 11050 binop( Iop_And32, 11051 mkexpr( A_NaN_true ), 11052 mkexpr( B_NaN_true ) ) ) ) ); 11053 11054 assign( cc0, binop( Iop_And32, 11055 mkexpr( finite_number ), 11056 binop( Iop_Shl32, 11057 unop( Iop_1Uto32, 11058 binop( Iop_CmpLT32U, 11059 mkexpr( exponent_A ), 11060 mkexpr( exponent_B ) ) ), 11061 mkU8( 3 ) ) ) ); 11062 11063 assign( cc1, binop( Iop_And32, 11064 mkexpr( finite_number ), 11065 binop( Iop_Shl32, 11066 unop( Iop_1Uto32, 11067 binop( Iop_CmpLT32U, 11068 mkexpr( exponent_B ), 11069 mkexpr( exponent_A ) ) ), 11070 mkU8( 2 ) ) ) ); 11071 11072 assign( cc2, binop( Iop_Shl32, 11073 binop( Iop_And32, 11074 mkexpr( A_equals_B ), 11075 mkU32( 1 ) ), 11076 mkU8( 1 ) ) ); 11077 11078 assign( cc3, binop( Iop_And32, 11079 unop( Iop_Not32, mkexpr( A_equals_B ) ), 11080 binop( Iop_And32, 11081 mkU32( 0x1 ), 11082 binop( Iop_Or32, 11083 binop( Iop_Or32, 11084 mkexpr ( A_inf_true ), 11085 mkexpr ( B_inf_true ) ), 11086 binop( Iop_Or32, 11087 mkexpr ( A_NaN_true ), 11088 mkexpr ( B_NaN_true ) ) ) 11089 ) ) ); 11090 11091 /* store the condition code */ 11092 putGST_field( PPC_GST_CR, 11093 binop( Iop_Or32, 11094 mkexpr( cc0 ), 11095 binop( Iop_Or32, 11096 mkexpr( cc1 ), 11097 binop( Iop_Or32, 11098 mkexpr( cc2 ), 11099 mkexpr( cc3 ) ) ) ), 11100 crfD ); 11101 return True; 11102 } 11103 11104 /* Test class/group/exponent/significance instructions. */ 11105 static Bool dis_dfp_class_test ( UInt theInstr ) 11106 { 11107 UChar frA_addr = ifieldRegA( theInstr ); 11108 IRTemp frA = newTemp( Ity_D64 ); 11109 IRTemp abs_frA = newTemp( Ity_D64 ); 11110 IRTemp frAI64_hi = newTemp( Ity_I64 ); 11111 IRTemp frAI64_lo = newTemp( Ity_I64 ); 11112 UInt opc1 = ifieldOPC( theInstr ); 11113 UInt opc2 = ifieldOPClo9( theInstr ); 11114 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 11115 UInt DCM = IFIELD( theInstr, 10, 6 ); 11116 IRTemp DCM_calc = newTemp( Ity_I32 ); 11117 UInt max_exp = 0; 11118 UInt min_exp = 0; 11119 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 11120 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 11121 IRTemp significand64 = newTemp( Ity_D64 ); 11122 IRTemp significand128 = newTemp( Ity_D128 ); 11123 IRTemp exp_min_normal = newTemp( Ity_I64 ); 11124 IRTemp exponent = newTemp( Ity_I32 ); 11125 11126 IRTemp infinity_true = newTemp( Ity_I32 ); 11127 IRTemp SNaN_true = newTemp( Ity_I32 ); 11128 IRTemp QNaN_true = newTemp( Ity_I32 ); 11129 IRTemp subnormal_true = newTemp( Ity_I32 ); 11130 IRTemp normal_true = newTemp( Ity_I32 ); 11131 IRTemp extreme_true = newTemp( Ity_I32 ); 11132 IRTemp lmd = newTemp( Ity_I32 ); 11133 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 11134 IRTemp zero_true = newTemp( Ity_I32 ); 11135 IRTemp sign = newTemp( Ity_I32 ); 11136 IRTemp field = newTemp( Ity_I32 ); 11137 IRTemp ccIR_zero = newTemp( Ity_I32 ); 11138 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 11139 11140 /* UInt size = DFP_LONG; JRS:unused */ 11141 IRTemp gfield = newTemp( Ity_I32 ); 11142 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 11143 IRTemp gfield_mask = newTemp( Ity_I32 ); 11144 IRTemp dcm0 = newTemp( Ity_I32 ); 11145 IRTemp dcm1 = newTemp( Ity_I32 ); 11146 IRTemp dcm2 = newTemp( Ity_I32 ); 11147 IRTemp dcm3 = newTemp( Ity_I32 ); 11148 IRTemp dcm4 = newTemp( Ity_I32 ); 11149 IRTemp dcm5 = newTemp( Ity_I32 ); 11150 11151 /* The only difference between the dtstdc and dtstdcq instructions is 11152 * size of the T and G fields. The calculation of the 4 bit field 11153 * is the same. Setup the parameters and values that are DFP size 11154 * specific. The rest of the code is independent of the DFP size. 11155 * 11156 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 11157 * The interpretation of the ccIR values is as follows: 11158 * 11159 * DFP cmp result | IR 11160 * -------------------------- 11161 * UN | 0x45 11162 * EQ | 0x40 11163 * GT | 0x00 11164 * LT | 0x01 11165 */ 11166 11167 assign( frA, getDReg( frA_addr ) ); 11168 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 11169 11170 assign( abs_frA, unop( Iop_ReinterpI64asD64, 11171 binop( Iop_And64, 11172 unop( Iop_ReinterpD64asI64, 11173 mkexpr( frA ) ), 11174 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 11175 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 11176 switch (opc1) { 11177 case 0x3b: // dtstdc, dtstdg 11178 DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 11179 crfD, frA_addr, DCM); 11180 /* setup the parameters for the long format of the two instructions */ 11181 assign( frAI64_lo, mkU64( 0 ) ); 11182 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 11183 max_exp = DFP_LONG_EXP_MAX; 11184 min_exp = DFP_LONG_EXP_MIN; 11185 11186 assign( exponent, unop( Iop_64to32, 11187 unop( Iop_ExtractExpD64, 11188 mkexpr( frA ) ) ) ); 11189 assign( significand64, 11190 unop( Iop_ReinterpI64asD64, 11191 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 11192 assign( exp_min_normal,mkU64( 398 - 383 ) ); 11193 assign( min_subnormalD64, 11194 binop( Iop_InsertExpD64, 11195 mkexpr( exp_min_normal ), 11196 mkexpr( significand64 ) ) ); 11197 11198 assign( ccIR_subnormal, 11199 binop( Iop_CmpD64, 11200 mkexpr( abs_frA ), 11201 mkexpr( min_subnormalD64 ) ) ); 11202 11203 /* compare absolute value of frA with zero */ 11204 assign( ccIR_zero, 11205 binop( Iop_CmpD64, 11206 mkexpr( abs_frA ), 11207 unop( Iop_ReinterpI64asD64, 11208 mkU64( 0x2238000000000000ULL ) ) ) ); 11209 11210 /* size = DFP_LONG; JRS: unused */ 11211 break; 11212 11213 case 0x3F: // dtstdcq, dtstdgq 11214 DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 11215 crfD, frA_addr, DCM); 11216 /* setup the parameters for the extended format of the 11217 * two instructions 11218 */ 11219 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 11220 getDReg( frA_addr+1 ) ) ); 11221 11222 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 11223 max_exp = DFP_EXTND_EXP_MAX; 11224 min_exp = DFP_EXTND_EXP_MIN; 11225 assign( exponent, unop( Iop_64to32, 11226 unop( Iop_ExtractExpD128, 11227 getDReg_pair( frA_addr) ) ) ); 11228 11229 /* create quand exponent for minimum normal number */ 11230 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 11231 assign( significand128, 11232 unop( Iop_D64toD128, 11233 unop( Iop_ReinterpI64asD64, 11234 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 11235 11236 assign( min_subnormalD128, 11237 binop( Iop_InsertExpD128, 11238 mkexpr( exp_min_normal ), 11239 mkexpr( significand128 ) ) ); 11240 11241 assign( ccIR_subnormal, 11242 binop( Iop_CmpD128, 11243 binop( Iop_D64HLtoD128, 11244 unop( Iop_ReinterpI64asD64, 11245 binop( Iop_And64, 11246 unop( Iop_ReinterpD64asI64, 11247 mkexpr( frA ) ), 11248 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 11249 getDReg( frA_addr+1 ) ), 11250 mkexpr( min_subnormalD128 ) ) ); 11251 assign( ccIR_zero, 11252 binop( Iop_CmpD128, 11253 binop( Iop_D64HLtoD128, 11254 mkexpr( abs_frA ), 11255 getDReg( frA_addr+1 ) ), 11256 unop( Iop_D64toD128, 11257 unop( Iop_ReinterpI64asD64, 11258 mkU64( 0x0ULL ) ) ) ) ); 11259 11260 /* size = DFP_EXTND; JRS:unused */ 11261 break; 11262 default: 11263 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 11264 return False; 11265 } 11266 11267 /* The G-field is in the upper 32-bits. The I64 logical operations 11268 * do not seem to be supported in 32-bit mode so keep things as 32-bit 11269 * operations. 11270 */ 11271 assign( gfield, binop( Iop_And32, 11272 mkexpr( gfield_mask ), 11273 unop( Iop_64HIto32, 11274 mkexpr(frAI64_hi) ) ) ); 11275 11276 /* There is a lot of code that is the same to do the class and group 11277 * instructions. Later there is an if statement to handle the specific 11278 * instruction. 11279 * 11280 * Will be using I32 values, compares, shifts and logical operations for 11281 * this code as the 64-bit compare, shifts, logical operations are not 11282 * supported in 32-bit mode. 11283 */ 11284 11285 /* Check the bits for Infinity, QNaN or Signaling NaN */ 11286 assign( infinity_true, 11287 unop( Iop_1Sto32, 11288 binop( Iop_CmpEQ32, 11289 binop( Iop_And32, 11290 mkU32( 0x7C000000 ), 11291 mkexpr( gfield ) ), 11292 mkU32( 0x78000000 ) ) ) ); 11293 11294 assign( SNaN_true, 11295 unop( Iop_1Sto32, 11296 binop( Iop_CmpEQ32, 11297 binop( Iop_And32, 11298 mkU32( 0x7E000000 ), 11299 mkexpr( gfield ) ), 11300 mkU32( 0x7E000000 ) ) ) ); 11301 11302 assign( QNaN_true, 11303 binop( Iop_And32, 11304 unop( Iop_1Sto32, 11305 binop( Iop_CmpEQ32, 11306 binop( Iop_And32, 11307 mkU32( 0x7E000000 ), 11308 mkexpr( gfield ) ), 11309 mkU32( 0x7C000000 ) ) ), 11310 unop( Iop_Not32, 11311 mkexpr( SNaN_true ) ) ) ); 11312 11313 assign( zero_true, 11314 binop( Iop_And32, 11315 unop(Iop_1Sto32, 11316 binop( Iop_CmpEQ32, 11317 mkexpr( ccIR_zero ), 11318 mkU32( 0x40 ) ) ), // ccIR code for Equal 11319 unop( Iop_Not32, 11320 binop( Iop_Or32, 11321 mkexpr( infinity_true ), 11322 binop( Iop_Or32, 11323 mkexpr( QNaN_true ), 11324 mkexpr( SNaN_true ) ) ) ) ) ); 11325 11326 /* Do compare of frA the minimum normal value. Comparison is size 11327 * depenent and was done above to get the ccIR value. 11328 */ 11329 assign( subnormal_true, 11330 binop( Iop_And32, 11331 binop( Iop_Or32, 11332 unop( Iop_1Sto32, 11333 binop( Iop_CmpEQ32, 11334 mkexpr( ccIR_subnormal ), 11335 mkU32( 0x40 ) ) ), // ccIR code for Equal 11336 unop( Iop_1Sto32, 11337 binop( Iop_CmpEQ32, 11338 mkexpr( ccIR_subnormal ), 11339 mkU32( 0x1 ) ) ) ), // ccIR code for LT 11340 unop( Iop_Not32, 11341 binop( Iop_Or32, 11342 binop( Iop_Or32, 11343 mkexpr( infinity_true ), 11344 mkexpr( zero_true) ), 11345 binop( Iop_Or32, 11346 mkexpr( QNaN_true ), 11347 mkexpr( SNaN_true ) ) ) ) ) ); 11348 11349 /* Normal number is not subnormal, infinity, NaN or Zero */ 11350 assign( normal_true, 11351 unop( Iop_Not32, 11352 binop( Iop_Or32, 11353 binop( Iop_Or32, 11354 mkexpr( infinity_true ), 11355 mkexpr( zero_true ) ), 11356 binop( Iop_Or32, 11357 mkexpr( subnormal_true ), 11358 binop( Iop_Or32, 11359 mkexpr( QNaN_true ), 11360 mkexpr( SNaN_true ) ) ) ) ) ); 11361 11362 /* Calculate the DCM bit field based on the tests for the specific 11363 * instruction 11364 */ 11365 if (opc2 == 0xC2) { // dtstdc, dtstdcq 11366 /* DCM[0:5] Bit Data Class definition 11367 * 0 Zero 11368 * 1 Subnormal 11369 * 2 Normal 11370 * 3 Infinity 11371 * 4 Quiet NaN 11372 * 5 Signaling NaN 11373 */ 11374 11375 assign( dcm0, binop( Iop_Shl32, 11376 mkexpr( zero_true ), 11377 mkU8( 5 ) ) ); 11378 assign( dcm1, binop( Iop_Shl32, 11379 binop( Iop_And32, 11380 mkexpr( subnormal_true ), 11381 mkU32( 1 ) ), 11382 mkU8( 4 ) ) ); 11383 assign( dcm2, binop( Iop_Shl32, 11384 binop( Iop_And32, 11385 mkexpr( normal_true ), 11386 mkU32( 1 ) ), 11387 mkU8( 3 ) ) ); 11388 assign( dcm3, binop( Iop_Shl32, 11389 binop( Iop_And32, 11390 mkexpr( infinity_true), 11391 mkU32( 1 ) ), 11392 mkU8( 2 ) ) ); 11393 assign( dcm4, binop( Iop_Shl32, 11394 binop( Iop_And32, 11395 mkexpr( QNaN_true ), 11396 mkU32( 1 ) ), 11397 mkU8( 1 ) ) ); 11398 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 11399 11400 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 11401 /* check if the exponent is extreme */ 11402 assign( extreme_true, binop( Iop_Or32, 11403 unop( Iop_1Sto32, 11404 binop( Iop_CmpEQ32, 11405 mkexpr( exponent ), 11406 mkU32( max_exp ) ) ), 11407 unop( Iop_1Sto32, 11408 binop( Iop_CmpEQ32, 11409 mkexpr( exponent ), 11410 mkU32( min_exp ) ) ) ) ); 11411 11412 /* Check if LMD is zero */ 11413 Get_lmd( &lmd, binop( Iop_Shr32, 11414 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 11415 11416 assign( lmd_zero_true, unop( Iop_1Sto32, 11417 binop( Iop_CmpEQ32, 11418 mkexpr( lmd ), 11419 mkU32( 0 ) ) ) ); 11420 11421 /* DCM[0:5] Bit Data Class definition 11422 * 0 Zero with non-extreme exponent 11423 * 1 Zero with extreme exponent 11424 * 2 Subnormal or (Normal with extreme exponent) 11425 * 3 Normal with non-extreme exponent and 11426 * leftmost zero digit in significand 11427 * 4 Normal with non-extreme exponent and 11428 * leftmost nonzero digit in significand 11429 * 5 Special symbol (Infinity, QNaN, or SNaN) 11430 */ 11431 assign( dcm0, binop( Iop_Shl32, 11432 binop( Iop_And32, 11433 binop( Iop_And32, 11434 unop( Iop_Not32, 11435 mkexpr( extreme_true ) ), 11436 mkexpr( zero_true ) ), 11437 mkU32( 0x1 ) ), 11438 mkU8( 5 ) ) ); 11439 11440 assign( dcm1, binop( Iop_Shl32, 11441 binop( Iop_And32, 11442 binop( Iop_And32, 11443 mkexpr( extreme_true ), 11444 mkexpr( zero_true ) ), 11445 mkU32( 0x1 ) ), 11446 mkU8( 4 ) ) ); 11447 11448 assign( dcm2, binop( Iop_Shl32, 11449 binop( Iop_And32, 11450 binop( Iop_Or32, 11451 binop( Iop_And32, 11452 mkexpr( extreme_true ), 11453 mkexpr( normal_true ) ), 11454 mkexpr( subnormal_true ) ), 11455 mkU32( 0x1 ) ), 11456 mkU8( 3 ) ) ); 11457 11458 assign( dcm3, binop( Iop_Shl32, 11459 binop( Iop_And32, 11460 binop( Iop_And32, 11461 binop( Iop_And32, 11462 unop( Iop_Not32, 11463 mkexpr( extreme_true ) ), 11464 mkexpr( normal_true ) ), 11465 unop( Iop_1Sto32, 11466 binop( Iop_CmpEQ32, 11467 mkexpr( lmd ), 11468 mkU32( 0 ) ) ) ), 11469 mkU32( 0x1 ) ), 11470 mkU8( 2 ) ) ); 11471 11472 assign( dcm4, binop( Iop_Shl32, 11473 binop( Iop_And32, 11474 binop( Iop_And32, 11475 binop( Iop_And32, 11476 unop( Iop_Not32, 11477 mkexpr( extreme_true ) ), 11478 mkexpr( normal_true ) ), 11479 unop( Iop_1Sto32, 11480 binop( Iop_CmpNE32, 11481 mkexpr( lmd ), 11482 mkU32( 0 ) ) ) ), 11483 mkU32( 0x1 ) ), 11484 mkU8( 1 ) ) ); 11485 11486 assign( dcm5, binop( Iop_And32, 11487 binop( Iop_Or32, 11488 mkexpr( SNaN_true), 11489 binop( Iop_Or32, 11490 mkexpr( QNaN_true), 11491 mkexpr( infinity_true) ) ), 11492 mkU32( 0x1 ) ) ); 11493 } 11494 11495 /* create DCM field */ 11496 assign( DCM_calc, 11497 binop( Iop_Or32, 11498 mkexpr( dcm0 ), 11499 binop( Iop_Or32, 11500 mkexpr( dcm1 ), 11501 binop( Iop_Or32, 11502 mkexpr( dcm2 ), 11503 binop( Iop_Or32, 11504 mkexpr( dcm3 ), 11505 binop( Iop_Or32, 11506 mkexpr( dcm4 ), 11507 mkexpr( dcm5 ) ) ) ) ) ) ); 11508 11509 /* Get the sign of the DFP number, ignore sign for QNaN */ 11510 assign( sign, 11511 unop( Iop_1Uto32, 11512 binop( Iop_CmpEQ32, 11513 binop( Iop_Shr32, 11514 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 11515 mkU8( 63 - 32 ) ), 11516 mkU32( 1 ) ) ) ); 11517 11518 /* This instruction generates a four bit field to be stored in the 11519 * condition code register. The condition code register consists of 7 11520 * fields. The field to be written to is specified by the BF (AKA crfD) 11521 * field. 11522 * 11523 * The field layout is as follows: 11524 * 11525 * Field Meaning 11526 * 0000 Operand positive with no match 11527 * 0100 Operand positive with at least one match 11528 * 0001 Operand negative with no match 11529 * 0101 Operand negative with at least one match 11530 */ 11531 assign( field, binop( Iop_Or32, 11532 binop( Iop_Shl32, 11533 mkexpr( sign ), 11534 mkU8( 3 ) ), 11535 binop( Iop_Shl32, 11536 unop( Iop_1Uto32, 11537 binop( Iop_CmpNE32, 11538 binop( Iop_And32, 11539 mkU32( DCM ), 11540 mkexpr( DCM_calc ) ), 11541 mkU32( 0 ) ) ), 11542 mkU8( 1 ) ) ) ); 11543 11544 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 11545 return True; 11546 } 11547 11548 static Bool dis_dfp_bcd(UInt theInstr) { 11549 UInt opc2 = ifieldOPClo10( theInstr ); 11550 ULong sp = IFIELD(theInstr, 19, 2); 11551 ULong s = IFIELD(theInstr, 20, 1); 11552 UChar frT_addr = ifieldRegDS( theInstr ); 11553 UChar frB_addr = ifieldRegB( theInstr ); 11554 IRTemp frB = newTemp( Ity_D64 ); 11555 IRTemp frBI64 = newTemp( Ity_I64 ); 11556 IRTemp result = newTemp( Ity_I64 ); 11557 IRTemp resultD64 = newTemp( Ity_D64 ); 11558 IRTemp bcd64 = newTemp( Ity_I64 ); 11559 IRTemp bcd_u = newTemp( Ity_I32 ); 11560 IRTemp bcd_l = newTemp( Ity_I32 ); 11561 IRTemp dbcd_u = newTemp( Ity_I32 ); 11562 IRTemp dbcd_l = newTemp( Ity_I32 ); 11563 IRTemp lmd = newTemp( Ity_I32 ); 11564 11565 assign( frB, getDReg( frB_addr ) ); 11566 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11567 11568 switch ( opc2 ) { 11569 case 0x142: // ddedpd DFP Decode DPD to BCD 11570 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11571 11572 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11573 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 11574 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 11575 11576 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11577 /* Unsigned BCD string */ 11578 Get_lmd( &lmd, 11579 binop( Iop_Shr32, 11580 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11581 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11582 11583 assign( result, 11584 binop( Iop_32HLto64, 11585 binop( Iop_Or32, 11586 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 11587 mkexpr( bcd_u ) ), 11588 mkexpr( bcd_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 11600 assign( sign, 11601 binop( Iop_Or32, 11602 binop( Iop_Shr32, 11603 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11604 mkU8( 31 ) ), 11605 mkU32( 0xC ) ) ); 11606 11607 } else if ( sp == 3 ) { 11608 /* Positive sign = 0xF, negative sign = 0xD */ 11609 IRTemp tmp32 = newTemp( Ity_I32 ); 11610 11611 /* Complement sign bit then OR into bit position 1 */ 11612 assign( tmp32, 11613 binop( Iop_Xor32, 11614 binop( Iop_Shr32, 11615 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 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 /* Put sign in bottom 4 bits, move most significant 4-bits from 11626 * bcd_l to bcd_u. 11627 */ 11628 assign( result, 11629 binop( Iop_32HLto64, 11630 binop( Iop_Or32, 11631 binop( Iop_Shr32, 11632 mkexpr( bcd_l ), 11633 mkU8( 28 ) ), 11634 binop( Iop_Shl32, 11635 mkexpr( bcd_u ), 11636 mkU8( 4 ) ) ), 11637 binop( Iop_Or32, 11638 mkexpr( sign ), 11639 binop( Iop_Shl32, 11640 mkexpr( bcd_l ), 11641 mkU8( 4 ) ) ) ) ); 11642 } 11643 11644 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 11645 break; 11646 11647 case 0x342: // denbcd DFP Encode BCD to DPD 11648 { 11649 IRTemp valid_mask = newTemp( Ity_I32 ); 11650 IRTemp invalid_mask = newTemp( Ity_I32 ); 11651 IRTemp without_lmd = newTemp( Ity_I64 ); 11652 IRTemp tmp64 = newTemp( Ity_I64 ); 11653 IRTemp dbcd64 = newTemp( Ity_I64 ); 11654 IRTemp left_exp = newTemp( Ity_I32 ); 11655 IRTemp g0_4 = newTemp( Ity_I32 ); 11656 11657 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11658 11659 if ( s == 0 ) { 11660 /* Unsigned BCD string */ 11661 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 11662 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 11663 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 11664 11665 assign( lmd, 11666 binop( Iop_Shr32, 11667 binop( Iop_And32, 11668 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11669 mkU32( 0xF0000000 ) ), 11670 mkU8( 28 ) ) ); 11671 11672 assign( invalid_mask, 11673 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11674 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 11675 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11676 11677 assign( without_lmd, 11678 unop( Iop_ReinterpD64asI64, 11679 binop( Iop_InsertExpD64, 11680 mkU64( DFP_LONG_BIAS ), 11681 unop( Iop_ReinterpI64asD64, 11682 binop( Iop_32HLto64, 11683 mkexpr( dbcd_u ), 11684 mkexpr( dbcd_l ) ) ) ) ) ); 11685 assign( left_exp, 11686 binop( Iop_Shr32, 11687 binop( Iop_And32, 11688 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 11689 mkU32( 0x60000000 ) ), 11690 mkU8( 29 ) ) ); 11691 11692 assign( g0_4, 11693 binop( Iop_Shl32, 11694 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 11695 mkU8( 26 ) ) ); 11696 11697 assign( tmp64, 11698 binop( Iop_32HLto64, 11699 binop( Iop_Or32, 11700 binop( Iop_And32, 11701 unop( Iop_64HIto32, 11702 mkexpr( without_lmd ) ), 11703 mkU32( 0x83FFFFFF ) ), 11704 mkexpr( g0_4 ) ), 11705 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 11706 11707 } else if ( s == 1 ) { 11708 IRTemp sign = newTemp( Ity_I32 ); 11709 IRTemp sign_bit = newTemp( Ity_I32 ); 11710 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11711 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11712 IRTemp tmp = newTemp( Ity_I64 ); 11713 11714 /* Signed BCD string, least significant 4 bits are sign bits 11715 * positive sign = 0xC, negative sign = 0xD 11716 */ 11717 assign( tmp, unop( Iop_BCDtoDPB, 11718 binop( Iop_32HLto64, 11719 binop( Iop_Shr32, 11720 unop( Iop_64HIto32, 11721 mkexpr( frBI64 ) ), 11722 mkU8( 4 ) ), 11723 binop( Iop_Or32, 11724 binop( Iop_Shr32, 11725 unop( Iop_64to32, 11726 mkexpr( frBI64 ) ), 11727 mkU8( 4 ) ), 11728 binop( Iop_Shl32, 11729 unop( Iop_64HIto32, 11730 mkexpr( frBI64 ) ), 11731 mkU8( 28 ) ) ) ) ) ); 11732 11733 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 11734 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 11735 11736 /* Get the sign of the BCD string. */ 11737 assign( sign, 11738 binop( Iop_And32, 11739 unop( Iop_64to32, mkexpr( frBI64 ) ), 11740 mkU32( 0xF ) ) ); 11741 11742 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11743 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11744 assign( sign_bit, 11745 Generate_sign_bit( mkexpr( pos_sign_mask ), 11746 mkexpr( neg_sign_mask ) ) ); 11747 11748 /* Check for invalid sign and BCD digit. Don't check the bottom 11749 * four bits of bcd_l as that is the sign value. 11750 */ 11751 assign( invalid_mask, 11752 Generate_inv_mask( 11753 bcd_digit_inval( unop( Iop_64HIto32, 11754 mkexpr( frBI64 ) ), 11755 binop( Iop_Shr32, 11756 unop( Iop_64to32, 11757 mkexpr( frBI64 ) ), 11758 mkU8( 4 ) ) ), 11759 mkexpr( pos_sign_mask ), 11760 mkexpr( neg_sign_mask ) ) ); 11761 11762 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11763 11764 /* Generate the result assuming the sign value was valid. */ 11765 assign( tmp64, 11766 unop( Iop_ReinterpD64asI64, 11767 binop( Iop_InsertExpD64, 11768 mkU64( DFP_LONG_BIAS ), 11769 unop( Iop_ReinterpI64asD64, 11770 binop( Iop_32HLto64, 11771 binop( Iop_Or32, 11772 mkexpr( dbcd_u ), 11773 mkexpr( sign_bit ) ), 11774 mkexpr( dbcd_l ) ) ) ) ) ); 11775 } 11776 11777 /* Generate the value to store depending on the validity of the 11778 * sign value and the validity of the BCD digits. 11779 */ 11780 assign( resultD64, 11781 unop( Iop_ReinterpI64asD64, 11782 binop( Iop_32HLto64, 11783 binop( Iop_Or32, 11784 binop( Iop_And32, 11785 mkexpr( valid_mask ), 11786 unop( Iop_64HIto32, 11787 mkexpr( tmp64 ) ) ), 11788 binop( Iop_And32, 11789 mkU32( 0x7C000000 ), 11790 mkexpr( invalid_mask ) ) ), 11791 binop( Iop_Or32, 11792 binop( Iop_And32, 11793 mkexpr( valid_mask ), 11794 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 11795 binop( Iop_And32, 11796 mkU32( 0x0 ), 11797 mkexpr( invalid_mask ) ) ) ) ) ); 11798 putDReg( frT_addr, mkexpr( resultD64 ) ); 11799 } 11800 break; 11801 default: 11802 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 11803 return False; 11804 } 11805 return True; 11806 } 11807 11808 static Bool dis_dfp_bcdq( UInt theInstr ) 11809 { 11810 UInt opc2 = ifieldOPClo10( theInstr ); 11811 ULong sp = IFIELD(theInstr, 19, 2); 11812 ULong s = IFIELD(theInstr, 20, 1); 11813 IRTemp frB_hi = newTemp( Ity_D64 ); 11814 IRTemp frB_lo = newTemp( Ity_D64 ); 11815 IRTemp frBI64_hi = newTemp( Ity_I64 ); 11816 IRTemp frBI64_lo = newTemp( Ity_I64 ); 11817 UChar frT_addr = ifieldRegDS( theInstr ); 11818 UChar frB_addr = ifieldRegB( theInstr ); 11819 11820 IRTemp lmd = newTemp( Ity_I32 ); 11821 IRTemp result_hi = newTemp( Ity_I64 ); 11822 IRTemp result_lo = newTemp( Ity_I64 ); 11823 11824 assign( frB_hi, getDReg( frB_addr ) ); 11825 assign( frB_lo, getDReg( frB_addr + 1 ) ); 11826 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 11827 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 11828 11829 switch ( opc2 ) { 11830 case 0x142: // ddedpdq DFP Decode DPD to BCD 11831 { 11832 IRTemp low_60_u = newTemp( Ity_I32 ); 11833 IRTemp low_60_l = newTemp( Ity_I32 ); 11834 IRTemp mid_60_u = newTemp( Ity_I32 ); 11835 IRTemp mid_60_l = newTemp( Ity_I32 ); 11836 IRTemp top_12_l = newTemp( Ity_I32 ); 11837 11838 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11839 11840 /* Note, instruction only stores the lower 32 BCD digits in 11841 * the result 11842 */ 11843 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 11844 mkexpr( frBI64_lo ), 11845 &top_12_l, 11846 &mid_60_u, 11847 &mid_60_l, 11848 &low_60_u, 11849 &low_60_l ); 11850 11851 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11852 /* Unsigned BCD string */ 11853 assign( result_hi, 11854 binop( Iop_32HLto64, 11855 binop( Iop_Or32, 11856 binop( Iop_Shl32, 11857 mkexpr( top_12_l ), 11858 mkU8( 24 ) ), 11859 binop( Iop_Shr32, 11860 mkexpr( mid_60_u ), 11861 mkU8( 4 ) ) ), 11862 binop( Iop_Or32, 11863 binop( Iop_Shl32, 11864 mkexpr( mid_60_u ), 11865 mkU8( 28 ) ), 11866 binop( Iop_Shr32, 11867 mkexpr( mid_60_l ), 11868 mkU8( 4 ) ) ) ) ); 11869 11870 assign( result_lo, 11871 binop( Iop_32HLto64, 11872 binop( Iop_Or32, 11873 binop( Iop_Shl32, 11874 mkexpr( mid_60_l ), 11875 mkU8( 28 ) ), 11876 mkexpr( low_60_u ) ), 11877 mkexpr( low_60_l ) ) ); 11878 11879 } else { 11880 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11881 * the positive and negative values are encoded in the least 11882 * significant bits. 11883 */ 11884 IRTemp sign = newTemp( Ity_I32 ); 11885 11886 if ( sp == 2 ) { 11887 /* Positive sign = 0xC, negative sign = 0xD */ 11888 assign( sign, 11889 binop( Iop_Or32, 11890 binop( Iop_Shr32, 11891 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11892 mkU8( 31 ) ), 11893 mkU32( 0xC ) ) ); 11894 11895 } else if ( sp == 3 ) { 11896 IRTemp tmp32 = newTemp( Ity_I32 ); 11897 11898 /* Positive sign = 0xF, negative sign = 0xD. 11899 * Need to complement sign bit then OR into bit position 1. 11900 */ 11901 assign( tmp32, 11902 binop( Iop_Xor32, 11903 binop( Iop_Shr32, 11904 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11905 mkU8( 30 ) ), 11906 mkU32( 0x2 ) ) ); 11907 11908 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11909 11910 } else { 11911 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11912 } 11913 11914 assign( result_hi, 11915 binop( Iop_32HLto64, 11916 binop( Iop_Or32, 11917 binop( Iop_Shl32, 11918 mkexpr( top_12_l ), 11919 mkU8( 28 ) ), 11920 mkexpr( mid_60_u ) ), 11921 mkexpr( mid_60_l ) ) ); 11922 11923 assign( result_lo, 11924 binop( Iop_32HLto64, 11925 binop( Iop_Or32, 11926 binop( Iop_Shl32, 11927 mkexpr( low_60_u ), 11928 mkU8( 4 ) ), 11929 binop( Iop_Shr32, 11930 mkexpr( low_60_l ), 11931 mkU8( 28 ) ) ), 11932 binop( Iop_Or32, 11933 binop( Iop_Shl32, 11934 mkexpr( low_60_l ), 11935 mkU8( 4 ) ), 11936 mkexpr( sign ) ) ) ); 11937 } 11938 11939 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11940 putDReg( frT_addr + 1, 11941 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11942 } 11943 break; 11944 case 0x342: // denbcdq DFP Encode BCD to DPD 11945 { 11946 IRTemp valid_mask = newTemp( Ity_I32 ); 11947 IRTemp invalid_mask = newTemp( Ity_I32 ); 11948 IRTemp result128 = newTemp( Ity_D128 ); 11949 IRTemp dfp_significand = newTemp( Ity_D128 ); 11950 IRTemp tmp_hi = newTemp( Ity_I64 ); 11951 IRTemp tmp_lo = newTemp( Ity_I64 ); 11952 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 11953 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 11954 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 11955 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 11956 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 11957 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 11958 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 11959 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 11960 IRTemp sign_bit = newTemp( Ity_I32 ); 11961 IRTemp tmptop10 = newTemp( Ity_I64 ); 11962 IRTemp tmpmid50 = newTemp( Ity_I64 ); 11963 IRTemp tmplow50 = newTemp( Ity_I64 ); 11964 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 11965 11966 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11967 11968 if ( s == 0 ) { 11969 /* Unsigned BCD string */ 11970 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 11971 11972 assign( bcd_top_8, 11973 binop( Iop_32HLto64, 11974 mkU32( 0 ), 11975 binop( Iop_And32, 11976 binop( Iop_Shr32, 11977 unop( Iop_64HIto32, 11978 mkexpr( frBI64_hi ) ), 11979 mkU8( 24 ) ), 11980 mkU32( 0xFF ) ) ) ); 11981 assign( bcd_mid_60, 11982 binop( Iop_32HLto64, 11983 binop( Iop_Or32, 11984 binop( Iop_Shr32, 11985 unop( Iop_64to32, 11986 mkexpr( frBI64_hi ) ), 11987 mkU8( 28 ) ), 11988 binop( Iop_Shl32, 11989 unop( Iop_64HIto32, 11990 mkexpr( frBI64_hi ) ), 11991 mkU8( 4 ) ) ), 11992 binop( Iop_Or32, 11993 binop( Iop_Shl32, 11994 unop( Iop_64to32, 11995 mkexpr( frBI64_hi ) ), 11996 mkU8( 4 ) ), 11997 binop( Iop_Shr32, 11998 unop( Iop_64HIto32, 11999 mkexpr( frBI64_lo ) ), 12000 mkU8( 28 ) ) ) ) ); 12001 12002 /* Note, the various helper functions ignores top 4-bits */ 12003 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 12004 12005 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 12006 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12007 12008 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 12009 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12010 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12011 12012 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12013 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12014 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12015 12016 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 12017 * value is not part of the final result. Only the right most 12018 * BCD digits are stored. 12019 */ 12020 assign( lmd, mkU32( 0 ) ); 12021 12022 assign( invalid_mask, 12023 binop( Iop_Or32, 12024 bcd_digit_inval( mkU32( 0 ), 12025 unop( Iop_64to32, 12026 mkexpr( bcd_top_8 ) ) ), 12027 binop( Iop_Or32, 12028 bcd_digit_inval( unop( Iop_64HIto32, 12029 mkexpr( bcd_mid_60 ) ), 12030 unop( Iop_64to32, 12031 mkexpr( bcd_mid_60 ) ) ), 12032 bcd_digit_inval( unop( Iop_64HIto32, 12033 mkexpr( bcd_low_60 ) ), 12034 unop( Iop_64to32, 12035 mkexpr( bcd_low_60 ) ) 12036 ) ) ) ); 12037 12038 } else if ( s == 1 ) { 12039 IRTemp sign = newTemp( Ity_I32 ); 12040 IRTemp zero = newTemp( Ity_I32 ); 12041 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 12042 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 12043 12044 /* The sign of the BCD string is stored in lower 4 bits */ 12045 assign( sign, 12046 binop( Iop_And32, 12047 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 12048 mkU32( 0xF ) ) ); 12049 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 12050 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 12051 assign( sign_bit, 12052 Generate_sign_bit( mkexpr( pos_sign_mask ), 12053 mkexpr( neg_sign_mask ) ) ); 12054 12055 /* Generate the value assuminig the sign and BCD digits are vaild */ 12056 assign( bcd_top_8, 12057 binop( Iop_32HLto64, 12058 mkU32( 0x0 ), 12059 binop( Iop_Shr32, 12060 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12061 mkU8( 28 ) ) ) ); 12062 12063 /* The various helper routines ignore the upper 4-bits */ 12064 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 12065 12066 /* Remove bottom four sign bits */ 12067 assign( bcd_low_60, 12068 binop( Iop_32HLto64, 12069 binop( Iop_Shr32, 12070 unop( Iop_64HIto32, 12071 mkexpr( frBI64_lo ) ), 12072 mkU8( 4 ) ), 12073 binop( Iop_Or32, 12074 binop( Iop_Shl32, 12075 unop( Iop_64HIto32, 12076 mkexpr( frBI64_lo ) ), 12077 mkU8( 28 ) ), 12078 binop( Iop_Shr32, 12079 unop( Iop_64to32, 12080 mkexpr( frBI64_lo ) ), 12081 mkU8( 4 ) ) ) ) ); 12082 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 12083 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12084 12085 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 12086 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12087 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12088 12089 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12090 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12091 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12092 12093 /* The entire BCD string fits in lower 110-bits. The LMD value 12094 * is not stored in the final result for the DFP Long instruction. 12095 */ 12096 assign( lmd, mkU32( 0 ) ); 12097 12098 /* Check for invalid sign and invalid BCD digit. Don't check the 12099 * bottom four bits of frBI64_lo as that is the sign value. 12100 */ 12101 assign( zero, mkU32( 0 ) ); 12102 assign( inval_bcd_digit_mask, 12103 binop( Iop_Or32, 12104 bcd_digit_inval( mkexpr( zero ), 12105 unop( Iop_64to32, 12106 mkexpr( bcd_top_8 ) ) ), 12107 binop( Iop_Or32, 12108 bcd_digit_inval( unop( Iop_64HIto32, 12109 mkexpr( bcd_mid_60 ) ), 12110 unop( Iop_64to32, 12111 mkexpr( bcd_mid_60 ) ) ), 12112 bcd_digit_inval( unop( Iop_64HIto32, 12113 mkexpr( frBI64_lo ) ), 12114 binop( Iop_Shr32, 12115 unop( Iop_64to32, 12116 mkexpr( frBI64_lo ) ), 12117 mkU8( 4 ) ) ) ) ) ); 12118 assign( invalid_mask, 12119 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 12120 mkexpr( pos_sign_mask ), 12121 mkexpr( neg_sign_mask ) ) ); 12122 12123 } 12124 12125 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 12126 12127 /* Calculate the value of the result assuming sign and BCD digits 12128 * are all valid. 12129 */ 12130 assign( dfp_significand, 12131 binop( Iop_D64HLtoD128, 12132 unop( Iop_ReinterpI64asD64, 12133 binop( Iop_32HLto64, 12134 binop( Iop_Or32, 12135 mkexpr( sign_bit ), 12136 mkexpr( dbcd_top_l ) ), 12137 binop( Iop_Or32, 12138 binop( Iop_Shl32, 12139 mkexpr( dbcd_mid_u ), 12140 mkU8( 18 ) ), 12141 binop( Iop_Shr32, 12142 mkexpr( dbcd_mid_l ), 12143 mkU8( 14 ) ) ) ) ), 12144 unop( Iop_ReinterpI64asD64, 12145 binop( Iop_32HLto64, 12146 binop( Iop_Or32, 12147 mkexpr( dbcd_low_u ), 12148 binop( Iop_Shl32, 12149 mkexpr( dbcd_mid_l ), 12150 mkU8( 18 ) ) ), 12151 mkexpr( dbcd_low_l ) ) ) ) ); 12152 12153 /* Break the result back down to 32-bit chunks and replace chunks. 12154 * If there was an invalid BCD digit or invalid sign value, replace 12155 * the calculated result with the invalid bit string. 12156 */ 12157 assign( result128, 12158 binop( Iop_InsertExpD128, 12159 mkU64( DFP_EXTND_BIAS ), 12160 mkexpr( dfp_significand ) ) ); 12161 12162 assign( tmp_hi, 12163 unop( Iop_ReinterpD64asI64, 12164 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 12165 12166 assign( tmp_lo, 12167 unop( Iop_ReinterpD64asI64, 12168 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 12169 12170 assign( result_hi, 12171 binop( Iop_32HLto64, 12172 binop( Iop_Or32, 12173 binop( Iop_And32, 12174 mkexpr( valid_mask ), 12175 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 12176 binop( Iop_And32, 12177 mkU32( 0x7C000000 ), 12178 mkexpr( invalid_mask ) ) ), 12179 binop( Iop_Or32, 12180 binop( Iop_And32, 12181 mkexpr( valid_mask ), 12182 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 12183 binop( Iop_And32, 12184 mkU32( 0x0 ), 12185 mkexpr( invalid_mask ) ) ) ) ); 12186 12187 assign( result_lo, 12188 binop( Iop_32HLto64, 12189 binop( Iop_Or32, 12190 binop( Iop_And32, 12191 mkexpr( valid_mask ), 12192 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 12193 binop( Iop_And32, 12194 mkU32( 0x0 ), 12195 mkexpr( invalid_mask ) ) ), 12196 binop( Iop_Or32, 12197 binop( Iop_And32, 12198 mkexpr( valid_mask ), 12199 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 12200 binop( Iop_And32, 12201 mkU32( 0x0 ), 12202 mkexpr( invalid_mask ) ) ) ) ); 12203 12204 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 12205 putDReg( frT_addr + 1, 12206 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 12207 12208 } 12209 break; 12210 default: 12211 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 12212 break; 12213 } 12214 return True; 12215 } 12216 12217 static Bool dis_dfp_significant_digits( UInt theInstr ) 12218 { 12219 UChar frA_addr = ifieldRegA( theInstr ); 12220 UChar frB_addr = ifieldRegB( theInstr ); 12221 IRTemp frA = newTemp( Ity_D64 ); 12222 UInt opc1 = ifieldOPC( theInstr ); 12223 IRTemp B_sig = newTemp( Ity_I8 ); 12224 IRTemp K = newTemp( Ity_I8 ); 12225 IRTemp lmd_B = newTemp( Ity_I32 ); 12226 IRTemp field = newTemp( Ity_I32 ); 12227 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 12228 IRTemp Unordered_true = newTemp( Ity_I32 ); 12229 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 12230 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 12231 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 12232 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 12233 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 12234 12235 /* Get the reference singificance stored in frA */ 12236 assign( frA, getDReg( frA_addr ) ); 12237 12238 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 12239 * supported in 32-bit mode. 12240 */ 12241 assign( K, unop( Iop_32to8, 12242 binop( Iop_And32, 12243 unop( Iop_64to32, 12244 unop( Iop_ReinterpD64asI64, 12245 mkexpr( frA ) ) ), 12246 mkU32( 0x3F ) ) ) ); 12247 12248 switch ( opc1 ) { 12249 case 0x3b: // dtstsf DFP Test Significance 12250 { 12251 IRTemp frB = newTemp( Ity_D64 ); 12252 IRTemp frBI64 = newTemp( Ity_I64 ); 12253 IRTemp B_bcd_u = newTemp( Ity_I32 ); 12254 IRTemp B_bcd_l = newTemp( Ity_I32 ); 12255 IRTemp tmp64 = newTemp( Ity_I64 ); 12256 12257 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12258 12259 assign( frB, getDReg( frB_addr ) ); 12260 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 12261 12262 /* Get the BCD string for the value stored in a series of I32 values. 12263 * Count the number of leading zeros. Subtract the number of leading 12264 * zeros from 16 (maximum number of significant digits in DFP 12265 * Long). 12266 */ 12267 Get_lmd( &lmd_B, 12268 binop( Iop_Shr32, 12269 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 12270 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12271 12272 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 12273 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 12274 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 12275 12276 assign( B_sig, 12277 binop( Iop_Sub8, 12278 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 12279 Count_leading_zeros_60( mkexpr( lmd_B ), 12280 mkexpr( B_bcd_u ), 12281 mkexpr( B_bcd_l ) ) ) ); 12282 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) ); 12283 } 12284 break; 12285 case 0x3F: // dtstsfq DFP Test Significance 12286 { 12287 IRTemp frB_hi = newTemp( Ity_D64 ); 12288 IRTemp frB_lo = newTemp( Ity_D64 ); 12289 IRTemp frBI64_hi = newTemp( Ity_I64 ); 12290 IRTemp frBI64_lo = newTemp( Ity_I64 ); 12291 IRTemp B_low_60_u = newTemp( Ity_I32 ); 12292 IRTemp B_low_60_l = newTemp( Ity_I32 ); 12293 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 12294 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 12295 IRTemp B_top_12_l = newTemp( Ity_I32 ); 12296 12297 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12298 12299 assign( frB_hi, getDReg( frB_addr ) ); 12300 assign( frB_lo, getDReg( frB_addr + 1 ) ); 12301 12302 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 12303 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 12304 12305 /* Get the BCD string for the value stored in a series of I32 values. 12306 * Count the number of leading zeros. Subtract the number of leading 12307 * zeros from 32 (maximum number of significant digits in DFP 12308 * extended). 12309 */ 12310 Get_lmd( &lmd_B, 12311 binop( Iop_Shr32, 12312 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12313 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12314 12315 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 12316 mkexpr( frBI64_lo ), 12317 &B_top_12_l, 12318 &B_mid_60_u, 12319 &B_mid_60_l, 12320 &B_low_60_u, 12321 &B_low_60_l ); 12322 12323 assign( B_sig, 12324 binop( Iop_Sub8, 12325 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 12326 Count_leading_zeros_128( mkexpr( lmd_B ), 12327 mkexpr( B_top_12_l ), 12328 mkexpr( B_mid_60_u ), 12329 mkexpr( B_mid_60_l ), 12330 mkexpr( B_low_60_u ), 12331 mkexpr( B_low_60_l ) ) ) ); 12332 12333 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) ); 12334 } 12335 break; 12336 } 12337 12338 /* Compare (16 - cnt[0]) against K and set the condition code field 12339 * accordingly. 12340 * 12341 * The field layout is as follows: 12342 * 12343 * bit[3:0] Description 12344 * 3 K != 0 and K < Number of significant digits if FRB 12345 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 12346 * 1 K != 0 and K = Number of significant digits if FRB 12347 * 0 K ? Number of significant digits if FRB 12348 */ 12349 assign( Eq_true_mask, 12350 unop( Iop_1Sto32, 12351 binop( Iop_CmpEQ32, 12352 unop( Iop_8Uto32, mkexpr( K ) ), 12353 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12354 assign( Lt_true_mask, 12355 unop( Iop_1Sto32, 12356 binop( Iop_CmpLT32U, 12357 unop( Iop_8Uto32, mkexpr( K ) ), 12358 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12359 assign( Gt_true_mask, 12360 unop( Iop_1Sto32, 12361 binop( Iop_CmpLT32U, 12362 unop( Iop_8Uto32, mkexpr( B_sig ) ), 12363 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 12364 12365 assign( KisZero_true_mask, 12366 unop( Iop_1Sto32, 12367 binop( Iop_CmpEQ32, 12368 unop( Iop_8Uto32, mkexpr( K ) ), 12369 mkU32( 0 ) ) ) ); 12370 assign( KisZero_false_mask, 12371 unop( Iop_1Sto32, 12372 binop( Iop_CmpNE32, 12373 unop( Iop_8Uto32, mkexpr( K ) ), 12374 mkU32( 0 ) ) ) ); 12375 12376 assign( field, 12377 binop( Iop_Or32, 12378 binop( Iop_And32, 12379 mkexpr( KisZero_false_mask ), 12380 binop( Iop_Or32, 12381 binop( Iop_And32, 12382 mkexpr( Lt_true_mask ), 12383 mkU32( 0x8 ) ), 12384 binop( Iop_Or32, 12385 binop( Iop_And32, 12386 mkexpr( Gt_true_mask ), 12387 mkU32( 0x4 ) ), 12388 binop( Iop_And32, 12389 mkexpr( Eq_true_mask ), 12390 mkU32( 0x2 ) ) ) ) ), 12391 binop( Iop_And32, 12392 mkexpr( KisZero_true_mask ), 12393 mkU32( 0x4 ) ) ) ); 12394 12395 putGST_field( PPC_GST_CR, 12396 binop( Iop_Or32, 12397 binop( Iop_And32, 12398 mkexpr( Unordered_true ), 12399 mkU32( 0x1 ) ), 12400 binop( Iop_And32, 12401 unop( Iop_Not32, mkexpr( Unordered_true ) ), 12402 mkexpr( field ) ) ), 12403 crfD ); 12404 12405 return True; 12406 } 12407 12408 /*------------------------------------------------------------*/ 12409 /*--- AltiVec Instruction Translation ---*/ 12410 /*------------------------------------------------------------*/ 12411 12412 /* 12413 Altivec Cache Control Instructions (Data Streams) 12414 */ 12415 static Bool dis_av_datastream ( UInt theInstr ) 12416 { 12417 /* X-Form */ 12418 UChar opc1 = ifieldOPC(theInstr); 12419 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 12420 UChar flag_A = flag_T; 12421 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 12422 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 12423 UChar rA_addr = ifieldRegA(theInstr); 12424 UChar rB_addr = ifieldRegB(theInstr); 12425 UInt opc2 = ifieldOPClo10(theInstr); 12426 UChar b0 = ifieldBIT0(theInstr); 12427 12428 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 12429 vex_printf("dis_av_datastream(ppc)(instr)\n"); 12430 return False; 12431 } 12432 12433 switch (opc2) { 12434 case 0x156: // dst (Data Stream Touch, AV p115) 12435 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12436 rA_addr, rB_addr, STRM); 12437 break; 12438 12439 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 12440 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12441 rA_addr, rB_addr, STRM); 12442 break; 12443 12444 case 0x336: // dss (Data Stream Stop, AV p114) 12445 if (rA_addr != 0 || rB_addr != 0) { 12446 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 12447 return False; 12448 } 12449 if (flag_A == 0) { 12450 DIP("dss %d\n", STRM); 12451 } else { 12452 DIP("dssall\n"); 12453 } 12454 break; 12455 12456 default: 12457 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 12458 return False; 12459 } 12460 return True; 12461 } 12462 12463 /* 12464 AltiVec Processor Control Instructions 12465 */ 12466 static Bool dis_av_procctl ( UInt theInstr ) 12467 { 12468 /* VX-Form */ 12469 UChar opc1 = ifieldOPC(theInstr); 12470 UChar vD_addr = ifieldRegDS(theInstr); 12471 UChar vA_addr = ifieldRegA(theInstr); 12472 UChar vB_addr = ifieldRegB(theInstr); 12473 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12474 12475 if (opc1 != 0x4) { 12476 vex_printf("dis_av_procctl(ppc)(instr)\n"); 12477 return False; 12478 } 12479 12480 switch (opc2) { 12481 case 0x604: // mfvscr (Move from VSCR, AV p129) 12482 if (vA_addr != 0 || vB_addr != 0) { 12483 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12484 return False; 12485 } 12486 DIP("mfvscr v%d\n", vD_addr); 12487 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 12488 break; 12489 12490 case 0x644: { // mtvscr (Move to VSCR, AV p130) 12491 IRTemp vB = newTemp(Ity_V128); 12492 if (vD_addr != 0 || vA_addr != 0) { 12493 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12494 return False; 12495 } 12496 DIP("mtvscr v%d\n", vB_addr); 12497 assign( vB, getVReg(vB_addr)); 12498 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 12499 break; 12500 } 12501 default: 12502 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 12503 return False; 12504 } 12505 return True; 12506 } 12507 12508 /* 12509 * VSX scalar and vector convert instructions 12510 */ 12511 static Bool 12512 dis_vx_conv ( UInt theInstr, UInt opc2 ) 12513 { 12514 /* XX2-Form */ 12515 UChar opc1 = ifieldOPC( theInstr ); 12516 UChar XT = ifieldRegXT( theInstr ); 12517 UChar XB = ifieldRegXB( theInstr ); 12518 IRTemp xB, xB2; 12519 IRTemp b3, b2, b1, b0; 12520 xB = xB2 = IRTemp_INVALID; 12521 12522 if (opc1 != 0x3C) { 12523 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 12524 return False; 12525 } 12526 12527 /* Create and assign temps only as needed for the given instruction. */ 12528 switch (opc2) { 12529 // scalar double-precision floating point argument 12530 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090: 12531 xB = newTemp(Ity_F64); 12532 assign( xB, 12533 unop( Iop_ReinterpI64asF64, 12534 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12535 break; 12536 // vector double-precision floating point arguments 12537 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 12538 12539 xB = newTemp(Ity_F64); 12540 xB2 = newTemp(Ity_F64); 12541 assign( xB, 12542 unop( Iop_ReinterpI64asF64, 12543 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12544 assign( xB2, 12545 unop( Iop_ReinterpI64asF64, 12546 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 12547 break; 12548 // vector single precision or [un]signed integer word arguments 12549 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 12550 case 0x1f0: case 0x1d0: 12551 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12552 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 12553 break; 12554 // vector [un]signed integer doubleword argument 12555 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 12556 xB = newTemp(Ity_I64); 12557 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12558 xB2 = newTemp(Ity_I64); 12559 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 12560 break; 12561 // scalar [un]signed integer doubleword argument 12562 case 0x250: case 0x270: case 0x2D0: case 0x2F0: 12563 xB = newTemp(Ity_I64); 12564 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12565 break; 12566 // scalar single precision argument 12567 case 0x292: // xscvspdp 12568 xB = newTemp(Ity_I32); 12569 12570 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32, 12571 unop( Iop_V128HIto64, 12572 getVSReg( XB ) ) ) ) ); 12573 break; 12574 case 0x296: // xscvspdpn (non signaling version of xscvpdp) 12575 xB = newTemp(Ity_I32); 12576 assign( xB, 12577 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12578 break; 12579 12580 /* Certain instructions have their complete implementation in the main switch statement 12581 * that follows this one; thus we have a "do nothing" case for those instructions here. 12582 */ 12583 case 0x170: case 0x150: 12584 break; // do nothing 12585 12586 default: 12587 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12588 return False; 12589 } 12590 12591 12592 switch (opc2) { 12593 case 0x2B0: 12594 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 12595 // to Signed Integer Doubleword format with Saturate) 12596 DIP("xscvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12597 putVSReg( XT, 12598 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 12599 mkU32( Irrm_ZERO ), 12600 mkexpr( xB ) ), mkU64( 0 ) ) ); 12601 break; 12602 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 12603 // Convert to Signed Integer Word format with Saturate) 12604 DIP("xscvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12605 putVSReg( XT, 12606 binop( Iop_64HLtoV128, 12607 unop( Iop_32Sto64, 12608 binop( Iop_F64toI32S, 12609 mkU32( Irrm_ZERO ), 12610 mkexpr( xB ) ) ), 12611 mkU64( 0ULL ) ) ); 12612 break; 12613 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 12614 // to Unsigned Integer Doubleword format with Saturate) 12615 DIP("xscvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12616 putVSReg( XT, 12617 binop( Iop_64HLtoV128, 12618 binop( Iop_F64toI64U, 12619 mkU32( Irrm_ZERO ), 12620 mkexpr( xB ) ), 12621 mkU64( 0ULL ) ) ); 12622 break; 12623 case 0x270: 12624 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword 12625 // to Single-Precision format) 12626 DIP("xscvsxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12627 putVSReg( XT, 12628 binop( Iop_64HLtoV128, 12629 unop( Iop_ReinterpF64asI64, 12630 binop( Iop_RoundF64toF32, 12631 get_IR_roundingmode(), 12632 binop( Iop_I64StoF64, 12633 get_IR_roundingmode(), 12634 mkexpr( xB ) ) ) ), 12635 mkU64( 0 ) ) ); 12636 break; 12637 case 0x2F0: 12638 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 12639 // Double-Precision format) 12640 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12641 putVSReg( XT, 12642 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12643 binop( Iop_I64StoF64, get_IR_roundingmode(), 12644 mkexpr( xB ) ) ), 12645 mkU64( 0 ) ) ); 12646 break; 12647 case 0x250: 12648 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer 12649 // Doubleword to Singel-Precision format) 12650 DIP("xscvuxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12651 putVSReg( XT, 12652 binop( Iop_64HLtoV128, 12653 unop( Iop_ReinterpF64asI64, 12654 binop( Iop_RoundF64toF32, 12655 get_IR_roundingmode(), 12656 binop( Iop_I64UtoF64, 12657 get_IR_roundingmode(), 12658 mkexpr( xB ) ) ) ), 12659 mkU64( 0 ) ) ); 12660 break; 12661 case 0x2D0: 12662 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 12663 // Double-Precision format) 12664 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12665 putVSReg( XT, 12666 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12667 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12668 mkexpr( xB ) ) ), 12669 mkU64( 0 ) ) ); 12670 break; 12671 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 12672 // to Signed Integer Word format with Saturate) 12673 { 12674 IRTemp hiResult_32 = newTemp(Ity_I32); 12675 IRTemp loResult_32 = newTemp(Ity_I32); 12676 IRExpr* rmZero = mkU32(Irrm_ZERO); 12677 12678 DIP("xvcvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12679 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 12680 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 12681 putVSReg( XT, 12682 binop( Iop_64HLtoV128, 12683 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 12684 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 12685 break; 12686 } 12687 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 12688 // (VSX Vector truncate Single-Precision to integer and 12689 // Convert to [Un]signed Integer Word format with Saturate) 12690 { 12691 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 12692 IRTemp tempResult = newTemp(Ity_V128); 12693 IRTemp res0 = newTemp(Ity_I32); 12694 IRTemp res1 = newTemp(Ity_I32); 12695 IRTemp res2 = newTemp(Ity_I32); 12696 IRTemp res3 = newTemp(Ity_I32); 12697 IRTemp hi64 = newTemp(Ity_I64); 12698 IRTemp lo64 = newTemp(Ity_I64); 12699 Bool un_signed = (opc2 == 0x110); 12700 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 12701 12702 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB); 12703 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 12704 * then result is set to 0x80000000. */ 12705 assign(tempResult, unop(op, getVSReg(XB))); 12706 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 12707 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 12708 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 12709 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 12710 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 12711 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 12712 12713 b3_result = IRExpr_ITE(is_NaN_32(b3), 12714 // then: result is 0x{8|0}80000000 12715 mkU32(un_signed ? 0x00000000 : 0x80000000), 12716 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12717 mkexpr(res3)); 12718 b2_result = IRExpr_ITE(is_NaN_32(b2), 12719 // then: result is 0x{8|0}80000000 12720 mkU32(un_signed ? 0x00000000 : 0x80000000), 12721 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12722 mkexpr(res2)); 12723 b1_result = IRExpr_ITE(is_NaN_32(b1), 12724 // then: result is 0x{8|0}80000000 12725 mkU32(un_signed ? 0x00000000 : 0x80000000), 12726 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12727 mkexpr(res1)); 12728 b0_result = IRExpr_ITE(is_NaN_32(b0), 12729 // then: result is 0x{8|0}80000000 12730 mkU32(un_signed ? 0x00000000 : 0x80000000), 12731 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12732 mkexpr(res0)); 12733 12734 putVSReg( XT, 12735 binop( Iop_64HLtoV128, 12736 binop( Iop_32HLto64, b3_result, b2_result ), 12737 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 12738 break; 12739 } 12740 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 12741 // Convert to Single-Precision format 12742 DIP("xscvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12743 putVSReg( XT, 12744 binop( Iop_64HLtoV128, 12745 binop( Iop_32HLto64, 12746 unop( Iop_ReinterpF32asI32, 12747 unop( Iop_TruncF64asF32, 12748 binop( Iop_RoundF64toF32, 12749 get_IR_roundingmode(), 12750 mkexpr( xB ) ) ) ), 12751 mkU32( 0 ) ), 12752 mkU64( 0ULL ) ) ); 12753 break; 12754 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to 12755 vector Single-Precision non-signalling */ 12756 DIP("xscvdpspn v%u,v%u\n", (UInt)XT, (UInt)XB); 12757 putVSReg( XT, 12758 binop( Iop_64HLtoV128, 12759 binop( Iop_32HLto64, 12760 unop( Iop_ReinterpF32asI32, 12761 unop( Iop_TruncF64asF32, 12762 mkexpr( xB ) ) ), 12763 mkU32( 0 ) ), 12764 mkU64( 0ULL ) ) ); 12765 break; 12766 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 12767 // and Convert to Unsigned Integer Word format with Saturate) 12768 DIP("xscvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12769 putVSReg( XT, 12770 binop( Iop_64HLtoV128, 12771 binop( Iop_32HLto64, 12772 mkU32( 0 ), 12773 binop( Iop_F64toI32U, 12774 mkU32( Irrm_ZERO ), 12775 mkexpr( xB ) ) ), 12776 mkU64( 0ULL ) ) ); 12777 break; 12778 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling) 12779 DIP("xscvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12780 putVSReg( XT, 12781 binop( Iop_64HLtoV128, 12782 unop( Iop_ReinterpF64asI64, 12783 unop( Iop_F32toF64, 12784 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12785 mkU64( 0ULL ) ) ); 12786 break; 12787 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling) 12788 DIP("xscvspdpn v%u,v%u\n", (UInt)XT, (UInt)XB); 12789 putVSReg( XT, 12790 binop( Iop_64HLtoV128, 12791 unop( Iop_ReinterpF64asI64, 12792 unop( Iop_F32toF64, 12793 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12794 mkU64( 0ULL ) ) ); 12795 break; 12796 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 12797 // and Convert to Single-Precision format) 12798 DIP("xvcvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12799 putVSReg( XT, 12800 binop( Iop_64HLtoV128, 12801 binop( Iop_32HLto64, 12802 unop( Iop_ReinterpF32asI32, 12803 unop( Iop_TruncF64asF32, 12804 binop( Iop_RoundF64toF32, 12805 get_IR_roundingmode(), 12806 mkexpr( xB ) ) ) ), 12807 mkU32( 0 ) ), 12808 binop( Iop_32HLto64, 12809 unop( Iop_ReinterpF32asI32, 12810 unop( Iop_TruncF64asF32, 12811 binop( Iop_RoundF64toF32, 12812 get_IR_roundingmode(), 12813 mkexpr( xB2 ) ) ) ), 12814 mkU32( 0 ) ) ) ); 12815 break; 12816 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 12817 // and Convert to Unsigned Integer Doubleword format 12818 // with Saturate) 12819 DIP("xvcvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12820 putVSReg( XT, 12821 binop( Iop_64HLtoV128, 12822 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12823 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12824 break; 12825 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 12826 // Convert to Unsigned Integer Word format with Saturate) 12827 DIP("xvcvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12828 putVSReg( XT, 12829 binop( Iop_64HLtoV128, 12830 binop( Iop_32HLto64, 12831 binop( Iop_F64toI32U, 12832 mkU32( Irrm_ZERO ), 12833 mkexpr( xB ) ), 12834 mkU32( 0 ) ), 12835 binop( Iop_32HLto64, 12836 binop( Iop_F64toI32U, 12837 mkU32( Irrm_ZERO ), 12838 mkexpr( xB2 ) ), 12839 mkU32( 0 ) ) ) ); 12840 break; 12841 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 12842 DIP("xvcvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12843 putVSReg( XT, 12844 binop( Iop_64HLtoV128, 12845 unop( Iop_ReinterpF64asI64, 12846 unop( Iop_F32toF64, 12847 unop( Iop_ReinterpI32asF32, 12848 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ), 12849 unop( Iop_ReinterpF64asI64, 12850 unop( Iop_F32toF64, 12851 unop( Iop_ReinterpI32asF32, 12852 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) ); 12853 break; 12854 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 12855 // Convert to Signed Integer Doubleword format with Saturate) 12856 DIP("xvcvspsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12857 putVSReg( XT, 12858 binop( Iop_64HLtoV128, 12859 binop( Iop_F64toI64S, 12860 mkU32( Irrm_ZERO ), 12861 unop( Iop_F32toF64, 12862 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12863 binop( Iop_F64toI64S, 12864 mkU32( Irrm_ZERO ), 12865 unop( Iop_F32toF64, 12866 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12867 break; 12868 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 12869 // Convert to Unsigned Integer Doubleword format with Saturate) 12870 DIP("xvcvspuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12871 putVSReg( XT, 12872 binop( Iop_64HLtoV128, 12873 binop( Iop_F64toI64U, 12874 mkU32( Irrm_ZERO ), 12875 unop( Iop_F32toF64, 12876 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12877 binop( Iop_F64toI64U, 12878 mkU32( Irrm_ZERO ), 12879 unop( Iop_F32toF64, 12880 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12881 break; 12882 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 12883 // Convert to Signed Integer Doubleword format with Saturate) 12884 DIP("xvcvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12885 putVSReg( XT, 12886 binop( Iop_64HLtoV128, 12887 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12888 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12889 break; 12890 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 12891 // to Double-Precision format) 12892 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12893 putVSReg( XT, 12894 binop( Iop_64HLtoV128, 12895 unop( Iop_ReinterpF64asI64, 12896 binop( Iop_I64StoF64, 12897 get_IR_roundingmode(), 12898 mkexpr( xB ) ) ), 12899 unop( Iop_ReinterpF64asI64, 12900 binop( Iop_I64StoF64, 12901 get_IR_roundingmode(), 12902 mkexpr( xB2 ) ) ) ) ); 12903 break; 12904 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 12905 // to Double-Precision format) 12906 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12907 putVSReg( XT, 12908 binop( Iop_64HLtoV128, 12909 unop( Iop_ReinterpF64asI64, 12910 binop( Iop_I64UtoF64, 12911 get_IR_roundingmode(), 12912 mkexpr( xB ) ) ), 12913 unop( Iop_ReinterpF64asI64, 12914 binop( Iop_I64UtoF64, 12915 get_IR_roundingmode(), 12916 mkexpr( xB2 ) ) ) ) ); 12917 12918 break; 12919 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 12920 // to Single-Precision format) 12921 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12922 putVSReg( XT, 12923 binop( Iop_64HLtoV128, 12924 binop( Iop_32HLto64, 12925 unop( Iop_ReinterpF32asI32, 12926 unop( Iop_TruncF64asF32, 12927 binop( Iop_RoundF64toF32, 12928 get_IR_roundingmode(), 12929 binop( Iop_I64StoF64, 12930 get_IR_roundingmode(), 12931 mkexpr( xB ) ) ) ) ), 12932 mkU32( 0 ) ), 12933 binop( Iop_32HLto64, 12934 unop( Iop_ReinterpF32asI32, 12935 unop( Iop_TruncF64asF32, 12936 binop( Iop_RoundF64toF32, 12937 get_IR_roundingmode(), 12938 binop( Iop_I64StoF64, 12939 get_IR_roundingmode(), 12940 mkexpr( xB2 ) ) ) ) ), 12941 mkU32( 0 ) ) ) ); 12942 break; 12943 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 12944 // to Single-Precision format) 12945 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12946 putVSReg( XT, 12947 binop( Iop_64HLtoV128, 12948 binop( Iop_32HLto64, 12949 unop( Iop_ReinterpF32asI32, 12950 unop( Iop_TruncF64asF32, 12951 binop( Iop_RoundF64toF32, 12952 get_IR_roundingmode(), 12953 binop( Iop_I64UtoF64, 12954 get_IR_roundingmode(), 12955 mkexpr( xB ) ) ) ) ), 12956 mkU32( 0 ) ), 12957 binop( Iop_32HLto64, 12958 unop( Iop_ReinterpF32asI32, 12959 unop( Iop_TruncF64asF32, 12960 binop( Iop_RoundF64toF32, 12961 get_IR_roundingmode(), 12962 binop( Iop_I64UtoF64, 12963 get_IR_roundingmode(), 12964 mkexpr( xB2 ) ) ) ) ), 12965 mkU32( 0 ) ) ) ); 12966 break; 12967 12968 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 12969 DIP("xvcvsxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12970 putVSReg( XT, 12971 binop( Iop_64HLtoV128, 12972 unop( Iop_ReinterpF64asI64, 12973 binop( Iop_I64StoF64, get_IR_roundingmode(), 12974 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 12975 unop( Iop_ReinterpF64asI64, 12976 binop( Iop_I64StoF64, get_IR_roundingmode(), 12977 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 12978 break; 12979 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 12980 DIP("xvcvuxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12981 putVSReg( XT, 12982 binop( Iop_64HLtoV128, 12983 unop( Iop_ReinterpF64asI64, 12984 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12985 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 12986 unop( Iop_ReinterpF64asI64, 12987 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12988 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 12989 break; 12990 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 12991 DIP("xvcvsxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12992 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 12993 break; 12994 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 12995 DIP("xvcvuxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12996 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 12997 break; 12998 12999 default: 13000 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 13001 return False; 13002 } 13003 return True; 13004 } 13005 13006 /* 13007 * VSX vector Double Precision Floating Point Arithmetic Instructions 13008 */ 13009 static Bool 13010 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 13011 { 13012 /* XX3-Form */ 13013 UChar opc1 = ifieldOPC( theInstr ); 13014 UChar XT = ifieldRegXT( theInstr ); 13015 UChar XA = ifieldRegXA( theInstr ); 13016 UChar XB = ifieldRegXB( theInstr ); 13017 IRExpr* rm = get_IR_roundingmode(); 13018 IRTemp frA = newTemp(Ity_F64); 13019 IRTemp frB = newTemp(Ity_F64); 13020 IRTemp frA2 = newTemp(Ity_F64); 13021 IRTemp frB2 = newTemp(Ity_F64); 13022 13023 if (opc1 != 0x3C) { 13024 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 13025 return False; 13026 } 13027 13028 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 13029 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13030 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 13031 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 13032 13033 switch (opc2) { 13034 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 13035 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 13036 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 13037 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 13038 { 13039 IROp mOp; 13040 const HChar * oper_name; 13041 switch (opc2) { 13042 case 0x1E0: 13043 mOp = Iop_DivF64; 13044 oper_name = "div"; 13045 break; 13046 case 0x1C0: 13047 mOp = Iop_MulF64; 13048 oper_name = "mul"; 13049 break; 13050 case 0x180: 13051 mOp = Iop_AddF64; 13052 oper_name = "add"; 13053 break; 13054 case 0x1A0: 13055 mOp = Iop_SubF64; 13056 oper_name = "sub"; 13057 break; 13058 13059 default: 13060 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 13061 } 13062 IRTemp hiResult = newTemp(Ity_I64); 13063 IRTemp loResult = newTemp(Ity_I64); 13064 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB); 13065 13066 assign( hiResult, 13067 unop( Iop_ReinterpF64asI64, 13068 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 13069 assign( loResult, 13070 unop( Iop_ReinterpF64asI64, 13071 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 13072 putVSReg( XT, 13073 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13074 break; 13075 } 13076 case 0x196: // xvsqrtdp 13077 { 13078 IRTemp hiResult = newTemp(Ity_I64); 13079 IRTemp loResult = newTemp(Ity_I64); 13080 DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13081 13082 assign( hiResult, 13083 unop( Iop_ReinterpF64asI64, 13084 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 13085 assign( loResult, 13086 unop( Iop_ReinterpF64asI64, 13087 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 13088 putVSReg( XT, 13089 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13090 break; 13091 } 13092 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 13093 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 13094 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 13095 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 13096 { 13097 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 13098 * XT == FRC 13099 * XA == FRA 13100 * XB == FRB 13101 * 13102 * and for xvm{add|sub}adp . . . 13103 * XT == FRB 13104 * XA == FRA 13105 * XB == FRC 13106 */ 13107 Bool negate; 13108 IROp mOp = Iop_INVALID; 13109 const HChar * oper_name = NULL; 13110 Bool mdp = False; 13111 13112 switch (opc2) { 13113 case 0x184: case 0x1A4: 13114 case 0x384: case 0x3A4: 13115 mOp = Iop_MAddF64; 13116 oper_name = "add"; 13117 mdp = (opc2 & 0x0FF) == 0x0A4; 13118 break; 13119 13120 case 0x1C4: case 0x1E4: 13121 case 0x3C4: case 0x3E4: 13122 mOp = Iop_MSubF64; 13123 oper_name = "sub"; 13124 mdp = (opc2 & 0x0FF) == 0x0E4; 13125 break; 13126 13127 default: 13128 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13129 } 13130 13131 switch (opc2) { 13132 case 0x384: case 0x3A4: 13133 case 0x3C4: case 0x3E4: 13134 negate = True; 13135 break; 13136 default: 13137 negate = False; 13138 } 13139 IRTemp hiResult = newTemp(Ity_I64); 13140 IRTemp loResult = newTemp(Ity_I64); 13141 IRTemp frT = newTemp(Ity_F64); 13142 IRTemp frT2 = newTemp(Ity_F64); 13143 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 13144 (UInt)XT, (UInt)XA, (UInt)XB); 13145 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 13146 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 13147 13148 assign( hiResult, 13149 unop( Iop_ReinterpF64asI64, 13150 qop( mOp, 13151 rm, 13152 mkexpr( frA ), 13153 mkexpr( mdp ? frT : frB ), 13154 mkexpr( mdp ? frB : frT ) ) ) ); 13155 assign( loResult, 13156 unop( Iop_ReinterpF64asI64, 13157 qop( mOp, 13158 rm, 13159 mkexpr( frA2 ), 13160 mkexpr( mdp ? frT2 : frB2 ), 13161 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 13162 putVSReg( XT, 13163 binop( Iop_64HLtoV128, 13164 mkexpr( negate ? getNegatedResult( hiResult ) 13165 : hiResult ), 13166 mkexpr( negate ? getNegatedResult( loResult ) 13167 : loResult ) ) ); 13168 break; 13169 } 13170 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 13171 { 13172 IRTemp frBHi_I64 = newTemp(Ity_I64); 13173 IRTemp frBLo_I64 = newTemp(Ity_I64); 13174 IRTemp flagsHi = newTemp(Ity_I32); 13175 IRTemp flagsLo = newTemp(Ity_I32); 13176 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13177 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13178 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13179 13180 DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 13181 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13182 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13183 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 13184 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 13185 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13186 * where fl_flag == 1 on ppc64. 13187 */ 13188 assign( flagsHi, 13189 binop( Iop_Or32, 13190 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13191 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13192 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13193 assign( flagsLo, 13194 binop( Iop_Or32, 13195 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13196 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13197 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13198 putGST_field( PPC_GST_CR, 13199 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13200 crfD ); 13201 break; 13202 } 13203 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 13204 { 13205 IRTemp frBHi_I64 = newTemp(Ity_I64); 13206 IRTemp frBLo_I64 = newTemp(Ity_I64); 13207 IRTemp frAHi_I64 = newTemp(Ity_I64); 13208 IRTemp frALo_I64 = newTemp(Ity_I64); 13209 IRTemp flagsHi = newTemp(Ity_I32); 13210 IRTemp flagsLo = newTemp(Ity_I32); 13211 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13212 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13213 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13214 13215 DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 13216 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 13217 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 13218 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13219 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13220 13221 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 13222 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 13223 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13224 * where fl_flag == 1 on ppc64. 13225 */ 13226 assign( flagsHi, 13227 binop( Iop_Or32, 13228 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13229 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13230 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13231 assign( flagsLo, 13232 binop( Iop_Or32, 13233 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13234 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13235 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13236 putGST_field( PPC_GST_CR, 13237 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13238 crfD ); 13239 break; 13240 } 13241 13242 default: 13243 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 13244 return False; 13245 } 13246 return True; 13247 } 13248 13249 /* 13250 * VSX vector Single Precision Floating Point Arithmetic Instructions 13251 */ 13252 static Bool 13253 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 13254 { 13255 /* XX3-Form */ 13256 UChar opc1 = ifieldOPC( theInstr ); 13257 UChar XT = ifieldRegXT( theInstr ); 13258 UChar XA = ifieldRegXA( theInstr ); 13259 UChar XB = ifieldRegXB( theInstr ); 13260 IRExpr* rm = get_IR_roundingmode(); 13261 IRTemp a3, a2, a1, a0; 13262 IRTemp b3, b2, b1, b0; 13263 IRTemp res0 = newTemp(Ity_I32); 13264 IRTemp res1 = newTemp(Ity_I32); 13265 IRTemp res2 = newTemp(Ity_I32); 13266 IRTemp res3 = newTemp(Ity_I32); 13267 13268 a3 = a2 = a1 = a0 = IRTemp_INVALID; 13269 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13270 13271 if (opc1 != 0x3C) { 13272 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 13273 return False; 13274 } 13275 13276 switch (opc2) { 13277 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 13278 DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13279 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4 13280 putVSReg( XT, triop(Iop_Add32Fx4, rm, 13281 getVSReg( XA ), getVSReg( XB )) ); 13282 break; 13283 13284 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 13285 DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13286 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4 13287 putVSReg( XT, triop(Iop_Mul32Fx4, rm, 13288 getVSReg( XA ), getVSReg( XB )) ); 13289 break; 13290 13291 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 13292 DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13293 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4 13294 putVSReg( XT, triop(Iop_Sub32Fx4, rm, 13295 getVSReg( XA ), getVSReg( XB )) ); 13296 break; 13297 13298 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 13299 { 13300 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 13301 * So there are two choices: 13302 * 1. Implement the xvdivsp with a native insn; or 13303 * 2. Extract the 4 single precision floats from each vector 13304 * register inputs and perform fdivs on each pair 13305 * I will do the latter, due to the general philosophy of 13306 * reusing existing implementations when practical. 13307 */ 13308 DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13309 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13310 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13311 13312 assign( res0, 13313 unop( Iop_ReinterpF32asI32, 13314 unop( Iop_TruncF64asF32, 13315 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 13316 assign( res1, 13317 unop( Iop_ReinterpF32asI32, 13318 unop( Iop_TruncF64asF32, 13319 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 13320 assign( res2, 13321 unop( Iop_ReinterpF32asI32, 13322 unop( Iop_TruncF64asF32, 13323 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 13324 assign( res3, 13325 unop( Iop_ReinterpF32asI32, 13326 unop( Iop_TruncF64asF32, 13327 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 13328 13329 putVSReg( XT, 13330 binop( Iop_64HLtoV128, 13331 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13332 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13333 break; 13334 } 13335 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 13336 { 13337 DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 13338 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13339 /* Note: The native xvsqrtsp insruction does not always give the same precision 13340 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 13341 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 13342 * to the actual instruction. 13343 */ 13344 13345 assign( res0, 13346 unop( Iop_ReinterpF32asI32, 13347 unop( Iop_TruncF64asF32, 13348 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 13349 assign( res1, 13350 unop( Iop_ReinterpF32asI32, 13351 unop( Iop_TruncF64asF32, 13352 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 13353 assign( res2, 13354 unop( Iop_ReinterpF32asI32, 13355 unop( Iop_TruncF64asF32, 13356 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 13357 assign( res3, 13358 unop( Iop_ReinterpF32asI32, 13359 unop( Iop_TruncF64asF32, 13360 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 13361 13362 putVSReg( XT, 13363 binop( Iop_64HLtoV128, 13364 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13365 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13366 break; 13367 } 13368 13369 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 13370 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 13371 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 13372 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 13373 { 13374 IRTemp t3, t2, t1, t0; 13375 Bool msp = False; 13376 Bool negate; 13377 const HChar * oper_name = NULL; 13378 IROp mOp = Iop_INVALID; 13379 switch (opc2) { 13380 case 0x104: case 0x124: 13381 case 0x304: case 0x324: 13382 msp = (opc2 & 0x0FF) == 0x024; 13383 mOp = Iop_MAddF64r32; 13384 oper_name = "madd"; 13385 break; 13386 13387 case 0x144: case 0x164: 13388 case 0x344: case 0x364: 13389 msp = (opc2 & 0x0FF) == 0x064; 13390 mOp = Iop_MSubF64r32; 13391 oper_name = "sub"; 13392 break; 13393 13394 default: 13395 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13396 } 13397 13398 switch (opc2) { 13399 case 0x304: case 0x324: 13400 case 0x344: case 0x364: 13401 negate = True; 13402 break; 13403 13404 default: 13405 negate = False; 13406 } 13407 13408 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp", 13409 (UInt)XT, (UInt)XA, (UInt)XB); 13410 13411 t3 = t2 = t1 = t0 = IRTemp_INVALID; 13412 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13413 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13414 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 13415 13416 assign( res0, 13417 unop( Iop_ReinterpF32asI32, 13418 unop( Iop_TruncF64asF32, 13419 qop( mOp, 13420 rm, 13421 mkexpr( a0 ), 13422 mkexpr( msp ? t0 : b0 ), 13423 mkexpr( msp ? b0 : t0 ) ) ) ) ); 13424 assign( res1, 13425 unop( Iop_ReinterpF32asI32, 13426 unop( Iop_TruncF64asF32, 13427 qop( mOp, 13428 rm, 13429 mkexpr( a1 ), 13430 mkexpr( msp ? t1 : b1 ), 13431 mkexpr( msp ? b1 : t1 ) ) ) ) ); 13432 assign( res2, 13433 unop( Iop_ReinterpF32asI32, 13434 unop( Iop_TruncF64asF32, 13435 qop( mOp, 13436 rm, 13437 mkexpr( a2 ), 13438 mkexpr( msp ? t2 : b2 ), 13439 mkexpr( msp ? b2 : t2 ) ) ) ) ); 13440 assign( res3, 13441 unop( Iop_ReinterpF32asI32, 13442 unop( Iop_TruncF64asF32, 13443 qop( mOp, 13444 rm, 13445 mkexpr( a3 ), 13446 mkexpr( msp ? t3 : b3 ), 13447 mkexpr( msp ? b3 : t3 ) ) ) ) ); 13448 13449 putVSReg( XT, 13450 binop( Iop_64HLtoV128, 13451 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 13452 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 13453 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 13454 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 13455 13456 break; 13457 } 13458 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 13459 { 13460 IRTemp flags0 = newTemp(Ity_I32); 13461 IRTemp flags1 = newTemp(Ity_I32); 13462 IRTemp flags2 = newTemp(Ity_I32); 13463 IRTemp flags3 = newTemp(Ity_I32); 13464 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13465 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13466 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13467 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13468 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13469 DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 13470 13471 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13472 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13473 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13474 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13475 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13476 13477 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13478 * where fl_flag == 1 on ppc64. 13479 */ 13480 assign( flags0, 13481 binop( Iop_Or32, 13482 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13483 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13484 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13485 assign( flags1, 13486 binop( Iop_Or32, 13487 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13488 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13489 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13490 assign( flags2, 13491 binop( Iop_Or32, 13492 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13493 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13494 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13495 assign( flags3, 13496 binop( Iop_Or32, 13497 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13498 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13499 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13500 putGST_field( PPC_GST_CR, 13501 binop( Iop_Or32, 13502 mkexpr( flags0 ), 13503 binop( Iop_Or32, 13504 mkexpr( flags1 ), 13505 binop( Iop_Or32, 13506 mkexpr( flags2 ), 13507 mkexpr( flags3 ) ) ) ), 13508 crfD ); 13509 13510 break; 13511 } 13512 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 13513 { 13514 IRTemp flags0 = newTemp(Ity_I32); 13515 IRTemp flags1 = newTemp(Ity_I32); 13516 IRTemp flags2 = newTemp(Ity_I32); 13517 IRTemp flags3 = newTemp(Ity_I32); 13518 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13519 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13520 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13521 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13522 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13523 DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 13524 13525 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13526 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13527 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13528 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13529 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13530 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13531 13532 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13533 * where fl_flag == 1 on ppc64. 13534 */ 13535 assign( flags0, 13536 binop( Iop_Or32, 13537 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13538 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13539 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13540 assign( flags1, 13541 binop( Iop_Or32, 13542 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13543 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13544 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13545 assign( flags2, 13546 binop( Iop_Or32, 13547 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13548 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13549 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13550 assign( flags3, 13551 binop( Iop_Or32, 13552 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13553 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13554 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13555 putGST_field( PPC_GST_CR, 13556 binop( Iop_Or32, 13557 mkexpr( flags0 ), 13558 binop( Iop_Or32, 13559 mkexpr( flags1 ), 13560 binop( Iop_Or32, 13561 mkexpr( flags2 ), 13562 mkexpr( flags3 ) ) ) ), 13563 crfD ); 13564 13565 break; 13566 } 13567 13568 default: 13569 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 13570 return False; 13571 } 13572 return True; 13573 } 13574 13575 /* 13576 * Vector Population Count/bit matrix transpose 13577 */ 13578 static Bool 13579 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) 13580 { 13581 UChar vRB_addr = ifieldRegB(theInstr); 13582 UChar vRT_addr = ifieldRegDS(theInstr); 13583 UChar opc1 = ifieldOPC( theInstr ); 13584 IRTemp vB = newTemp(Ity_V128); 13585 assign( vB, getVReg(vRB_addr)); 13586 13587 if (opc1 != 0x4) { 13588 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" ); 13589 return False; 13590 } 13591 13592 switch (opc2) { 13593 case 0x702: // vclzb 13594 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr); 13595 putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) ); 13596 break; 13597 13598 case 0x742: // vclzh 13599 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr); 13600 putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) ); 13601 break; 13602 13603 case 0x782: // vclzw 13604 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr); 13605 putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) ); 13606 break; 13607 13608 case 0x7C2: // vclzd 13609 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr); 13610 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) ); 13611 break; 13612 13613 case 0x703: // vpopcntb 13614 { 13615 /* Break vector into 32-bit words and do the population count 13616 * on byte in the words 13617 */ 13618 IRType ty = Ity_I32; 13619 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13620 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13621 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13622 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13623 13624 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr); 13625 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13626 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE); 13627 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE); 13628 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE); 13629 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE); 13630 13631 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13632 cnt_bits32_63, cnt_bits0_31) ); 13633 break; 13634 } 13635 13636 case 0x743: // vpopcnth 13637 { 13638 /* Break vector into 32-bit words and do the population count 13639 * for each half word 13640 */ 13641 IRType ty = Ity_I32; 13642 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13643 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13644 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13645 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13646 13647 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr); 13648 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13649 13650 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD); 13651 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD); 13652 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD); 13653 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD); 13654 13655 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13656 cnt_bits32_63, cnt_bits0_31) ); 13657 break; 13658 } 13659 13660 case 0x783: // vpopcntw 13661 { 13662 /* Break vector into 32-bit words and do the population count 13663 * on each word. 13664 */ 13665 IRType ty = Ity_I32; 13666 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13667 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13668 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13669 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13670 13671 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr); 13672 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13673 13674 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD); 13675 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD); 13676 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD); 13677 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD); 13678 13679 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13680 cnt_bits32_63, cnt_bits0_31) ); 13681 break; 13682 } 13683 13684 case 0x7C3: // vpopcntd 13685 { 13686 if (mode64) { 13687 /* Break vector into 64-bit double words and do the population count 13688 * on each double word. 13689 */ 13690 IRType ty = Ity_I64; 13691 IRTemp bits0_63 = newTemp(Ity_I64); 13692 IRTemp bits64_127 = newTemp(Ity_I64); 13693 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13694 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13695 13696 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13697 13698 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) ); 13699 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 13700 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD); 13701 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD); 13702 13703 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13704 mkexpr( cnt_bits64_127 ), 13705 mkexpr( cnt_bits0_63 ) ) ); 13706 } else { 13707 /* Break vector into 32-bit words and do the population count 13708 * on each doubleword. 13709 */ 13710 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13711 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13712 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13713 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13714 13715 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13716 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13717 13718 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63); 13719 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127); 13720 13721 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13722 mkexpr( cnt_bits64_127 ), 13723 mkexpr( cnt_bits0_63 ) ) ); 13724 } 13725 break; 13726 } 13727 13728 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword 13729 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr); 13730 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) ); 13731 break; 13732 13733 default: 13734 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n"); 13735 return False; 13736 break; 13737 } 13738 return True; 13739 } 13740 13741 typedef enum { 13742 PPC_CMP_EQ = 2, 13743 PPC_CMP_GT = 4, 13744 PPC_CMP_GE = 6, 13745 PPC_CMP_LT = 8 13746 } ppc_cmp_t; 13747 13748 13749 /* 13750 This helper function takes as input the IRExpr returned 13751 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 13752 in IR form. This helper function converts it to PPC form. 13753 13754 Map compare result from IR to PPC 13755 13756 FP cmp result | PPC | IR 13757 -------------------------- 13758 UN | 0x1 | 0x45 13759 EQ | 0x2 | 0x40 13760 GT | 0x4 | 0x00 13761 LT | 0x8 | 0x01 13762 13763 condcode = Shl(1, (~(ccIR>>5) & 2) 13764 | ((ccIR ^ (ccIR>>6)) & 1) 13765 */ 13766 static IRTemp 13767 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 13768 { 13769 IRTemp condcode = newTemp( Ity_I32 ); 13770 IRTemp ccIR = newTemp( Ity_I32 ); 13771 13772 assign(ccIR, ccIR_expr); 13773 assign( condcode, 13774 binop( Iop_Shl32, 13775 mkU32( 1 ), 13776 unop( Iop_32to8, 13777 binop( Iop_Or32, 13778 binop( Iop_And32, 13779 unop( Iop_Not32, 13780 binop( Iop_Shr32, 13781 mkexpr( ccIR ), 13782 mkU8( 5 ) ) ), 13783 mkU32( 2 ) ), 13784 binop( Iop_And32, 13785 binop( Iop_Xor32, 13786 mkexpr( ccIR ), 13787 binop( Iop_Shr32, 13788 mkexpr( ccIR ), 13789 mkU8( 6 ) ) ), 13790 mkU32( 1 ) ) ) ) ) ); 13791 return condcode; 13792 } 13793 13794 /* 13795 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 13796 * following these special rules: 13797 * - The max/min of a QNaN and any value is that value 13798 * (When two QNaNs are being compared, the frA QNaN is the return value.) 13799 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 13800 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 13801 */ 13802 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 13803 { 13804 IRTemp frA_isNaN = newTemp(Ity_I1); 13805 IRTemp frB_isNaN = newTemp(Ity_I1); 13806 IRTemp frA_isSNaN = newTemp(Ity_I1); 13807 IRTemp frB_isSNaN = newTemp(Ity_I1); 13808 IRTemp frA_isQNaN = newTemp(Ity_I1); 13809 IRTemp frB_isQNaN = newTemp(Ity_I1); 13810 13811 assign( frA_isNaN, is_NaN( frA_I64 ) ); 13812 assign( frB_isNaN, is_NaN( frB_I64 ) ); 13813 // If operand is a NAN and bit 12 is '0', then it's an SNaN 13814 assign( frA_isSNaN, 13815 mkAND1( mkexpr(frA_isNaN), 13816 binop( Iop_CmpEQ32, 13817 binop( Iop_And32, 13818 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 13819 mkU32( 0x00080000 ) ), 13820 mkU32( 0 ) ) ) ); 13821 assign( frB_isSNaN, 13822 mkAND1( mkexpr(frB_isNaN), 13823 binop( Iop_CmpEQ32, 13824 binop( Iop_And32, 13825 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 13826 mkU32( 0x00080000 ) ), 13827 mkU32( 0 ) ) ) ); 13828 assign( frA_isQNaN, 13829 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 13830 assign( frB_isQNaN, 13831 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 13832 13833 /* Based on the rules specified in the function prologue, the algorithm is as follows: 13834 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13835 * if frA is a SNaN 13836 * result = frA converted to QNaN 13837 * else if frB is a SNaN 13838 * result = frB converted to QNaN 13839 * else if frB is a QNaN 13840 * result = frA 13841 * // One of frA or frB was a NaN in order for this function to be called, so 13842 * // if we get to this point, we KNOW that frA must be a QNaN. 13843 * else // frA is a QNaN 13844 * result = frB 13845 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13846 */ 13847 13848 #define SNAN_MASK 0x0008000000000000ULL 13849 return 13850 IRExpr_ITE(mkexpr(frA_isSNaN), 13851 /* then: result = frA converted to QNaN */ 13852 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)), 13853 /* else: if frB is a SNaN */ 13854 IRExpr_ITE(mkexpr(frB_isSNaN), 13855 /* then: result = frB converted to QNaN */ 13856 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)), 13857 /* else: if frB is a QNaN */ 13858 IRExpr_ITE(mkexpr(frB_isQNaN), 13859 /* then: result = frA */ 13860 mkexpr(frA_I64), 13861 /* else: frA is a QNaN, so result = frB */ 13862 mkexpr(frB_I64)))); 13863 } 13864 13865 /* 13866 * Helper function for get_max_min_fp. 13867 */ 13868 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 13869 { 13870 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 13871 unop( Iop_ReinterpI64asF64, 13872 mkexpr( src1 ) ), 13873 unop( Iop_ReinterpI64asF64, 13874 mkexpr( src2 ) ) ) ); 13875 13876 return IRExpr_ITE( binop( Iop_CmpEQ32, 13877 mkexpr( src1cmpsrc2 ), 13878 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ), 13879 /* then: use src1 */ 13880 mkexpr( src1 ), 13881 /* else: use src2 */ 13882 mkexpr( src2 ) ); 13883 } 13884 13885 /* 13886 * Helper function for "Maximum/Minimum Double Precision" operations. 13887 * Arguments: frA and frb are Ity_I64 13888 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 13889 */ 13890 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 13891 { 13892 /* There are three special cases where get_fp_cmp_CR_val is not helpful 13893 * for ascertaining the maximum between two doubles: 13894 * 1. The max/min of +0 and -0 is +0. 13895 * 2. The max/min of a QNaN and any value is that value. 13896 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 13897 * We perform the check for [+/-]0 here in this function and use the 13898 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 13899 * to do the standard comparison function. 13900 */ 13901 IRTemp anyNaN = newTemp(Ity_I1); 13902 IRTemp frA_isZero = newTemp(Ity_I1); 13903 IRTemp frB_isZero = newTemp(Ity_I1); 13904 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 13905 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 13906 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 13907 #define MINUS_ZERO 0x8000000000000000ULL 13908 13909 return IRExpr_ITE( /* If both arguments are zero . . . */ 13910 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ), 13911 /* then: if frA is -0 and isMin==True, return -0; 13912 * else if frA is +0 and isMin==False; return +0; 13913 * otherwise, simply return frB. */ 13914 IRExpr_ITE( binop( Iop_CmpEQ32, 13915 unop( Iop_64HIto32, 13916 mkexpr( frA_I64 ) ), 13917 mkU32( isMin ? 0x80000000 : 0 ) ), 13918 mkU64( isMin ? MINUS_ZERO : 0ULL ), 13919 mkexpr( frB_I64 ) ), 13920 /* else: check if either input is a NaN*/ 13921 IRExpr_ITE( mkexpr( anyNaN ), 13922 /* then: use "NaN helper" */ 13923 _get_maxmin_fp_NaN( frA_I64, frB_I64 ), 13924 /* else: use "comparison helper" */ 13925 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) )); 13926 } 13927 13928 static const HChar * _get_vsx_rdpi_suffix(UInt opc2) 13929 { 13930 switch (opc2 & 0x7F) { 13931 case 0x72: 13932 return "m"; 13933 case 0x52: 13934 return "p"; 13935 case 0x56: 13936 return "c"; 13937 case 0x32: 13938 return "z"; 13939 case 0x12: 13940 return ""; 13941 13942 default: // Impossible to get here 13943 vex_printf("Unrecognized opcode %x\n", opc2); 13944 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)"); 13945 } 13946 } 13947 13948 /* 13949 * Helper function for vector/scalar double precision fp round to integer instructions. 13950 */ 13951 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) 13952 { 13953 13954 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 13955 IRTemp frB = newTemp(Ity_F64); 13956 IRTemp frD = newTemp(Ity_F64); 13957 IRTemp intermediateResult = newTemp(Ity_I64); 13958 IRTemp is_SNAN = newTemp(Ity_I1); 13959 IRExpr * hi32; 13960 IRExpr * rxpi_rm; 13961 switch (opc2 & 0x7F) { 13962 case 0x72: 13963 rxpi_rm = mkU32(Irrm_NegINF); 13964 break; 13965 case 0x52: 13966 rxpi_rm = mkU32(Irrm_PosINF); 13967 break; 13968 case 0x56: 13969 rxpi_rm = get_IR_roundingmode(); 13970 break; 13971 case 0x32: 13972 rxpi_rm = mkU32(Irrm_ZERO); 13973 break; 13974 case 0x12: 13975 rxpi_rm = mkU32(Irrm_NEAREST); 13976 break; 13977 13978 default: // Impossible to get here 13979 vex_printf("Unrecognized opcode %x\n", opc2); 13980 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)"); 13981 } 13982 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 13983 assign( intermediateResult, 13984 binop( Iop_F64toI64S, rxpi_rm, 13985 mkexpr( frB ) ) ); 13986 13987 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 13988 /* F64 has only log10(2**52) significant digits anyway */ 13989 /* need to preserve sign of zero */ 13990 /* frD = (fabs(frB) > 9e18) ? frB : 13991 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 13992 assign( frD, 13993 IRExpr_ITE( 13994 binop( Iop_CmpNE8, 13995 unop( Iop_32to8, 13996 binop( Iop_CmpF64, 13997 IRExpr_Const( IRConst_F64( 9e18 ) ), 13998 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 13999 mkU8(0) ), 14000 mkexpr( frB ), 14001 IRExpr_ITE( 14002 binop( Iop_CmpNE32, 14003 binop( Iop_Shr32, 14004 unop( Iop_64HIto32, 14005 mkexpr( frB_I64 ) ), 14006 mkU8( 31 ) ), 14007 mkU32(0) ), 14008 unop( Iop_NegF64, 14009 unop( Iop_AbsF64, 14010 binop( Iop_I64StoF64, 14011 mkU32( 0 ), 14012 mkexpr( intermediateResult ) ) ) ), 14013 binop( Iop_I64StoF64, 14014 mkU32( 0 ), 14015 mkexpr( intermediateResult ) ) 14016 ) 14017 ) 14018 ); 14019 14020 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 14021 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 14022 */ 14023 #define SNAN_MASK 0x0008000000000000ULL 14024 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 14025 assign( is_SNAN, 14026 mkAND1( is_NaN( frB_I64 ), 14027 binop( Iop_CmpEQ32, 14028 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 14029 mkU32( 0 ) ) ) ); 14030 14031 return IRExpr_ITE( mkexpr( is_SNAN ), 14032 unop( Iop_ReinterpI64asF64, 14033 binop( Iop_Xor64, 14034 mkU64( SNAN_MASK ), 14035 mkexpr( frB_I64 ) ) ), 14036 mkexpr( frD )); 14037 } 14038 14039 /* 14040 * Miscellaneous VSX vector instructions 14041 */ 14042 static Bool 14043 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 14044 { 14045 /* XX3-Form */ 14046 UChar opc1 = ifieldOPC( theInstr ); 14047 UChar XT = ifieldRegXT( theInstr ); 14048 UChar XB = ifieldRegXB( theInstr ); 14049 14050 if (opc1 != 0x3C) { 14051 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 14052 return False; 14053 } 14054 14055 switch (opc2) { 14056 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 14057 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 14058 // Double-Precision) 14059 { 14060 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14061 IRExpr* rm = get_IR_roundingmode(); 14062 IRTemp frB = newTemp(Ity_I64); 14063 IRTemp frB2 = newTemp(Ity_I64); 14064 Bool redp = opc2 == 0x1B4; 14065 IRTemp sqrtHi = newTemp(Ity_F64); 14066 IRTemp sqrtLo = newTemp(Ity_F64); 14067 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14068 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14069 14070 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB); 14071 if (!redp) { 14072 assign( sqrtHi, 14073 binop( Iop_SqrtF64, 14074 rm, 14075 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 14076 assign( sqrtLo, 14077 binop( Iop_SqrtF64, 14078 rm, 14079 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 14080 } 14081 putVSReg( XT, 14082 binop( Iop_64HLtoV128, 14083 unop( Iop_ReinterpF64asI64, 14084 triop( Iop_DivF64, 14085 rm, 14086 ieee_one, 14087 redp ? unop( Iop_ReinterpI64asF64, 14088 mkexpr( frB ) ) 14089 : mkexpr( sqrtHi ) ) ), 14090 unop( Iop_ReinterpF64asI64, 14091 triop( Iop_DivF64, 14092 rm, 14093 ieee_one, 14094 redp ? unop( Iop_ReinterpI64asF64, 14095 mkexpr( frB2 ) ) 14096 : mkexpr( sqrtLo ) ) ) ) ); 14097 break; 14098 14099 } 14100 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 14101 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 14102 { 14103 IRTemp b3, b2, b1, b0; 14104 IRTemp res0 = newTemp(Ity_I32); 14105 IRTemp res1 = newTemp(Ity_I32); 14106 IRTemp res2 = newTemp(Ity_I32); 14107 IRTemp res3 = newTemp(Ity_I32); 14108 IRTemp sqrt3 = newTemp(Ity_F64); 14109 IRTemp sqrt2 = newTemp(Ity_F64); 14110 IRTemp sqrt1 = newTemp(Ity_F64); 14111 IRTemp sqrt0 = newTemp(Ity_F64); 14112 IRExpr* rm = get_IR_roundingmode(); 14113 Bool resp = opc2 == 0x134; 14114 14115 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14116 14117 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14118 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB); 14119 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14120 14121 if (!resp) { 14122 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 14123 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 14124 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 14125 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 14126 } 14127 14128 assign( res0, 14129 unop( Iop_ReinterpF32asI32, 14130 unop( Iop_TruncF64asF32, 14131 triop( Iop_DivF64r32, 14132 rm, 14133 ieee_one, 14134 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 14135 assign( res1, 14136 unop( Iop_ReinterpF32asI32, 14137 unop( Iop_TruncF64asF32, 14138 triop( Iop_DivF64r32, 14139 rm, 14140 ieee_one, 14141 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 14142 assign( res2, 14143 unop( Iop_ReinterpF32asI32, 14144 unop( Iop_TruncF64asF32, 14145 triop( Iop_DivF64r32, 14146 rm, 14147 ieee_one, 14148 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 14149 assign( res3, 14150 unop( Iop_ReinterpF32asI32, 14151 unop( Iop_TruncF64asF32, 14152 triop( Iop_DivF64r32, 14153 rm, 14154 ieee_one, 14155 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 14156 putVSReg( XT, 14157 binop( Iop_64HLtoV128, 14158 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14159 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14160 break; 14161 } 14162 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 14163 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 14164 { 14165 UChar XA = ifieldRegXA( theInstr ); 14166 IRTemp a3, a2, a1, a0; 14167 IRTemp b3, b2, b1, b0; 14168 IRTemp res0 = newTemp( Ity_I32 ); 14169 IRTemp res1 = newTemp( Ity_I32 ); 14170 IRTemp res2 = newTemp( Ity_I32 ); 14171 IRTemp res3 = newTemp( Ity_I32 ); 14172 IRTemp a0_I64 = newTemp( Ity_I64 ); 14173 IRTemp a1_I64 = newTemp( Ity_I64 ); 14174 IRTemp a2_I64 = newTemp( Ity_I64 ); 14175 IRTemp a3_I64 = newTemp( Ity_I64 ); 14176 IRTemp b0_I64 = newTemp( Ity_I64 ); 14177 IRTemp b1_I64 = newTemp( Ity_I64 ); 14178 IRTemp b2_I64 = newTemp( Ity_I64 ); 14179 IRTemp b3_I64 = newTemp( Ity_I64 ); 14180 14181 Bool isMin = opc2 == 0x320 ? True : False; 14182 14183 a3 = a2 = a1 = a0 = IRTemp_INVALID; 14184 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14185 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB); 14186 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 14187 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14188 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 14189 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 14190 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 14191 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 14192 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 14193 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 14194 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 14195 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 14196 assign( res0, 14197 unop( Iop_ReinterpF32asI32, 14198 unop( Iop_TruncF64asF32, 14199 unop( Iop_ReinterpI64asF64, 14200 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 14201 assign( res1, 14202 unop( Iop_ReinterpF32asI32, 14203 unop( Iop_TruncF64asF32, 14204 unop( Iop_ReinterpI64asF64, 14205 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 14206 assign( res2, 14207 unop( Iop_ReinterpF32asI32, 14208 unop( Iop_TruncF64asF32, 14209 unop( Iop_ReinterpI64asF64, 14210 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 14211 assign( res3, 14212 unop( Iop_ReinterpF32asI32, 14213 unop( Iop_TruncF64asF32, 14214 unop( Iop_ReinterpI64asF64, 14215 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 14216 putVSReg( XT, 14217 binop( Iop_64HLtoV128, 14218 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14219 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14220 break; 14221 } 14222 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 14223 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 14224 { 14225 UChar XA = ifieldRegXA( theInstr ); 14226 IRTemp frA = newTemp(Ity_I64); 14227 IRTemp frB = newTemp(Ity_I64); 14228 IRTemp frA2 = newTemp(Ity_I64); 14229 IRTemp frB2 = newTemp(Ity_I64); 14230 Bool isMin = opc2 == 0x3A0 ? True : False; 14231 14232 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14233 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14234 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14235 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14236 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB); 14237 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 14238 14239 break; 14240 } 14241 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 14242 { 14243 UChar XA = ifieldRegXA( theInstr ); 14244 IRTemp frA = newTemp(Ity_I64); 14245 IRTemp frB = newTemp(Ity_I64); 14246 IRTemp frA2 = newTemp(Ity_I64); 14247 IRTemp frB2 = newTemp(Ity_I64); 14248 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14249 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14250 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14251 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14252 14253 DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14254 putVSReg( XT, 14255 binop( Iop_64HLtoV128, 14256 binop( Iop_Or64, 14257 binop( Iop_And64, 14258 mkexpr( frA ), 14259 mkU64( SIGN_BIT ) ), 14260 binop( Iop_And64, 14261 mkexpr( frB ), 14262 mkU64( SIGN_MASK ) ) ), 14263 binop( Iop_Or64, 14264 binop( Iop_And64, 14265 mkexpr( frA2 ), 14266 mkU64( SIGN_BIT ) ), 14267 binop( Iop_And64, 14268 mkexpr( frB2 ), 14269 mkU64( SIGN_MASK ) ) ) ) ); 14270 break; 14271 } 14272 case 0x340: // xvcpsgnsp 14273 { 14274 UChar XA = ifieldRegXA( theInstr ); 14275 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 14276 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 14277 IRTemp resHi = newTemp(Ity_I64); 14278 IRTemp resLo = newTemp(Ity_I64); 14279 14280 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 14281 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 14282 DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB); 14283 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 14284 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 14285 14286 assign( resHi, 14287 binop( Iop_32HLto64, 14288 binop( Iop_Or32, 14289 binop( Iop_And32, 14290 unop(Iop_64to32, mkexpr( a3_I64 ) ), 14291 mkU32( SIGN_BIT32 ) ), 14292 binop( Iop_And32, 14293 unop(Iop_64to32, mkexpr( b3_I64 ) ), 14294 mkU32( SIGN_MASK32) ) ), 14295 14296 binop( Iop_Or32, 14297 binop( Iop_And32, 14298 unop(Iop_64to32, mkexpr( a2_I64 ) ), 14299 mkU32( SIGN_BIT32 ) ), 14300 binop( Iop_And32, 14301 unop(Iop_64to32, mkexpr( b2_I64 ) ), 14302 mkU32( SIGN_MASK32 ) ) ) ) ); 14303 assign( resLo, 14304 binop( Iop_32HLto64, 14305 binop( Iop_Or32, 14306 binop( Iop_And32, 14307 unop(Iop_64to32, mkexpr( a1_I64 ) ), 14308 mkU32( SIGN_BIT32 ) ), 14309 binop( Iop_And32, 14310 unop(Iop_64to32, mkexpr( b1_I64 ) ), 14311 mkU32( SIGN_MASK32 ) ) ), 14312 14313 binop( Iop_Or32, 14314 binop( Iop_And32, 14315 unop(Iop_64to32, mkexpr( a0_I64 ) ), 14316 mkU32( SIGN_BIT32 ) ), 14317 binop( Iop_And32, 14318 unop(Iop_64to32, mkexpr( b0_I64 ) ), 14319 mkU32( SIGN_MASK32 ) ) ) ) ); 14320 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 14321 break; 14322 } 14323 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 14324 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 14325 { 14326 IRTemp frB = newTemp(Ity_F64); 14327 IRTemp frB2 = newTemp(Ity_F64); 14328 IRTemp abs_resultHi = newTemp(Ity_F64); 14329 IRTemp abs_resultLo = newTemp(Ity_F64); 14330 Bool make_negative = (opc2 == 0x3D2) ? True : False; 14331 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14332 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14333 14334 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB); 14335 if (make_negative) { 14336 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 14337 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 14338 14339 } else { 14340 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 14341 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 14342 } 14343 putVSReg( XT, binop( Iop_64HLtoV128, 14344 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 14345 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 14346 break; 14347 } 14348 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 14349 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 14350 { 14351 /* 14352 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 14353 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 14354 * of this function is so easy using shifts, I choose to emulate this instruction that 14355 * way versus a native instruction method of implementation. 14356 */ 14357 Bool make_negative = (opc2 == 0x352) ? True : False; 14358 IRTemp shiftVector = newTemp(Ity_V128); 14359 IRTemp absVal_vector = newTemp(Ity_V128); 14360 assign( shiftVector, 14361 binop( Iop_64HLtoV128, 14362 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 14363 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 14364 assign( absVal_vector, 14365 binop( Iop_Shr32x4, 14366 binop( Iop_Shl32x4, 14367 getVSReg( XB ), 14368 mkexpr( shiftVector ) ), 14369 mkexpr( shiftVector ) ) ); 14370 if (make_negative) { 14371 IRTemp signBit_vector = newTemp(Ity_V128); 14372 assign( signBit_vector, 14373 binop( Iop_64HLtoV128, 14374 binop( Iop_32HLto64, 14375 mkU32( 0x80000000 ), 14376 mkU32( 0x80000000 ) ), 14377 binop( Iop_32HLto64, 14378 mkU32( 0x80000000 ), 14379 mkU32( 0x80000000 ) ) ) ); 14380 putVSReg( XT, 14381 binop( Iop_OrV128, 14382 mkexpr( absVal_vector ), 14383 mkexpr( signBit_vector ) ) ); 14384 } else { 14385 putVSReg( XT, mkexpr( absVal_vector ) ); 14386 } 14387 break; 14388 } 14389 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 14390 { 14391 IRTemp frB = newTemp(Ity_F64); 14392 IRTemp frB2 = newTemp(Ity_F64); 14393 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14394 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14395 DIP("xvnegdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14396 putVSReg( XT, 14397 binop( Iop_64HLtoV128, 14398 unop( Iop_ReinterpF64asI64, 14399 unop( Iop_NegF64, mkexpr( frB ) ) ), 14400 unop( Iop_ReinterpF64asI64, 14401 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 14402 break; 14403 } 14404 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 14405 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 14406 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 14407 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 14408 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 14409 { 14410 IRTemp frBHi_I64 = newTemp(Ity_I64); 14411 IRTemp frBLo_I64 = newTemp(Ity_I64); 14412 IRExpr * frD_fp_roundHi = NULL; 14413 IRExpr * frD_fp_roundLo = NULL; 14414 14415 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 14416 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2); 14417 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 14418 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2); 14419 14420 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 14421 putVSReg( XT, 14422 binop( Iop_64HLtoV128, 14423 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 14424 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 14425 break; 14426 } 14427 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 14428 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 14429 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 14430 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 14431 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 14432 { 14433 const HChar * insn_suffix = NULL; 14434 IROp op; 14435 if (opc2 != 0x156) { 14436 // Use pre-defined IRop's for vrfi{m|n|p|z} 14437 switch (opc2) { 14438 case 0x112: 14439 insn_suffix = ""; 14440 op = Iop_RoundF32x4_RN; 14441 break; 14442 case 0x172: 14443 insn_suffix = "m"; 14444 op = Iop_RoundF32x4_RM; 14445 break; 14446 case 0x152: 14447 insn_suffix = "p"; 14448 op = Iop_RoundF32x4_RP; 14449 break; 14450 case 0x132: 14451 insn_suffix = "z"; 14452 op = Iop_RoundF32x4_RZ; 14453 break; 14454 14455 default: 14456 vex_printf("Unrecognized opcode %x\n", opc2); 14457 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n"); 14458 } 14459 DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 14460 putVSReg( XT, unop( op, getVSReg(XB) ) ); 14461 } else { 14462 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 14463 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 14464 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 14465 IRTemp b3_I64 = newTemp(Ity_I64); 14466 IRTemp b2_I64 = newTemp(Ity_I64); 14467 IRTemp b1_I64 = newTemp(Ity_I64); 14468 IRTemp b0_I64 = newTemp(Ity_I64); 14469 14470 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 14471 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 14472 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 14473 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 14474 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 14475 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 14476 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 14477 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 14478 _do_vsx_fp_roundToInt(b3_I64, opc2)); 14479 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 14480 _do_vsx_fp_roundToInt(b2_I64, opc2)); 14481 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 14482 _do_vsx_fp_roundToInt(b1_I64, opc2)); 14483 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 14484 _do_vsx_fp_roundToInt(b0_I64, opc2)); 14485 DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB); 14486 putVSReg( XT, 14487 binop( Iop_64HLtoV128, 14488 binop( Iop_32HLto64, 14489 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 14490 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 14491 binop( Iop_32HLto64, 14492 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 14493 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 14494 } 14495 break; 14496 } 14497 14498 default: 14499 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 14500 return False; 14501 } 14502 return True; 14503 } 14504 14505 14506 /* 14507 * VSX Scalar Floating Point Arithmetic Instructions 14508 */ 14509 static Bool 14510 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 14511 { 14512 /* XX3-Form */ 14513 UChar opc1 = ifieldOPC( theInstr ); 14514 UChar XT = ifieldRegXT( theInstr ); 14515 UChar XA = ifieldRegXA( theInstr ); 14516 UChar XB = ifieldRegXB( theInstr ); 14517 IRExpr* rm = get_IR_roundingmode(); 14518 IRTemp frA = newTemp(Ity_F64); 14519 IRTemp frB = newTemp(Ity_F64); 14520 14521 if (opc1 != 0x3C) { 14522 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 14523 return False; 14524 } 14525 14526 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14527 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14528 14529 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 14530 * of VSX[XT] are undefined after the operation; therefore, we can simply set 14531 * element to zero where it makes sense to do so. 14532 */ 14533 switch (opc2) { 14534 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision) 14535 DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14536 putVSReg( XT, binop( Iop_64HLtoV128, 14537 unop( Iop_ReinterpF64asI64, 14538 binop( Iop_RoundF64toF32, rm, 14539 triop( Iop_AddF64, rm, 14540 mkexpr( frA ), 14541 mkexpr( frB ) ) ) ), 14542 mkU64( 0 ) ) ); 14543 break; 14544 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision) 14545 DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14546 putVSReg( XT, binop( Iop_64HLtoV128, 14547 unop( Iop_ReinterpF64asI64, 14548 binop( Iop_RoundF64toF32, rm, 14549 triop( Iop_SubF64, rm, 14550 mkexpr( frA ), 14551 mkexpr( frB ) ) ) ), 14552 mkU64( 0 ) ) ); 14553 break; 14554 case 0x080: // xsadddp (VSX scalar add double-precision) 14555 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14556 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14557 triop( Iop_AddF64, rm, 14558 mkexpr( frA ), 14559 mkexpr( frB ) ) ), 14560 mkU64( 0 ) ) ); 14561 break; 14562 case 0x060: // xsdivsp (VSX scalar divide single-precision) 14563 DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14564 putVSReg( XT, binop( Iop_64HLtoV128, 14565 unop( Iop_ReinterpF64asI64, 14566 binop( Iop_RoundF64toF32, rm, 14567 triop( Iop_DivF64, rm, 14568 mkexpr( frA ), 14569 mkexpr( frB ) ) ) ), 14570 mkU64( 0 ) ) ); 14571 break; 14572 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 14573 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14574 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14575 triop( Iop_DivF64, rm, 14576 mkexpr( frA ), 14577 mkexpr( frB ) ) ), 14578 mkU64( 0 ) ) ); 14579 break; 14580 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add 14581 * single-precision) 14582 */ 14583 { 14584 IRTemp frT = newTemp(Ity_F64); 14585 Bool mdp = opc2 == 0x024; 14586 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14587 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14588 getVSReg( XT ) ) ) ); 14589 putVSReg( XT, 14590 binop( Iop_64HLtoV128, 14591 unop( Iop_ReinterpF64asI64, 14592 binop( Iop_RoundF64toF32, rm, 14593 qop( Iop_MAddF64, rm, 14594 mkexpr( frA ), 14595 mkexpr( mdp ? frT : frB ), 14596 mkexpr( mdp ? frB : frT ) ) ) ), 14597 mkU64( 0 ) ) ); 14598 break; 14599 } 14600 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 14601 { 14602 IRTemp frT = newTemp(Ity_F64); 14603 Bool mdp = opc2 == 0x0A4; 14604 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14605 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14606 getVSReg( XT ) ) ) ); 14607 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14608 qop( Iop_MAddF64, rm, 14609 mkexpr( frA ), 14610 mkexpr( mdp ? frT : frB ), 14611 mkexpr( mdp ? frB : frT ) ) ), 14612 mkU64( 0 ) ) ); 14613 break; 14614 } 14615 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar 14616 * multiply-subtract single-precision) 14617 */ 14618 { 14619 IRTemp frT = newTemp(Ity_F64); 14620 Bool mdp = opc2 == 0x064; 14621 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14622 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14623 getVSReg( XT ) ) ) ); 14624 putVSReg( XT, 14625 binop( Iop_64HLtoV128, 14626 unop( Iop_ReinterpF64asI64, 14627 binop( Iop_RoundF64toF32, rm, 14628 qop( Iop_MSubF64, rm, 14629 mkexpr( frA ), 14630 mkexpr( mdp ? frT : frB ), 14631 mkexpr( mdp ? frB : frT ) ) ) ), 14632 mkU64( 0 ) ) ); 14633 break; 14634 } 14635 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 14636 { 14637 IRTemp frT = newTemp(Ity_F64); 14638 Bool mdp = opc2 == 0x0E4; 14639 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14640 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14641 getVSReg( XT ) ) ) ); 14642 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14643 qop( Iop_MSubF64, rm, 14644 mkexpr( frA ), 14645 mkexpr( mdp ? frT : frB ), 14646 mkexpr( mdp ? frB : frT ) ) ), 14647 mkU64( 0 ) ) ); 14648 break; 14649 } 14650 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 14651 { 14652 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 14653 * of fnmadd and use pretty much the same code. However, that code has a bug in the 14654 * way it blindly negates the signbit, even if the floating point result is a NaN. 14655 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 14656 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 14657 * bit for NaN result. 14658 */ 14659 Bool mdp = opc2 == 0x2A4; 14660 IRTemp frT = newTemp(Ity_F64); 14661 IRTemp maddResult = newTemp(Ity_I64); 14662 14663 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14664 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14665 getVSReg( XT ) ) ) ); 14666 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 14667 mkexpr( frA ), 14668 mkexpr( mdp ? frT : frB ), 14669 mkexpr( mdp ? frB : frT ) ) ) ); 14670 14671 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 14672 mkU64( 0 ) ) ); 14673 break; 14674 } 14675 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar 14676 * multiply-add single-precision) 14677 */ 14678 { 14679 Bool mdp = opc2 == 0x224; 14680 IRTemp frT = newTemp(Ity_F64); 14681 IRTemp maddResult = newTemp(Ity_I64); 14682 14683 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14684 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14685 getVSReg( XT ) ) ) ); 14686 assign( maddResult, 14687 unop( Iop_ReinterpF64asI64, 14688 binop( Iop_RoundF64toF32, rm, 14689 qop( Iop_MAddF64, rm, 14690 mkexpr( frA ), 14691 mkexpr( mdp ? frT : frB ), 14692 mkexpr( mdp ? frB : frT ) ) ) ) ); 14693 14694 putVSReg( XT, binop( Iop_64HLtoV128, 14695 mkexpr( getNegatedResult(maddResult) ), 14696 mkU64( 0 ) ) ); 14697 break; 14698 } 14699 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative 14700 * Multiply-Subtract Single-Precision) 14701 */ 14702 { 14703 IRTemp frT = newTemp(Ity_F64); 14704 Bool mdp = opc2 == 0x264; 14705 IRTemp msubResult = newTemp(Ity_I64); 14706 14707 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14708 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14709 getVSReg( XT ) ) ) ); 14710 assign( msubResult, 14711 unop( Iop_ReinterpF64asI64, 14712 binop( Iop_RoundF64toF32, rm, 14713 qop( Iop_MSubF64, rm, 14714 mkexpr( frA ), 14715 mkexpr( mdp ? frT : frB ), 14716 mkexpr( mdp ? frB : frT ) ) ) ) ); 14717 14718 putVSReg( XT, binop( Iop_64HLtoV128, 14719 mkexpr( getNegatedResult(msubResult) ), 14720 mkU64( 0 ) ) ); 14721 14722 break; 14723 } 14724 14725 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 14726 { 14727 IRTemp frT = newTemp(Ity_F64); 14728 Bool mdp = opc2 == 0x2E4; 14729 IRTemp msubResult = newTemp(Ity_I64); 14730 14731 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14732 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14733 getVSReg( XT ) ) ) ); 14734 assign(msubResult, unop( Iop_ReinterpF64asI64, 14735 qop( Iop_MSubF64, 14736 rm, 14737 mkexpr( frA ), 14738 mkexpr( mdp ? frT : frB ), 14739 mkexpr( mdp ? frB : frT ) ) )); 14740 14741 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 14742 14743 break; 14744 } 14745 14746 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision) 14747 DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14748 putVSReg( XT, binop( Iop_64HLtoV128, 14749 unop( Iop_ReinterpF64asI64, 14750 binop( Iop_RoundF64toF32, rm, 14751 triop( Iop_MulF64, rm, 14752 mkexpr( frA ), 14753 mkexpr( frB ) ) ) ), 14754 mkU64( 0 ) ) ); 14755 break; 14756 14757 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 14758 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14759 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14760 triop( Iop_MulF64, rm, 14761 mkexpr( frA ), 14762 mkexpr( frB ) ) ), 14763 mkU64( 0 ) ) ); 14764 break; 14765 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 14766 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14767 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14768 triop( Iop_SubF64, rm, 14769 mkexpr( frA ), 14770 mkexpr( frB ) ) ), 14771 mkU64( 0 ) ) ); 14772 break; 14773 14774 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision) 14775 DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 14776 putVSReg( XT, 14777 binop( Iop_64HLtoV128, 14778 unop( Iop_ReinterpF64asI64, 14779 binop( Iop_RoundF64toF32, rm, 14780 binop( Iop_SqrtF64, rm, 14781 mkexpr( frB ) ) ) ), 14782 mkU64( 0 ) ) ); 14783 break; 14784 14785 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 14786 DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14787 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14788 binop( Iop_SqrtF64, rm, 14789 mkexpr( frB ) ) ), 14790 mkU64( 0 ) ) ); 14791 break; 14792 14793 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 14794 { 14795 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14796 IRTemp frA_I64 = newTemp(Ity_I64); 14797 IRTemp frB_I64 = newTemp(Ity_I64); 14798 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB); 14799 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 14800 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 14801 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 14802 break; 14803 } 14804 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 14805 { 14806 IRTemp frB_I64 = newTemp(Ity_I64); 14807 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14808 IRTemp flags = newTemp(Ity_I32); 14809 IRTemp fe_flag, fg_flag; 14810 fe_flag = fg_flag = IRTemp_INVALID; 14811 DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14812 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 14813 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 14814 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 14815 * where fl_flag == 1 on ppc64. 14816 */ 14817 assign( flags, 14818 binop( Iop_Or32, 14819 binop( Iop_Or32, mkU32( 8 ), // fl_flag 14820 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 14821 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 14822 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 14823 break; 14824 } 14825 14826 default: 14827 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 14828 return False; 14829 } 14830 14831 return True; 14832 } 14833 14834 14835 /* 14836 * VSX Floating Point Compare Instructions 14837 */ 14838 static Bool 14839 dis_vx_cmp( UInt theInstr, UInt opc2 ) 14840 { 14841 /* XX3-Form and XX2-Form */ 14842 UChar opc1 = ifieldOPC( theInstr ); 14843 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14844 IRTemp ccPPC32; 14845 UChar XA = ifieldRegXA ( theInstr ); 14846 UChar XB = ifieldRegXB ( theInstr ); 14847 IRTemp frA = newTemp(Ity_F64); 14848 IRTemp frB = newTemp(Ity_F64); 14849 14850 if (opc1 != 0x3C) { 14851 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 14852 return False; 14853 } 14854 14855 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14856 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14857 switch (opc2) { 14858 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 14859 /* Note: Differences between xscmpudp and xscmpodp are only in 14860 * exception flag settings, which aren't supported anyway. */ 14861 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 14862 crfD, (UInt)XA, (UInt)XB); 14863 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 14864 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 14865 break; 14866 14867 default: 14868 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 14869 return False; 14870 } 14871 return True; 14872 } 14873 14874 static void 14875 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 14876 ppc_cmp_t cmp_type ) 14877 { 14878 IRTemp frA_hi = newTemp(Ity_F64); 14879 IRTemp frB_hi = newTemp(Ity_F64); 14880 IRTemp frA_lo = newTemp(Ity_F64); 14881 IRTemp frB_lo = newTemp(Ity_F64); 14882 IRTemp ccPPC32 = newTemp(Ity_I32); 14883 IRTemp ccIR_hi; 14884 IRTemp ccIR_lo; 14885 14886 IRTemp hiResult = newTemp(Ity_I64); 14887 IRTemp loResult = newTemp(Ity_I64); 14888 IRTemp hiEQlo = newTemp(Ity_I1); 14889 IRTemp all_elem_true = newTemp(Ity_I32); 14890 IRTemp all_elem_false = newTemp(Ity_I32); 14891 14892 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 14893 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 14894 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 14895 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 14896 14897 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14898 mkexpr( frA_hi ), 14899 mkexpr( frB_hi ) ) ); 14900 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14901 mkexpr( frA_lo ), 14902 mkexpr( frB_lo ) ) ); 14903 14904 if (cmp_type != PPC_CMP_GE) { 14905 assign( hiResult, 14906 unop( Iop_1Sto64, 14907 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 14908 assign( loResult, 14909 unop( Iop_1Sto64, 14910 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 14911 } else { 14912 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 14913 // the other element compare may return "2" (for "equal to"). 14914 IRTemp lo_GE = newTemp(Ity_I1); 14915 IRTemp hi_GE = newTemp(Ity_I1); 14916 14917 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 14918 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 14919 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 14920 14921 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 14922 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 14923 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 14924 } 14925 14926 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 14927 assign( hiEQlo, 14928 binop( Iop_CmpEQ32, 14929 unop( Iop_64to32, mkexpr( hiResult ) ), 14930 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 14931 putVSReg( XT, 14932 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 14933 14934 assign( all_elem_true, 14935 unop( Iop_1Uto32, 14936 mkAND1( mkexpr( hiEQlo ), 14937 binop( Iop_CmpEQ32, 14938 mkU32( 0xffffffff ), 14939 unop( Iop_64to32, 14940 mkexpr( hiResult ) ) ) ) ) ); 14941 14942 assign( all_elem_false, 14943 unop( Iop_1Uto32, 14944 mkAND1( mkexpr( hiEQlo ), 14945 binop( Iop_CmpEQ32, 14946 mkU32( 0 ), 14947 unop( Iop_64to32, 14948 mkexpr( hiResult ) ) ) ) ) ); 14949 assign( ccPPC32, 14950 binop( Iop_Or32, 14951 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 14952 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 14953 14954 if (flag_rC) { 14955 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 14956 } 14957 } 14958 14959 /* 14960 * VSX Vector Compare Instructions 14961 */ 14962 static Bool 14963 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 14964 { 14965 /* XX3-Form */ 14966 UChar opc1 = ifieldOPC( theInstr ); 14967 UChar XT = ifieldRegXT ( theInstr ); 14968 UChar XA = ifieldRegXA ( theInstr ); 14969 UChar XB = ifieldRegXB ( theInstr ); 14970 UChar flag_rC = ifieldBIT10(theInstr); 14971 IRTemp vA = newTemp( Ity_V128 ); 14972 IRTemp vB = newTemp( Ity_V128 ); 14973 14974 if (opc1 != 0x3C) { 14975 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 14976 return False; 14977 } 14978 14979 assign( vA, getVSReg( XA ) ); 14980 assign( vB, getVSReg( XB ) ); 14981 14982 switch (opc2) { 14983 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 14984 { 14985 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14986 (UInt)XT, (UInt)XA, (UInt)XB); 14987 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 14988 break; 14989 } 14990 14991 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 14992 { 14993 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14994 (UInt)XT, (UInt)XA, (UInt)XB); 14995 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 14996 break; 14997 } 14998 14999 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 15000 { 15001 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15002 (UInt)XT, (UInt)XA, (UInt)XB); 15003 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 15004 break; 15005 } 15006 15007 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 15008 { 15009 IRTemp vD = newTemp(Ity_V128); 15010 15011 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15012 (UInt)XT, (UInt)XA, (UInt)XB); 15013 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 15014 putVSReg( XT, mkexpr(vD) ); 15015 if (flag_rC) { 15016 set_AV_CR6( mkexpr(vD), True ); 15017 } 15018 break; 15019 } 15020 15021 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 15022 { 15023 IRTemp vD = newTemp(Ity_V128); 15024 15025 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15026 (UInt)XT, (UInt)XA, (UInt)XB); 15027 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 15028 putVSReg( XT, mkexpr(vD) ); 15029 if (flag_rC) { 15030 set_AV_CR6( mkexpr(vD), True ); 15031 } 15032 break; 15033 } 15034 15035 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 15036 { 15037 IRTemp vD = newTemp(Ity_V128); 15038 15039 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15040 (UInt)XT, (UInt)XA, (UInt)XB); 15041 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 15042 putVSReg( XT, mkexpr(vD) ); 15043 if (flag_rC) { 15044 set_AV_CR6( mkexpr(vD), True ); 15045 } 15046 break; 15047 } 15048 15049 default: 15050 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 15051 return False; 15052 } 15053 return True; 15054 } 15055 /* 15056 * Miscellaneous VSX Scalar Instructions 15057 */ 15058 static Bool 15059 dis_vxs_misc( UInt theInstr, UInt opc2 ) 15060 { 15061 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL 15062 /* XX3-Form and XX2-Form */ 15063 UChar opc1 = ifieldOPC( theInstr ); 15064 UChar XT = ifieldRegXT ( theInstr ); 15065 UChar XA = ifieldRegXA ( theInstr ); 15066 UChar XB = ifieldRegXB ( theInstr ); 15067 IRTemp vA = newTemp( Ity_V128 ); 15068 IRTemp vB = newTemp( Ity_V128 ); 15069 15070 if (opc1 != 0x3C) { 15071 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 15072 return False; 15073 } 15074 15075 assign( vA, getVSReg( XA ) ); 15076 assign( vB, getVSReg( XB ) ); 15077 15078 /* For all the VSX move instructions, the contents of doubleword element 1 15079 * of VSX[XT] are undefined after the operation; therefore, we can simply 15080 * move the entire array element where it makes sense to do so. 15081 */ 15082 15083 switch (opc2) { 15084 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 15085 { 15086 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 15087 IRTemp absVal = newTemp(Ity_V128); 15088 if (host_endness == VexEndnessLE) { 15089 IRTemp hi64 = newTemp(Ity_I64); 15090 IRTemp lo64 = newTemp(Ity_I64); 15091 assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15092 assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) ); 15093 assign( absVal, binop( Iop_64HLtoV128, 15094 binop( Iop_And64, mkexpr(hi64), 15095 mkU64(VG_PPC_SIGN_MASK) ), 15096 mkexpr(lo64) ) ); 15097 } else { 15098 assign(absVal, binop(Iop_ShrV128, 15099 binop(Iop_ShlV128, mkexpr(vB), 15100 mkU8(1)), mkU8(1))); 15101 } 15102 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15103 putVSReg(XT, mkexpr(absVal)); 15104 break; 15105 } 15106 case 0x2C0: // xscpsgndp 15107 { 15108 /* Scalar copy sign double-precision */ 15109 IRTemp vecA_signed = newTemp(Ity_I64); 15110 IRTemp vecB_unsigned = newTemp(Ity_I64); 15111 IRTemp vec_result = newTemp(Ity_V128); 15112 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15113 assign( vecA_signed, binop( Iop_And64, 15114 unop( Iop_V128HIto64, 15115 mkexpr(vA)), 15116 mkU64(~VG_PPC_SIGN_MASK) ) ); 15117 assign( vecB_unsigned, binop( Iop_And64, 15118 unop( Iop_V128HIto64, 15119 mkexpr(vB) ), 15120 mkU64(VG_PPC_SIGN_MASK) ) ); 15121 assign( vec_result, binop( Iop_64HLtoV128, 15122 binop( Iop_Or64, 15123 mkexpr(vecA_signed), 15124 mkexpr(vecB_unsigned) ), 15125 mkU64(0x0ULL))); 15126 putVSReg(XT, mkexpr(vec_result)); 15127 break; 15128 } 15129 case 0x2D2: // xsnabsdp 15130 { 15131 /* Scalar negative absolute value double-precision */ 15132 IRTemp BHi_signed = newTemp(Ity_I64); 15133 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15134 assign( BHi_signed, binop( Iop_Or64, 15135 unop( Iop_V128HIto64, 15136 mkexpr(vB) ), 15137 mkU64(~VG_PPC_SIGN_MASK) ) ); 15138 putVSReg(XT, binop( Iop_64HLtoV128, 15139 mkexpr(BHi_signed), mkU64(0x0ULL) ) ); 15140 break; 15141 } 15142 case 0x2F2: // xsnegdp 15143 { 15144 /* Scalar negate double-precision */ 15145 IRTemp BHi_signed = newTemp(Ity_I64); 15146 IRTemp BHi_unsigned = newTemp(Ity_I64); 15147 IRTemp BHi_negated = newTemp(Ity_I64); 15148 IRTemp BHi_negated_signbit = newTemp(Ity_I1); 15149 IRTemp vec_result = newTemp(Ity_V128); 15150 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15151 assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15152 assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed), 15153 mkU64(VG_PPC_SIGN_MASK) ) ); 15154 assign( BHi_negated_signbit, 15155 unop( Iop_Not1, 15156 unop( Iop_32to1, 15157 binop( Iop_Shr32, 15158 unop( Iop_64HIto32, 15159 binop( Iop_And64, 15160 mkexpr(BHi_signed), 15161 mkU64(~VG_PPC_SIGN_MASK) ) 15162 ), 15163 mkU8(31) ) ) ) ); 15164 assign( BHi_negated, 15165 binop( Iop_Or64, 15166 binop( Iop_32HLto64, 15167 binop( Iop_Shl32, 15168 unop( Iop_1Uto32, 15169 mkexpr(BHi_negated_signbit) ), 15170 mkU8(31) ), 15171 mkU32(0) ), 15172 mkexpr(BHi_unsigned) ) ); 15173 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated), 15174 mkU64(0x0ULL))); 15175 putVSReg( XT, mkexpr(vec_result)); 15176 break; 15177 } 15178 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 15179 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 15180 { 15181 IRTemp frA = newTemp(Ity_I64); 15182 IRTemp frB = newTemp(Ity_I64); 15183 Bool isMin = opc2 == 0x2A0 ? True : False; 15184 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB); 15185 15186 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 15187 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 15188 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 15189 15190 break; 15191 } 15192 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 15193 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 15194 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 15195 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 15196 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 15197 { 15198 IRTemp frB_I64 = newTemp(Ity_I64); 15199 IRExpr * frD_fp_round = NULL; 15200 15201 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 15202 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2); 15203 15204 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 15205 putVSReg( XT, 15206 binop( Iop_64HLtoV128, 15207 unop( Iop_ReinterpF64asI64, frD_fp_round), 15208 mkU64( 0 ) ) ); 15209 break; 15210 } 15211 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision) 15212 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate 15213 * single-Precision) 15214 */ 15215 { 15216 IRTemp frB = newTemp(Ity_F64); 15217 IRTemp sqrt = newTemp(Ity_F64); 15218 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15219 IRExpr* rm = get_IR_roundingmode(); 15220 Bool redp = opc2 == 0x034; 15221 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT, 15222 (UInt)XB); 15223 15224 assign( frB, 15225 unop( Iop_ReinterpI64asF64, 15226 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15227 15228 if (!redp) 15229 assign( sqrt, 15230 binop( Iop_SqrtF64, 15231 rm, 15232 mkexpr(frB) ) ); 15233 putVSReg( XT, 15234 binop( Iop_64HLtoV128, 15235 unop( Iop_ReinterpF64asI64, 15236 binop( Iop_RoundF64toF32, rm, 15237 triop( Iop_DivF64, 15238 rm, 15239 ieee_one, 15240 redp ? mkexpr( frB ) : 15241 mkexpr( sqrt ) ) ) ), 15242 mkU64( 0 ) ) ); 15243 break; 15244 } 15245 15246 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 15247 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 15248 15249 { 15250 IRTemp frB = newTemp(Ity_F64); 15251 IRTemp sqrt = newTemp(Ity_F64); 15252 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15253 IRExpr* rm = get_IR_roundingmode(); 15254 Bool redp = opc2 == 0x0B4; 15255 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB); 15256 assign( frB, 15257 unop( Iop_ReinterpI64asF64, 15258 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15259 15260 if (!redp) 15261 assign( sqrt, 15262 binop( Iop_SqrtF64, 15263 rm, 15264 mkexpr(frB) ) ); 15265 putVSReg( XT, 15266 binop( Iop_64HLtoV128, 15267 unop( Iop_ReinterpF64asI64, 15268 triop( Iop_DivF64, 15269 rm, 15270 ieee_one, 15271 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 15272 mkU64( 0 ) ) ); 15273 break; 15274 } 15275 15276 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision) 15277 { 15278 IRTemp frB = newTemp(Ity_F64); 15279 IRExpr* rm = get_IR_roundingmode(); 15280 DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB); 15281 assign( frB, 15282 unop( Iop_ReinterpI64asF64, 15283 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15284 15285 putVSReg( XT, binop( Iop_64HLtoV128, 15286 unop( Iop_ReinterpF64asI64, 15287 binop( Iop_RoundF64toF32, 15288 rm, 15289 mkexpr( frB ) ) ), 15290 mkU64( 0 ) ) ); 15291 break; 15292 } 15293 15294 default: 15295 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 15296 return False; 15297 } 15298 return True; 15299 } 15300 15301 /* 15302 * VSX Logical Instructions 15303 */ 15304 static Bool 15305 dis_vx_logic ( UInt theInstr, UInt opc2 ) 15306 { 15307 /* XX3-Form */ 15308 UChar opc1 = ifieldOPC( theInstr ); 15309 UChar XT = ifieldRegXT ( theInstr ); 15310 UChar XA = ifieldRegXA ( theInstr ); 15311 UChar XB = ifieldRegXB ( theInstr ); 15312 IRTemp vA = newTemp( Ity_V128 ); 15313 IRTemp vB = newTemp( Ity_V128 ); 15314 15315 if (opc1 != 0x3C) { 15316 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 15317 return False; 15318 } 15319 15320 assign( vA, getVSReg( XA ) ); 15321 assign( vB, getVSReg( XB ) ); 15322 15323 switch (opc2) { 15324 case 0x268: // xxlxor 15325 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15326 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 15327 break; 15328 case 0x248: // xxlor 15329 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15330 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 15331 break; 15332 case 0x288: // xxlnor 15333 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15334 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 15335 mkexpr( vB ) ) ) ); 15336 break; 15337 case 0x208: // xxland 15338 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15339 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 15340 break; 15341 case 0x228: //xxlandc 15342 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15343 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 15344 mkexpr( vB ) ) ) ); 15345 break; 15346 case 0x2A8: // xxlorc (VSX Logical OR with complement) 15347 DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15348 putVSReg( XT, binop( Iop_OrV128, 15349 mkexpr( vA ), 15350 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 15351 break; 15352 case 0x2C8: // xxlnand (VSX Logical NAND) 15353 DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15354 putVSReg( XT, unop( Iop_NotV128, 15355 binop( Iop_AndV128, mkexpr( vA ), 15356 mkexpr( vB ) ) ) ); 15357 break; 15358 case 0x2E8: // xxleqv (VSX Logical Equivalence) 15359 DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15360 putVSReg( XT, unop( Iop_NotV128, 15361 binop( Iop_XorV128, 15362 mkexpr( vA ), mkexpr( vB ) ) ) ); 15363 break; 15364 default: 15365 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 15366 return False; 15367 } 15368 return True; 15369 } 15370 15371 /* 15372 * VSX Load Instructions 15373 * NOTE: VSX supports word-aligned storage access. 15374 */ 15375 static Bool 15376 dis_vx_load ( UInt theInstr ) 15377 { 15378 /* XX1-Form */ 15379 UChar opc1 = ifieldOPC( theInstr ); 15380 UChar XT = ifieldRegXT ( theInstr ); 15381 UChar rA_addr = ifieldRegA( theInstr ); 15382 UChar rB_addr = ifieldRegB( theInstr ); 15383 UInt opc2 = ifieldOPClo10( theInstr ); 15384 15385 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15386 IRTemp EA = newTemp( ty ); 15387 15388 if (opc1 != 0x1F) { 15389 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 15390 return False; 15391 } 15392 15393 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15394 15395 switch (opc2) { 15396 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) 15397 { 15398 IRExpr * exp; 15399 DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15400 15401 if (host_endness == VexEndnessLE) 15402 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15403 else 15404 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15405 15406 putVSReg( XT, binop( Iop_64HLtoV128, 15407 unop( Iop_32Uto64, exp), 15408 mkU64(0) ) ); 15409 break; 15410 } 15411 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) 15412 { 15413 IRExpr * exp; 15414 DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15415 15416 if (host_endness == VexEndnessLE) 15417 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15418 else 15419 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15420 15421 putVSReg( XT, binop( Iop_64HLtoV128, 15422 unop( Iop_32Sto64, exp), 15423 mkU64(0) ) ); 15424 break; 15425 } 15426 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed) 15427 { 15428 IRExpr * exp; 15429 DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15430 /* Take 32-bit floating point value in the upper half of the fetched 15431 * 64-bit value, convert to 64-bit floating point value and load into 15432 * top word of V128. 15433 */ 15434 exp = unop( Iop_ReinterpF64asI64, 15435 unop( Iop_F32toF64, 15436 unop( Iop_ReinterpI32asF32, 15437 load( Ity_I32, mkexpr( EA ) ) ) ) ); 15438 15439 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); 15440 break; 15441 } 15442 case 0x24C: // lxsdx 15443 { 15444 IRExpr * exp; 15445 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15446 exp = load( Ity_I64, mkexpr( EA ) ); 15447 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 15448 // we just performed is only a DW. But since the contents of VSR[XT] element 1 15449 // are undefined after this operation, we can just do a splat op. 15450 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 15451 break; 15452 } 15453 case 0x34C: // lxvd2x 15454 { 15455 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 15456 IRExpr * high, *low; 15457 ULong ea_off = 8; 15458 IRExpr* high_addr; 15459 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15460 high = load( Ity_I64, mkexpr( EA ) ); 15461 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 15462 : mkU32( ea_off ) ); 15463 low = load( Ity_I64, high_addr ); 15464 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 15465 break; 15466 } 15467 case 0x14C: // lxvdsx 15468 { 15469 IRTemp data = newTemp(Ity_I64); 15470 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15471 assign( data, load( Ity_I64, mkexpr( EA ) ) ); 15472 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 15473 break; 15474 } 15475 case 0x30C: 15476 { 15477 IRExpr *t0; 15478 15479 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15480 15481 /* The load will result in the data being in BE order. */ 15482 if (host_endness == VexEndnessLE) { 15483 IRExpr *t0_BE; 15484 IRTemp perm_LE = newTemp(Ity_V128); 15485 15486 t0_BE = load( Ity_V128, mkexpr( EA ) ); 15487 15488 /* Permute the data to LE format */ 15489 assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL), 15490 mkU64(0x0405060700010203ULL))); 15491 15492 t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) ); 15493 } else { 15494 t0 = load( Ity_V128, mkexpr( EA ) ); 15495 } 15496 15497 putVSReg( XT, t0 ); 15498 break; 15499 } 15500 default: 15501 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 15502 return False; 15503 } 15504 return True; 15505 } 15506 15507 /* 15508 * VSX Store Instructions 15509 * NOTE: VSX supports word-aligned storage access. 15510 */ 15511 static Bool 15512 dis_vx_store ( UInt theInstr ) 15513 { 15514 /* XX1-Form */ 15515 UChar opc1 = ifieldOPC( theInstr ); 15516 UChar XS = ifieldRegXS( theInstr ); 15517 UChar rA_addr = ifieldRegA( theInstr ); 15518 UChar rB_addr = ifieldRegB( theInstr ); 15519 IRTemp vS = newTemp( Ity_V128 ); 15520 UInt opc2 = ifieldOPClo10( theInstr ); 15521 15522 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15523 IRTemp EA = newTemp( ty ); 15524 15525 if (opc1 != 0x1F) { 15526 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 15527 return False; 15528 } 15529 15530 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15531 assign( vS, getVSReg( XS ) ); 15532 15533 switch (opc2) { 15534 case 0x08C: 15535 { 15536 /* Need the next to the most significant 32-bit word from 15537 * the 128-bit vector. 15538 */ 15539 IRExpr * high64, * low32; 15540 DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15541 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15542 low32 = unop( Iop_64to32, high64 ); 15543 store( mkexpr( EA ), low32 ); 15544 break; 15545 } 15546 case 0x28C: 15547 { 15548 IRTemp high64 = newTemp(Ity_F64); 15549 IRTemp val32 = newTemp(Ity_I32); 15550 DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15551 assign(high64, unop( Iop_ReinterpI64asF64, 15552 unop( Iop_V128HIto64, mkexpr( vS ) ) ) ); 15553 assign(val32, unop( Iop_ReinterpF32asI32, 15554 unop( Iop_TruncF64asF32, 15555 mkexpr(high64) ) ) ); 15556 store( mkexpr( EA ), mkexpr( val32 ) ); 15557 break; 15558 } 15559 case 0x2CC: 15560 { 15561 IRExpr * high64; 15562 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15563 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15564 store( mkexpr( EA ), high64 ); 15565 break; 15566 } 15567 case 0x3CC: 15568 { 15569 IRExpr * high64, *low64; 15570 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15571 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15572 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 15573 store( mkexpr( EA ), high64 ); 15574 store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15575 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 ); 15576 break; 15577 } 15578 case 0x38C: 15579 { 15580 UInt ea_off = 0; 15581 IRExpr* irx_addr; 15582 IRTemp hi64 = newTemp( Ity_I64 ); 15583 IRTemp lo64 = newTemp( Ity_I64 ); 15584 15585 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15586 15587 // This instruction supports word-aligned stores, so EA may not be 15588 // quad-word aligned. Therefore, do 4 individual word-size stores. 15589 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 15590 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 15591 store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 15592 ea_off += 4; 15593 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15594 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15595 store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 15596 ea_off += 4; 15597 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15598 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15599 store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 15600 ea_off += 4; 15601 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15602 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15603 store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 15604 15605 break; 15606 } 15607 default: 15608 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 15609 return False; 15610 } 15611 return True; 15612 } 15613 15614 /* 15615 * VSX permute and other miscealleous instructions 15616 */ 15617 static Bool 15618 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 15619 { 15620 /* XX3-Form */ 15621 UChar opc1 = ifieldOPC( theInstr ); 15622 UChar XT = ifieldRegXT ( theInstr ); 15623 UChar XA = ifieldRegXA ( theInstr ); 15624 UChar XB = ifieldRegXB ( theInstr ); 15625 IRTemp vT = newTemp( Ity_V128 ); 15626 IRTemp vA = newTemp( Ity_V128 ); 15627 IRTemp vB = newTemp( Ity_V128 ); 15628 15629 if (opc1 != 0x3C) { 15630 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 15631 return False; 15632 } 15633 15634 assign( vA, getVSReg( XA ) ); 15635 assign( vB, getVSReg( XB ) ); 15636 15637 switch (opc2) { 15638 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 15639 { 15640 UChar SHW = ifieldSHW ( theInstr ); 15641 IRTemp result = newTemp(Ity_V128); 15642 if ( SHW != 0 ) { 15643 IRTemp hi = newTemp(Ity_V128); 15644 IRTemp lo = newTemp(Ity_V128); 15645 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 15646 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 15647 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 15648 } else 15649 assign ( result, mkexpr(vA) ); 15650 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW); 15651 putVSReg( XT, mkexpr(result) ); 15652 break; 15653 } 15654 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 15655 { 15656 UChar DM = ifieldDM ( theInstr ); 15657 IRTemp hi = newTemp(Ity_I64); 15658 IRTemp lo = newTemp(Ity_I64); 15659 15660 if (DM & 0x2) 15661 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 15662 else 15663 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 15664 15665 if (DM & 0x1) 15666 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 15667 else 15668 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 15669 15670 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 15671 15672 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM); 15673 putVSReg( XT, mkexpr( vT ) ); 15674 break; 15675 } 15676 case 0x48: // xxmrghw (VSX Merge High Word) 15677 case 0xc8: // xxmrglw (VSX Merge Low Word) 15678 { 15679 const HChar type = (opc2 == 0x48) ? 'h' : 'l'; 15680 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 15681 IRTemp a64 = newTemp(Ity_I64); 15682 IRTemp ahi32 = newTemp(Ity_I32); 15683 IRTemp alo32 = newTemp(Ity_I32); 15684 IRTemp b64 = newTemp(Ity_I64); 15685 IRTemp bhi32 = newTemp(Ity_I32); 15686 IRTemp blo32 = newTemp(Ity_I32); 15687 15688 assign( a64, unop(word_op, mkexpr(vA)) ); 15689 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 15690 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 15691 15692 assign( b64, unop(word_op, mkexpr(vB)) ); 15693 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 15694 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 15695 15696 assign( vT, binop(Iop_64HLtoV128, 15697 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 15698 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 15699 15700 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB); 15701 putVSReg( XT, mkexpr( vT ) ); 15702 break; 15703 } 15704 case 0x018: // xxsel (VSX Select) 15705 { 15706 UChar XC = ifieldRegXC(theInstr); 15707 IRTemp vC = newTemp( Ity_V128 ); 15708 assign( vC, getVSReg( XC ) ); 15709 DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC); 15710 /* vD = (vA & ~vC) | (vB & vC) */ 15711 putVSReg( XT, binop(Iop_OrV128, 15712 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 15713 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 15714 break; 15715 } 15716 case 0x148: // xxspltw (VSX Splat Word) 15717 { 15718 UChar UIM = ifieldRegA(theInstr) & 3; 15719 UChar sh_uim = (3 - (UIM)) * 32; 15720 DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM); 15721 putVSReg( XT, 15722 unop( Iop_Dup32x4, 15723 unop( Iop_V128to32, 15724 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 15725 break; 15726 } 15727 15728 default: 15729 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 15730 return False; 15731 } 15732 return True; 15733 } 15734 15735 /* 15736 AltiVec Load Instructions 15737 */ 15738 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) 15739 { 15740 /* X-Form */ 15741 UChar opc1 = ifieldOPC(theInstr); 15742 UChar vD_addr = ifieldRegDS(theInstr); 15743 UChar rA_addr = ifieldRegA(theInstr); 15744 UChar rB_addr = ifieldRegB(theInstr); 15745 UInt opc2 = ifieldOPClo10(theInstr); 15746 UChar b0 = ifieldBIT0(theInstr); 15747 15748 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15749 IRTemp EA = newTemp(ty); 15750 IRTemp EA_align16 = newTemp(ty); 15751 15752 if (opc1 != 0x1F || b0 != 0) { 15753 vex_printf("dis_av_load(ppc)(instr)\n"); 15754 return False; 15755 } 15756 15757 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15758 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 15759 15760 switch (opc2) { 15761 15762 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 15763 IRDirty* d; 15764 UInt vD_off = vectorGuestRegOffset(vD_addr); 15765 IRExpr** args_be = mkIRExprVec_5( 15766 IRExpr_BBPTR(), 15767 mkU32(vD_off), 15768 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15769 mkU32(0xF)), 15770 mkU32(0)/*left*/, 15771 mkU32(1)/*Big Endian*/); 15772 IRExpr** args_le = mkIRExprVec_5( 15773 IRExpr_BBPTR(), 15774 mkU32(vD_off), 15775 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15776 mkU32(0xF)), 15777 mkU32(0)/*left*/, 15778 mkU32(0)/*Little Endian*/); 15779 if (!mode64) { 15780 d = unsafeIRDirty_0_N ( 15781 0/*regparms*/, 15782 "ppc32g_dirtyhelper_LVS", 15783 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15784 args_be ); 15785 } else { 15786 if (host_endness == VexEndnessBE) 15787 d = unsafeIRDirty_0_N ( 15788 0/*regparms*/, 15789 "ppc64g_dirtyhelper_LVS", 15790 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15791 args_be ); 15792 else 15793 d = unsafeIRDirty_0_N ( 15794 0/*regparms*/, 15795 "ppc64g_dirtyhelper_LVS", 15796 &ppc64g_dirtyhelper_LVS, 15797 args_le ); 15798 } 15799 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15800 /* declare guest state effects */ 15801 d->nFxState = 1; 15802 vex_bzero(&d->fxState, sizeof(d->fxState)); 15803 d->fxState[0].fx = Ifx_Write; 15804 d->fxState[0].offset = vD_off; 15805 d->fxState[0].size = sizeof(U128); 15806 15807 /* execute the dirty call, side-effecting guest state */ 15808 stmt( IRStmt_Dirty(d) ); 15809 break; 15810 } 15811 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 15812 IRDirty* d; 15813 UInt vD_off = vectorGuestRegOffset(vD_addr); 15814 IRExpr** args_be = mkIRExprVec_5( 15815 IRExpr_BBPTR(), 15816 mkU32(vD_off), 15817 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15818 mkU32(0xF)), 15819 mkU32(1)/*right*/, 15820 mkU32(1)/*Big Endian*/); 15821 IRExpr** args_le = mkIRExprVec_5( 15822 IRExpr_BBPTR(), 15823 mkU32(vD_off), 15824 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15825 mkU32(0xF)), 15826 mkU32(1)/*right*/, 15827 mkU32(0)/*Little Endian*/); 15828 15829 if (!mode64) { 15830 d = unsafeIRDirty_0_N ( 15831 0/*regparms*/, 15832 "ppc32g_dirtyhelper_LVS", 15833 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15834 args_be ); 15835 } else { 15836 if (host_endness == VexEndnessBE) 15837 d = unsafeIRDirty_0_N ( 15838 0/*regparms*/, 15839 "ppc64g_dirtyhelper_LVS", 15840 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15841 args_be ); 15842 else 15843 d = unsafeIRDirty_0_N ( 15844 0/*regparms*/, 15845 "ppc64g_dirtyhelper_LVS", 15846 &ppc64g_dirtyhelper_LVS, 15847 args_le ); 15848 } 15849 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15850 /* declare guest state effects */ 15851 d->nFxState = 1; 15852 vex_bzero(&d->fxState, sizeof(d->fxState)); 15853 d->fxState[0].fx = Ifx_Write; 15854 d->fxState[0].offset = vD_off; 15855 d->fxState[0].size = sizeof(U128); 15856 15857 /* execute the dirty call, side-effecting guest state */ 15858 stmt( IRStmt_Dirty(d) ); 15859 break; 15860 } 15861 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 15862 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15863 /* loads addressed byte into vector[EA[0:3] 15864 since all other destination bytes are undefined, 15865 can simply load entire vector from 16-aligned EA */ 15866 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15867 break; 15868 15869 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 15870 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15871 /* see note for lvebx */ 15872 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15873 break; 15874 15875 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 15876 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15877 /* see note for lvebx */ 15878 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15879 break; 15880 15881 case 0x067: // lvx (Load Vector Indexed, AV p127) 15882 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15883 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15884 break; 15885 15886 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 15887 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15888 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15889 break; 15890 15891 default: 15892 vex_printf("dis_av_load(ppc)(opc2)\n"); 15893 return False; 15894 } 15895 return True; 15896 } 15897 15898 /* 15899 AltiVec Store Instructions 15900 */ 15901 static Bool dis_av_store ( UInt theInstr ) 15902 { 15903 /* X-Form */ 15904 UChar opc1 = ifieldOPC(theInstr); 15905 UChar vS_addr = ifieldRegDS(theInstr); 15906 UChar rA_addr = ifieldRegA(theInstr); 15907 UChar rB_addr = ifieldRegB(theInstr); 15908 UInt opc2 = ifieldOPClo10(theInstr); 15909 UChar b0 = ifieldBIT0(theInstr); 15910 15911 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15912 IRTemp EA = newTemp(ty); 15913 IRTemp addr_aligned = newTemp(ty); 15914 IRTemp vS = newTemp(Ity_V128); 15915 IRTemp eb = newTemp(Ity_I8); 15916 IRTemp idx = newTemp(Ity_I8); 15917 15918 if (opc1 != 0x1F || b0 != 0) { 15919 vex_printf("dis_av_store(ppc)(instr)\n"); 15920 return False; 15921 } 15922 15923 assign( vS, getVReg(vS_addr)); 15924 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15925 15926 switch (opc2) { 15927 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 15928 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15929 assign( eb, binop(Iop_And8, mkU8(0xF), 15930 unop(Iop_32to8, 15931 mkNarrowTo32(ty, mkexpr(EA)) )) ); 15932 if (host_endness == VexEndnessLE) { 15933 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15934 } else { 15935 assign( idx, binop(Iop_Shl8, 15936 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 15937 mkU8(3)) ); 15938 } 15939 store( mkexpr(EA), 15940 unop( Iop_32to8, unop(Iop_V128to32, 15941 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15942 break; 15943 } 15944 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 15945 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15946 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 15947 assign( eb, binop(Iop_And8, mkU8(0xF), 15948 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15949 if (host_endness == VexEndnessLE) { 15950 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15951 } else { 15952 assign( idx, binop(Iop_Shl8, 15953 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 15954 mkU8(3)) ); 15955 } 15956 store( mkexpr(addr_aligned), 15957 unop( Iop_32to16, unop(Iop_V128to32, 15958 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15959 break; 15960 } 15961 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 15962 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15963 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 15964 assign( eb, binop(Iop_And8, mkU8(0xF), 15965 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15966 if (host_endness == VexEndnessLE) { 15967 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15968 } else { 15969 assign( idx, binop(Iop_Shl8, 15970 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 15971 mkU8(3)) ); 15972 } 15973 store( mkexpr( addr_aligned), 15974 unop( Iop_V128to32, 15975 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 15976 break; 15977 } 15978 15979 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 15980 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15981 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15982 break; 15983 15984 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 15985 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15986 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15987 break; 15988 15989 default: 15990 vex_printf("dis_av_store(ppc)(opc2)\n"); 15991 return False; 15992 } 15993 return True; 15994 } 15995 15996 /* 15997 AltiVec Arithmetic Instructions 15998 */ 15999 static Bool dis_av_arith ( UInt theInstr ) 16000 { 16001 /* VX-Form */ 16002 UChar opc1 = ifieldOPC(theInstr); 16003 UChar vD_addr = ifieldRegDS(theInstr); 16004 UChar vA_addr = ifieldRegA(theInstr); 16005 UChar vB_addr = ifieldRegB(theInstr); 16006 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16007 16008 IRTemp vA = newTemp(Ity_V128); 16009 IRTemp vB = newTemp(Ity_V128); 16010 IRTemp z3 = newTemp(Ity_I64); 16011 IRTemp z2 = newTemp(Ity_I64); 16012 IRTemp z1 = newTemp(Ity_I64); 16013 IRTemp z0 = newTemp(Ity_I64); 16014 IRTemp aEvn, aOdd; 16015 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 16016 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 16017 IRTemp b3, b2, b1, b0; 16018 16019 aEvn = aOdd = IRTemp_INVALID; 16020 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 16021 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 16022 b3 = b2 = b1 = b0 = IRTemp_INVALID; 16023 16024 assign( vA, getVReg(vA_addr)); 16025 assign( vB, getVReg(vB_addr)); 16026 16027 if (opc1 != 0x4) { 16028 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 16029 return False; 16030 } 16031 16032 switch (opc2) { 16033 /* Add */ 16034 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 16035 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16036 /* unsigned_ov(x+y) = (y >u not(x)) */ 16037 putVReg( vD_addr, binop(Iop_ShrN32x4, 16038 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16039 unop(Iop_NotV128, mkexpr(vA))), 16040 mkU8(31)) ); 16041 break; 16042 } 16043 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 16044 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16045 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 16046 break; 16047 16048 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 16049 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16050 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 16051 break; 16052 16053 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 16054 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16055 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 16056 break; 16057 16058 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo) 16059 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16060 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) ); 16061 break; 16062 16063 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 16064 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16065 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 16066 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 16067 break; 16068 16069 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 16070 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16071 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 16072 // TODO: set VSCR[SAT] 16073 break; 16074 16075 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 16076 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16077 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 16078 // TODO: set VSCR[SAT] 16079 break; 16080 16081 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 16082 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16083 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 16084 // TODO: set VSCR[SAT] 16085 break; 16086 16087 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 16088 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16089 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 16090 // TODO: set VSCR[SAT] 16091 break; 16092 16093 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 16094 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16095 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 16096 // TODO: set VSCR[SAT] 16097 break; 16098 16099 16100 /* Subtract */ 16101 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 16102 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16103 /* unsigned_ov(x-y) = (y >u x) */ 16104 putVReg( vD_addr, binop(Iop_ShrN32x4, 16105 unop(Iop_NotV128, 16106 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16107 mkexpr(vA))), 16108 mkU8(31)) ); 16109 break; 16110 } 16111 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 16112 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16113 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 16114 break; 16115 16116 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 16117 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16118 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 16119 break; 16120 16121 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 16122 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16123 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 16124 break; 16125 16126 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo) 16127 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16128 putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) ); 16129 break; 16130 16131 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 16132 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16133 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 16134 // TODO: set VSCR[SAT] 16135 break; 16136 16137 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 16138 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16139 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 16140 // TODO: set VSCR[SAT] 16141 break; 16142 16143 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 16144 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16145 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 16146 // TODO: set VSCR[SAT] 16147 break; 16148 16149 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 16150 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16151 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 16152 // TODO: set VSCR[SAT] 16153 break; 16154 16155 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 16156 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16157 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 16158 // TODO: set VSCR[SAT] 16159 break; 16160 16161 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 16162 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16163 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 16164 // TODO: set VSCR[SAT] 16165 break; 16166 16167 16168 /* Maximum */ 16169 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 16170 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16171 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 16172 break; 16173 16174 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 16175 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16176 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 16177 break; 16178 16179 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 16180 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16181 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 16182 break; 16183 16184 case 0x0C2: // vmaxud (Maximum Unsigned Double word) 16185 DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16186 putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) ); 16187 break; 16188 16189 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 16190 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16191 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 16192 break; 16193 16194 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 16195 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16196 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 16197 break; 16198 16199 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 16200 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16201 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 16202 break; 16203 16204 case 0x1C2: // vmaxsd (Maximum Signed Double word) 16205 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16206 putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) ); 16207 break; 16208 16209 /* Minimum */ 16210 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 16211 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16212 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 16213 break; 16214 16215 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 16216 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16217 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 16218 break; 16219 16220 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 16221 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16222 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 16223 break; 16224 16225 case 0x2C2: // vminud (Minimum Unsigned Double Word) 16226 DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16227 putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) ); 16228 break; 16229 16230 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 16231 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16232 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 16233 break; 16234 16235 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 16236 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16237 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 16238 break; 16239 16240 case 0x382: // vminsw (Minimum Signed Word, AV p190) 16241 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16242 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 16243 break; 16244 16245 case 0x3C2: // vminsd (Minimum Signed Double Word) 16246 DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16247 putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) ); 16248 break; 16249 16250 16251 /* Average */ 16252 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 16253 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16254 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 16255 break; 16256 16257 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 16258 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16259 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 16260 break; 16261 16262 case 0x482: // vavguw (Average Unsigned Word, AV p154) 16263 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16264 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 16265 break; 16266 16267 case 0x502: // vavgsb (Average Signed Byte, AV p149) 16268 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16269 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 16270 break; 16271 16272 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 16273 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16274 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 16275 break; 16276 16277 case 0x582: // vavgsw (Average Signed Word, AV p151) 16278 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16279 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 16280 break; 16281 16282 16283 /* Multiply */ 16284 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 16285 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16286 putVReg( vD_addr, 16287 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 16288 break; 16289 16290 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 16291 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16292 putVReg( vD_addr, 16293 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 16294 break; 16295 16296 case 0x088: // vmulouw (Multiply Odd Unsigned Word) 16297 DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16298 putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) ); 16299 break; 16300 16301 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo) 16302 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16303 putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) ); 16304 break; 16305 16306 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 16307 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16308 putVReg( vD_addr, 16309 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 16310 break; 16311 16312 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 16313 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16314 putVReg( vD_addr, 16315 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 16316 break; 16317 16318 case 0x188: // vmulosw (Multiply Odd Signed Word) 16319 DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16320 putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) ); 16321 break; 16322 16323 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 16324 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16325 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 16326 break; 16327 16328 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 16329 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16330 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 16331 break; 16332 16333 case 0x288: // vmuleuw (Multiply Even Unsigned Word) 16334 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16335 putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) ); 16336 break; 16337 16338 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 16339 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16340 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 16341 break; 16342 16343 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 16344 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16345 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16346 break; 16347 16348 case 0x388: // vmulesw (Multiply Even Signed Word) 16349 DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16350 putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) ); 16351 break; 16352 16353 /* Sum Across Partial */ 16354 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 16355 IRTemp aEE, aEO, aOE, aOO; 16356 aEE = aEO = aOE = aOO = IRTemp_INVALID; 16357 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16358 16359 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 16360 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 16361 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 16362 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 16363 16364 /* break V128 to 4xI32's, zero-extending to I64's */ 16365 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 16366 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 16367 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 16368 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 16369 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16370 16371 /* add lanes */ 16372 assign( z3, binop(Iop_Add64, mkexpr(b3), 16373 binop(Iop_Add64, 16374 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 16375 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 16376 assign( z2, binop(Iop_Add64, mkexpr(b2), 16377 binop(Iop_Add64, 16378 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16379 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16380 assign( z1, binop(Iop_Add64, mkexpr(b1), 16381 binop(Iop_Add64, 16382 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16383 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16384 assign( z0, binop(Iop_Add64, mkexpr(b0), 16385 binop(Iop_Add64, 16386 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16387 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16388 16389 /* saturate-narrow to 32bit, and combine to V128 */ 16390 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 16391 mkexpr(z1), mkexpr(z0)) ); 16392 break; 16393 } 16394 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 16395 IRTemp aEE, aEO, aOE, aOO; 16396 aEE = aEO = aOE = aOO = IRTemp_INVALID; 16397 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16398 16399 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 16400 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 16401 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 16402 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 16403 16404 /* break V128 to 4xI32's, sign-extending to I64's */ 16405 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 16406 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 16407 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 16408 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 16409 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16410 16411 /* add lanes */ 16412 assign( z3, binop(Iop_Add64, mkexpr(b3), 16413 binop(Iop_Add64, 16414 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 16415 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 16416 assign( z2, binop(Iop_Add64, mkexpr(b2), 16417 binop(Iop_Add64, 16418 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16419 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16420 assign( z1, binop(Iop_Add64, mkexpr(b1), 16421 binop(Iop_Add64, 16422 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16423 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16424 assign( z0, binop(Iop_Add64, mkexpr(b0), 16425 binop(Iop_Add64, 16426 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16427 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16428 16429 /* saturate-narrow to 32bit, and combine to V128 */ 16430 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16431 mkexpr(z1), mkexpr(z0)) ); 16432 break; 16433 } 16434 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 16435 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16436 16437 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 16438 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 16439 16440 /* break V128 to 4xI32's, sign-extending to I64's */ 16441 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 16442 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 16443 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16444 16445 /* add lanes */ 16446 assign( z3, binop(Iop_Add64, mkexpr(b3), 16447 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 16448 assign( z2, binop(Iop_Add64, mkexpr(b2), 16449 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 16450 assign( z1, binop(Iop_Add64, mkexpr(b1), 16451 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 16452 assign( z0, binop(Iop_Add64, mkexpr(b0), 16453 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 16454 16455 /* saturate-narrow to 32bit, and combine to V128 */ 16456 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16457 mkexpr(z1), mkexpr(z0)) ); 16458 break; 16459 } 16460 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 16461 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16462 16463 /* break V128 to 4xI32's, sign-extending to I64's */ 16464 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16465 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16466 16467 /* add lanes */ 16468 assign( z2, binop(Iop_Add64, mkexpr(b2), 16469 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 16470 assign( z0, binop(Iop_Add64, mkexpr(b0), 16471 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 16472 16473 /* saturate-narrow to 32bit, and combine to V128 */ 16474 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 16475 mkU64(0), mkexpr(z0)) ); 16476 break; 16477 } 16478 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 16479 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16480 16481 /* break V128 to 4xI32's, sign-extending to I64's */ 16482 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16483 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16484 16485 /* add lanes */ 16486 assign( z0, binop(Iop_Add64, mkexpr(b0), 16487 binop(Iop_Add64, 16488 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16489 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16490 16491 /* saturate-narrow to 32bit, and combine to V128 */ 16492 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 16493 mkU64(0), mkexpr(z0)) ); 16494 break; 16495 } 16496 default: 16497 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 16498 return False; 16499 } 16500 return True; 16501 } 16502 16503 /* 16504 AltiVec Logic Instructions 16505 */ 16506 static Bool dis_av_logic ( UInt theInstr ) 16507 { 16508 /* VX-Form */ 16509 UChar opc1 = ifieldOPC(theInstr); 16510 UChar vD_addr = ifieldRegDS(theInstr); 16511 UChar vA_addr = ifieldRegA(theInstr); 16512 UChar vB_addr = ifieldRegB(theInstr); 16513 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16514 16515 IRTemp vA = newTemp(Ity_V128); 16516 IRTemp vB = newTemp(Ity_V128); 16517 assign( vA, getVReg(vA_addr)); 16518 assign( vB, getVReg(vB_addr)); 16519 16520 if (opc1 != 0x4) { 16521 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 16522 return False; 16523 } 16524 16525 switch (opc2) { 16526 case 0x404: // vand (And, AV p147) 16527 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16528 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 16529 break; 16530 16531 case 0x444: // vandc (And, AV p148) 16532 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16533 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 16534 unop(Iop_NotV128, mkexpr(vB))) ); 16535 break; 16536 16537 case 0x484: // vor (Or, AV p217) 16538 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16539 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 16540 break; 16541 16542 case 0x4C4: // vxor (Xor, AV p282) 16543 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16544 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 16545 break; 16546 16547 case 0x504: // vnor (Nor, AV p216) 16548 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16549 putVReg( vD_addr, 16550 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 16551 break; 16552 16553 case 0x544: // vorc (vA Or'd with complement of vb) 16554 DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16555 putVReg( vD_addr, binop( Iop_OrV128, 16556 mkexpr( vA ), 16557 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 16558 break; 16559 16560 case 0x584: // vnand (Nand) 16561 DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16562 putVReg( vD_addr, unop( Iop_NotV128, 16563 binop(Iop_AndV128, mkexpr( vA ), 16564 mkexpr( vB ) ) ) ); 16565 break; 16566 16567 case 0x684: // veqv (complemented XOr) 16568 DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16569 putVReg( vD_addr, unop( Iop_NotV128, 16570 binop( Iop_XorV128, mkexpr( vA ), 16571 mkexpr( vB ) ) ) ); 16572 break; 16573 16574 default: 16575 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 16576 return False; 16577 } 16578 return True; 16579 } 16580 16581 /* 16582 AltiVec Compare Instructions 16583 */ 16584 static Bool dis_av_cmp ( UInt theInstr ) 16585 { 16586 /* VXR-Form */ 16587 UChar opc1 = ifieldOPC(theInstr); 16588 UChar vD_addr = ifieldRegDS(theInstr); 16589 UChar vA_addr = ifieldRegA(theInstr); 16590 UChar vB_addr = ifieldRegB(theInstr); 16591 UChar flag_rC = ifieldBIT10(theInstr); 16592 UInt opc2 = IFIELD( theInstr, 0, 10 ); 16593 16594 IRTemp vA = newTemp(Ity_V128); 16595 IRTemp vB = newTemp(Ity_V128); 16596 IRTemp vD = newTemp(Ity_V128); 16597 assign( vA, getVReg(vA_addr)); 16598 assign( vB, getVReg(vB_addr)); 16599 16600 if (opc1 != 0x4) { 16601 vex_printf("dis_av_cmp(ppc)(instr)\n"); 16602 return False; 16603 } 16604 16605 switch (opc2) { 16606 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 16607 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16608 vD_addr, vA_addr, vB_addr); 16609 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 16610 break; 16611 16612 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 16613 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16614 vD_addr, vA_addr, vB_addr); 16615 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 16616 break; 16617 16618 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 16619 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16620 vD_addr, vA_addr, vB_addr); 16621 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 16622 break; 16623 16624 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword) 16625 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16626 vD_addr, vA_addr, vB_addr); 16627 assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) ); 16628 break; 16629 16630 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 16631 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16632 vD_addr, vA_addr, vB_addr); 16633 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 16634 break; 16635 16636 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 16637 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16638 vD_addr, vA_addr, vB_addr); 16639 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 16640 break; 16641 16642 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 16643 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16644 vD_addr, vA_addr, vB_addr); 16645 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 16646 break; 16647 16648 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double) 16649 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16650 vD_addr, vA_addr, vB_addr); 16651 assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) ); 16652 break; 16653 16654 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 16655 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16656 vD_addr, vA_addr, vB_addr); 16657 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 16658 break; 16659 16660 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 16661 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16662 vD_addr, vA_addr, vB_addr); 16663 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 16664 break; 16665 16666 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 16667 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16668 vD_addr, vA_addr, vB_addr); 16669 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 16670 break; 16671 16672 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double) 16673 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16674 vD_addr, vA_addr, vB_addr); 16675 assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) ); 16676 break; 16677 16678 default: 16679 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 16680 return False; 16681 } 16682 16683 putVReg( vD_addr, mkexpr(vD) ); 16684 16685 if (flag_rC) { 16686 set_AV_CR6( mkexpr(vD), True ); 16687 } 16688 return True; 16689 } 16690 16691 /* 16692 AltiVec Multiply-Sum Instructions 16693 */ 16694 static Bool dis_av_multarith ( UInt theInstr ) 16695 { 16696 /* VA-Form */ 16697 UChar opc1 = ifieldOPC(theInstr); 16698 UChar vD_addr = ifieldRegDS(theInstr); 16699 UChar vA_addr = ifieldRegA(theInstr); 16700 UChar vB_addr = ifieldRegB(theInstr); 16701 UChar vC_addr = ifieldRegC(theInstr); 16702 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 16703 16704 IRTemp vA = newTemp(Ity_V128); 16705 IRTemp vB = newTemp(Ity_V128); 16706 IRTemp vC = newTemp(Ity_V128); 16707 IRTemp zeros = newTemp(Ity_V128); 16708 IRTemp aLo = newTemp(Ity_V128); 16709 IRTemp bLo = newTemp(Ity_V128); 16710 IRTemp cLo = newTemp(Ity_V128); 16711 IRTemp zLo = newTemp(Ity_V128); 16712 IRTemp aHi = newTemp(Ity_V128); 16713 IRTemp bHi = newTemp(Ity_V128); 16714 IRTemp cHi = newTemp(Ity_V128); 16715 IRTemp zHi = newTemp(Ity_V128); 16716 IRTemp abEvn = newTemp(Ity_V128); 16717 IRTemp abOdd = newTemp(Ity_V128); 16718 IRTemp z3 = newTemp(Ity_I64); 16719 IRTemp z2 = newTemp(Ity_I64); 16720 IRTemp z1 = newTemp(Ity_I64); 16721 IRTemp z0 = newTemp(Ity_I64); 16722 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 16723 IRTemp c3, c2, c1, c0; 16724 16725 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 16726 c3 = c2 = c1 = c0 = IRTemp_INVALID; 16727 16728 assign( vA, getVReg(vA_addr)); 16729 assign( vB, getVReg(vB_addr)); 16730 assign( vC, getVReg(vC_addr)); 16731 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 16732 16733 if (opc1 != 0x4) { 16734 vex_printf("dis_av_multarith(ppc)(instr)\n"); 16735 return False; 16736 } 16737 16738 switch (opc2) { 16739 /* Multiply-Add */ 16740 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 16741 IRTemp cSigns = newTemp(Ity_V128); 16742 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 16743 vD_addr, vA_addr, vB_addr, vC_addr); 16744 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 16745 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16746 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16747 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16748 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16749 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16750 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16751 16752 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16753 binop(Iop_SarN32x4, 16754 binop(Iop_MullEven16Sx8, 16755 mkexpr(aLo), mkexpr(bLo)), 16756 mkU8(15))) ); 16757 16758 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16759 binop(Iop_SarN32x4, 16760 binop(Iop_MullEven16Sx8, 16761 mkexpr(aHi), mkexpr(bHi)), 16762 mkU8(15))) ); 16763 16764 putVReg( vD_addr, 16765 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16766 break; 16767 } 16768 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 16769 IRTemp zKonst = newTemp(Ity_V128); 16770 IRTemp cSigns = newTemp(Ity_V128); 16771 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 16772 vD_addr, vA_addr, vB_addr, vC_addr); 16773 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 16774 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16775 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16776 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16777 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16778 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16779 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16780 16781 /* shifting our const avoids store/load version of Dup */ 16782 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 16783 mkU8(14)) ); 16784 16785 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16786 binop(Iop_SarN32x4, 16787 binop(Iop_Add32x4, mkexpr(zKonst), 16788 binop(Iop_MullEven16Sx8, 16789 mkexpr(aLo), mkexpr(bLo))), 16790 mkU8(15))) ); 16791 16792 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16793 binop(Iop_SarN32x4, 16794 binop(Iop_Add32x4, mkexpr(zKonst), 16795 binop(Iop_MullEven16Sx8, 16796 mkexpr(aHi), mkexpr(bHi))), 16797 mkU8(15))) ); 16798 16799 putVReg( vD_addr, 16800 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16801 break; 16802 } 16803 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 16804 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 16805 vD_addr, vA_addr, vB_addr, vC_addr); 16806 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16807 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16808 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 16809 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16810 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16811 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 16812 assign(zLo, binop(Iop_Add32x4, 16813 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 16814 mkexpr(cLo)) ); 16815 assign(zHi, binop(Iop_Add32x4, 16816 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 16817 mkexpr(cHi))); 16818 putVReg( vD_addr, 16819 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 16820 break; 16821 } 16822 16823 16824 /* Multiply-Sum */ 16825 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 16826 IRTemp abEE, abEO, abOE, abOO; 16827 abEE = abEO = abOE = abOO = IRTemp_INVALID; 16828 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 16829 vD_addr, vA_addr, vB_addr, vC_addr); 16830 16831 /* multiply vA,vB (unsigned, widening) */ 16832 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 16833 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 16834 16835 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 16836 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 16837 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 16838 16839 putVReg( vD_addr, 16840 binop(Iop_Add32x4, mkexpr(vC), 16841 binop(Iop_Add32x4, 16842 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 16843 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 16844 break; 16845 } 16846 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 16847 IRTemp aEvn, aOdd, bEvn, bOdd; 16848 IRTemp abEE = newTemp(Ity_V128); 16849 IRTemp abEO = newTemp(Ity_V128); 16850 IRTemp abOE = newTemp(Ity_V128); 16851 IRTemp abOO = newTemp(Ity_V128); 16852 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 16853 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 16854 vD_addr, vA_addr, vB_addr, vC_addr); 16855 16856 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 16857 (separating out adjacent lanes to different vectors) */ 16858 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 16859 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 16860 16861 /* multiply vA, vB, again separating adjacent lanes */ 16862 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 16863 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 16864 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 16865 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 16866 16867 /* add results together, + vC */ 16868 putVReg( vD_addr, 16869 binop(Iop_QAdd32Sx4, mkexpr(vC), 16870 binop(Iop_QAdd32Sx4, 16871 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 16872 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 16873 break; 16874 } 16875 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 16876 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 16877 vD_addr, vA_addr, vB_addr, vC_addr); 16878 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 16879 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 16880 putVReg( vD_addr, 16881 binop(Iop_Add32x4, mkexpr(vC), 16882 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 16883 break; 16884 } 16885 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 16886 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 16887 vD_addr, vA_addr, vB_addr, vC_addr); 16888 /* widening multiply, separating lanes */ 16889 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 16890 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 16891 16892 /* break V128 to 4xI32's, zero-extending to I64's */ 16893 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 16894 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 16895 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 16896 16897 /* add lanes */ 16898 assign( z3, binop(Iop_Add64, mkexpr(c3), 16899 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 16900 assign( z2, binop(Iop_Add64, mkexpr(c2), 16901 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 16902 assign( z1, binop(Iop_Add64, mkexpr(c1), 16903 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 16904 assign( z0, binop(Iop_Add64, mkexpr(c0), 16905 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 16906 16907 /* saturate-narrow to 32bit, and combine to V128 */ 16908 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 16909 mkexpr(z1), mkexpr(z0)) ); 16910 16911 break; 16912 } 16913 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 16914 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 16915 vD_addr, vA_addr, vB_addr, vC_addr); 16916 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16917 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 16918 putVReg( vD_addr, 16919 binop(Iop_Add32x4, mkexpr(vC), 16920 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 16921 break; 16922 } 16923 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 16924 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 16925 vD_addr, vA_addr, vB_addr, vC_addr); 16926 /* widening multiply, separating lanes */ 16927 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16928 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 16929 16930 /* break V128 to 4xI32's, sign-extending to I64's */ 16931 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 16932 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 16933 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 16934 16935 /* add lanes */ 16936 assign( z3, binop(Iop_Add64, mkexpr(c3), 16937 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 16938 assign( z2, binop(Iop_Add64, mkexpr(c2), 16939 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 16940 assign( z1, binop(Iop_Add64, mkexpr(c1), 16941 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 16942 assign( z0, binop(Iop_Add64, mkexpr(c0), 16943 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 16944 16945 /* saturate-narrow to 32bit, and combine to V128 */ 16946 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16947 mkexpr(z1), mkexpr(z0)) ); 16948 break; 16949 } 16950 default: 16951 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 16952 return False; 16953 } 16954 return True; 16955 } 16956 16957 /* 16958 AltiVec Polynomial Multiply-Sum Instructions 16959 */ 16960 static Bool dis_av_polymultarith ( UInt theInstr ) 16961 { 16962 /* VA-Form */ 16963 UChar opc1 = ifieldOPC(theInstr); 16964 UChar vD_addr = ifieldRegDS(theInstr); 16965 UChar vA_addr = ifieldRegA(theInstr); 16966 UChar vB_addr = ifieldRegB(theInstr); 16967 UChar vC_addr = ifieldRegC(theInstr); 16968 UInt opc2 = IFIELD(theInstr, 0, 11); 16969 IRTemp vA = newTemp(Ity_V128); 16970 IRTemp vB = newTemp(Ity_V128); 16971 IRTemp vC = newTemp(Ity_V128); 16972 16973 assign( vA, getVReg(vA_addr)); 16974 assign( vB, getVReg(vB_addr)); 16975 assign( vC, getVReg(vC_addr)); 16976 16977 if (opc1 != 0x4) { 16978 vex_printf("dis_av_polymultarith(ppc)(instr)\n"); 16979 return False; 16980 } 16981 16982 switch (opc2) { 16983 /* Polynomial Multiply-Add */ 16984 case 0x408: // vpmsumb Vector Polynomial Multipy-sum Byte 16985 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16986 putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16, 16987 mkexpr(vA), mkexpr(vB)) ); 16988 break; 16989 case 0x448: // vpmsumd Vector Polynomial Multipy-sum Double Word 16990 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16991 putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2, 16992 mkexpr(vA), mkexpr(vB)) ); 16993 break; 16994 case 0x488: // vpmsumw Vector Polynomial Multipy-sum Word 16995 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16996 putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4, 16997 mkexpr(vA), mkexpr(vB)) ); 16998 break; 16999 case 0x4C8: // vpmsumh Vector Polynomial Multipy-sum Half Word 17000 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17001 putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8, 17002 mkexpr(vA), mkexpr(vB)) ); 17003 break; 17004 default: 17005 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2); 17006 return False; 17007 } 17008 return True; 17009 } 17010 17011 /* 17012 AltiVec Shift/Rotate Instructions 17013 */ 17014 static Bool dis_av_shift ( UInt theInstr ) 17015 { 17016 /* VX-Form */ 17017 UChar opc1 = ifieldOPC(theInstr); 17018 UChar vD_addr = ifieldRegDS(theInstr); 17019 UChar vA_addr = ifieldRegA(theInstr); 17020 UChar vB_addr = ifieldRegB(theInstr); 17021 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17022 17023 IRTemp vA = newTemp(Ity_V128); 17024 IRTemp vB = newTemp(Ity_V128); 17025 assign( vA, getVReg(vA_addr)); 17026 assign( vB, getVReg(vB_addr)); 17027 17028 if (opc1 != 0x4){ 17029 vex_printf("dis_av_shift(ppc)(instr)\n"); 17030 return False; 17031 } 17032 17033 switch (opc2) { 17034 /* Rotate */ 17035 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 17036 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17037 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 17038 break; 17039 17040 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 17041 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17042 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 17043 break; 17044 17045 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 17046 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17047 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 17048 break; 17049 17050 case 0x0C4: // vrld (Rotate Left Integer Double Word) 17051 DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17052 putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) ); 17053 break; 17054 17055 17056 /* Shift Left */ 17057 case 0x104: // vslb (Shift Left Integer B, AV p240) 17058 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17059 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 17060 break; 17061 17062 case 0x144: // vslh (Shift Left Integer HW, AV p242) 17063 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17064 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 17065 break; 17066 17067 case 0x184: // vslw (Shift Left Integer W, AV p244) 17068 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17069 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 17070 break; 17071 17072 case 0x5C4: // vsld (Shift Left Integer Double Word) 17073 DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17074 putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) ); 17075 break; 17076 17077 case 0x1C4: { // vsl (Shift Left, AV p239) 17078 IRTemp sh = newTemp(Ity_I8); 17079 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17080 assign( sh, binop(Iop_And8, mkU8(0x7), 17081 unop(Iop_32to8, 17082 unop(Iop_V128to32, mkexpr(vB)))) ); 17083 putVReg( vD_addr, 17084 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 17085 break; 17086 } 17087 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 17088 IRTemp sh = newTemp(Ity_I8); 17089 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17090 assign( sh, binop(Iop_And8, mkU8(0x78), 17091 unop(Iop_32to8, 17092 unop(Iop_V128to32, mkexpr(vB)))) ); 17093 putVReg( vD_addr, 17094 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 17095 break; 17096 } 17097 17098 17099 /* Shift Right */ 17100 case 0x204: // vsrb (Shift Right B, AV p256) 17101 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17102 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 17103 break; 17104 17105 case 0x244: // vsrh (Shift Right HW, AV p257) 17106 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17107 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 17108 break; 17109 17110 case 0x284: // vsrw (Shift Right W, AV p259) 17111 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17112 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 17113 break; 17114 17115 case 0x2C4: { // vsr (Shift Right, AV p251) 17116 IRTemp sh = newTemp(Ity_I8); 17117 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17118 assign( sh, binop(Iop_And8, mkU8(0x7), 17119 unop(Iop_32to8, 17120 unop(Iop_V128to32, mkexpr(vB)))) ); 17121 putVReg( vD_addr, 17122 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 17123 break; 17124 } 17125 case 0x304: // vsrab (Shift Right Alg B, AV p253) 17126 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17127 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 17128 break; 17129 17130 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 17131 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17132 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 17133 break; 17134 17135 case 0x384: // vsraw (Shift Right Alg W, AV p255) 17136 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17137 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 17138 break; 17139 17140 case 0x3C4: // vsrad (Shift Right Alg Double Word) 17141 DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17142 putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) ); 17143 break; 17144 17145 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 17146 IRTemp sh = newTemp(Ity_I8); 17147 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17148 assign( sh, binop(Iop_And8, mkU8(0x78), 17149 unop(Iop_32to8, 17150 unop(Iop_V128to32, mkexpr(vB)))) ); 17151 putVReg( vD_addr, 17152 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 17153 break; 17154 } 17155 17156 case 0x6C4: // vsrd (Shift Right Double Word) 17157 DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17158 putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) ); 17159 break; 17160 17161 17162 default: 17163 vex_printf("dis_av_shift(ppc)(opc2)\n"); 17164 return False; 17165 } 17166 return True; 17167 } 17168 17169 /* 17170 AltiVec Permute Instructions 17171 */ 17172 static Bool dis_av_permute ( UInt theInstr ) 17173 { 17174 /* VA-Form, VX-Form */ 17175 UChar opc1 = ifieldOPC(theInstr); 17176 UChar vD_addr = ifieldRegDS(theInstr); 17177 UChar vA_addr = ifieldRegA(theInstr); 17178 UChar UIMM_5 = vA_addr; 17179 UChar vB_addr = ifieldRegB(theInstr); 17180 UChar vC_addr = ifieldRegC(theInstr); 17181 UChar b10 = ifieldBIT10(theInstr); 17182 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 17183 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 17184 17185 UChar SIMM_8 = extend_s_5to8(UIMM_5); 17186 17187 IRTemp vA = newTemp(Ity_V128); 17188 IRTemp vB = newTemp(Ity_V128); 17189 IRTemp vC = newTemp(Ity_V128); 17190 assign( vA, getVReg(vA_addr)); 17191 assign( vB, getVReg(vB_addr)); 17192 assign( vC, getVReg(vC_addr)); 17193 17194 if (opc1 != 0x4) { 17195 vex_printf("dis_av_permute(ppc)(instr)\n"); 17196 return False; 17197 } 17198 17199 switch (opc2) { 17200 case 0x2A: // vsel (Conditional Select, AV p238) 17201 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 17202 /* vD = (vA & ~vC) | (vB & vC) */ 17203 putVReg( vD_addr, binop(Iop_OrV128, 17204 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 17205 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 17206 return True; 17207 17208 case 0x2B: { // vperm (Permute, AV p218) 17209 /* limited to two args for IR, so have to play games... */ 17210 IRTemp a_perm = newTemp(Ity_V128); 17211 IRTemp b_perm = newTemp(Ity_V128); 17212 IRTemp mask = newTemp(Ity_V128); 17213 IRTemp vC_andF = newTemp(Ity_V128); 17214 DIP("vperm v%d,v%d,v%d,v%d\n", 17215 vD_addr, vA_addr, vB_addr, vC_addr); 17216 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 17217 IR specifies, and also to hide irrelevant bits from 17218 memcheck */ 17219 assign( vC_andF, 17220 binop(Iop_AndV128, mkexpr(vC), 17221 unop(Iop_Dup8x16, mkU8(0xF))) ); 17222 assign( a_perm, 17223 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 17224 assign( b_perm, 17225 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 17226 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 17227 assign( mask, binop(Iop_SarN8x16, 17228 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 17229 mkU8(7)) ); 17230 // dst = (a & ~mask) | (b & mask) 17231 putVReg( vD_addr, binop(Iop_OrV128, 17232 binop(Iop_AndV128, mkexpr(a_perm), 17233 unop(Iop_NotV128, mkexpr(mask))), 17234 binop(Iop_AndV128, mkexpr(b_perm), 17235 mkexpr(mask))) ); 17236 return True; 17237 } 17238 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 17239 if (b10 != 0) { 17240 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 17241 return False; 17242 } 17243 DIP("vsldoi v%d,v%d,v%d,%d\n", 17244 vD_addr, vA_addr, vB_addr, SHB_uimm4); 17245 if (SHB_uimm4 == 0) 17246 putVReg( vD_addr, mkexpr(vA) ); 17247 else 17248 putVReg( vD_addr, 17249 binop(Iop_OrV128, 17250 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 17251 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 17252 return True; 17253 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR) 17254 IRTemp a_perm = newTemp(Ity_V128); 17255 IRTemp b_perm = newTemp(Ity_V128); 17256 IRTemp vrc_a = newTemp(Ity_V128); 17257 IRTemp vrc_b = newTemp(Ity_V128); 17258 17259 /* IBM index is 0:7, Change index value to index 7:0 */ 17260 assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ), 17261 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) ); 17262 assign( vrc_a, binop( Iop_ShrV128, 17263 binop( Iop_AndV128, mkexpr( vC ), 17264 unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ), 17265 mkU8 ( 4 ) ) ); 17266 assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) ); 17267 assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) ); 17268 putVReg( vD_addr, binop( Iop_XorV128, 17269 mkexpr( a_perm ), mkexpr( b_perm) ) ); 17270 return True; 17271 } 17272 default: 17273 break; // Fall through... 17274 } 17275 17276 opc2 = IFIELD( theInstr, 0, 11 ); 17277 switch (opc2) { 17278 17279 /* Merge */ 17280 case 0x00C: // vmrghb (Merge High B, AV p195) 17281 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17282 putVReg( vD_addr, 17283 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 17284 break; 17285 17286 case 0x04C: // vmrghh (Merge High HW, AV p196) 17287 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17288 putVReg( vD_addr, 17289 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 17290 break; 17291 17292 case 0x08C: // vmrghw (Merge High W, AV p197) 17293 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17294 putVReg( vD_addr, 17295 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 17296 break; 17297 17298 case 0x10C: // vmrglb (Merge Low B, AV p198) 17299 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17300 putVReg( vD_addr, 17301 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 17302 break; 17303 17304 case 0x14C: // vmrglh (Merge Low HW, AV p199) 17305 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17306 putVReg( vD_addr, 17307 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 17308 break; 17309 17310 case 0x18C: // vmrglw (Merge Low W, AV p200) 17311 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17312 putVReg( vD_addr, 17313 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 17314 break; 17315 17316 17317 /* Splat */ 17318 case 0x20C: { // vspltb (Splat Byte, AV p245) 17319 /* vD = Dup8x16( vB[UIMM_5] ) */ 17320 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 17321 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17322 putVReg( vD_addr, unop(Iop_Dup8x16, 17323 unop(Iop_32to8, unop(Iop_V128to32, 17324 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 17325 break; 17326 } 17327 case 0x24C: { // vsplth (Splat Half Word, AV p246) 17328 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 17329 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17330 putVReg( vD_addr, unop(Iop_Dup16x8, 17331 unop(Iop_32to16, unop(Iop_V128to32, 17332 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 17333 break; 17334 } 17335 case 0x28C: { // vspltw (Splat Word, AV p250) 17336 /* vD = Dup32x4( vB[UIMM_5] ) */ 17337 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 17338 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17339 putVReg( vD_addr, unop(Iop_Dup32x4, 17340 unop(Iop_V128to32, 17341 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 17342 break; 17343 } 17344 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 17345 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 17346 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 17347 break; 17348 17349 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 17350 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 17351 putVReg( vD_addr, 17352 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 17353 break; 17354 17355 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 17356 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 17357 putVReg( vD_addr, 17358 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 17359 break; 17360 17361 case 0x68C: // vmrgow (Merge Odd Word) 17362 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17363 /* VD[0] <- VA[1] 17364 VD[1] <- VB[1] 17365 VD[2] <- VA[3] 17366 VD[3] <- VB[3] 17367 */ 17368 putVReg( vD_addr, 17369 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 17370 break; 17371 17372 case 0x78C: // vmrgew (Merge Even Word) 17373 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17374 /* VD[0] <- VA[0] 17375 VD[1] <- VB[0] 17376 VD[2] <- VA[2] 17377 VD[3] <- VB[2] 17378 */ 17379 putVReg( vD_addr, 17380 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 17381 break; 17382 17383 default: 17384 vex_printf("dis_av_permute(ppc)(opc2)\n"); 17385 return False; 17386 } 17387 return True; 17388 } 17389 17390 /* 17391 AltiVec Pack/Unpack Instructions 17392 */ 17393 static Bool dis_av_pack ( UInt theInstr ) 17394 { 17395 /* VX-Form */ 17396 UChar opc1 = ifieldOPC(theInstr); 17397 UChar vD_addr = ifieldRegDS(theInstr); 17398 UChar vA_addr = ifieldRegA(theInstr); 17399 UChar vB_addr = ifieldRegB(theInstr); 17400 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17401 17402 IRTemp signs = IRTemp_INVALID; 17403 IRTemp zeros = IRTemp_INVALID; 17404 IRTemp vA = newTemp(Ity_V128); 17405 IRTemp vB = newTemp(Ity_V128); 17406 assign( vA, getVReg(vA_addr)); 17407 assign( vB, getVReg(vB_addr)); 17408 17409 if (opc1 != 0x4) { 17410 vex_printf("dis_av_pack(ppc)(instr)\n"); 17411 return False; 17412 } 17413 switch (opc2) { 17414 /* Packing */ 17415 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 17416 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17417 putVReg( vD_addr, 17418 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 17419 return True; 17420 17421 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 17422 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17423 putVReg( vD_addr, 17424 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 17425 return True; 17426 17427 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 17428 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17429 putVReg( vD_addr, 17430 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 17431 // TODO: set VSCR[SAT] 17432 return True; 17433 17434 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 17435 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17436 putVReg( vD_addr, 17437 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 17438 // TODO: set VSCR[SAT] 17439 return True; 17440 17441 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 17442 // This insn does a signed->unsigned saturating conversion. 17443 // Conversion done here, then uses unsigned->unsigned vpk insn: 17444 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 17445 IRTemp vA_tmp = newTemp(Ity_V128); 17446 IRTemp vB_tmp = newTemp(Ity_V128); 17447 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17448 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17449 unop(Iop_NotV128, 17450 binop(Iop_SarN16x8, 17451 mkexpr(vA), mkU8(15)))) ); 17452 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17453 unop(Iop_NotV128, 17454 binop(Iop_SarN16x8, 17455 mkexpr(vB), mkU8(15)))) ); 17456 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 17457 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17458 // TODO: set VSCR[SAT] 17459 return True; 17460 } 17461 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 17462 // This insn does a signed->unsigned saturating conversion. 17463 // Conversion done here, then uses unsigned->unsigned vpk insn: 17464 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17465 IRTemp vA_tmp = newTemp(Ity_V128); 17466 IRTemp vB_tmp = newTemp(Ity_V128); 17467 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17468 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17469 unop(Iop_NotV128, 17470 binop(Iop_SarN32x4, 17471 mkexpr(vA), mkU8(31)))) ); 17472 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17473 unop(Iop_NotV128, 17474 binop(Iop_SarN32x4, 17475 mkexpr(vB), mkU8(31)))) ); 17476 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 17477 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17478 // TODO: set VSCR[SAT] 17479 return True; 17480 } 17481 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 17482 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17483 putVReg( vD_addr, 17484 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 17485 // TODO: set VSCR[SAT] 17486 return True; 17487 17488 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 17489 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17490 putVReg( vD_addr, 17491 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 17492 // TODO: set VSCR[SAT] 17493 return True; 17494 17495 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 17496 /* CAB: Worth a new primop? */ 17497 /* Using shifts to compact pixel elements, then packing them */ 17498 IRTemp a1 = newTemp(Ity_V128); 17499 IRTemp a2 = newTemp(Ity_V128); 17500 IRTemp a3 = newTemp(Ity_V128); 17501 IRTemp a_tmp = newTemp(Ity_V128); 17502 IRTemp b1 = newTemp(Ity_V128); 17503 IRTemp b2 = newTemp(Ity_V128); 17504 IRTemp b3 = newTemp(Ity_V128); 17505 IRTemp b_tmp = newTemp(Ity_V128); 17506 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17507 assign( a1, binop(Iop_ShlN16x8, 17508 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 17509 mkU8(10)) ); 17510 assign( a2, binop(Iop_ShlN16x8, 17511 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 17512 mkU8(5)) ); 17513 assign( a3, binop(Iop_ShrN16x8, 17514 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 17515 mkU8(11)) ); 17516 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 17517 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 17518 17519 assign( b1, binop(Iop_ShlN16x8, 17520 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 17521 mkU8(10)) ); 17522 assign( b2, binop(Iop_ShlN16x8, 17523 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 17524 mkU8(5)) ); 17525 assign( b3, binop(Iop_ShrN16x8, 17526 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 17527 mkU8(11)) ); 17528 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 17529 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 17530 17531 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 17532 mkexpr(a_tmp), mkexpr(b_tmp)) ); 17533 return True; 17534 } 17535 17536 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo) 17537 DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17538 putVReg( vD_addr, 17539 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) ); 17540 return True; 17541 17542 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate) 17543 DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17544 putVReg( vD_addr, 17545 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) ); 17546 // TODO: set VSCR[SAT] 17547 return True; 17548 17549 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate) 17550 // This insn does a doubled signed->double unsigned saturating conversion 17551 // Conversion done here, then uses unsigned->unsigned vpk insn: 17552 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17553 // This is similar to the technique used for vpkswus, except done 17554 // with double word integers versus word integers. 17555 IRTemp vA_tmp = newTemp(Ity_V128); 17556 IRTemp vB_tmp = newTemp(Ity_V128); 17557 DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17558 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17559 unop(Iop_NotV128, 17560 binop(Iop_SarN64x2, 17561 mkexpr(vA), mkU8(63)))) ); 17562 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17563 unop(Iop_NotV128, 17564 binop(Iop_SarN64x2, 17565 mkexpr(vB), mkU8(63)))) ); 17566 putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4, 17567 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17568 // TODO: set VSCR[SAT] 17569 return True; 17570 } 17571 17572 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate) 17573 DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17574 putVReg( vD_addr, 17575 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) ); 17576 // TODO: set VSCR[SAT] 17577 return True; 17578 default: 17579 break; // Fall through... 17580 } 17581 17582 17583 if (vA_addr != 0) { 17584 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 17585 return False; 17586 } 17587 17588 signs = newTemp(Ity_V128); 17589 zeros = newTemp(Ity_V128); 17590 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 17591 17592 switch (opc2) { 17593 /* Unpacking */ 17594 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 17595 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 17596 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17597 putVReg( vD_addr, 17598 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 17599 break; 17600 } 17601 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 17602 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 17603 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17604 putVReg( vD_addr, 17605 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 17606 break; 17607 } 17608 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 17609 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 17610 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17611 putVReg( vD_addr, 17612 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 17613 break; 17614 } 17615 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 17616 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 17617 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17618 putVReg( vD_addr, 17619 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 17620 break; 17621 } 17622 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 17623 /* CAB: Worth a new primop? */ 17624 /* Using shifts to isolate pixel elements, then expanding them */ 17625 IRTemp z0 = newTemp(Ity_V128); 17626 IRTemp z1 = newTemp(Ity_V128); 17627 IRTemp z01 = newTemp(Ity_V128); 17628 IRTemp z2 = newTemp(Ity_V128); 17629 IRTemp z3 = newTemp(Ity_V128); 17630 IRTemp z23 = newTemp(Ity_V128); 17631 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 17632 assign( z0, binop(Iop_ShlN16x8, 17633 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17634 mkU8(8)) ); 17635 assign( z1, binop(Iop_ShrN16x8, 17636 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17637 mkU8(11)) ); 17638 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17639 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17640 assign( z2, binop(Iop_ShrN16x8, 17641 binop(Iop_ShlN16x8, 17642 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17643 mkU8(11)), 17644 mkU8(3)) ); 17645 assign( z3, binop(Iop_ShrN16x8, 17646 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17647 mkU8(11)) ); 17648 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17649 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17650 putVReg( vD_addr, 17651 binop(Iop_OrV128, 17652 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17653 mkexpr(z23)) ); 17654 break; 17655 } 17656 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 17657 /* identical to vupkhpx, except interleaving LO */ 17658 IRTemp z0 = newTemp(Ity_V128); 17659 IRTemp z1 = newTemp(Ity_V128); 17660 IRTemp z01 = newTemp(Ity_V128); 17661 IRTemp z2 = newTemp(Ity_V128); 17662 IRTemp z3 = newTemp(Ity_V128); 17663 IRTemp z23 = newTemp(Ity_V128); 17664 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 17665 assign( z0, binop(Iop_ShlN16x8, 17666 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17667 mkU8(8)) ); 17668 assign( z1, binop(Iop_ShrN16x8, 17669 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17670 mkU8(11)) ); 17671 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17672 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17673 assign( z2, binop(Iop_ShrN16x8, 17674 binop(Iop_ShlN16x8, 17675 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17676 mkU8(11)), 17677 mkU8(3)) ); 17678 assign( z3, binop(Iop_ShrN16x8, 17679 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17680 mkU8(11)) ); 17681 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17682 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17683 putVReg( vD_addr, 17684 binop(Iop_OrV128, 17685 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17686 mkexpr(z23)) ); 17687 break; 17688 } 17689 case 0x64E: { // vupkhsw (Unpack High Signed Word) 17690 DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr); 17691 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17692 putVReg( vD_addr, 17693 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) ); 17694 break; 17695 } 17696 case 0x6CE: { // vupklsw (Unpack Low Signed Word) 17697 DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr); 17698 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17699 putVReg( vD_addr, 17700 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) ); 17701 break; 17702 } 17703 default: 17704 vex_printf("dis_av_pack(ppc)(opc2)\n"); 17705 return False; 17706 } 17707 return True; 17708 } 17709 17710 /* 17711 AltiVec Cipher Instructions 17712 */ 17713 static Bool dis_av_cipher ( UInt theInstr ) 17714 { 17715 /* VX-Form */ 17716 UChar opc1 = ifieldOPC(theInstr); 17717 UChar vD_addr = ifieldRegDS(theInstr); 17718 UChar vA_addr = ifieldRegA(theInstr); 17719 UChar vB_addr = ifieldRegB(theInstr); 17720 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17721 17722 IRTemp vA = newTemp(Ity_V128); 17723 IRTemp vB = newTemp(Ity_V128); 17724 assign( vA, getVReg(vA_addr)); 17725 assign( vB, getVReg(vB_addr)); 17726 17727 if (opc1 != 0x4) { 17728 vex_printf("dis_av_cipher(ppc)(instr)\n"); 17729 return False; 17730 } 17731 switch (opc2) { 17732 case 0x508: // vcipher (Vector Inverser Cipher) 17733 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17734 putVReg( vD_addr, 17735 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) ); 17736 return True; 17737 17738 case 0x509: // vcipherlast (Vector Inverser Cipher Last) 17739 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17740 putVReg( vD_addr, 17741 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) ); 17742 return True; 17743 17744 case 0x548: // vncipher (Vector Inverser Cipher) 17745 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17746 putVReg( vD_addr, 17747 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) ); 17748 return True; 17749 17750 case 0x549: // vncipherlast (Vector Inverser Cipher Last) 17751 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17752 putVReg( vD_addr, 17753 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) ); 17754 return True; 17755 17756 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher 17757 * subBytes transform) 17758 */ 17759 DIP("vsbox v%d,v%d\n", vD_addr, vA_addr); 17760 putVReg( vD_addr, 17761 unop(Iop_CipherSV128, mkexpr(vA) ) ); 17762 return True; 17763 17764 default: 17765 vex_printf("dis_av_cipher(ppc)(opc2)\n"); 17766 return False; 17767 } 17768 return True; 17769 } 17770 17771 /* 17772 AltiVec Secure Hash Instructions 17773 */ 17774 static Bool dis_av_hash ( UInt theInstr ) 17775 { 17776 /* VX-Form */ 17777 UChar opc1 = ifieldOPC(theInstr); 17778 UChar vRT_addr = ifieldRegDS(theInstr); 17779 UChar vRA_addr = ifieldRegA(theInstr); 17780 UChar s_field = IFIELD( theInstr, 11, 5 ); // st and six field 17781 UChar st = IFIELD( theInstr, 15, 1 ); // st 17782 UChar six = IFIELD( theInstr, 11, 4 ); // six field 17783 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17784 17785 IRTemp vA = newTemp(Ity_V128); 17786 IRTemp dst = newTemp(Ity_V128); 17787 assign( vA, getVReg(vRA_addr)); 17788 17789 if (opc1 != 0x4) { 17790 vex_printf("dis_av_hash(ppc)(instr)\n"); 17791 return False; 17792 } 17793 17794 switch (opc2) { 17795 case 0x682: // vshasigmaw 17796 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17797 assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) ); 17798 putVReg( vRT_addr, mkexpr(dst)); 17799 return True; 17800 17801 case 0x6C2: // vshasigmad, 17802 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17803 putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) ); 17804 return True; 17805 17806 default: 17807 vex_printf("dis_av_hash(ppc)(opc2)\n"); 17808 return False; 17809 } 17810 return True; 17811 } 17812 17813 /* 17814 * This function is used by the Vector add/subtract [extended] modulo/carry 17815 * instructions. 17816 * - For the non-extended add instructions, the cin arg is set to zero. 17817 * - For the extended add instructions, cin is the integer value of 17818 * src3.bit[127]. 17819 * - For the non-extended subtract instructions, src1 is added to the one's 17820 * complement of src2 + 1. We re-use the cin argument to hold the '1' 17821 * value for this operation. 17822 * - For the extended subtract instructions, cin is the integer value of src3.bit[127]. 17823 */ 17824 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB, 17825 IRExpr * cin, Bool modulo) 17826 { 17827 IRTemp _vecA_32 = IRTemp_INVALID; 17828 IRTemp _vecB_32 = IRTemp_INVALID; 17829 IRTemp res_32 = IRTemp_INVALID; 17830 IRTemp result = IRTemp_INVALID; 17831 IRTemp tmp_result = IRTemp_INVALID; 17832 IRTemp carry = IRTemp_INVALID; 17833 Int i; 17834 IRExpr * _vecA_low64 = unop( Iop_V128to64, vecA ); 17835 IRExpr * _vecB_low64 = unop( Iop_V128to64, vecB ); 17836 IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA ); 17837 IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB ); 17838 17839 for (i = 0; i < 4; i++) { 17840 _vecA_32 = newTemp(Ity_I32); 17841 _vecB_32 = newTemp(Ity_I32); 17842 res_32 = newTemp(Ity_I32); 17843 switch (i) { 17844 case 0: 17845 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) ); 17846 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) ); 17847 break; 17848 case 1: 17849 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) ); 17850 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) ); 17851 break; 17852 case 2: 17853 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) ); 17854 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) ); 17855 break; 17856 case 3: 17857 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) ); 17858 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) ); 17859 break; 17860 } 17861 17862 assign(res_32, binop( Iop_Add32, 17863 binop( Iop_Add32, 17864 binop ( Iop_Add32, 17865 mkexpr(_vecA_32), 17866 mkexpr(_vecB_32) ), 17867 (i == 0) ? mkU32(0) : mkexpr(carry) ), 17868 (i == 0) ? cin : mkU32(0) ) ); 17869 if (modulo) { 17870 result = newTemp(Ity_V128); 17871 assign(result, binop( Iop_OrV128, 17872 (i == 0) ? binop( Iop_64HLtoV128, 17873 mkU64(0), 17874 mkU64(0) ) : mkexpr(tmp_result), 17875 binop( Iop_ShlV128, 17876 binop( Iop_64HLtoV128, 17877 mkU64(0), 17878 binop( Iop_32HLto64, 17879 mkU32(0), 17880 mkexpr(res_32) ) ), 17881 mkU8(i * 32) ) ) ); 17882 tmp_result = newTemp(Ity_V128); 17883 assign(tmp_result, mkexpr(result)); 17884 } 17885 carry = newTemp(Ity_I32); 17886 assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U, 17887 mkexpr(res_32), 17888 mkexpr(_vecA_32 ) ) ) ); 17889 } 17890 if (modulo) 17891 return result; 17892 else 17893 return carry; 17894 } 17895 17896 17897 static Bool dis_av_quad ( UInt theInstr ) 17898 { 17899 /* VX-Form */ 17900 UChar opc1 = ifieldOPC(theInstr); 17901 UChar vRT_addr = ifieldRegDS(theInstr); 17902 UChar vRA_addr = ifieldRegA(theInstr); 17903 UChar vRB_addr = ifieldRegB(theInstr); 17904 UChar vRC_addr; 17905 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17906 17907 IRTemp vA = newTemp(Ity_V128); 17908 IRTemp vB = newTemp(Ity_V128); 17909 IRTemp vC = IRTemp_INVALID; 17910 IRTemp cin = IRTemp_INVALID; 17911 assign( vA, getVReg(vRA_addr)); 17912 assign( vB, getVReg(vRB_addr)); 17913 17914 if (opc1 != 0x4) { 17915 vex_printf("dis_av_quad(ppc)(instr)\n"); 17916 return False; 17917 } 17918 17919 switch (opc2) { 17920 case 0x140: // vaddcuq 17921 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17922 putVReg( vRT_addr, unop( Iop_32UtoV128, 17923 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17924 mkexpr(vB), 17925 mkU32(0), False) ) ) ); 17926 return True; 17927 case 0x100: // vadduqm 17928 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17929 putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17930 mkexpr(vB), mkU32(0), True) ) ); 17931 return True; 17932 case 0x540: // vsubcuq 17933 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17934 putVReg( vRT_addr, 17935 unop( Iop_32UtoV128, 17936 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17937 unop( Iop_NotV128, 17938 mkexpr(vB) ), 17939 mkU32(1), False) ) ) ); 17940 return True; 17941 case 0x500: // vsubuqm 17942 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17943 putVReg( vRT_addr, 17944 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17945 unop( Iop_NotV128, mkexpr(vB) ), 17946 mkU32(1), True) ) ); 17947 return True; 17948 case 0x054C: // vbpermq 17949 { 17950 #define BPERMD_IDX_MASK 0x00000000000000FFULL 17951 #define BPERMD_BIT_MASK 0x8000000000000000ULL 17952 int i; 17953 IRExpr * vB_expr = mkexpr(vB); 17954 IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0)); 17955 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17956 for (i = 0; i < 16; i++) { 17957 IRTemp idx_tmp = newTemp( Ity_V128 ); 17958 IRTemp perm_bit = newTemp( Ity_V128 ); 17959 IRTemp idx = newTemp( Ity_I8 ); 17960 IRTemp idx_LT127 = newTemp( Ity_I1 ); 17961 IRTemp idx_LT127_ity128 = newTemp( Ity_V128 ); 17962 17963 assign( idx_tmp, 17964 binop( Iop_AndV128, 17965 binop( Iop_64HLtoV128, 17966 mkU64(0), 17967 mkU64(BPERMD_IDX_MASK) ), 17968 vB_expr ) ); 17969 assign( idx_LT127, 17970 binop( Iop_CmpEQ32, 17971 unop ( Iop_64to32, 17972 unop( Iop_V128to64, binop( Iop_ShrV128, 17973 mkexpr(idx_tmp), 17974 mkU8(7) ) ) ), 17975 mkU32(0) ) ); 17976 17977 /* Below, we set idx to determine which bit of vA to use for the 17978 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'. 17979 */ 17980 assign( idx, 17981 binop( Iop_And8, 17982 unop( Iop_1Sto8, 17983 mkexpr(idx_LT127) ), 17984 unop( Iop_32to8, 17985 unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) ); 17986 17987 assign( idx_LT127_ity128, 17988 binop( Iop_64HLtoV128, 17989 mkU64(0), 17990 unop( Iop_32Uto64, 17991 unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) ); 17992 assign( perm_bit, 17993 binop( Iop_AndV128, 17994 mkexpr( idx_LT127_ity128 ), 17995 binop( Iop_ShrV128, 17996 binop( Iop_AndV128, 17997 binop (Iop_64HLtoV128, 17998 mkU64( BPERMD_BIT_MASK ), 17999 mkU64(0)), 18000 binop( Iop_ShlV128, 18001 mkexpr( vA ), 18002 mkexpr( idx ) ) ), 18003 mkU8( 127 ) ) ) ); 18004 res = binop( Iop_OrV128, 18005 res, 18006 binop( Iop_ShlV128, 18007 mkexpr( perm_bit ), 18008 mkU8( i + 64 ) ) ); 18009 vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) ); 18010 } 18011 putVReg( vRT_addr, res); 18012 return True; 18013 #undef BPERMD_IDX_MASK 18014 #undef BPERMD_BIT_MASK 18015 } 18016 18017 default: 18018 break; // fall through 18019 } 18020 18021 opc2 = IFIELD( theInstr, 0, 6 ); 18022 vRC_addr = ifieldRegC(theInstr); 18023 vC = newTemp(Ity_V128); 18024 cin = newTemp(Ity_I32); 18025 switch (opc2) { 18026 case 0x3D: // vaddecuq 18027 assign( vC, getVReg(vRC_addr)); 18028 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18029 vRC_addr); 18030 assign(cin, binop( Iop_And32, 18031 unop( Iop_64to32, 18032 unop( Iop_V128to64, mkexpr(vC) ) ), 18033 mkU32(1) ) ); 18034 putVReg( vRT_addr, 18035 unop( Iop_32UtoV128, 18036 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 18037 mkexpr(cin), 18038 False) ) ) ); 18039 return True; 18040 case 0x3C: // vaddeuqm 18041 assign( vC, getVReg(vRC_addr)); 18042 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18043 vRC_addr); 18044 assign(cin, binop( Iop_And32, 18045 unop( Iop_64to32, 18046 unop( Iop_V128to64, mkexpr(vC) ) ), 18047 mkU32(1) ) ); 18048 putVReg( vRT_addr, 18049 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 18050 mkexpr(cin), 18051 True) ) ); 18052 return True; 18053 case 0x3F: // vsubecuq 18054 assign( vC, getVReg(vRC_addr)); 18055 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18056 vRC_addr); 18057 assign(cin, binop( Iop_And32, 18058 unop( Iop_64to32, 18059 unop( Iop_V128to64, mkexpr(vC) ) ), 18060 mkU32(1) ) ); 18061 putVReg( vRT_addr, 18062 unop( Iop_32UtoV128, 18063 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18064 unop( Iop_NotV128, 18065 mkexpr(vB) ), 18066 mkexpr(cin), 18067 False) ) ) ); 18068 return True; 18069 case 0x3E: // vsubeuqm 18070 assign( vC, getVReg(vRC_addr)); 18071 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18072 vRC_addr); 18073 assign(cin, binop( Iop_And32, 18074 unop( Iop_64to32, 18075 unop( Iop_V128to64, mkexpr(vC) ) ), 18076 mkU32(1) ) ); 18077 putVReg( vRT_addr, 18078 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18079 unop( Iop_NotV128, mkexpr(vB) ), 18080 mkexpr(cin), 18081 True) ) ); 18082 return True; 18083 default: 18084 vex_printf("dis_av_quad(ppc)(opc2.2)\n"); 18085 return False; 18086 } 18087 18088 return True; 18089 } 18090 18091 18092 /* 18093 AltiVec BCD Arithmetic instructions. 18094 These instructions modify CR6 for various conditions in the result, 18095 including when an overflow occurs. We could easily detect all conditions 18096 except when an overflow occurs. But since we can't be 100% accurate 18097 in our emulation of CR6, it seems best to just not support it all. 18098 */ 18099 static Bool dis_av_bcd ( UInt theInstr ) 18100 { 18101 /* VX-Form */ 18102 UChar opc1 = ifieldOPC(theInstr); 18103 UChar vRT_addr = ifieldRegDS(theInstr); 18104 UChar vRA_addr = ifieldRegA(theInstr); 18105 UChar vRB_addr = ifieldRegB(theInstr); 18106 UChar ps = IFIELD( theInstr, 9, 1 ); 18107 UInt opc2 = IFIELD( theInstr, 0, 9 ); 18108 18109 IRTemp vA = newTemp(Ity_V128); 18110 IRTemp vB = newTemp(Ity_V128); 18111 IRTemp dst = newTemp(Ity_V128); 18112 assign( vA, getVReg(vRA_addr)); 18113 assign( vB, getVReg(vRB_addr)); 18114 18115 if (opc1 != 0x4) { 18116 vex_printf("dis_av_bcd(ppc)(instr)\n"); 18117 return False; 18118 } 18119 18120 switch (opc2) { 18121 case 0x1: // bcdadd 18122 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 18123 assign( dst, triop( Iop_BCDAdd, mkexpr( vA ), 18124 mkexpr( vB ), mkU8( ps ) ) ); 18125 putVReg( vRT_addr, mkexpr(dst)); 18126 return True; 18127 18128 case 0x41: // bcdsub 18129 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 18130 assign( dst, triop( Iop_BCDSub, mkexpr( vA ), 18131 mkexpr( vB ), mkU8( ps ) ) ); 18132 putVReg( vRT_addr, mkexpr(dst)); 18133 return True; 18134 18135 default: 18136 vex_printf("dis_av_bcd(ppc)(opc2)\n"); 18137 return False; 18138 } 18139 return True; 18140 } 18141 18142 /* 18143 AltiVec Floating Point Arithmetic Instructions 18144 */ 18145 static Bool dis_av_fp_arith ( UInt theInstr ) 18146 { 18147 /* VA-Form */ 18148 UChar opc1 = ifieldOPC(theInstr); 18149 UChar vD_addr = ifieldRegDS(theInstr); 18150 UChar vA_addr = ifieldRegA(theInstr); 18151 UChar vB_addr = ifieldRegB(theInstr); 18152 UChar vC_addr = ifieldRegC(theInstr); 18153 UInt opc2=0; 18154 18155 IRTemp vA = newTemp(Ity_V128); 18156 IRTemp vB = newTemp(Ity_V128); 18157 IRTemp vC = newTemp(Ity_V128); 18158 assign( vA, getVReg(vA_addr)); 18159 assign( vB, getVReg(vB_addr)); 18160 assign( vC, getVReg(vC_addr)); 18161 18162 if (opc1 != 0x4) { 18163 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 18164 return False; 18165 } 18166 18167 IRTemp rm = newTemp(Ity_I32); 18168 assign(rm, get_IR_roundingmode()); 18169 18170 opc2 = IFIELD( theInstr, 0, 6 ); 18171 switch (opc2) { 18172 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 18173 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 18174 vD_addr, vA_addr, vC_addr, vB_addr); 18175 putVReg( vD_addr, 18176 triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST), 18177 mkexpr(vB), 18178 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18179 mkexpr(vA), mkexpr(vC))) ); 18180 return True; 18181 18182 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 18183 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 18184 vD_addr, vA_addr, vC_addr, vB_addr); 18185 putVReg( vD_addr, 18186 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 18187 mkexpr(vB), 18188 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18189 mkexpr(vA), mkexpr(vC))) ); 18190 return True; 18191 } 18192 18193 default: 18194 break; // Fall through... 18195 } 18196 18197 opc2 = IFIELD( theInstr, 0, 11 ); 18198 switch (opc2) { 18199 case 0x00A: // vaddfp (Add FP, AV p137) 18200 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18201 putVReg( vD_addr, triop(Iop_Add32Fx4, 18202 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 18203 return True; 18204 18205 case 0x04A: // vsubfp (Subtract FP, AV p261) 18206 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18207 putVReg( vD_addr, triop(Iop_Sub32Fx4, 18208 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 18209 return True; 18210 18211 case 0x40A: // vmaxfp (Maximum FP, AV p178) 18212 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18213 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 18214 return True; 18215 18216 case 0x44A: // vminfp (Minimum FP, AV p187) 18217 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18218 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 18219 return True; 18220 18221 default: 18222 break; // Fall through... 18223 } 18224 18225 18226 if (vA_addr != 0) { 18227 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 18228 return False; 18229 } 18230 18231 switch (opc2) { 18232 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 18233 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 18234 putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) ); 18235 return True; 18236 18237 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 18238 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 18239 putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) ); 18240 return True; 18241 18242 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 18243 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 18244 DIP(" => not implemented\n"); 18245 return False; 18246 18247 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 18248 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 18249 DIP(" => not implemented\n"); 18250 return False; 18251 18252 default: 18253 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 18254 return False; 18255 } 18256 return True; 18257 } 18258 18259 /* 18260 AltiVec Floating Point Compare Instructions 18261 */ 18262 static Bool dis_av_fp_cmp ( UInt theInstr ) 18263 { 18264 /* VXR-Form */ 18265 UChar opc1 = ifieldOPC(theInstr); 18266 UChar vD_addr = ifieldRegDS(theInstr); 18267 UChar vA_addr = ifieldRegA(theInstr); 18268 UChar vB_addr = ifieldRegB(theInstr); 18269 UChar flag_rC = ifieldBIT10(theInstr); 18270 UInt opc2 = IFIELD( theInstr, 0, 10 ); 18271 18272 Bool cmp_bounds = False; 18273 18274 IRTemp vA = newTemp(Ity_V128); 18275 IRTemp vB = newTemp(Ity_V128); 18276 IRTemp vD = newTemp(Ity_V128); 18277 assign( vA, getVReg(vA_addr)); 18278 assign( vB, getVReg(vB_addr)); 18279 18280 if (opc1 != 0x4) { 18281 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 18282 return False; 18283 } 18284 18285 switch (opc2) { 18286 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 18287 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18288 vD_addr, vA_addr, vB_addr); 18289 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 18290 break; 18291 18292 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 18293 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18294 vD_addr, vA_addr, vB_addr); 18295 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 18296 break; 18297 18298 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 18299 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18300 vD_addr, vA_addr, vB_addr); 18301 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 18302 break; 18303 18304 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 18305 IRTemp gt = newTemp(Ity_V128); 18306 IRTemp lt = newTemp(Ity_V128); 18307 IRTemp zeros = newTemp(Ity_V128); 18308 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18309 vD_addr, vA_addr, vB_addr); 18310 cmp_bounds = True; 18311 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 18312 18313 /* Note: making use of fact that the ppc backend for compare insns 18314 return zero'd lanes if either of the corresponding arg lanes is 18315 a nan. 18316 18317 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 18318 need this for the other compares too (vcmpeqfp etc)... 18319 Better still, tighten down the spec for compare irops. 18320 */ 18321 assign( gt, unop(Iop_NotV128, 18322 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 18323 assign( lt, unop(Iop_NotV128, 18324 binop(Iop_CmpGE32Fx4, mkexpr(vA), 18325 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 18326 mkexpr(zeros), 18327 mkexpr(vB)))) ); 18328 18329 // finally, just shift gt,lt to correct position 18330 assign( vD, binop(Iop_ShlN32x4, 18331 binop(Iop_OrV128, 18332 binop(Iop_AndV128, mkexpr(gt), 18333 unop(Iop_Dup32x4, mkU32(0x2))), 18334 binop(Iop_AndV128, mkexpr(lt), 18335 unop(Iop_Dup32x4, mkU32(0x1)))), 18336 mkU8(30)) ); 18337 break; 18338 } 18339 18340 default: 18341 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 18342 return False; 18343 } 18344 18345 putVReg( vD_addr, mkexpr(vD) ); 18346 18347 if (flag_rC) { 18348 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 18349 } 18350 return True; 18351 } 18352 18353 /* 18354 AltiVec Floating Point Convert/Round Instructions 18355 */ 18356 static Bool dis_av_fp_convert ( UInt theInstr ) 18357 { 18358 /* VX-Form */ 18359 UChar opc1 = ifieldOPC(theInstr); 18360 UChar vD_addr = ifieldRegDS(theInstr); 18361 UChar UIMM_5 = ifieldRegA(theInstr); 18362 UChar vB_addr = ifieldRegB(theInstr); 18363 UInt opc2 = IFIELD( theInstr, 0, 11 ); 18364 18365 IRTemp vB = newTemp(Ity_V128); 18366 IRTemp vScale = newTemp(Ity_V128); 18367 IRTemp vInvScale = newTemp(Ity_V128); 18368 18369 float scale, inv_scale; 18370 18371 assign( vB, getVReg(vB_addr)); 18372 18373 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 18374 scale = (float)( (unsigned int) 1<<UIMM_5 ); 18375 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 18376 inv_scale = 1/scale; 18377 assign( vInvScale, 18378 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 18379 18380 if (opc1 != 0x4) { 18381 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 18382 return False; 18383 } 18384 18385 switch (opc2) { 18386 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 18387 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18388 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18389 unop(Iop_I32UtoFx4, mkexpr(vB)), 18390 mkexpr(vInvScale)) ); 18391 return True; 18392 18393 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 18394 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18395 18396 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18397 unop(Iop_I32StoFx4, mkexpr(vB)), 18398 mkexpr(vInvScale)) ); 18399 return True; 18400 18401 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 18402 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18403 putVReg( vD_addr, 18404 unop(Iop_QFtoI32Ux4_RZ, 18405 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18406 mkexpr(vB), mkexpr(vScale))) ); 18407 return True; 18408 18409 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 18410 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18411 putVReg( vD_addr, 18412 unop(Iop_QFtoI32Sx4_RZ, 18413 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18414 mkexpr(vB), mkexpr(vScale))) ); 18415 return True; 18416 18417 default: 18418 break; // Fall through... 18419 } 18420 18421 if (UIMM_5 != 0) { 18422 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 18423 return False; 18424 } 18425 18426 switch (opc2) { 18427 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 18428 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 18429 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 18430 break; 18431 18432 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 18433 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 18434 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 18435 break; 18436 18437 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 18438 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 18439 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 18440 break; 18441 18442 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 18443 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 18444 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 18445 break; 18446 18447 default: 18448 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 18449 return False; 18450 } 18451 return True; 18452 } 18453 18454 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr, 18455 const VexAbiInfo* vbi, 18456 /*OUT*/DisResult* dres, 18457 Bool (*resteerOkFn)(void*,Addr), 18458 void* callback_opaque ) 18459 { 18460 UInt opc2 = IFIELD( theInstr, 1, 10 ); 18461 18462 switch (opc2) { 18463 case 0x28E: { //tbegin. 18464 /* The current implementation is to just fail the tbegin and execute 18465 * the failure path. The failure path is assumed to be functionaly 18466 * equivalent to the transactional path with the needed data locking 18467 * to ensure correctness. The tend is just a noop and shouldn't 18468 * actually get executed. 18469 * 1) set cr0 to 0x2 18470 * 2) Initialize TFHAR to CIA+4 18471 * 3) Initialize TEXASR 18472 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.) 18473 * 5) Continue executing at the next instruction. 18474 */ 18475 UInt R = IFIELD( theInstr, 21, 1 ); 18476 18477 ULong tm_reason; 18478 UInt failure_code = 0; /* Forcing failure, will not be due to tabort 18479 * or treclaim. 18480 */ 18481 UInt persistant = 1; /* set persistant since we are always failing 18482 * the tbegin. 18483 */ 18484 UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this 18485 as the reason for failing the trasaction */ 18486 UInt tm_exact = 1; /* have exact address for failure */ 18487 18488 DIP("tbegin. %d\n", R); 18489 18490 /* Set the CR0 field to indicate the tbegin failed. Then let 18491 * the code do the branch to the failure path. 18492 * 18493 * 000 || 0 Transaction initiation successful, 18494 * unnested (Transaction state of 18495 * Non-transactional prior to tbegin.) 18496 * 010 || 0 Transaction initiation successful, nested 18497 * (Transaction state of Transactional 18498 * prior to tbegin.) 18499 * 001 || 0 Transaction initiation unsuccessful, 18500 * (Transaction state of Suspended prior 18501 * to tbegin.) 18502 */ 18503 putCR321( 0, mkU8( 0x2 ) ); 18504 18505 tm_reason = generate_TMreason( failure_code, persistant, 18506 nest_overflow, tm_exact ); 18507 18508 storeTMfailure( guest_CIA_curr_instr, tm_reason, 18509 guest_CIA_curr_instr+4 ); 18510 18511 return True; 18512 18513 break; 18514 } 18515 18516 case 0x2AE: { //tend. 18517 /* The tend. is just a noop. Do nothing */ 18518 UInt A = IFIELD( theInstr, 25, 1 ); 18519 18520 DIP("tend. %d\n", A); 18521 break; 18522 } 18523 18524 case 0x2EE: { //tsr. 18525 /* The tsr. is just a noop. Do nothing */ 18526 UInt L = IFIELD( theInstr, 21, 1 ); 18527 18528 DIP("tsr. %d\n", L); 18529 break; 18530 } 18531 18532 case 0x2CE: { //tcheck. 18533 /* The tcheck. is just a noop. Do nothing */ 18534 UInt BF = IFIELD( theInstr, 25, 1 ); 18535 18536 DIP("tcheck. %d\n", BF); 18537 break; 18538 } 18539 18540 case 0x30E: { //tbortwc. 18541 /* The tabortwc. is just a noop. Do nothing */ 18542 UInt TO = IFIELD( theInstr, 25, 1 ); 18543 UInt RA = IFIELD( theInstr, 16, 5 ); 18544 UInt RB = IFIELD( theInstr, 11, 5 ); 18545 18546 DIP("tabortwc. %d,%d,%d\n", TO, RA, RB); 18547 break; 18548 } 18549 18550 case 0x32E: { //tbortdc. 18551 /* The tabortdc. is just a noop. Do nothing */ 18552 UInt TO = IFIELD( theInstr, 25, 1 ); 18553 UInt RA = IFIELD( theInstr, 16, 5 ); 18554 UInt RB = IFIELD( theInstr, 11, 5 ); 18555 18556 DIP("tabortdc. %d,%d,%d\n", TO, RA, RB); 18557 break; 18558 } 18559 18560 case 0x34E: { //tbortwci. 18561 /* The tabortwci. is just a noop. Do nothing */ 18562 UInt TO = IFIELD( theInstr, 25, 1 ); 18563 UInt RA = IFIELD( theInstr, 16, 5 ); 18564 UInt SI = IFIELD( theInstr, 11, 5 ); 18565 18566 DIP("tabortwci. %d,%d,%d\n", TO, RA, SI); 18567 break; 18568 } 18569 18570 case 0x36E: { //tbortdci. 18571 /* The tabortdci. is just a noop. Do nothing */ 18572 UInt TO = IFIELD( theInstr, 25, 1 ); 18573 UInt RA = IFIELD( theInstr, 16, 5 ); 18574 UInt SI = IFIELD( theInstr, 11, 5 ); 18575 18576 DIP("tabortdci. %d,%d,%d\n", TO, RA, SI); 18577 break; 18578 } 18579 18580 case 0x38E: { //tbort. 18581 /* The tabort. is just a noop. Do nothing */ 18582 UInt RA = IFIELD( theInstr, 16, 5 ); 18583 18584 DIP("tabort. %d\n", RA); 18585 break; 18586 } 18587 18588 case 0x3AE: { //treclaim. 18589 /* The treclaim. is just a noop. Do nothing */ 18590 UInt RA = IFIELD( theInstr, 16, 5 ); 18591 18592 DIP("treclaim. %d\n", RA); 18593 break; 18594 } 18595 18596 case 0x3EE: { //trechkpt. 18597 /* The trechkpt. is just a noop. Do nothing */ 18598 DIP("trechkpt.\n"); 18599 break; 18600 } 18601 18602 default: 18603 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n"); 18604 return False; 18605 } 18606 18607 return True; 18608 } 18609 18610 18611 /* The 0x3C primary opcode (VSX category) uses several different forms of 18612 * extended opcodes: 18613 * o XX2-form: 18614 * - [10:2] (IBM notation [21:29]) 18615 * o XX3-form variants: 18616 * - variant 1: [10:3] (IBM notation [21:28]) 18617 * - variant 2: [9:3] (IBM notation [22:28]) 18618 * - variant 3: [7:3] (IBM notation [24:28]) 18619 * o XX-4 form: 18620 * - [10:6] (IBM notation [21:25]) 18621 * 18622 * The XX2-form needs bit 0 masked from the standard extended opcode 18623 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 18624 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 18625 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 18626 * front end since their encoding does not begin at bit 21 like the standard 18627 * format. 18628 * 18629 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 18630 * secondary opcode for such VSX instructions. 18631 * 18632 */ 18633 18634 18635 struct vsx_insn { 18636 UInt opcode; 18637 const HChar * name; 18638 }; 18639 18640 // ATTENTION: Keep this array sorted on the opcocde!!! 18641 static struct vsx_insn vsx_all[] = { 18642 { 0x0, "xsaddsp" }, 18643 { 0x4, "xsmaddasp" }, 18644 { 0x8, "xxsldwi" }, 18645 { 0x14, "xsrsqrtesp" }, 18646 { 0x16, "xssqrtsp" }, 18647 { 0x18, "xxsel" }, 18648 { 0x20, "xssubsp" }, 18649 { 0x24, "xsmaddmsp" }, 18650 { 0x28, "xxpermdi" }, 18651 { 0x34, "xsresp" }, 18652 { 0x40, "xsmulsp" }, 18653 { 0x44, "xsmsubasp" }, 18654 { 0x48, "xxmrghw" }, 18655 { 0x60, "xsdivsp" }, 18656 { 0x64, "xsmsubmsp" }, 18657 { 0x80, "xsadddp" }, 18658 { 0x84, "xsmaddadp" }, 18659 { 0x8c, "xscmpudp" }, 18660 { 0x90, "xscvdpuxws" }, 18661 { 0x92, "xsrdpi" }, 18662 { 0x94, "xsrsqrtedp" }, 18663 { 0x96, "xssqrtdp" }, 18664 { 0xa0, "xssubdp" }, 18665 { 0xa4, "xsmaddmdp" }, 18666 { 0xac, "xscmpodp" }, 18667 { 0xb0, "xscvdpsxws" }, 18668 { 0xb2, "xsrdpiz" }, 18669 { 0xb4, "xsredp" }, 18670 { 0xc0, "xsmuldp" }, 18671 { 0xc4, "xsmsubadp" }, 18672 { 0xc8, "xxmrglw" }, 18673 { 0xd2, "xsrdpip" }, 18674 { 0xd4, "xstsqrtdp" }, 18675 { 0xd6, "xsrdpic" }, 18676 { 0xe0, "xsdivdp" }, 18677 { 0xe4, "xsmsubmdp" }, 18678 { 0xf2, "xsrdpim" }, 18679 { 0xf4, "xstdivdp" }, 18680 { 0x100, "xvaddsp" }, 18681 { 0x104, "xvmaddasp" }, 18682 { 0x10c, "xvcmpeqsp" }, 18683 { 0x110, "xvcvspuxws" }, 18684 { 0x112, "xvrspi" }, 18685 { 0x114, "xvrsqrtesp" }, 18686 { 0x116, "xvsqrtsp" }, 18687 { 0x120, "xvsubsp" }, 18688 { 0x124, "xvmaddmsp" }, 18689 { 0x12c, "xvcmpgtsp" }, 18690 { 0x130, "xvcvspsxws" }, 18691 { 0x132, "xvrspiz" }, 18692 { 0x134, "xvresp" }, 18693 { 0x140, "xvmulsp" }, 18694 { 0x144, "xvmsubasp" }, 18695 { 0x148, "xxspltw" }, 18696 { 0x14c, "xvcmpgesp" }, 18697 { 0x150, "xvcvuxwsp" }, 18698 { 0x152, "xvrspip" }, 18699 { 0x154, "xvtsqrtsp" }, 18700 { 0x156, "xvrspic" }, 18701 { 0x160, "xvdivsp" }, 18702 { 0x164, "xvmsubmsp" }, 18703 { 0x170, "xvcvsxwsp" }, 18704 { 0x172, "xvrspim" }, 18705 { 0x174, "xvtdivsp" }, 18706 { 0x180, "xvadddp" }, 18707 { 0x184, "xvmaddadp" }, 18708 { 0x18c, "xvcmpeqdp" }, 18709 { 0x190, "xvcvdpuxws" }, 18710 { 0x192, "xvrdpi" }, 18711 { 0x194, "xvrsqrtedp" }, 18712 { 0x196, "xvsqrtdp" }, 18713 { 0x1a0, "xvsubdp" }, 18714 { 0x1a4, "xvmaddmdp" }, 18715 { 0x1ac, "xvcmpgtdp" }, 18716 { 0x1b0, "xvcvdpsxws" }, 18717 { 0x1b2, "xvrdpiz" }, 18718 { 0x1b4, "xvredp" }, 18719 { 0x1c0, "xvmuldp" }, 18720 { 0x1c4, "xvmsubadp" }, 18721 { 0x1cc, "xvcmpgedp" }, 18722 { 0x1d0, "xvcvuxwdp" }, 18723 { 0x1d2, "xvrdpip" }, 18724 { 0x1d4, "xvtsqrtdp" }, 18725 { 0x1d6, "xvrdpic" }, 18726 { 0x1e0, "xvdivdp" }, 18727 { 0x1e4, "xvmsubmdp" }, 18728 { 0x1f0, "xvcvsxwdp" }, 18729 { 0x1f2, "xvrdpim" }, 18730 { 0x1f4, "xvtdivdp" }, 18731 { 0x204, "xsnmaddasp" }, 18732 { 0x208, "xxland" }, 18733 { 0x212, "xscvdpsp" }, 18734 { 0x216, "xscvdpspn" }, 18735 { 0x224, "xsnmaddmsp" }, 18736 { 0x228, "xxlandc" }, 18737 { 0x232, "xxrsp" }, 18738 { 0x244, "xsnmsubasp" }, 18739 { 0x248, "xxlor" }, 18740 { 0x250, "xscvuxdsp" }, 18741 { 0x264, "xsnmsubmsp" }, 18742 { 0x268, "xxlxor" }, 18743 { 0x270, "xscvsxdsp" }, 18744 { 0x280, "xsmaxdp" }, 18745 { 0x284, "xsnmaddadp" }, 18746 { 0x288, "xxlnor" }, 18747 { 0x290, "xscvdpuxds" }, 18748 { 0x292, "xscvspdp" }, 18749 { 0x296, "xscvspdpn" }, 18750 { 0x2a0, "xsmindp" }, 18751 { 0x2a4, "xsnmaddmdp" }, 18752 { 0x2a8, "xxlorc" }, 18753 { 0x2b0, "xscvdpsxds" }, 18754 { 0x2b2, "xsabsdp" }, 18755 { 0x2c0, "xscpsgndp" }, 18756 { 0x2c4, "xsnmsubadp" }, 18757 { 0x2c8, "xxlnand" }, 18758 { 0x2d0, "xscvuxddp" }, 18759 { 0x2d2, "xsnabsdp" }, 18760 { 0x2e4, "xsnmsubmdp" }, 18761 { 0x2e8, "xxleqv" }, 18762 { 0x2f0, "xscvsxddp" }, 18763 { 0x2f2, "xsnegdp" }, 18764 { 0x300, "xvmaxsp" }, 18765 { 0x304, "xvnmaddasp" }, 18766 { 0x30c, "xvcmpeqsp." }, 18767 { 0x310, "xvcvspuxds" }, 18768 { 0x312, "xvcvdpsp" }, 18769 { 0x320, "xvminsp" }, 18770 { 0x324, "xvnmaddmsp" }, 18771 { 0x32c, "xvcmpgtsp." }, 18772 { 0x330, "xvcvspsxds" }, 18773 { 0x332, "xvabssp" }, 18774 { 0x340, "xvcpsgnsp" }, 18775 { 0x344, "xvnmsubasp" }, 18776 { 0x34c, "xvcmpgesp." }, 18777 { 0x350, "xvcvuxdsp" }, 18778 { 0x352, "xvnabssp" }, 18779 { 0x364, "xvnmsubmsp" }, 18780 { 0x370, "xvcvsxdsp" }, 18781 { 0x372, "xvnegsp" }, 18782 { 0x380, "xvmaxdp" }, 18783 { 0x384, "xvnmaddadp" }, 18784 { 0x38c, "xvcmpeqdp." }, 18785 { 0x390, "xvcvdpuxds" }, 18786 { 0x392, "xvcvspdp" }, 18787 { 0x3a0, "xvmindp" }, 18788 { 0x3a4, "xvnmaddmdp" }, 18789 { 0x3ac, "xvcmpgtdp." }, 18790 { 0x3b0, "xvcvdpsxds" }, 18791 { 0x3b2, "xvabsdp" }, 18792 { 0x3c0, "xvcpsgndp" }, 18793 { 0x3c4, "xvnmsubadp" }, 18794 { 0x3cc, "xvcmpgedp." }, 18795 { 0x3d0, "xvcvuxddp" }, 18796 { 0x3d2, "xvnabsdp" }, 18797 { 0x3e4, "xvnmsubmdp" }, 18798 { 0x3f0, "xvcvsxddp" }, 18799 { 0x3f2, "xvnegdp" } 18800 }; 18801 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all) 18802 18803 18804 // ATTENTION: This search function assumes vsx_all array is sorted. 18805 static Int findVSXextOpCode(UInt opcode) 18806 { 18807 Int low, mid, high; 18808 low = 0; 18809 high = VSX_ALL_LEN - 1; 18810 while (low <= high) { 18811 mid = (low + high)/2; 18812 if (opcode < vsx_all[mid].opcode) 18813 high = mid - 1; 18814 else if (opcode > vsx_all[mid].opcode) 18815 low = mid + 1; 18816 else 18817 return mid; 18818 } 18819 return -1; 18820 } 18821 18822 18823 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 18824 * passed, and we then try to match it up with one of the VSX forms 18825 * below. 18826 */ 18827 static UInt get_VSX60_opc2(UInt opc2_full) 18828 { 18829 #define XX2_MASK 0x000003FE 18830 #define XX3_1_MASK 0x000003FC 18831 #define XX3_2_MASK 0x000001FC 18832 #define XX3_3_MASK 0x0000007C 18833 #define XX4_MASK 0x00000018 18834 Int ret; 18835 UInt vsxExtOpcode = 0; 18836 18837 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0) 18838 vsxExtOpcode = vsx_all[ret].opcode; 18839 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0) 18840 vsxExtOpcode = vsx_all[ret].opcode; 18841 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0) 18842 vsxExtOpcode = vsx_all[ret].opcode; 18843 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0) 18844 vsxExtOpcode = vsx_all[ret].opcode; 18845 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0) 18846 vsxExtOpcode = vsx_all[ret].opcode; 18847 18848 return vsxExtOpcode; 18849 } 18850 18851 /*------------------------------------------------------------*/ 18852 /*--- Disassemble a single instruction ---*/ 18853 /*------------------------------------------------------------*/ 18854 18855 /* Disassemble a single instruction into IR. The instruction 18856 is located in host memory at &guest_code[delta]. */ 18857 18858 static 18859 DisResult disInstr_PPC_WRK ( 18860 Bool (*resteerOkFn) ( /*opaque*/void*, Addr ), 18861 Bool resteerCisOk, 18862 void* callback_opaque, 18863 Long delta64, 18864 const VexArchInfo* archinfo, 18865 const VexAbiInfo* abiinfo, 18866 Bool sigill_diag 18867 ) 18868 { 18869 UChar opc1; 18870 UInt opc2; 18871 DisResult dres; 18872 UInt theInstr; 18873 IRType ty = mode64 ? Ity_I64 : Ity_I32; 18874 Bool allow_F = False; 18875 Bool allow_V = False; 18876 Bool allow_FX = False; 18877 Bool allow_GX = False; 18878 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 18879 Bool allow_DFP = False; 18880 Bool allow_isa_2_07 = False; 18881 UInt hwcaps = archinfo->hwcaps; 18882 Long delta; 18883 18884 /* What insn variants are we supporting today? */ 18885 if (mode64) { 18886 allow_F = True; 18887 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 18888 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 18889 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 18890 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 18891 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); 18892 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07)); 18893 } else { 18894 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 18895 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 18896 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 18897 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 18898 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 18899 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); 18900 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07)); 18901 } 18902 18903 /* The running delta */ 18904 delta = (Long)mkSzAddr(ty, (ULong)delta64); 18905 18906 /* Set result defaults. */ 18907 dres.whatNext = Dis_Continue; 18908 dres.len = 0; 18909 dres.continueAt = 0; 18910 dres.jk_StopHere = Ijk_INVALID; 18911 18912 /* At least this is simple on PPC32: insns are all 4 bytes long, and 18913 4-aligned. So just fish the whole thing out of memory right now 18914 and have done. */ 18915 theInstr = getUIntPPCendianly( &guest_code[delta] ); 18916 18917 if (0) vex_printf("insn: 0x%x\n", theInstr); 18918 18919 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 18920 18921 /* Spot "Special" instructions (see comment at top of file). */ 18922 { 18923 const UChar* code = guest_code + delta; 18924 /* Spot the 16-byte preamble: 18925 32-bit mode: 18926 5400183E rlwinm 0,0,3,0,31 18927 5400683E rlwinm 0,0,13,0,31 18928 5400E83E rlwinm 0,0,29,0,31 18929 5400983E rlwinm 0,0,19,0,31 18930 64-bit mode: 18931 78001800 rotldi 0,0,3 18932 78006800 rotldi 0,0,13 18933 7800E802 rotldi 0,0,61 18934 78009802 rotldi 0,0,51 18935 */ 18936 UInt word1 = mode64 ? 0x78001800 : 0x5400183E; 18937 UInt word2 = mode64 ? 0x78006800 : 0x5400683E; 18938 UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; 18939 UInt word4 = mode64 ? 0x78009802 : 0x5400983E; 18940 Bool is_special_preamble = False; 18941 if (getUIntPPCendianly(code+ 0) == word1 && 18942 getUIntPPCendianly(code+ 4) == word2 && 18943 getUIntPPCendianly(code+ 8) == word3 && 18944 getUIntPPCendianly(code+12) == word4) { 18945 is_special_preamble = True; 18946 } else if (! mode64 && 18947 getUIntPPCendianly(code+ 0) == 0x54001800 && 18948 getUIntPPCendianly(code+ 4) == 0x54006800 && 18949 getUIntPPCendianly(code+ 8) == 0x5400E800 && 18950 getUIntPPCendianly(code+12) == 0x54009800) { 18951 static Bool reported = False; 18952 if (!reported) { 18953 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n"); 18954 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n"); 18955 reported = True; 18956 } 18957 is_special_preamble = True; 18958 } 18959 if (is_special_preamble) { 18960 /* Got a "Special" instruction preamble. Which one is it? */ 18961 if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 18962 /* %R3 = client_request ( %R4 ) */ 18963 DIP("r3 = client_request ( %%r4 )\n"); 18964 delta += 20; 18965 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 18966 dres.jk_StopHere = Ijk_ClientReq; 18967 dres.whatNext = Dis_StopHere; 18968 goto decode_success; 18969 } 18970 else 18971 if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 18972 /* %R3 = guest_NRADDR */ 18973 DIP("r3 = guest_NRADDR\n"); 18974 delta += 20; 18975 dres.len = 20; 18976 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 18977 goto decode_success; 18978 } 18979 else 18980 if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 18981 delta += 20; 18982 if (host_endness == VexEndnessLE) { 18983 /* branch-and-link-to-noredir %R12 */ 18984 DIP("branch-and-link-to-noredir r12\n"); 18985 putGST( PPC_GST_LR, 18986 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 18987 putGST( PPC_GST_CIA, getIReg(12)); 18988 } else { 18989 /* branch-and-link-to-noredir %R11 */ 18990 DIP("branch-and-link-to-noredir r11\n"); 18991 putGST( PPC_GST_LR, 18992 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 18993 putGST( PPC_GST_CIA, getIReg(11)); 18994 } 18995 dres.jk_StopHere = Ijk_NoRedir; 18996 dres.whatNext = Dis_StopHere; 18997 goto decode_success; 18998 } 18999 else 19000 if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 19001 /* %R3 = guest_NRADDR_GPR2 */ 19002 DIP("r3 = guest_NRADDR_GPR2\n"); 19003 delta += 20; 19004 dres.len = 20; 19005 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 19006 goto decode_success; 19007 } 19008 else 19009 if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { 19010 DIP("IR injection\n"); 19011 if (host_endness == VexEndnessBE) 19012 vex_inject_ir(irsb, Iend_BE); 19013 else 19014 vex_inject_ir(irsb, Iend_LE); 19015 19016 delta += 20; 19017 dres.len = 20; 19018 19019 // Invalidate the current insn. The reason is that the IRop we're 19020 // injecting here can change. In which case the translation has to 19021 // be redone. For ease of handling, we simply invalidate all the 19022 // time. 19023 19024 stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr))); 19025 stmt(IRStmt_Put(OFFB_CMLEN, mkSzImm(ty, 20))); 19026 19027 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 19028 dres.whatNext = Dis_StopHere; 19029 dres.jk_StopHere = Ijk_InvalICache; 19030 goto decode_success; 19031 } 19032 /* We don't know what it is. Set opc1/opc2 so decode_failure 19033 can print the insn following the Special-insn preamble. */ 19034 theInstr = getUIntPPCendianly(code+16); 19035 opc1 = ifieldOPC(theInstr); 19036 opc2 = ifieldOPClo10(theInstr); 19037 goto decode_failure; 19038 /*NOTREACHED*/ 19039 } 19040 } 19041 19042 opc1 = ifieldOPC(theInstr); 19043 opc2 = ifieldOPClo10(theInstr); 19044 19045 // Note: all 'reserved' bits must be cleared, else invalid 19046 switch (opc1) { 19047 19048 /* Integer Arithmetic Instructions */ 19049 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 19050 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 19051 if (dis_int_arith( theInstr )) goto decode_success; 19052 goto decode_failure; 19053 19054 /* Integer Compare Instructions */ 19055 case 0x0B: case 0x0A: // cmpi, cmpli 19056 if (dis_int_cmp( theInstr )) goto decode_success; 19057 goto decode_failure; 19058 19059 /* Integer Logical Instructions */ 19060 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 19061 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 19062 if (dis_int_logic( theInstr )) goto decode_success; 19063 goto decode_failure; 19064 19065 /* Integer Rotate Instructions */ 19066 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 19067 if (dis_int_rot( theInstr )) goto decode_success; 19068 goto decode_failure; 19069 19070 /* 64bit Integer Rotate Instructions */ 19071 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 19072 if (!mode64) goto decode_failure; 19073 if (dis_int_rot( theInstr )) goto decode_success; 19074 goto decode_failure; 19075 19076 /* Integer Load Instructions */ 19077 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 19078 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 19079 case 0x20: case 0x21: // lwz, lwzu 19080 if (dis_int_load( theInstr )) goto decode_success; 19081 goto decode_failure; 19082 19083 /* Integer Store Instructions */ 19084 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 19085 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 19086 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19087 goto decode_failure; 19088 19089 /* Integer Load and Store Multiple Instructions */ 19090 case 0x2E: case 0x2F: // lmw, stmw 19091 if (dis_int_ldst_mult( theInstr )) goto decode_success; 19092 goto decode_failure; 19093 19094 /* Branch Instructions */ 19095 case 0x12: case 0x10: // b, bc 19096 if (dis_branch(theInstr, abiinfo, &dres, 19097 resteerOkFn, callback_opaque)) 19098 goto decode_success; 19099 goto decode_failure; 19100 19101 /* System Linkage Instructions */ 19102 case 0x11: // sc 19103 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 19104 goto decode_failure; 19105 19106 /* Trap Instructions */ 19107 case 0x02: // tdi 19108 if (!mode64) goto decode_failure; 19109 if (dis_trapi(theInstr, &dres)) goto decode_success; 19110 goto decode_failure; 19111 19112 case 0x03: // twi 19113 if (dis_trapi(theInstr, &dres)) goto decode_success; 19114 goto decode_failure; 19115 19116 /* Floating Point Load Instructions */ 19117 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 19118 case 0x33: // lfdu 19119 if (!allow_F) goto decode_noF; 19120 if (dis_fp_load( theInstr )) goto decode_success; 19121 goto decode_failure; 19122 19123 /* Floating Point Store Instructions */ 19124 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 19125 case 0x37: // stfdux 19126 if (!allow_F) goto decode_noF; 19127 if (dis_fp_store( theInstr )) goto decode_success; 19128 goto decode_failure; 19129 19130 /* Floating Point Load Double Pair Instructions */ 19131 case 0x39: case 0x3D: 19132 if (!allow_F) goto decode_noF; 19133 if (dis_fp_pair( theInstr )) goto decode_success; 19134 goto decode_failure; 19135 19136 /* 128-bit Integer Load */ 19137 case 0x38: // lq 19138 if (dis_int_load( theInstr )) goto decode_success; 19139 goto decode_failure; 19140 19141 /* 64bit Integer Loads */ 19142 case 0x3A: // ld, ldu, lwa 19143 if (!mode64) goto decode_failure; 19144 if (dis_int_load( theInstr )) goto decode_success; 19145 goto decode_failure; 19146 19147 case 0x3B: 19148 if (!allow_F) goto decode_noF; 19149 opc2 = ifieldOPClo10(theInstr); 19150 19151 switch (opc2) { 19152 case 0x2: // dadd - DFP Add 19153 case 0x202: // dsub - DFP Subtract 19154 case 0x22: // dmul - DFP Mult 19155 case 0x222: // ddiv - DFP Divide 19156 if (!allow_DFP) goto decode_noDFP; 19157 if (dis_dfp_arith( theInstr )) 19158 goto decode_success; 19159 case 0x82: // dcmpo, DFP comparison ordered instruction 19160 case 0x282: // dcmpu, DFP comparison unordered instruction 19161 if (!allow_DFP) goto decode_noDFP; 19162 if (dis_dfp_compare( theInstr ) ) 19163 goto decode_success; 19164 goto decode_failure; 19165 case 0x102: // dctdp - DFP convert to DFP long 19166 case 0x302: // drsp - DFP round to dfp short 19167 case 0x122: // dctfix - DFP convert to fixed 19168 if (!allow_DFP) goto decode_noDFP; 19169 if (dis_dfp_fmt_conv( theInstr )) 19170 goto decode_success; 19171 goto decode_failure; 19172 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed 19173 if (!allow_VX) 19174 goto decode_failure; 19175 if (dis_dfp_fmt_conv( theInstr )) 19176 goto decode_success; 19177 goto decode_failure; 19178 case 0x2A2: // dtstsf - DFP number of significant digits 19179 if (!allow_DFP) goto decode_noDFP; 19180 if (dis_dfp_significant_digits(theInstr)) 19181 goto decode_success; 19182 goto decode_failure; 19183 case 0x142: // ddedpd DFP Decode DPD to BCD 19184 case 0x342: // denbcd DFP Encode BCD to DPD 19185 if (!allow_DFP) goto decode_noDFP; 19186 if (dis_dfp_bcd(theInstr)) 19187 goto decode_success; 19188 goto decode_failure; 19189 case 0x162: // dxex - Extract exponent 19190 case 0x362: // diex - Insert exponent 19191 if (!allow_DFP) goto decode_noDFP; 19192 if (dis_dfp_extract_insert( theInstr ) ) 19193 goto decode_success; 19194 goto decode_failure; 19195 case 0x3CE: // fcfidus (implemented as native insn) 19196 if (!allow_VX) 19197 goto decode_noVX; 19198 if (dis_fp_round( theInstr )) 19199 goto decode_success; 19200 goto decode_failure; 19201 case 0x34E: // fcfids 19202 if (dis_fp_round( theInstr )) 19203 goto decode_success; 19204 goto decode_failure; 19205 } 19206 19207 opc2 = ifieldOPClo9( theInstr ); 19208 switch (opc2) { 19209 case 0x42: // dscli, DFP shift left 19210 case 0x62: // dscri, DFP shift right 19211 if (!allow_DFP) goto decode_noDFP; 19212 if (dis_dfp_shift( theInstr )) 19213 goto decode_success; 19214 goto decode_failure; 19215 case 0xc2: // dtstdc, DFP test data class 19216 case 0xe2: // dtstdg, DFP test data group 19217 if (!allow_DFP) goto decode_noDFP; 19218 if (dis_dfp_class_test( theInstr )) 19219 goto decode_success; 19220 goto decode_failure; 19221 } 19222 19223 opc2 = ifieldOPClo8( theInstr ); 19224 switch (opc2) { 19225 case 0x3: // dqua - DFP Quantize 19226 case 0x23: // drrnd - DFP Reround 19227 case 0x43: // dquai - DFP Quantize immediate 19228 if (!allow_DFP) goto decode_noDFP; 19229 if (dis_dfp_quantize_sig_rrnd( theInstr ) ) 19230 goto decode_success; 19231 goto decode_failure; 19232 case 0xA2: // dtstex - DFP Test exponent 19233 if (!allow_DFP) goto decode_noDFP; 19234 if (dis_dfp_exponent_test( theInstr ) ) 19235 goto decode_success; 19236 goto decode_failure; 19237 case 0x63: // drintx - Round to an integer value 19238 case 0xE3: // drintn - Round to an integer value 19239 if (!allow_DFP) goto decode_noDFP; 19240 if (dis_dfp_round( theInstr ) ) { 19241 goto decode_success; 19242 } 19243 goto decode_failure; 19244 default: 19245 break; /* fall through to next opc2 check */ 19246 } 19247 19248 opc2 = IFIELD(theInstr, 1, 5); 19249 switch (opc2) { 19250 /* Floating Point Arith Instructions */ 19251 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 19252 case 0x19: // fmuls 19253 if (dis_fp_arith(theInstr)) goto decode_success; 19254 goto decode_failure; 19255 case 0x16: // fsqrts 19256 if (!allow_FX) goto decode_noFX; 19257 if (dis_fp_arith(theInstr)) goto decode_success; 19258 goto decode_failure; 19259 case 0x18: // fres 19260 if (!allow_GX) goto decode_noGX; 19261 if (dis_fp_arith(theInstr)) goto decode_success; 19262 goto decode_failure; 19263 19264 /* Floating Point Mult-Add Instructions */ 19265 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 19266 case 0x1F: // fnmadds 19267 if (dis_fp_multadd(theInstr)) goto decode_success; 19268 goto decode_failure; 19269 19270 case 0x1A: // frsqrtes 19271 if (!allow_GX) goto decode_noGX; 19272 if (dis_fp_arith(theInstr)) goto decode_success; 19273 goto decode_failure; 19274 19275 default: 19276 goto decode_failure; 19277 } 19278 break; 19279 19280 case 0x3C: // VSX instructions (except load/store) 19281 { 19282 // All of these VSX instructions use some VMX facilities, so 19283 // if allow_V is not set, we'll skip trying to decode. 19284 if (!allow_V) goto decode_noVX; 19285 19286 UInt vsxOpc2 = get_VSX60_opc2(opc2); 19287 /* The vsxOpc2 returned is the "normalized" value, representing the 19288 * instructions secondary opcode as taken from the standard secondary 19289 * opcode field [21:30] (IBM notatition), even if the actual field 19290 * is non-standard. These normalized values are given in the opcode 19291 * appendices of the ISA 2.06 document. 19292 */ 19293 19294 switch (vsxOpc2) { 19295 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 19296 case 0x018: case 0x148: // xxsel, xxspltw 19297 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 19298 goto decode_failure; 19299 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor, 19300 case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc 19301 case 0x2C8: case 0x2E8: // xxlnand, xxleqv 19302 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 19303 goto decode_failure; 19304 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 19305 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 19306 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 19307 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 19308 case 0x034: case 0x014: // xsresp, xsrsqrtesp 19309 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 19310 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 19311 case 0x092: case 0x232: // xsrdpi, xsrsp 19312 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success; 19313 goto decode_failure; 19314 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 19315 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 19316 goto decode_failure; 19317 case 0x0: case 0x020: // xsaddsp, xssubsp 19318 case 0x080: // xsadddp 19319 case 0x060: case 0x0E0: // xsdivsp, xsdivdp 19320 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp 19321 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 19322 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp 19323 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 19324 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp 19325 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 19326 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp 19327 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 19328 case 0x040: case 0x0C0: // xsmulsp, xsmuldp 19329 case 0x0A0: // xssubdp 19330 case 0x016: case 0x096: // xssqrtsp,xssqrtdp 19331 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp 19332 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 19333 goto decode_failure; 19334 case 0x180: // xvadddp 19335 case 0x1E0: // xvdivdp 19336 case 0x1C0: // xvmuldp 19337 case 0x1A0: // xvsubdp 19338 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 19339 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 19340 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 19341 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 19342 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 19343 case 0x196: // xvsqrtdp 19344 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 19345 goto decode_failure; 19346 case 0x100: // xvaddsp 19347 case 0x160: // xvdivsp 19348 case 0x140: // xvmulsp 19349 case 0x120: // xvsubsp 19350 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 19351 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 19352 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 19353 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 19354 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 19355 case 0x116: // xvsqrtsp 19356 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 19357 goto decode_failure; 19358 19359 case 0x250: // xscvuxdsp 19360 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp 19361 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp 19362 case 0x090: // xscvdpuxws 19363 // The above VSX conversion instructions employ some ISA 2.06 19364 // floating point conversion instructions under the covers, 19365 // so if allow_VX (which means "supports ISA 2.06") is not set, 19366 // we'll skip the decode. 19367 if (!allow_VX) goto decode_noVX; 19368 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 19369 goto decode_failure; 19370 19371 case 0x2B0: // xscvdpsxds 19372 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp 19373 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 19374 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 19375 case 0x212: case 0x216: // xscvdpsp, xscvdpspn 19376 case 0x292: case 0x296: // xscvspdp, xscvspdpn 19377 case 0x312: // xvcvdpsp 19378 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 19379 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 19380 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 19381 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 19382 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 19383 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 19384 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 19385 goto decode_failure; 19386 19387 case 0x18C: case 0x38C: // xvcmpeqdp[.] 19388 case 0x10C: case 0x30C: // xvcmpeqsp[.] 19389 case 0x14C: case 0x34C: // xvcmpgesp[.] 19390 case 0x12C: case 0x32C: // xvcmpgtsp[.] 19391 case 0x1CC: case 0x3CC: // xvcmpgedp[.] 19392 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] 19393 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 19394 goto decode_failure; 19395 19396 case 0x134: // xvresp 19397 case 0x1B4: // xvredp 19398 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 19399 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 19400 case 0x300: case 0x320: // xvmaxsp, xvminsp 19401 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 19402 case 0x3B2: case 0x332: // xvabsdp, xvabssp 19403 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 19404 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 19405 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 19406 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 19407 case 0x112: case 0x156: // xvrspi, xvrspic 19408 case 0x172: case 0x152: // xvrspim, xvrspip 19409 case 0x132: // xvrspiz 19410 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 19411 goto decode_failure; 19412 19413 default: 19414 goto decode_failure; 19415 } 19416 break; 19417 } 19418 19419 /* 64bit Integer Stores */ 19420 case 0x3E: // std, stdu, stq 19421 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19422 goto decode_failure; 19423 19424 case 0x3F: 19425 if (!allow_F) goto decode_noF; 19426 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 19427 so we can simply fall through the first switch statement */ 19428 19429 opc2 = IFIELD(theInstr, 1, 5); 19430 switch (opc2) { 19431 /* Floating Point Arith Instructions */ 19432 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 19433 case 0x19: // fmul 19434 if (dis_fp_arith(theInstr)) goto decode_success; 19435 goto decode_failure; 19436 case 0x16: // fsqrt 19437 if (!allow_FX) goto decode_noFX; 19438 if (dis_fp_arith(theInstr)) goto decode_success; 19439 goto decode_failure; 19440 case 0x17: case 0x1A: // fsel, frsqrte 19441 if (!allow_GX) goto decode_noGX; 19442 if (dis_fp_arith(theInstr)) goto decode_success; 19443 goto decode_failure; 19444 19445 /* Floating Point Mult-Add Instructions */ 19446 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 19447 case 0x1F: // fnmadd 19448 if (dis_fp_multadd(theInstr)) goto decode_success; 19449 goto decode_failure; 19450 19451 case 0x18: // fre 19452 if (!allow_GX) goto decode_noGX; 19453 if (dis_fp_arith(theInstr)) goto decode_success; 19454 goto decode_failure; 19455 19456 default: 19457 break; // Fall through 19458 } 19459 19460 opc2 = IFIELD(theInstr, 1, 10); 19461 switch (opc2) { 19462 /* 128-bit DFP instructions */ 19463 case 0x2: // daddq - DFP Add 19464 case 0x202: // dsubq - DFP Subtract 19465 case 0x22: // dmulq - DFP Mult 19466 case 0x222: // ddivq - DFP Divide 19467 if (!allow_DFP) goto decode_noDFP; 19468 if (dis_dfp_arithq( theInstr )) 19469 goto decode_success; 19470 goto decode_failure; 19471 case 0x162: // dxexq - DFP Extract exponent 19472 case 0x362: // diexq - DFP Insert exponent 19473 if (!allow_DFP) goto decode_noDFP; 19474 if (dis_dfp_extract_insertq( theInstr )) 19475 goto decode_success; 19476 goto decode_failure; 19477 19478 case 0x82: // dcmpoq, DFP comparison ordered instruction 19479 case 0x282: // dcmpuq, DFP comparison unordered instruction 19480 if (!allow_DFP) goto decode_noDFP; 19481 if (dis_dfp_compare( theInstr ) ) 19482 goto decode_success; 19483 goto decode_failure; 19484 19485 case 0x102: // dctqpq - DFP convert to DFP extended 19486 case 0x302: // drdpq - DFP round to dfp Long 19487 case 0x122: // dctfixq - DFP convert to fixed quad 19488 case 0x322: // dcffixq - DFP convert from fixed quad 19489 if (!allow_DFP) goto decode_noDFP; 19490 if (dis_dfp_fmt_convq( theInstr )) 19491 goto decode_success; 19492 goto decode_failure; 19493 19494 case 0x2A2: // dtstsfq - DFP number of significant digits 19495 if (!allow_DFP) goto decode_noDFP; 19496 if (dis_dfp_significant_digits(theInstr)) 19497 goto decode_success; 19498 goto decode_failure; 19499 19500 case 0x142: // ddedpdq DFP Decode DPD to BCD 19501 case 0x342: // denbcdq DFP Encode BCD to DPD 19502 if (!allow_DFP) goto decode_noDFP; 19503 if (dis_dfp_bcdq(theInstr)) 19504 goto decode_success; 19505 goto decode_failure; 19506 19507 /* Floating Point Compare Instructions */ 19508 case 0x000: // fcmpu 19509 case 0x020: // fcmpo 19510 if (dis_fp_cmp(theInstr)) goto decode_success; 19511 goto decode_failure; 19512 19513 case 0x080: // ftdiv 19514 case 0x0A0: // ftsqrt 19515 if (dis_fp_tests(theInstr)) goto decode_success; 19516 goto decode_failure; 19517 19518 /* Floating Point Rounding/Conversion Instructions */ 19519 case 0x00C: // frsp 19520 case 0x00E: // fctiw 19521 case 0x00F: // fctiwz 19522 case 0x32E: // fctid 19523 case 0x32F: // fctidz 19524 case 0x34E: // fcfid 19525 if (dis_fp_round(theInstr)) goto decode_success; 19526 goto decode_failure; 19527 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 19528 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 19529 if (!allow_VX) goto decode_noVX; 19530 if (dis_fp_round(theInstr)) goto decode_success; 19531 goto decode_failure; 19532 19533 /* Power6 rounding stuff */ 19534 case 0x1E8: // frim 19535 case 0x1C8: // frip 19536 case 0x188: // frin 19537 case 0x1A8: // friz 19538 /* A hack to check for P6 capability . . . */ 19539 if ((allow_F && allow_V && allow_FX && allow_GX) && 19540 (dis_fp_round(theInstr))) 19541 goto decode_success; 19542 goto decode_failure; 19543 19544 /* Floating Point Move Instructions */ 19545 case 0x008: // fcpsgn 19546 case 0x028: // fneg 19547 case 0x048: // fmr 19548 case 0x088: // fnabs 19549 case 0x108: // fabs 19550 if (dis_fp_move( theInstr )) goto decode_success; 19551 goto decode_failure; 19552 19553 case 0x3c6: case 0x346: // fmrgew, fmrgow 19554 if (dis_fp_merge( theInstr )) goto decode_success; 19555 goto decode_failure; 19556 19557 /* Floating Point Status/Control Register Instructions */ 19558 case 0x026: // mtfsb1 19559 case 0x040: // mcrfs 19560 case 0x046: // mtfsb0 19561 case 0x086: // mtfsfi 19562 case 0x247: // mffs 19563 case 0x2C7: // mtfsf 19564 // Some of the above instructions need to know more about the 19565 // ISA level supported by the host. 19566 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success; 19567 goto decode_failure; 19568 19569 default: 19570 break; // Fall through... 19571 } 19572 19573 opc2 = ifieldOPClo9( theInstr ); 19574 switch (opc2) { 19575 case 0x42: // dscli, DFP shift left 19576 case 0x62: // dscri, DFP shift right 19577 if (!allow_DFP) goto decode_noDFP; 19578 if (dis_dfp_shiftq( theInstr )) 19579 goto decode_success; 19580 goto decode_failure; 19581 case 0xc2: // dtstdc, DFP test data class 19582 case 0xe2: // dtstdg, DFP test data group 19583 if (!allow_DFP) goto decode_noDFP; 19584 if (dis_dfp_class_test( theInstr )) 19585 goto decode_success; 19586 goto decode_failure; 19587 default: 19588 break; 19589 } 19590 19591 opc2 = ifieldOPClo8( theInstr ); 19592 switch (opc2) { 19593 case 0x3: // dquaq - DFP Quantize Quad 19594 case 0x23: // drrndq - DFP Reround Quad 19595 case 0x43: // dquaiq - DFP Quantize immediate Quad 19596 if (!allow_DFP) goto decode_noDFP; 19597 if (dis_dfp_quantize_sig_rrndq( theInstr )) 19598 goto decode_success; 19599 goto decode_failure; 19600 case 0xA2: // dtstexq - DFP Test exponent Quad 19601 if (dis_dfp_exponent_test( theInstr ) ) 19602 goto decode_success; 19603 goto decode_failure; 19604 case 0x63: // drintxq - DFP Round to an integer value 19605 case 0xE3: // drintnq - DFP Round to an integer value 19606 if (!allow_DFP) goto decode_noDFP; 19607 if (dis_dfp_roundq( theInstr )) 19608 goto decode_success; 19609 goto decode_failure; 19610 19611 default: 19612 goto decode_failure; 19613 } 19614 break; 19615 19616 case 0x13: 19617 switch (opc2) { 19618 19619 /* Condition Register Logical Instructions */ 19620 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 19621 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 19622 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 19623 if (dis_cond_logic( theInstr )) goto decode_success; 19624 goto decode_failure; 19625 19626 /* Branch Instructions */ 19627 case 0x210: case 0x010: // bcctr, bclr 19628 if (dis_branch(theInstr, abiinfo, &dres, 19629 resteerOkFn, callback_opaque)) 19630 goto decode_success; 19631 goto decode_failure; 19632 19633 /* Memory Synchronization Instructions */ 19634 case 0x096: // isync 19635 if (dis_memsync( theInstr )) goto decode_success; 19636 goto decode_failure; 19637 19638 default: 19639 goto decode_failure; 19640 } 19641 break; 19642 19643 19644 case 0x1F: 19645 19646 /* For arith instns, bit10 is the OE flag (overflow enable) */ 19647 19648 opc2 = IFIELD(theInstr, 1, 9); 19649 switch (opc2) { 19650 /* Integer Arithmetic Instructions */ 19651 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 19652 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 19653 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 19654 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 19655 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 19656 case 0x0C8: // subfze 19657 if (dis_int_arith( theInstr )) goto decode_success; 19658 goto decode_failure; 19659 19660 case 0x18B: // divweu (implemented as native insn) 19661 case 0x1AB: // divwe (implemented as native insn) 19662 if (!allow_VX) goto decode_noVX; 19663 if (dis_int_arith( theInstr )) goto decode_success; 19664 goto decode_failure; 19665 19666 /* 64bit Integer Arithmetic */ 19667 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 19668 case 0x1C9: case 0x1E9: // divdu, divd 19669 if (!mode64) goto decode_failure; 19670 if (dis_int_arith( theInstr )) goto decode_success; 19671 goto decode_failure; 19672 19673 case 0x1A9: // divde (implemented as native insn) 19674 case 0x189: // divdeuo (implemented as native insn) 19675 if (!allow_VX) goto decode_noVX; 19676 if (!mode64) goto decode_failure; 19677 if (dis_int_arith( theInstr )) goto decode_success; 19678 goto decode_failure; 19679 19680 case 0x1FC: // cmpb 19681 if (dis_int_logic( theInstr )) goto decode_success; 19682 goto decode_failure; 19683 19684 default: 19685 break; // Fall through... 19686 } 19687 19688 /* All remaining opcodes use full 10 bits. */ 19689 19690 opc2 = IFIELD(theInstr, 1, 10); 19691 switch (opc2) { 19692 /* Integer Compare Instructions */ 19693 case 0x000: case 0x020: // cmp, cmpl 19694 if (dis_int_cmp( theInstr )) goto decode_success; 19695 goto decode_failure; 19696 19697 /* Integer Logical Instructions */ 19698 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 19699 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 19700 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 19701 case 0x19C: case 0x13C: // orc, xor 19702 case 0x2DF: case 0x25F: // mftgpr, mffgpr 19703 if (dis_int_logic( theInstr )) goto decode_success; 19704 goto decode_failure; 19705 19706 case 0x28E: case 0x2AE: // tbegin., tend. 19707 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc. 19708 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. 19709 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt. 19710 if (dis_transactional_memory( theInstr, 19711 getUIntPPCendianly( &guest_code[delta + 4]), 19712 abiinfo, &dres, 19713 resteerOkFn, callback_opaque)) 19714 goto decode_success; 19715 goto decode_failure; 19716 19717 /* 64bit Integer Logical Instructions */ 19718 case 0x3DA: case 0x03A: // extsw, cntlzd 19719 if (!mode64) goto decode_failure; 19720 if (dis_int_logic( theInstr )) goto decode_success; 19721 goto decode_failure; 19722 19723 /* 64bit Integer Parity Instructions */ 19724 case 0xba: // prtyd 19725 if (!mode64) goto decode_failure; 19726 if (dis_int_parity( theInstr )) goto decode_success; 19727 goto decode_failure; 19728 19729 case 0x9a: // prtyw 19730 if (dis_int_parity( theInstr )) goto decode_success; 19731 goto decode_failure; 19732 19733 /* Integer Shift Instructions */ 19734 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 19735 case 0x218: // srw 19736 if (dis_int_shift( theInstr )) goto decode_success; 19737 goto decode_failure; 19738 19739 /* 64bit Integer Shift Instructions */ 19740 case 0x01B: case 0x31A: // sld, srad 19741 case 0x33A: case 0x33B: // sradi 19742 case 0x21B: // srd 19743 if (!mode64) goto decode_failure; 19744 if (dis_int_shift( theInstr )) goto decode_success; 19745 goto decode_failure; 19746 19747 /* Integer Load Instructions */ 19748 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 19749 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 19750 case 0x017: case 0x037: // lwzx, lwzux 19751 if (dis_int_load( theInstr )) goto decode_success; 19752 goto decode_failure; 19753 19754 /* 64bit Integer Load Instructions */ 19755 case 0x035: case 0x015: // ldux, ldx 19756 case 0x175: case 0x155: // lwaux, lwax 19757 if (!mode64) goto decode_failure; 19758 if (dis_int_load( theInstr )) goto decode_success; 19759 goto decode_failure; 19760 19761 /* Integer Store Instructions */ 19762 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 19763 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 19764 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19765 goto decode_failure; 19766 19767 /* 64bit Integer Store Instructions */ 19768 case 0x0B5: case 0x095: // stdux, stdx 19769 if (!mode64) goto decode_failure; 19770 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19771 goto decode_failure; 19772 19773 /* Integer Load and Store with Byte Reverse Instructions */ 19774 case 0x214: case 0x294: // ldbrx, stdbrx 19775 if (!mode64) goto decode_failure; 19776 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19777 goto decode_failure; 19778 19779 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx 19780 case 0x396: // sthbrx 19781 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19782 goto decode_failure; 19783 19784 /* Integer Load and Store String Instructions */ 19785 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 19786 case 0x295: { // stswx 19787 Bool stopHere = False; 19788 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 19789 if (!ok) goto decode_failure; 19790 if (stopHere) { 19791 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) ); 19792 dres.jk_StopHere = Ijk_Boring; 19793 dres.whatNext = Dis_StopHere; 19794 } 19795 goto decode_success; 19796 } 19797 19798 /* Memory Synchronization Instructions */ 19799 case 0x034: case 0x074: // lbarx, lharx 19800 case 0x2B6: case 0x2D6: // stbcx, sthcx 19801 if (!allow_isa_2_07) goto decode_noP8; 19802 if (dis_memsync( theInstr )) goto decode_success; 19803 goto decode_failure; 19804 19805 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 19806 case 0x256: // sync 19807 if (dis_memsync( theInstr )) goto decode_success; 19808 goto decode_failure; 19809 19810 /* 64bit Memory Synchronization Instructions */ 19811 case 0x054: case 0x0D6: // ldarx, stdcx. 19812 if (!mode64) goto decode_failure; 19813 if (dis_memsync( theInstr )) goto decode_success; 19814 goto decode_failure; 19815 19816 case 0x114: case 0x0B6: // lqarx, stqcx. 19817 if (dis_memsync( theInstr )) goto decode_success; 19818 goto decode_failure; 19819 19820 /* Processor Control Instructions */ 19821 case 0x33: case 0x73: // mfvsrd, mfvsrwz 19822 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz 19823 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 19824 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 19825 case 0x220: // mcrxrt 19826 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 19827 goto decode_failure; 19828 19829 /* Cache Management Instructions */ 19830 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 19831 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 19832 case 0x3D6: // icbi 19833 if (dis_cache_manage( theInstr, &dres, archinfo )) 19834 goto decode_success; 19835 goto decode_failure; 19836 19837 //zz /* External Control Instructions */ 19838 //zz case 0x136: case 0x1B6: // eciwx, ecowx 19839 //zz DIP("external control op => not implemented\n"); 19840 //zz goto decode_failure; 19841 19842 /* Trap Instructions */ 19843 case 0x004: // tw 19844 if (dis_trap(theInstr, &dres)) goto decode_success; 19845 goto decode_failure; 19846 19847 case 0x044: // td 19848 if (!mode64) goto decode_failure; 19849 if (dis_trap(theInstr, &dres)) goto decode_success; 19850 goto decode_failure; 19851 19852 /* Floating Point Load Instructions */ 19853 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 19854 case 0x277: // lfdux 19855 if (!allow_F) goto decode_noF; 19856 if (dis_fp_load( theInstr )) goto decode_success; 19857 goto decode_failure; 19858 19859 /* Floating Point Store Instructions */ 19860 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 19861 case 0x2F7: // stfdu, stfiwx 19862 if (!allow_F) goto decode_noF; 19863 if (dis_fp_store( theInstr )) goto decode_success; 19864 goto decode_failure; 19865 case 0x3D7: // stfiwx 19866 if (!allow_F) goto decode_noF; 19867 if (!allow_GX) goto decode_noGX; 19868 if (dis_fp_store( theInstr )) goto decode_success; 19869 goto decode_failure; 19870 19871 /* Floating Point Double Pair Indexed Instructions */ 19872 case 0x317: // lfdpx (Power6) 19873 case 0x397: // stfdpx (Power6) 19874 if (!allow_F) goto decode_noF; 19875 if (dis_fp_pair(theInstr)) goto decode_success; 19876 goto decode_failure; 19877 19878 case 0x357: // lfiwax 19879 if (!allow_F) goto decode_noF; 19880 if (dis_fp_load( theInstr )) goto decode_success; 19881 goto decode_failure; 19882 19883 case 0x377: // lfiwzx 19884 if (!allow_F) goto decode_noF; 19885 if (dis_fp_load( theInstr )) goto decode_success; 19886 goto decode_failure; 19887 19888 /* AltiVec instructions */ 19889 19890 /* AV Cache Control - Data streams */ 19891 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 19892 if (!allow_V) goto decode_noV; 19893 if (dis_av_datastream( theInstr )) goto decode_success; 19894 goto decode_failure; 19895 19896 /* AV Load */ 19897 case 0x006: case 0x026: // lvsl, lvsr 19898 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 19899 case 0x067: case 0x167: // lvx, lvxl 19900 if (!allow_V) goto decode_noV; 19901 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 19902 goto decode_failure; 19903 19904 /* AV Store */ 19905 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 19906 case 0x0E7: case 0x1E7: // stvx, stvxl 19907 if (!allow_V) goto decode_noV; 19908 if (dis_av_store( theInstr )) goto decode_success; 19909 goto decode_failure; 19910 19911 /* VSX Load */ 19912 case 0x00C: // lxsiwzx 19913 case 0x04C: // lxsiwax 19914 case 0x20C: // lxsspx 19915 case 0x24C: // lxsdx 19916 case 0x34C: // lxvd2x 19917 case 0x14C: // lxvdsx 19918 case 0x30C: // lxvw4x 19919 // All of these VSX load instructions use some VMX facilities, so 19920 // if allow_V is not set, we'll skip trying to decode. 19921 if (!allow_V) goto decode_noV; 19922 19923 if (dis_vx_load( theInstr )) goto decode_success; 19924 goto decode_failure; 19925 19926 /* VSX Store */ 19927 case 0x08C: // stxsiwx 19928 case 0x28C: // stxsspx 19929 case 0x2CC: // stxsdx 19930 case 0x3CC: // stxvd2x 19931 case 0x38C: // stxvw4x 19932 // All of these VSX store instructions use some VMX facilities, so 19933 // if allow_V is not set, we'll skip trying to decode. 19934 if (!allow_V) goto decode_noV; 19935 19936 if (dis_vx_store( theInstr )) goto decode_success; 19937 goto decode_failure; 19938 19939 /* Miscellaneous ISA 2.06 instructions */ 19940 case 0x1FA: // popcntd 19941 case 0x17A: // popcntw 19942 case 0x7A: // popcntb 19943 if (dis_int_logic( theInstr )) goto decode_success; 19944 goto decode_failure; 19945 19946 case 0x0FC: // bpermd 19947 if (!mode64) goto decode_failure; 19948 if (dis_int_logic( theInstr )) goto decode_success; 19949 goto decode_failure; 19950 19951 default: 19952 /* Deal with some other cases that we would otherwise have 19953 punted on. */ 19954 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 19955 /* only decode this insn when reserved bit 0 (31 in IBM's 19956 notation) is zero */ 19957 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 19958 UInt rT = ifieldRegDS( theInstr ); 19959 UInt rA = ifieldRegA( theInstr ); 19960 UInt rB = ifieldRegB( theInstr ); 19961 UInt bi = ifieldRegC( theInstr ); 19962 putIReg( 19963 rT, 19964 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)), 19965 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 19966 : getIReg(rA), 19967 getIReg(rB)) 19968 19969 ); 19970 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 19971 goto decode_success; 19972 } 19973 goto decode_failure; 19974 } 19975 break; 19976 19977 19978 case 0x04: 19979 /* AltiVec instructions */ 19980 19981 opc2 = IFIELD(theInstr, 0, 6); 19982 switch (opc2) { 19983 /* AV Mult-Add, Mult-Sum */ 19984 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 19985 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 19986 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 19987 if (!allow_V) goto decode_noV; 19988 if (dis_av_multarith( theInstr )) goto decode_success; 19989 goto decode_failure; 19990 19991 /* AV Permutations */ 19992 case 0x2A: // vsel 19993 case 0x2B: // vperm 19994 case 0x2C: // vsldoi 19995 if (!allow_V) goto decode_noV; 19996 if (dis_av_permute( theInstr )) goto decode_success; 19997 goto decode_failure; 19998 19999 case 0x2D: // vpermxor 20000 if (!allow_isa_2_07) goto decode_noP8; 20001 if (dis_av_permute( theInstr )) goto decode_success; 20002 goto decode_failure; 20003 20004 /* AV Floating Point Mult-Add/Sub */ 20005 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 20006 if (!allow_V) goto decode_noV; 20007 if (dis_av_fp_arith( theInstr )) goto decode_success; 20008 goto decode_failure; 20009 20010 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm 20011 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm 20012 if (!allow_V) goto decode_noV; 20013 if (dis_av_quad( theInstr)) goto decode_success; 20014 goto decode_failure; 20015 20016 default: 20017 break; // Fall through... 20018 } 20019 20020 opc2 = IFIELD(theInstr, 0, 9); 20021 switch (opc2) { 20022 /* BCD arithmetic */ 20023 case 0x1: case 0x41: // bcdadd, bcdsub 20024 if (!allow_isa_2_07) goto decode_noP8; 20025 if (dis_av_bcd( theInstr )) goto decode_success; 20026 goto decode_failure; 20027 20028 default: 20029 break; // Fall through... 20030 } 20031 20032 opc2 = IFIELD(theInstr, 0, 11); 20033 switch (opc2) { 20034 /* AV Arithmetic */ 20035 case 0x180: // vaddcuw 20036 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 20037 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 20038 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 20039 case 0x580: // vsubcuw 20040 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 20041 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 20042 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 20043 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 20044 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 20045 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 20046 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 20047 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 20048 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 20049 case 0x008: case 0x048: // vmuloub, vmulouh 20050 case 0x108: case 0x148: // vmulosb, vmulosh 20051 case 0x208: case 0x248: // vmuleub, vmuleuh 20052 case 0x308: case 0x348: // vmulesb, vmulesh 20053 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 20054 case 0x688: case 0x788: // vsum2sws, vsumsws 20055 if (!allow_V) goto decode_noV; 20056 if (dis_av_arith( theInstr )) goto decode_success; 20057 goto decode_failure; 20058 20059 case 0x088: case 0x089: // vmulouw, vmuluwm 20060 case 0x0C0: case 0x0C2: // vaddudm, vmaxud 20061 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd 20062 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw 20063 case 0x4C0: // vsubudm 20064 if (!allow_isa_2_07) goto decode_noP8; 20065 if (dis_av_arith( theInstr )) goto decode_success; 20066 goto decode_failure; 20067 20068 /* AV Polynomial Vector Multiply Add */ 20069 case 0x408: case 0x448: // vpmsumb, vpmsumd 20070 case 0x488: case 0x4C8: // vpmsumw, vpmsumh 20071 if (!allow_isa_2_07) goto decode_noP8; 20072 if (dis_av_polymultarith( theInstr )) goto decode_success; 20073 goto decode_failure; 20074 20075 /* AV Rotate, Shift */ 20076 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 20077 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 20078 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 20079 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 20080 case 0x1C4: case 0x2C4: // vsl, vsr 20081 case 0x40C: case 0x44C: // vslo, vsro 20082 if (!allow_V) goto decode_noV; 20083 if (dis_av_shift( theInstr )) goto decode_success; 20084 goto decode_failure; 20085 20086 case 0x0C4: // vrld 20087 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd 20088 if (!allow_isa_2_07) goto decode_noP8; 20089 if (dis_av_shift( theInstr )) goto decode_success; 20090 goto decode_failure; 20091 20092 /* AV Logic */ 20093 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 20094 case 0x4C4: case 0x504: // vxor, vnor 20095 if (!allow_V) goto decode_noV; 20096 if (dis_av_logic( theInstr )) goto decode_success; 20097 goto decode_failure; 20098 20099 case 0x544: // vorc 20100 case 0x584: case 0x684: // vnand, veqv 20101 if (!allow_isa_2_07) goto decode_noP8; 20102 if (dis_av_logic( theInstr )) goto decode_success; 20103 goto decode_failure; 20104 20105 /* AV Processor Control */ 20106 case 0x604: case 0x644: // mfvscr, mtvscr 20107 if (!allow_V) goto decode_noV; 20108 if (dis_av_procctl( theInstr )) goto decode_success; 20109 goto decode_failure; 20110 20111 /* AV Floating Point Arithmetic */ 20112 case 0x00A: case 0x04A: // vaddfp, vsubfp 20113 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 20114 case 0x1CA: // vlogefp 20115 case 0x40A: case 0x44A: // vmaxfp, vminfp 20116 if (!allow_V) goto decode_noV; 20117 if (dis_av_fp_arith( theInstr )) goto decode_success; 20118 goto decode_failure; 20119 20120 /* AV Floating Point Round/Convert */ 20121 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 20122 case 0x2CA: // vrfim 20123 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 20124 case 0x3CA: // vctsxs 20125 if (!allow_V) goto decode_noV; 20126 if (dis_av_fp_convert( theInstr )) goto decode_success; 20127 goto decode_failure; 20128 20129 /* AV Merge, Splat */ 20130 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 20131 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 20132 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 20133 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 20134 if (!allow_V) goto decode_noV; 20135 if (dis_av_permute( theInstr )) goto decode_success; 20136 goto decode_failure; 20137 20138 case 0x68C: case 0x78C: // vmrgow, vmrgew 20139 if (!allow_isa_2_07) goto decode_noP8; 20140 if (dis_av_permute( theInstr )) goto decode_success; 20141 goto decode_failure; 20142 20143 /* AV Pack, Unpack */ 20144 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 20145 case 0x0CE: // vpkuwus 20146 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 20147 case 0x1CE: // vpkswss 20148 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 20149 case 0x2CE: // vupklsh 20150 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 20151 if (!allow_V) goto decode_noV; 20152 if (dis_av_pack( theInstr )) goto decode_success; 20153 goto decode_failure; 20154 20155 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus 20156 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw 20157 if (!allow_isa_2_07) goto decode_noP8; 20158 if (dis_av_pack( theInstr )) goto decode_success; 20159 goto decode_failure; 20160 20161 case 0x508: case 0x509: // vcipher, vcipherlast 20162 case 0x548: case 0x549: // vncipher, vncipherlast 20163 case 0x5C8: // vsbox 20164 if (!allow_isa_2_07) goto decode_noP8; 20165 if (dis_av_cipher( theInstr )) goto decode_success; 20166 goto decode_failure; 20167 20168 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad 20169 if (!allow_isa_2_07) goto decode_noP8; 20170 if (dis_av_hash( theInstr )) goto decode_success; 20171 goto decode_failure; 20172 20173 case 0x702: case 0x742: // vclzb, vclzh 20174 case 0x782: case 0x7c2: // vclzw, vclzd 20175 if (!allow_isa_2_07) goto decode_noP8; 20176 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20177 goto decode_failure; 20178 20179 case 0x703: case 0x743: // vpopcntb, vpopcnth 20180 case 0x783: case 0x7c3: // vpopcntw, vpopcntd 20181 if (!allow_isa_2_07) goto decode_noP8; 20182 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20183 goto decode_failure; 20184 20185 case 0x50c: // vgbbd 20186 if (!allow_isa_2_07) goto decode_noP8; 20187 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20188 goto decode_failure; 20189 20190 case 0x140: case 0x100: // vaddcuq, vadduqm 20191 case 0x540: case 0x500: // vsubcuq, vsubuqm 20192 case 0x54C: // vbpermq 20193 if (!allow_V) goto decode_noV; 20194 if (dis_av_quad( theInstr)) goto decode_success; 20195 goto decode_failure; 20196 20197 default: 20198 break; // Fall through... 20199 } 20200 20201 opc2 = IFIELD(theInstr, 0, 10); 20202 switch (opc2) { 20203 20204 /* AV Compare */ 20205 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 20206 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 20207 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 20208 if (!allow_V) goto decode_noV; 20209 if (dis_av_cmp( theInstr )) goto decode_success; 20210 goto decode_failure; 20211 20212 case 0x0C7: // vcmpequd 20213 case 0x2C7: // vcmpgtud 20214 case 0x3C7: // vcmpgtsd 20215 if (!allow_isa_2_07) goto decode_noP8; 20216 if (dis_av_cmp( theInstr )) goto decode_success; 20217 goto decode_failure; 20218 20219 /* AV Floating Point Compare */ 20220 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 20221 case 0x3C6: // vcmpbfp 20222 if (!allow_V) goto decode_noV; 20223 if (dis_av_fp_cmp( theInstr )) goto decode_success; 20224 goto decode_failure; 20225 20226 default: 20227 goto decode_failure; 20228 } 20229 break; 20230 20231 default: 20232 goto decode_failure; 20233 20234 decode_noF: 20235 vassert(!allow_F); 20236 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n" 20237 "can't be handled by Valgrind on this host. This instruction\n" 20238 "requires a host that supports Floating Point instructions.\n", 20239 theInstr); 20240 goto not_supported; 20241 decode_noV: 20242 vassert(!allow_V); 20243 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n" 20244 "that can't be handled by Valgrind. If this instruction is an\n" 20245 "Altivec instruction, Valgrind must be run on a host that supports" 20246 "AltiVec instructions. If the application was compiled for e500, then\n" 20247 "unfortunately Valgrind does not yet support e500 instructions.\n", 20248 theInstr); 20249 goto not_supported; 20250 decode_noVX: 20251 vassert(!allow_VX); 20252 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n" 20253 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n" 20254 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n", 20255 theInstr); 20256 goto not_supported; 20257 decode_noFX: 20258 vassert(!allow_FX); 20259 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n" 20260 "that can't be handled by Valgrind on this host. This instruction\n" 20261 "requires a host that supports the General Purpose-Optional instructions.\n", 20262 theInstr); 20263 goto not_supported; 20264 decode_noGX: 20265 vassert(!allow_GX); 20266 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n" 20267 "that can't be handled by Valgrind on this host. This instruction\n" 20268 "requires a host that supports the Graphic-Optional instructions.\n", 20269 theInstr); 20270 goto not_supported; 20271 decode_noDFP: 20272 vassert(!allow_DFP); 20273 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n" 20274 "that can't be handled by Valgrind on this host. This instruction\n" 20275 "requires a host that supports DFP instructions.\n", 20276 theInstr); 20277 goto not_supported; 20278 decode_noP8: 20279 vassert(!allow_isa_2_07); 20280 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n" 20281 "by Valgrind on this host. This instruction requires a host that\n" 20282 "supports Power 8 instructions.\n", 20283 theInstr); 20284 goto not_supported; 20285 20286 20287 decode_failure: 20288 /* All decode failures end up here. */ 20289 opc2 = (theInstr) & 0x7FF; 20290 if (sigill_diag) { 20291 vex_printf("disInstr(ppc): unhandled instruction: " 20292 "0x%x\n", theInstr); 20293 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 20294 opc1, opc1, opc2, opc2); 20295 } 20296 20297 not_supported: 20298 /* Tell the dispatcher that this insn cannot be decoded, and so has 20299 not been executed, and (is currently) the next to be executed. 20300 CIA should be up-to-date since it made so at the start of each 20301 insn, but nevertheless be paranoid and update it again right 20302 now. */ 20303 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 20304 dres.len = 0; 20305 dres.whatNext = Dis_StopHere; 20306 dres.jk_StopHere = Ijk_NoDecode; 20307 dres.continueAt = 0; 20308 return dres; 20309 } /* switch (opc) for the main (primary) opcode switch. */ 20310 20311 decode_success: 20312 /* All decode successes end up here. */ 20313 switch (dres.whatNext) { 20314 case Dis_Continue: 20315 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4)); 20316 break; 20317 case Dis_ResteerU: 20318 case Dis_ResteerC: 20319 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt)); 20320 break; 20321 case Dis_StopHere: 20322 break; 20323 default: 20324 vassert(0); 20325 } 20326 DIP("\n"); 20327 20328 if (dres.len == 0) { 20329 dres.len = 4; 20330 } else { 20331 vassert(dres.len == 20); 20332 } 20333 return dres; 20334 } 20335 20336 #undef DIP 20337 #undef DIS 20338 20339 20340 /*------------------------------------------------------------*/ 20341 /*--- Top-level fn ---*/ 20342 /*------------------------------------------------------------*/ 20343 20344 /* Disassemble a single instruction into IR. The instruction 20345 is located in host memory at &guest_code[delta]. */ 20346 20347 DisResult disInstr_PPC ( IRSB* irsb_IN, 20348 Bool (*resteerOkFn) ( void*, Addr ), 20349 Bool resteerCisOk, 20350 void* callback_opaque, 20351 const UChar* guest_code_IN, 20352 Long delta, 20353 Addr guest_IP, 20354 VexArch guest_arch, 20355 const VexArchInfo* archinfo, 20356 const VexAbiInfo* abiinfo, 20357 VexEndness host_endness_IN, 20358 Bool sigill_diag_IN ) 20359 { 20360 IRType ty; 20361 DisResult dres; 20362 UInt mask32, mask64; 20363 UInt hwcaps_guest = archinfo->hwcaps; 20364 20365 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 20366 20367 /* global -- ick */ 20368 mode64 = guest_arch == VexArchPPC64; 20369 ty = mode64 ? Ity_I64 : Ity_I32; 20370 if (!mode64 && (host_endness_IN == VexEndnessLE)) { 20371 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n"); 20372 dres.len = 0; 20373 dres.whatNext = Dis_StopHere; 20374 dres.jk_StopHere = Ijk_NoDecode; 20375 dres.continueAt = 0; 20376 return dres; 20377 } 20378 20379 /* do some sanity checks */ 20380 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 20381 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX 20382 | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07; 20383 20384 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 20385 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP 20386 | VEX_HWCAPS_PPC64_ISA2_07; 20387 20388 if (mode64) { 20389 vassert((hwcaps_guest & mask32) == 0); 20390 } else { 20391 vassert((hwcaps_guest & mask64) == 0); 20392 } 20393 20394 /* Set globals (see top of this file) */ 20395 guest_code = guest_code_IN; 20396 irsb = irsb_IN; 20397 host_endness = host_endness_IN; 20398 20399 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 20400 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 20401 20402 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque, 20403 delta, archinfo, abiinfo, sigill_diag_IN); 20404 20405 return dres; 20406 } 20407 20408 20409 /*------------------------------------------------------------*/ 20410 /*--- Unused stuff ---*/ 20411 /*------------------------------------------------------------*/ 20412 20413 ///* A potentially more memcheck-friendly implementation of Clz32, with 20414 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 20415 // 20416 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 20417 //{ 20418 // /* Welcome ... to SSA R Us. */ 20419 // IRTemp n1 = newTemp(Ity_I32); 20420 // IRTemp n2 = newTemp(Ity_I32); 20421 // IRTemp n3 = newTemp(Ity_I32); 20422 // IRTemp n4 = newTemp(Ity_I32); 20423 // IRTemp n5 = newTemp(Ity_I32); 20424 // IRTemp n6 = newTemp(Ity_I32); 20425 // IRTemp n7 = newTemp(Ity_I32); 20426 // IRTemp n8 = newTemp(Ity_I32); 20427 // IRTemp n9 = newTemp(Ity_I32); 20428 // IRTemp n10 = newTemp(Ity_I32); 20429 // IRTemp n11 = newTemp(Ity_I32); 20430 // IRTemp n12 = newTemp(Ity_I32); 20431 // 20432 // /* First, propagate the most significant 1-bit into all lower 20433 // positions in the word. */ 20434 // /* unsigned int clz ( unsigned int n ) 20435 // { 20436 // n |= (n >> 1); 20437 // n |= (n >> 2); 20438 // n |= (n >> 4); 20439 // n |= (n >> 8); 20440 // n |= (n >> 16); 20441 // return bitcount(~n); 20442 // } 20443 // */ 20444 // assign(n1, mkexpr(arg)); 20445 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 20446 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 20447 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 20448 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 20449 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 20450 // /* This gives a word of the form 0---01---1. Now invert it, giving 20451 // a word of the form 1---10---0, then do a population-count idiom 20452 // (to count the 1s, which is the number of leading zeroes, or 32 20453 // if the original word was 0. */ 20454 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 20455 // 20456 // /* unsigned int bitcount ( unsigned int n ) 20457 // { 20458 // n = n - ((n >> 1) & 0x55555555); 20459 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 20460 // n = (n + (n >> 4)) & 0x0F0F0F0F; 20461 // n = n + (n >> 8); 20462 // n = (n + (n >> 16)) & 0x3F; 20463 // return n; 20464 // } 20465 // */ 20466 // assign(n8, 20467 // binop(Iop_Sub32, 20468 // mkexpr(n7), 20469 // binop(Iop_And32, 20470 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 20471 // mkU32(0x55555555)))); 20472 // assign(n9, 20473 // binop(Iop_Add32, 20474 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 20475 // binop(Iop_And32, 20476 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 20477 // mkU32(0x33333333)))); 20478 // assign(n10, 20479 // binop(Iop_And32, 20480 // binop(Iop_Add32, 20481 // mkexpr(n9), 20482 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 20483 // mkU32(0x0F0F0F0F))); 20484 // assign(n11, 20485 // binop(Iop_Add32, 20486 // mkexpr(n10), 20487 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 20488 // assign(n12, 20489 // binop(Iop_Add32, 20490 // mkexpr(n11), 20491 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 20492 // return 20493 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 20494 //} 20495 20496 /*--------------------------------------------------------------------*/ 20497 /*--- end guest_ppc_toIR.c ---*/ 20498 /*--------------------------------------------------------------------*/ 20499