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-2015 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 #define OFFB_PPR offsetofPPCGuestState(guest_PPR) 292 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB) 293 294 295 /*------------------------------------------------------------*/ 296 /*--- Extract instruction fields --- */ 297 /*------------------------------------------------------------*/ 298 299 /* Extract field from insn, given idx (zero = lsb) and field length */ 300 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 301 302 /* Extract primary opcode, instr[31:26] */ 303 static UChar ifieldOPC( UInt instr ) { 304 return toUChar( IFIELD( instr, 26, 6 ) ); 305 } 306 307 /* Extract 10-bit secondary opcode, instr[10:1] */ 308 static UInt ifieldOPClo10 ( UInt instr) { 309 return IFIELD( instr, 1, 10 ); 310 } 311 312 /* Extract 9-bit secondary opcode, instr[9:1] */ 313 static UInt ifieldOPClo9 ( UInt instr) { 314 return IFIELD( instr, 1, 9 ); 315 } 316 317 /* Extract 8-bit secondary opcode, instr[8:1] */ 318 static UInt ifieldOPClo8 ( UInt instr) { 319 return IFIELD( instr, 1, 8 ); 320 } 321 322 /* Extract 5-bit secondary opcode, instr[5:1] */ 323 static UInt ifieldOPClo5 ( UInt instr) { 324 return IFIELD( instr, 1, 5 ); 325 } 326 327 /* Extract RD (destination register) field, instr[25:21] */ 328 static UChar ifieldRegDS( UInt instr ) { 329 return toUChar( IFIELD( instr, 21, 5 ) ); 330 } 331 332 /* Extract XT (destination register) field, instr[0,25:21] */ 333 static UChar ifieldRegXT ( UInt instr ) 334 { 335 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 336 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 337 return (upper_bit << 5) | lower_bits; 338 } 339 340 /* Extract XS (store source register) field, instr[0,25:21] */ 341 static inline UChar ifieldRegXS ( UInt instr ) 342 { 343 return ifieldRegXT ( instr ); 344 } 345 346 /* Extract RA (1st source register) field, instr[20:16] */ 347 static UChar ifieldRegA ( UInt instr ) { 348 return toUChar( IFIELD( instr, 16, 5 ) ); 349 } 350 351 /* Extract XA (1st source register) field, instr[2,20:16] */ 352 static UChar ifieldRegXA ( UInt instr ) 353 { 354 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 355 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 356 return (upper_bit << 5) | lower_bits; 357 } 358 359 /* Extract RB (2nd source register) field, instr[15:11] */ 360 static UChar ifieldRegB ( UInt instr ) { 361 return toUChar( IFIELD( instr, 11, 5 ) ); 362 } 363 364 /* Extract XB (2nd source register) field, instr[1,15:11] */ 365 static UChar ifieldRegXB ( UInt instr ) 366 { 367 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 368 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 369 return (upper_bit << 5) | lower_bits; 370 } 371 372 /* Extract RC (3rd source register) field, instr[10:6] */ 373 static UChar ifieldRegC ( UInt instr ) { 374 return toUChar( IFIELD( instr, 6, 5 ) ); 375 } 376 377 /* Extract XC (3rd source register) field, instr[3,10:6] */ 378 static UChar ifieldRegXC ( UInt instr ) 379 { 380 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 381 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 382 return (upper_bit << 5) | lower_bits; 383 } 384 385 /* Extract bit 10, instr[10] */ 386 static UChar ifieldBIT10 ( UInt instr ) { 387 return toUChar( IFIELD( instr, 10, 1 ) ); 388 } 389 390 /* Extract 2nd lowest bit, instr[1] */ 391 static UChar ifieldBIT1 ( UInt instr ) { 392 return toUChar( IFIELD( instr, 1, 1 ) ); 393 } 394 395 /* Extract lowest bit, instr[0] */ 396 static UChar ifieldBIT0 ( UInt instr ) { 397 return toUChar( instr & 0x1 ); 398 } 399 400 /* Extract unsigned bottom half, instr[15:0] */ 401 static UInt ifieldUIMM16 ( UInt instr ) { 402 return instr & 0xFFFF; 403 } 404 405 /* Extract unsigned bottom 26 bits, instr[25:0] */ 406 static UInt ifieldUIMM26 ( UInt instr ) { 407 return instr & 0x3FFFFFF; 408 } 409 410 /* Extract DM field, instr[9:8] */ 411 static UChar ifieldDM ( UInt instr ) { 412 return toUChar( IFIELD( instr, 8, 2 ) ); 413 } 414 415 /* Extract SHW field, instr[9:8] */ 416 static inline UChar ifieldSHW ( UInt instr ) 417 { 418 return ifieldDM ( instr ); 419 } 420 421 /*------------------------------------------------------------*/ 422 /*--- Guest-state identifiers ---*/ 423 /*------------------------------------------------------------*/ 424 425 typedef enum { 426 PPC_GST_CIA, // Current Instruction Address 427 PPC_GST_LR, // Link Register 428 PPC_GST_CTR, // Count Register 429 PPC_GST_XER, // Overflow, carry flags, byte count 430 PPC_GST_CR, // Condition Register 431 PPC_GST_FPSCR, // Floating Point Status/Control Register 432 PPC_GST_VRSAVE, // Vector Save/Restore Register 433 PPC_GST_VSCR, // Vector Status and Control Register 434 PPC_GST_EMWARN, // Emulation warnings 435 PPC_GST_CMSTART,// For icbi: start of area to invalidate 436 PPC_GST_CMLEN, // For icbi: length of area to invalidate 437 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 438 PPC_GST_SPRG3_RO, // SPRG3 439 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 440 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 441 PPC_GST_TEXASR, // Transactional EXception And Summary Register 442 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 443 PPC_GST_PPR, // Program Priority register 444 PPC_GST_PPR32, // Upper 32-bits of Program Priority register 445 PPC_GST_PSPB, /* Problem State Priority Boost register, Note, the 446 * register is initialized to a non-zero value. Currently 447 * Valgrind is not supporting the register value to 448 * automatically decrement. Could be added later if 449 * needed. 450 */ 451 PPC_GST_MAX 452 } PPC_GST; 453 454 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 455 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 456 #define MASK_VSCR_VALID 0x00010001 457 458 459 /*------------------------------------------------------------*/ 460 /*--- FP Helpers ---*/ 461 /*------------------------------------------------------------*/ 462 463 /* Produce the 32-bit pattern corresponding to the supplied 464 float. */ 465 static UInt float_to_bits ( Float f ) 466 { 467 union { UInt i; Float f; } u; 468 vassert(4 == sizeof(UInt)); 469 vassert(4 == sizeof(Float)); 470 vassert(4 == sizeof(u)); 471 u.f = f; 472 return u.i; 473 } 474 475 476 /*------------------------------------------------------------*/ 477 /*--- Misc Helpers ---*/ 478 /*------------------------------------------------------------*/ 479 480 /* Generate mask with 1's from 'begin' through 'end', 481 wrapping if begin > end. 482 begin->end works from right to left, 0=lsb 483 */ 484 static UInt MASK32( UInt begin, UInt end ) 485 { 486 UInt m1, m2, mask; 487 vassert(begin < 32); 488 vassert(end < 32); 489 m1 = ((UInt)(-1)) << begin; 490 m2 = ((UInt)(-1)) << end << 1; 491 mask = m1 ^ m2; 492 if (begin > end) mask = ~mask; // wrap mask 493 return mask; 494 } 495 496 static ULong MASK64( UInt begin, UInt end ) 497 { 498 ULong m1, m2, mask; 499 vassert(begin < 64); 500 vassert(end < 64); 501 m1 = ((ULong)(-1)) << begin; 502 m2 = ((ULong)(-1)) << end << 1; 503 mask = m1 ^ m2; 504 if (begin > end) mask = ~mask; // wrap mask 505 return mask; 506 } 507 508 static Addr64 nextInsnAddr( void ) 509 { 510 return guest_CIA_curr_instr + 4; 511 } 512 513 514 /*------------------------------------------------------------*/ 515 /*--- Helper bits and pieces for deconstructing the ---*/ 516 /*--- ppc32/64 insn stream. ---*/ 517 /*------------------------------------------------------------*/ 518 519 /* Add a statement to the list held by "irsb". */ 520 static void stmt ( IRStmt* st ) 521 { 522 addStmtToIRSB( irsb, st ); 523 } 524 525 /* Generate a new temporary of the given type. */ 526 static IRTemp newTemp ( IRType ty ) 527 { 528 vassert(isPlausibleIRType(ty)); 529 return newIRTemp( irsb->tyenv, ty ); 530 } 531 532 /* Various simple conversions */ 533 534 static UChar extend_s_5to8 ( UChar x ) 535 { 536 return toUChar((((Int)x) << 27) >> 27); 537 } 538 539 static UInt extend_s_8to32( UChar x ) 540 { 541 return (UInt)((((Int)x) << 24) >> 24); 542 } 543 544 static UInt extend_s_16to32 ( UInt x ) 545 { 546 return (UInt)((((Int)x) << 16) >> 16); 547 } 548 549 static ULong extend_s_16to64 ( UInt x ) 550 { 551 return (ULong)((((Long)x) << 48) >> 48); 552 } 553 554 static ULong extend_s_26to64 ( UInt x ) 555 { 556 return (ULong)((((Long)x) << 38) >> 38); 557 } 558 559 static ULong extend_s_32to64 ( UInt x ) 560 { 561 return (ULong)((((Long)x) << 32) >> 32); 562 } 563 564 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 565 of the underlying host. */ 566 static UInt getUIntPPCendianly ( const UChar* p ) 567 { 568 UInt w = 0; 569 if (host_endness == VexEndnessBE) { 570 w = (w << 8) | p[0]; 571 w = (w << 8) | p[1]; 572 w = (w << 8) | p[2]; 573 w = (w << 8) | p[3]; 574 } else { 575 w = (w << 8) | p[3]; 576 w = (w << 8) | p[2]; 577 w = (w << 8) | p[1]; 578 w = (w << 8) | p[0]; 579 } 580 return w; 581 } 582 583 584 /*------------------------------------------------------------*/ 585 /*--- Helpers for constructing IR. ---*/ 586 /*------------------------------------------------------------*/ 587 588 static void assign ( IRTemp dst, IRExpr* e ) 589 { 590 stmt( IRStmt_WrTmp(dst, e) ); 591 } 592 593 /* This generates a normal (non store-conditional) store. */ 594 static void store ( IRExpr* addr, IRExpr* data ) 595 { 596 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 597 vassert(tyA == Ity_I32 || tyA == Ity_I64); 598 599 if (host_endness == VexEndnessBE) 600 stmt( IRStmt_Store(Iend_BE, addr, data) ); 601 else 602 stmt( IRStmt_Store(Iend_LE, addr, data) ); 603 } 604 605 static IRExpr* unop ( IROp op, IRExpr* a ) 606 { 607 return IRExpr_Unop(op, a); 608 } 609 610 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 611 { 612 return IRExpr_Binop(op, a1, a2); 613 } 614 615 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 616 { 617 return IRExpr_Triop(op, a1, a2, a3); 618 } 619 620 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 621 IRExpr* a3, IRExpr* a4 ) 622 { 623 return IRExpr_Qop(op, a1, a2, a3, a4); 624 } 625 626 static IRExpr* mkexpr ( IRTemp tmp ) 627 { 628 return IRExpr_RdTmp(tmp); 629 } 630 631 static IRExpr* mkU8 ( UChar i ) 632 { 633 return IRExpr_Const(IRConst_U8(i)); 634 } 635 636 static IRExpr* mkU16 ( UInt i ) 637 { 638 return IRExpr_Const(IRConst_U16(i)); 639 } 640 641 static IRExpr* mkU32 ( UInt i ) 642 { 643 return IRExpr_Const(IRConst_U32(i)); 644 } 645 646 static IRExpr* mkU64 ( ULong i ) 647 { 648 return IRExpr_Const(IRConst_U64(i)); 649 } 650 651 static IRExpr* mkV128 ( UShort i ) 652 { 653 vassert(i == 0 || i == 0xffff); 654 return IRExpr_Const(IRConst_V128(i)); 655 } 656 657 /* This generates a normal (non load-linked) load. */ 658 static IRExpr* load ( IRType ty, IRExpr* addr ) 659 { 660 if (host_endness == VexEndnessBE) 661 return IRExpr_Load(Iend_BE, ty, addr); 662 else 663 return IRExpr_Load(Iend_LE, ty, addr); 664 } 665 666 static IRStmt* stmt_load ( IRTemp result, 667 IRExpr* addr, IRExpr* storedata ) 668 { 669 if (host_endness == VexEndnessBE) 670 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 671 else 672 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 673 } 674 675 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 676 { 677 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 678 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 679 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 680 unop(Iop_1Uto32, arg2))); 681 } 682 683 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 684 { 685 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 686 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 687 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 688 unop(Iop_1Uto32, arg2))); 689 } 690 691 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 692 static void expand8Ux16( IRExpr* vIn, 693 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 694 { 695 IRTemp ones8x16 = newTemp(Ity_V128); 696 697 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 698 vassert(vEvn && *vEvn == IRTemp_INVALID); 699 vassert(vOdd && *vOdd == IRTemp_INVALID); 700 *vEvn = newTemp(Ity_V128); 701 *vOdd = newTemp(Ity_V128); 702 703 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 704 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 705 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 706 binop(Iop_ShrV128, vIn, mkU8(8))) ); 707 } 708 709 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 710 static void expand8Sx16( IRExpr* vIn, 711 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 712 { 713 IRTemp ones8x16 = newTemp(Ity_V128); 714 715 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 716 vassert(vEvn && *vEvn == IRTemp_INVALID); 717 vassert(vOdd && *vOdd == IRTemp_INVALID); 718 *vEvn = newTemp(Ity_V128); 719 *vOdd = newTemp(Ity_V128); 720 721 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 722 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 723 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 724 binop(Iop_ShrV128, vIn, mkU8(8))) ); 725 } 726 727 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 728 static void expand16Ux8( IRExpr* vIn, 729 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 730 { 731 IRTemp ones16x8 = newTemp(Ity_V128); 732 733 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 734 vassert(vEvn && *vEvn == IRTemp_INVALID); 735 vassert(vOdd && *vOdd == IRTemp_INVALID); 736 *vEvn = newTemp(Ity_V128); 737 *vOdd = newTemp(Ity_V128); 738 739 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 740 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 741 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 742 binop(Iop_ShrV128, vIn, mkU8(16))) ); 743 } 744 745 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 746 static void expand16Sx8( IRExpr* vIn, 747 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 748 { 749 IRTemp ones16x8 = newTemp(Ity_V128); 750 751 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 752 vassert(vEvn && *vEvn == IRTemp_INVALID); 753 vassert(vOdd && *vOdd == IRTemp_INVALID); 754 *vEvn = newTemp(Ity_V128); 755 *vOdd = newTemp(Ity_V128); 756 757 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 758 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 759 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 760 binop(Iop_ShrV128, vIn, mkU8(16))) ); 761 } 762 763 /* break V128 to 4xF64's*/ 764 static void breakV128to4xF64( IRExpr* t128, 765 /*OUTs*/ 766 IRTemp* t3, IRTemp* t2, 767 IRTemp* t1, IRTemp* t0 ) 768 { 769 IRTemp hi64 = newTemp(Ity_I64); 770 IRTemp lo64 = newTemp(Ity_I64); 771 772 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 773 vassert(t0 && *t0 == IRTemp_INVALID); 774 vassert(t1 && *t1 == IRTemp_INVALID); 775 vassert(t2 && *t2 == IRTemp_INVALID); 776 vassert(t3 && *t3 == IRTemp_INVALID); 777 *t0 = newTemp(Ity_F64); 778 *t1 = newTemp(Ity_F64); 779 *t2 = newTemp(Ity_F64); 780 *t3 = newTemp(Ity_F64); 781 782 assign( hi64, unop(Iop_V128HIto64, t128) ); 783 assign( lo64, unop(Iop_V128to64, t128) ); 784 assign( *t3, 785 unop( Iop_F32toF64, 786 unop( Iop_ReinterpI32asF32, 787 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 788 assign( *t2, 789 unop( Iop_F32toF64, 790 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 791 assign( *t1, 792 unop( Iop_F32toF64, 793 unop( Iop_ReinterpI32asF32, 794 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 795 assign( *t0, 796 unop( Iop_F32toF64, 797 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 798 } 799 800 801 /* break V128 to 4xI32's, then sign-extend to I64's */ 802 static void breakV128to4x64S( IRExpr* t128, 803 /*OUTs*/ 804 IRTemp* t3, IRTemp* t2, 805 IRTemp* t1, IRTemp* t0 ) 806 { 807 IRTemp hi64 = newTemp(Ity_I64); 808 IRTemp lo64 = newTemp(Ity_I64); 809 810 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 811 vassert(t0 && *t0 == IRTemp_INVALID); 812 vassert(t1 && *t1 == IRTemp_INVALID); 813 vassert(t2 && *t2 == IRTemp_INVALID); 814 vassert(t3 && *t3 == IRTemp_INVALID); 815 *t0 = newTemp(Ity_I64); 816 *t1 = newTemp(Ity_I64); 817 *t2 = newTemp(Ity_I64); 818 *t3 = newTemp(Ity_I64); 819 820 assign( hi64, unop(Iop_V128HIto64, t128) ); 821 assign( lo64, unop(Iop_V128to64, t128) ); 822 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 823 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 824 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 825 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 826 } 827 828 /* break V128 to 4xI32's, then zero-extend to I64's */ 829 static void breakV128to4x64U ( IRExpr* t128, 830 /*OUTs*/ 831 IRTemp* t3, IRTemp* t2, 832 IRTemp* t1, IRTemp* t0 ) 833 { 834 IRTemp hi64 = newTemp(Ity_I64); 835 IRTemp lo64 = newTemp(Ity_I64); 836 837 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 838 vassert(t0 && *t0 == IRTemp_INVALID); 839 vassert(t1 && *t1 == IRTemp_INVALID); 840 vassert(t2 && *t2 == IRTemp_INVALID); 841 vassert(t3 && *t3 == IRTemp_INVALID); 842 *t0 = newTemp(Ity_I64); 843 *t1 = newTemp(Ity_I64); 844 *t2 = newTemp(Ity_I64); 845 *t3 = newTemp(Ity_I64); 846 847 assign( hi64, unop(Iop_V128HIto64, t128) ); 848 assign( lo64, unop(Iop_V128to64, t128) ); 849 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 850 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 851 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 852 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 853 } 854 855 static void breakV128to4x32( IRExpr* t128, 856 /*OUTs*/ 857 IRTemp* t3, IRTemp* t2, 858 IRTemp* t1, IRTemp* t0 ) 859 { 860 IRTemp hi64 = newTemp(Ity_I64); 861 IRTemp lo64 = newTemp(Ity_I64); 862 863 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 864 vassert(t0 && *t0 == IRTemp_INVALID); 865 vassert(t1 && *t1 == IRTemp_INVALID); 866 vassert(t2 && *t2 == IRTemp_INVALID); 867 vassert(t3 && *t3 == IRTemp_INVALID); 868 *t0 = newTemp(Ity_I32); 869 *t1 = newTemp(Ity_I32); 870 *t2 = newTemp(Ity_I32); 871 *t3 = newTemp(Ity_I32); 872 873 assign( hi64, unop(Iop_V128HIto64, t128) ); 874 assign( lo64, unop(Iop_V128to64, t128) ); 875 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 876 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 877 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 878 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 879 } 880 881 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 882 IRTemp t1, IRTemp t0 ) 883 { 884 return 885 binop( Iop_64HLtoV128, 886 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 887 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 888 ); 889 } 890 891 892 /* Signed saturating narrow 64S to 32 */ 893 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 894 { 895 IRTemp hi32 = newTemp(Ity_I32); 896 IRTemp lo32 = newTemp(Ity_I32); 897 898 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 899 900 assign( hi32, unop(Iop_64HIto32, t64)); 901 assign( lo32, unop(Iop_64to32, t64)); 902 903 return IRExpr_ITE( 904 /* if (hi32 == (lo32 >>s 31)) */ 905 binop(Iop_CmpEQ32, mkexpr(hi32), 906 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 907 /* then: within signed-32 range: lo half good enough */ 908 mkexpr(lo32), 909 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 910 binop(Iop_Add32, mkU32(0x7FFFFFFF), 911 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 912 } 913 914 /* Unsigned saturating narrow 64S to 32 */ 915 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 916 { 917 IRTemp hi32 = newTemp(Ity_I32); 918 IRTemp lo32 = newTemp(Ity_I32); 919 920 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 921 922 assign( hi32, unop(Iop_64HIto32, t64)); 923 assign( lo32, unop(Iop_64to32, t64)); 924 925 return IRExpr_ITE( 926 /* if (top 32 bits of t64 are 0) */ 927 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 928 /* then: within unsigned-32 range: lo half good enough */ 929 mkexpr(lo32), 930 /* else: positive saturate -> 0xFFFFFFFF */ 931 mkU32(0xFFFFFFFF)); 932 } 933 934 /* Signed saturate narrow 64->32, combining to V128 */ 935 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 936 IRExpr* t1, IRExpr* t0 ) 937 { 938 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 939 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 940 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 941 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 942 return binop(Iop_64HLtoV128, 943 binop(Iop_32HLto64, 944 mkQNarrow64Sto32( t3 ), 945 mkQNarrow64Sto32( t2 )), 946 binop(Iop_32HLto64, 947 mkQNarrow64Sto32( t1 ), 948 mkQNarrow64Sto32( t0 ))); 949 } 950 951 /* Unsigned saturate narrow 64->32, combining to V128 */ 952 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 953 IRExpr* t1, IRExpr* t0 ) 954 { 955 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 956 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 957 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 958 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 959 return binop(Iop_64HLtoV128, 960 binop(Iop_32HLto64, 961 mkQNarrow64Uto32( t3 ), 962 mkQNarrow64Uto32( t2 )), 963 binop(Iop_32HLto64, 964 mkQNarrow64Uto32( t1 ), 965 mkQNarrow64Uto32( t0 ))); 966 } 967 968 /* Simulate irops Iop_MullOdd*, since we don't have them */ 969 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 970 binop(Iop_MullEven8Ux16, \ 971 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 972 binop(Iop_ShrV128, expr_vB, mkU8(8))) 973 974 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 975 binop(Iop_MullEven8Sx16, \ 976 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 977 binop(Iop_ShrV128, expr_vB, mkU8(8))) 978 979 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 980 binop(Iop_MullEven16Ux8, \ 981 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 982 binop(Iop_ShrV128, expr_vB, mkU8(16))) 983 984 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 985 binop(Iop_MullEven32Ux4, \ 986 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 987 binop(Iop_ShrV128, expr_vB, mkU8(32))) 988 989 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 990 binop(Iop_MullEven16Sx8, \ 991 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 992 binop(Iop_ShrV128, expr_vB, mkU8(16))) 993 994 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 995 binop(Iop_MullEven32Sx4, \ 996 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 997 binop(Iop_ShrV128, expr_vB, mkU8(32))) 998 999 1000 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 1001 { 1002 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1003 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 1004 } 1005 1006 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 1007 { 1008 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1009 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1010 } 1011 1012 static IROp mkSzOp ( IRType ty, IROp op8 ) 1013 { 1014 Int adj; 1015 vassert(ty == Ity_I8 || ty == Ity_I16 || 1016 ty == Ity_I32 || ty == Ity_I64); 1017 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1018 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1019 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1020 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1021 op8 == Iop_Not8 ); 1022 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1023 return adj + op8; 1024 } 1025 1026 /* Make sure we get valid 32 and 64bit addresses */ 1027 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1028 { 1029 vassert(ty == Ity_I32 || ty == Ity_I64); 1030 return ( ty == Ity_I64 ? 1031 (Addr64)addr : 1032 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1033 } 1034 1035 /* sz, ULong -> IRExpr */ 1036 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1037 { 1038 vassert(ty == Ity_I32 || ty == Ity_I64); 1039 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1040 } 1041 1042 /* sz, ULong -> IRConst */ 1043 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1044 { 1045 vassert(ty == Ity_I32 || ty == Ity_I64); 1046 return ( ty == Ity_I64 ? 1047 IRConst_U64(imm64) : 1048 IRConst_U32((UInt)imm64) ); 1049 } 1050 1051 /* Sign extend imm16 -> IRExpr* */ 1052 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1053 { 1054 vassert(ty == Ity_I32 || ty == Ity_I64); 1055 return ( ty == Ity_I64 ? 1056 mkU64(extend_s_16to64(imm16)) : 1057 mkU32(extend_s_16to32(imm16)) ); 1058 } 1059 1060 /* Sign extend imm32 -> IRExpr* */ 1061 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1062 { 1063 vassert(ty == Ity_I32 || ty == Ity_I64); 1064 return ( ty == Ity_I64 ? 1065 mkU64(extend_s_32to64(imm32)) : 1066 mkU32(imm32) ); 1067 } 1068 1069 /* IR narrows I32/I64 -> I8/I16/I32 */ 1070 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1071 { 1072 vassert(ty == Ity_I32 || ty == Ity_I64); 1073 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1074 } 1075 1076 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1077 { 1078 vassert(ty == Ity_I32 || ty == Ity_I64); 1079 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1080 } 1081 1082 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1083 { 1084 vassert(ty == Ity_I32 || ty == Ity_I64); 1085 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1086 } 1087 1088 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1089 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1090 { 1091 IROp op; 1092 vassert(ty == Ity_I32 || ty == Ity_I64); 1093 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1094 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1095 return unop(op, src); 1096 } 1097 1098 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1099 { 1100 IROp op; 1101 vassert(ty == Ity_I32 || ty == Ity_I64); 1102 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1103 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1104 return unop(op, src); 1105 } 1106 1107 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1108 { 1109 vassert(ty == Ity_I32 || ty == Ity_I64); 1110 if (ty == Ity_I32) 1111 return src; 1112 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1113 } 1114 1115 1116 static Int integerGuestRegOffset ( UInt archreg ) 1117 { 1118 vassert(archreg < 32); 1119 1120 // jrs: probably not necessary; only matters if we reference sub-parts 1121 // of the ppc registers, but that isn't the case 1122 // later: this might affect Altivec though? 1123 1124 switch (archreg) { 1125 case 0: return offsetofPPCGuestState(guest_GPR0); 1126 case 1: return offsetofPPCGuestState(guest_GPR1); 1127 case 2: return offsetofPPCGuestState(guest_GPR2); 1128 case 3: return offsetofPPCGuestState(guest_GPR3); 1129 case 4: return offsetofPPCGuestState(guest_GPR4); 1130 case 5: return offsetofPPCGuestState(guest_GPR5); 1131 case 6: return offsetofPPCGuestState(guest_GPR6); 1132 case 7: return offsetofPPCGuestState(guest_GPR7); 1133 case 8: return offsetofPPCGuestState(guest_GPR8); 1134 case 9: return offsetofPPCGuestState(guest_GPR9); 1135 case 10: return offsetofPPCGuestState(guest_GPR10); 1136 case 11: return offsetofPPCGuestState(guest_GPR11); 1137 case 12: return offsetofPPCGuestState(guest_GPR12); 1138 case 13: return offsetofPPCGuestState(guest_GPR13); 1139 case 14: return offsetofPPCGuestState(guest_GPR14); 1140 case 15: return offsetofPPCGuestState(guest_GPR15); 1141 case 16: return offsetofPPCGuestState(guest_GPR16); 1142 case 17: return offsetofPPCGuestState(guest_GPR17); 1143 case 18: return offsetofPPCGuestState(guest_GPR18); 1144 case 19: return offsetofPPCGuestState(guest_GPR19); 1145 case 20: return offsetofPPCGuestState(guest_GPR20); 1146 case 21: return offsetofPPCGuestState(guest_GPR21); 1147 case 22: return offsetofPPCGuestState(guest_GPR22); 1148 case 23: return offsetofPPCGuestState(guest_GPR23); 1149 case 24: return offsetofPPCGuestState(guest_GPR24); 1150 case 25: return offsetofPPCGuestState(guest_GPR25); 1151 case 26: return offsetofPPCGuestState(guest_GPR26); 1152 case 27: return offsetofPPCGuestState(guest_GPR27); 1153 case 28: return offsetofPPCGuestState(guest_GPR28); 1154 case 29: return offsetofPPCGuestState(guest_GPR29); 1155 case 30: return offsetofPPCGuestState(guest_GPR30); 1156 case 31: return offsetofPPCGuestState(guest_GPR31); 1157 default: break; 1158 } 1159 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1160 } 1161 1162 static IRExpr* getIReg ( UInt archreg ) 1163 { 1164 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1165 vassert(archreg < 32); 1166 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1167 } 1168 1169 /* Ditto, but write to a reg instead. */ 1170 static void putIReg ( UInt archreg, IRExpr* e ) 1171 { 1172 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1173 vassert(archreg < 32); 1174 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1175 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1176 } 1177 1178 1179 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1180 static Int floatGuestRegOffset ( UInt archreg ) 1181 { 1182 vassert(archreg < 32); 1183 1184 if (host_endness == VexEndnessLE) { 1185 switch (archreg) { 1186 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1187 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1188 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1189 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1190 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1191 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1192 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1193 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1194 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1195 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1196 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1197 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1198 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1199 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1200 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1201 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1202 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1203 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1204 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1205 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1206 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1207 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1208 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1209 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1210 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1211 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1212 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1213 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1214 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1215 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1216 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1217 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1218 default: break; 1219 } 1220 } else { 1221 switch (archreg) { 1222 case 0: return offsetofPPCGuestState(guest_VSR0); 1223 case 1: return offsetofPPCGuestState(guest_VSR1); 1224 case 2: return offsetofPPCGuestState(guest_VSR2); 1225 case 3: return offsetofPPCGuestState(guest_VSR3); 1226 case 4: return offsetofPPCGuestState(guest_VSR4); 1227 case 5: return offsetofPPCGuestState(guest_VSR5); 1228 case 6: return offsetofPPCGuestState(guest_VSR6); 1229 case 7: return offsetofPPCGuestState(guest_VSR7); 1230 case 8: return offsetofPPCGuestState(guest_VSR8); 1231 case 9: return offsetofPPCGuestState(guest_VSR9); 1232 case 10: return offsetofPPCGuestState(guest_VSR10); 1233 case 11: return offsetofPPCGuestState(guest_VSR11); 1234 case 12: return offsetofPPCGuestState(guest_VSR12); 1235 case 13: return offsetofPPCGuestState(guest_VSR13); 1236 case 14: return offsetofPPCGuestState(guest_VSR14); 1237 case 15: return offsetofPPCGuestState(guest_VSR15); 1238 case 16: return offsetofPPCGuestState(guest_VSR16); 1239 case 17: return offsetofPPCGuestState(guest_VSR17); 1240 case 18: return offsetofPPCGuestState(guest_VSR18); 1241 case 19: return offsetofPPCGuestState(guest_VSR19); 1242 case 20: return offsetofPPCGuestState(guest_VSR20); 1243 case 21: return offsetofPPCGuestState(guest_VSR21); 1244 case 22: return offsetofPPCGuestState(guest_VSR22); 1245 case 23: return offsetofPPCGuestState(guest_VSR23); 1246 case 24: return offsetofPPCGuestState(guest_VSR24); 1247 case 25: return offsetofPPCGuestState(guest_VSR25); 1248 case 26: return offsetofPPCGuestState(guest_VSR26); 1249 case 27: return offsetofPPCGuestState(guest_VSR27); 1250 case 28: return offsetofPPCGuestState(guest_VSR28); 1251 case 29: return offsetofPPCGuestState(guest_VSR29); 1252 case 30: return offsetofPPCGuestState(guest_VSR30); 1253 case 31: return offsetofPPCGuestState(guest_VSR31); 1254 default: break; 1255 } 1256 } 1257 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1258 } 1259 1260 static IRExpr* getFReg ( UInt archreg ) 1261 { 1262 vassert(archreg < 32); 1263 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1264 } 1265 1266 /* Ditto, but write to a reg instead. */ 1267 static void putFReg ( UInt archreg, IRExpr* e ) 1268 { 1269 vassert(archreg < 32); 1270 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1271 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1272 } 1273 1274 /* get Decimal float value. Note, they share floating point register file. */ 1275 static IRExpr* getDReg(UInt archreg) { 1276 IRExpr *e; 1277 vassert( archreg < 32 ); 1278 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1279 return e; 1280 } 1281 static IRExpr* getDReg32(UInt archreg) { 1282 IRExpr *e; 1283 vassert( archreg < 32 ); 1284 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1285 return e; 1286 } 1287 1288 /* Read a floating point register pair and combine their contents into a 1289 128-bit value */ 1290 static IRExpr *getDReg_pair(UInt archreg) { 1291 IRExpr *high = getDReg( archreg ); 1292 IRExpr *low = getDReg( archreg + 1 ); 1293 1294 return binop( Iop_D64HLtoD128, high, low ); 1295 } 1296 1297 /* Ditto, but write to a reg instead. */ 1298 static void putDReg32(UInt archreg, IRExpr* e) { 1299 vassert( archreg < 32 ); 1300 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1301 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1302 } 1303 1304 static void putDReg(UInt archreg, IRExpr* e) { 1305 vassert( archreg < 32 ); 1306 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1307 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1308 } 1309 1310 /* Write a 128-bit floating point value into a register pair. */ 1311 static void putDReg_pair(UInt archreg, IRExpr *e) { 1312 IRTemp low = newTemp( Ity_D64 ); 1313 IRTemp high = newTemp( Ity_D64 ); 1314 1315 vassert( archreg < 32 ); 1316 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1317 1318 assign( low, unop( Iop_D128LOtoD64, e ) ); 1319 assign( high, unop( Iop_D128HItoD64, e ) ); 1320 1321 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1322 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1323 } 1324 1325 static Int vsxGuestRegOffset ( UInt archreg ) 1326 { 1327 vassert(archreg < 64); 1328 switch (archreg) { 1329 case 0: return offsetofPPCGuestState(guest_VSR0); 1330 case 1: return offsetofPPCGuestState(guest_VSR1); 1331 case 2: return offsetofPPCGuestState(guest_VSR2); 1332 case 3: return offsetofPPCGuestState(guest_VSR3); 1333 case 4: return offsetofPPCGuestState(guest_VSR4); 1334 case 5: return offsetofPPCGuestState(guest_VSR5); 1335 case 6: return offsetofPPCGuestState(guest_VSR6); 1336 case 7: return offsetofPPCGuestState(guest_VSR7); 1337 case 8: return offsetofPPCGuestState(guest_VSR8); 1338 case 9: return offsetofPPCGuestState(guest_VSR9); 1339 case 10: return offsetofPPCGuestState(guest_VSR10); 1340 case 11: return offsetofPPCGuestState(guest_VSR11); 1341 case 12: return offsetofPPCGuestState(guest_VSR12); 1342 case 13: return offsetofPPCGuestState(guest_VSR13); 1343 case 14: return offsetofPPCGuestState(guest_VSR14); 1344 case 15: return offsetofPPCGuestState(guest_VSR15); 1345 case 16: return offsetofPPCGuestState(guest_VSR16); 1346 case 17: return offsetofPPCGuestState(guest_VSR17); 1347 case 18: return offsetofPPCGuestState(guest_VSR18); 1348 case 19: return offsetofPPCGuestState(guest_VSR19); 1349 case 20: return offsetofPPCGuestState(guest_VSR20); 1350 case 21: return offsetofPPCGuestState(guest_VSR21); 1351 case 22: return offsetofPPCGuestState(guest_VSR22); 1352 case 23: return offsetofPPCGuestState(guest_VSR23); 1353 case 24: return offsetofPPCGuestState(guest_VSR24); 1354 case 25: return offsetofPPCGuestState(guest_VSR25); 1355 case 26: return offsetofPPCGuestState(guest_VSR26); 1356 case 27: return offsetofPPCGuestState(guest_VSR27); 1357 case 28: return offsetofPPCGuestState(guest_VSR28); 1358 case 29: return offsetofPPCGuestState(guest_VSR29); 1359 case 30: return offsetofPPCGuestState(guest_VSR30); 1360 case 31: return offsetofPPCGuestState(guest_VSR31); 1361 case 32: return offsetofPPCGuestState(guest_VSR32); 1362 case 33: return offsetofPPCGuestState(guest_VSR33); 1363 case 34: return offsetofPPCGuestState(guest_VSR34); 1364 case 35: return offsetofPPCGuestState(guest_VSR35); 1365 case 36: return offsetofPPCGuestState(guest_VSR36); 1366 case 37: return offsetofPPCGuestState(guest_VSR37); 1367 case 38: return offsetofPPCGuestState(guest_VSR38); 1368 case 39: return offsetofPPCGuestState(guest_VSR39); 1369 case 40: return offsetofPPCGuestState(guest_VSR40); 1370 case 41: return offsetofPPCGuestState(guest_VSR41); 1371 case 42: return offsetofPPCGuestState(guest_VSR42); 1372 case 43: return offsetofPPCGuestState(guest_VSR43); 1373 case 44: return offsetofPPCGuestState(guest_VSR44); 1374 case 45: return offsetofPPCGuestState(guest_VSR45); 1375 case 46: return offsetofPPCGuestState(guest_VSR46); 1376 case 47: return offsetofPPCGuestState(guest_VSR47); 1377 case 48: return offsetofPPCGuestState(guest_VSR48); 1378 case 49: return offsetofPPCGuestState(guest_VSR49); 1379 case 50: return offsetofPPCGuestState(guest_VSR50); 1380 case 51: return offsetofPPCGuestState(guest_VSR51); 1381 case 52: return offsetofPPCGuestState(guest_VSR52); 1382 case 53: return offsetofPPCGuestState(guest_VSR53); 1383 case 54: return offsetofPPCGuestState(guest_VSR54); 1384 case 55: return offsetofPPCGuestState(guest_VSR55); 1385 case 56: return offsetofPPCGuestState(guest_VSR56); 1386 case 57: return offsetofPPCGuestState(guest_VSR57); 1387 case 58: return offsetofPPCGuestState(guest_VSR58); 1388 case 59: return offsetofPPCGuestState(guest_VSR59); 1389 case 60: return offsetofPPCGuestState(guest_VSR60); 1390 case 61: return offsetofPPCGuestState(guest_VSR61); 1391 case 62: return offsetofPPCGuestState(guest_VSR62); 1392 case 63: return offsetofPPCGuestState(guest_VSR63); 1393 default: break; 1394 } 1395 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1396 } 1397 1398 /* Vector registers are mapped to VSX registers[32..63]. */ 1399 static Int vectorGuestRegOffset ( UInt archreg ) 1400 { 1401 vassert(archreg < 32); 1402 1403 switch (archreg) { 1404 case 0: return offsetofPPCGuestState(guest_VSR32); 1405 case 1: return offsetofPPCGuestState(guest_VSR33); 1406 case 2: return offsetofPPCGuestState(guest_VSR34); 1407 case 3: return offsetofPPCGuestState(guest_VSR35); 1408 case 4: return offsetofPPCGuestState(guest_VSR36); 1409 case 5: return offsetofPPCGuestState(guest_VSR37); 1410 case 6: return offsetofPPCGuestState(guest_VSR38); 1411 case 7: return offsetofPPCGuestState(guest_VSR39); 1412 case 8: return offsetofPPCGuestState(guest_VSR40); 1413 case 9: return offsetofPPCGuestState(guest_VSR41); 1414 case 10: return offsetofPPCGuestState(guest_VSR42); 1415 case 11: return offsetofPPCGuestState(guest_VSR43); 1416 case 12: return offsetofPPCGuestState(guest_VSR44); 1417 case 13: return offsetofPPCGuestState(guest_VSR45); 1418 case 14: return offsetofPPCGuestState(guest_VSR46); 1419 case 15: return offsetofPPCGuestState(guest_VSR47); 1420 case 16: return offsetofPPCGuestState(guest_VSR48); 1421 case 17: return offsetofPPCGuestState(guest_VSR49); 1422 case 18: return offsetofPPCGuestState(guest_VSR50); 1423 case 19: return offsetofPPCGuestState(guest_VSR51); 1424 case 20: return offsetofPPCGuestState(guest_VSR52); 1425 case 21: return offsetofPPCGuestState(guest_VSR53); 1426 case 22: return offsetofPPCGuestState(guest_VSR54); 1427 case 23: return offsetofPPCGuestState(guest_VSR55); 1428 case 24: return offsetofPPCGuestState(guest_VSR56); 1429 case 25: return offsetofPPCGuestState(guest_VSR57); 1430 case 26: return offsetofPPCGuestState(guest_VSR58); 1431 case 27: return offsetofPPCGuestState(guest_VSR59); 1432 case 28: return offsetofPPCGuestState(guest_VSR60); 1433 case 29: return offsetofPPCGuestState(guest_VSR61); 1434 case 30: return offsetofPPCGuestState(guest_VSR62); 1435 case 31: return offsetofPPCGuestState(guest_VSR63); 1436 default: break; 1437 } 1438 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1439 } 1440 1441 static IRExpr* getVReg ( UInt archreg ) 1442 { 1443 vassert(archreg < 32); 1444 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1445 } 1446 1447 /* Ditto, but write to a reg instead. */ 1448 static void putVReg ( UInt archreg, IRExpr* e ) 1449 { 1450 vassert(archreg < 32); 1451 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1452 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1453 } 1454 1455 /* Get contents of VSX guest register */ 1456 static IRExpr* getVSReg ( UInt archreg ) 1457 { 1458 vassert(archreg < 64); 1459 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1460 } 1461 1462 /* Ditto, but write to a VSX reg instead. */ 1463 static void putVSReg ( UInt archreg, IRExpr* e ) 1464 { 1465 vassert(archreg < 64); 1466 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1467 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1468 } 1469 1470 1471 static Int guestCR321offset ( UInt cr ) 1472 { 1473 switch (cr) { 1474 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1475 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1476 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1477 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1478 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1479 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1480 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1481 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1482 default: vpanic("guestCR321offset(ppc)"); 1483 } 1484 } 1485 1486 static Int guestCR0offset ( UInt cr ) 1487 { 1488 switch (cr) { 1489 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1490 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1491 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1492 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1493 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1494 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1495 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1496 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1497 default: vpanic("guestCR3offset(ppc)"); 1498 } 1499 } 1500 1501 typedef enum { 1502 _placeholder0, 1503 _placeholder1, 1504 _placeholder2, 1505 BYTE, 1506 HWORD, 1507 WORD, 1508 DWORD 1509 } _popcount_data_type; 1510 1511 /* Generate an IR sequence to do a popcount operation on the supplied 1512 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1513 Ity_I32 or Ity_I64 only. */ 1514 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1515 { 1516 /* Do count across 2^data_type bits, 1517 byte: data_type = 3 1518 half word: data_type = 4 1519 word: data_type = 5 1520 double word: data_type = 6 (not supported for 32-bit type) 1521 */ 1522 Int shift[6]; 1523 _popcount_data_type idx, i; 1524 IRTemp mask[6]; 1525 IRTemp old = IRTemp_INVALID; 1526 IRTemp nyu = IRTemp_INVALID; 1527 1528 vassert(ty == Ity_I64 || ty == Ity_I32); 1529 1530 if (ty == Ity_I32) { 1531 1532 for (idx = 0; idx < WORD; idx++) { 1533 mask[idx] = newTemp(ty); 1534 shift[idx] = 1 << idx; 1535 } 1536 assign(mask[0], mkU32(0x55555555)); 1537 assign(mask[1], mkU32(0x33333333)); 1538 assign(mask[2], mkU32(0x0F0F0F0F)); 1539 assign(mask[3], mkU32(0x00FF00FF)); 1540 assign(mask[4], mkU32(0x0000FFFF)); 1541 old = src; 1542 for (i = 0; i < data_type; i++) { 1543 nyu = newTemp(ty); 1544 assign(nyu, 1545 binop(Iop_Add32, 1546 binop(Iop_And32, 1547 mkexpr(old), 1548 mkexpr(mask[i])), 1549 binop(Iop_And32, 1550 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1551 mkexpr(mask[i])))); 1552 old = nyu; 1553 } 1554 return nyu; 1555 } 1556 1557 // else, ty == Ity_I64 1558 vassert(mode64); 1559 1560 for (i = 0; i < DWORD; i++) { 1561 mask[i] = newTemp( Ity_I64 ); 1562 shift[i] = 1 << i; 1563 } 1564 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1565 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1566 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1567 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1568 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1569 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1570 old = src; 1571 for (i = 0; i < data_type; i++) { 1572 nyu = newTemp( Ity_I64 ); 1573 assign( nyu, 1574 binop( Iop_Add64, 1575 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1576 binop( Iop_And64, 1577 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1578 mkexpr( mask[i] ) ) ) ); 1579 old = nyu; 1580 } 1581 return nyu; 1582 } 1583 1584 /* Special purpose population count function for 1585 * vpopcntd in 32-bit mode. 1586 */ 1587 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1588 { 1589 Int i, shift[6]; 1590 IRTemp mask[6]; 1591 IRTemp old = IRTemp_INVALID; 1592 IRTemp nyu1 = IRTemp_INVALID; 1593 IRTemp nyu2 = IRTemp_INVALID; 1594 IRTemp retval = newTemp(Ity_I64); 1595 1596 vassert(!mode64); 1597 1598 for (i = 0; i < WORD; i++) { 1599 mask[i] = newTemp(Ity_I32); 1600 shift[i] = 1 << i; 1601 } 1602 assign(mask[0], mkU32(0x55555555)); 1603 assign(mask[1], mkU32(0x33333333)); 1604 assign(mask[2], mkU32(0x0F0F0F0F)); 1605 assign(mask[3], mkU32(0x00FF00FF)); 1606 assign(mask[4], mkU32(0x0000FFFF)); 1607 old = src1; 1608 for (i = 0; i < WORD; i++) { 1609 nyu1 = newTemp(Ity_I32); 1610 assign(nyu1, 1611 binop(Iop_Add32, 1612 binop(Iop_And32, 1613 mkexpr(old), 1614 mkexpr(mask[i])), 1615 binop(Iop_And32, 1616 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1617 mkexpr(mask[i])))); 1618 old = nyu1; 1619 } 1620 1621 old = src2; 1622 for (i = 0; i < WORD; i++) { 1623 nyu2 = newTemp(Ity_I32); 1624 assign(nyu2, 1625 binop(Iop_Add32, 1626 binop(Iop_And32, 1627 mkexpr(old), 1628 mkexpr(mask[i])), 1629 binop(Iop_And32, 1630 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1631 mkexpr(mask[i])))); 1632 old = nyu2; 1633 } 1634 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1635 return retval; 1636 } 1637 1638 1639 // ROTL(src32/64, rot_amt5/6) 1640 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1641 IRExpr* rot_amt ) 1642 { 1643 IRExpr *mask, *rot; 1644 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1645 1646 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1647 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1648 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1649 rot = binop(Iop_Or64, 1650 binop(Iop_Shl64, src, mask), 1651 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1652 } else { 1653 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1654 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1655 rot = binop(Iop_Or32, 1656 binop(Iop_Shl32, src, mask), 1657 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1658 } 1659 /* Note: the ITE not merely an optimisation; it's needed 1660 because otherwise the Shr is a shift by the word size when 1661 mask denotes zero. For rotates by immediates, a lot of 1662 this junk gets folded out. */ 1663 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1664 /* non-zero rotate */ rot, 1665 /* zero rotate */ src); 1666 } 1667 1668 /* Standard effective address calc: (rA + rB) */ 1669 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1670 { 1671 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1672 vassert(rA < 32); 1673 vassert(rB < 32); 1674 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1675 } 1676 1677 /* Standard effective address calc: (rA + simm) */ 1678 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1679 { 1680 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1681 vassert(rA < 32); 1682 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1683 mkSzExtendS16(ty, simm16)); 1684 } 1685 1686 /* Standard effective address calc: (rA|0) */ 1687 static IRExpr* ea_rAor0 ( UInt rA ) 1688 { 1689 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1690 vassert(rA < 32); 1691 if (rA == 0) { 1692 return mkSzImm(ty, 0); 1693 } else { 1694 return getIReg(rA); 1695 } 1696 } 1697 1698 /* Standard effective address calc: (rA|0) + rB */ 1699 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1700 { 1701 vassert(rA < 32); 1702 vassert(rB < 32); 1703 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1704 } 1705 1706 /* Standard effective address calc: (rA|0) + simm16 */ 1707 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1708 { 1709 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1710 vassert(rA < 32); 1711 if (rA == 0) { 1712 return mkSzExtendS16(ty, simm16); 1713 } else { 1714 return ea_rA_simm( rA, simm16 ); 1715 } 1716 } 1717 1718 1719 /* Align effective address */ 1720 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1721 { 1722 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1723 ULong mask; 1724 switch (align) { 1725 case 1: return addr; // byte aligned 1726 case 2: mask = ~0ULL << 1; break; // half-word aligned 1727 case 4: mask = ~0ULL << 2; break; // word aligned 1728 case 16: mask = ~0ULL << 4; break; // quad-word aligned 1729 default: 1730 vex_printf("addr_align: align = %u\n", align); 1731 vpanic("addr_align(ppc)"); 1732 } 1733 1734 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1735 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1736 } 1737 1738 1739 /* Exit the trace if ADDR (intended to be a guest memory address) is 1740 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1741 restart of the current insn. */ 1742 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1743 { 1744 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1745 if (mode64) { 1746 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1747 stmt( 1748 IRStmt_Exit( 1749 binop(Iop_CmpNE64, 1750 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1751 mkU64(0)), 1752 Ijk_SigBUS, 1753 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1754 ) 1755 ); 1756 } else { 1757 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1758 stmt( 1759 IRStmt_Exit( 1760 binop(Iop_CmpNE32, 1761 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1762 mkU32(0)), 1763 Ijk_SigBUS, 1764 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1765 ) 1766 ); 1767 } 1768 } 1769 1770 1771 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1772 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1773 N) becomes undefined. That is at function calls and returns. ELF 1774 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1775 the address of the next instruction to be executed. 1776 */ 1777 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1778 IRTemp nia, const HChar* who ) 1779 { 1780 Int szB = vbi->guest_stack_redzone_size; 1781 if (0) vex_printf("AbiHint: %s\n", who); 1782 vassert(szB >= 0); 1783 if (szB > 0) { 1784 if (mode64) { 1785 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1786 stmt( IRStmt_AbiHint( 1787 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1788 szB, 1789 mkexpr(nia) 1790 )); 1791 } else { 1792 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1793 stmt( IRStmt_AbiHint( 1794 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1795 szB, 1796 mkexpr(nia) 1797 )); 1798 } 1799 } 1800 } 1801 1802 1803 /*------------------------------------------------------------*/ 1804 /*--- Helpers for condition codes. ---*/ 1805 /*------------------------------------------------------------*/ 1806 1807 /* Condition register layout. 1808 1809 In the hardware, CR is laid out like this. The leftmost end is the 1810 most significant bit in the register; however the IBM documentation 1811 numbers the bits backwards for some reason. 1812 1813 CR0 CR1 .......... CR6 CR7 1814 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1815 31 28 3 0 (normal bit numbering) 1816 1817 Each CR field is 4 bits: [<,>,==,SO] 1818 1819 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1820 1821 Indexing from BI to guest state: 1822 1823 let n = BI / 4 1824 off = BI % 4 1825 this references CR n: 1826 1827 off==0 -> guest_CRn_321 >> 3 1828 off==1 -> guest_CRn_321 >> 2 1829 off==2 -> guest_CRn_321 >> 1 1830 off==3 -> guest_CRn_SO 1831 1832 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1833 (normal notation) and in guest_CRn_321 the significant bits are 1834 3, 2 and 1 (normal notation). 1835 */ 1836 1837 static void putCR321 ( UInt cr, IRExpr* e ) 1838 { 1839 vassert(cr < 8); 1840 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1841 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1842 } 1843 1844 static void putCR0 ( UInt cr, IRExpr* e ) 1845 { 1846 vassert(cr < 8); 1847 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1848 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1849 } 1850 1851 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1852 { 1853 vassert(cr < 8); 1854 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1855 } 1856 1857 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1858 { 1859 vassert(cr < 8); 1860 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1861 } 1862 1863 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1864 return it at the bottom of an I32; the top 31 bits are guaranteed 1865 to be zero. */ 1866 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1867 { 1868 UInt n = bi / 4; 1869 UInt off = bi % 4; 1870 vassert(bi < 32); 1871 if (off == 3) { 1872 /* Fetch the SO bit for this CR field */ 1873 /* Note: And32 is redundant paranoia iff guest state only has 0 1874 or 1 in that slot. */ 1875 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1876 } else { 1877 /* Fetch the <, > or == bit for this CR field */ 1878 return binop( Iop_And32, 1879 binop( Iop_Shr32, 1880 unop(Iop_8Uto32, getCR321(n)), 1881 mkU8(toUChar(3-off)) ), 1882 mkU32(1) ); 1883 } 1884 } 1885 1886 /* Dually, write the least significant bit of BIT to the specified CR 1887 bit. Indexing as per getCRbit. */ 1888 static void putCRbit ( UInt bi, IRExpr* bit ) 1889 { 1890 UInt n, off; 1891 IRExpr* safe; 1892 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1893 safe = binop(Iop_And32, bit, mkU32(1)); 1894 n = bi / 4; 1895 off = bi % 4; 1896 vassert(bi < 32); 1897 if (off == 3) { 1898 /* This is the SO bit for this CR field */ 1899 putCR0(n, unop(Iop_32to8, safe)); 1900 } else { 1901 off = 3 - off; 1902 vassert(off == 1 || off == 2 || off == 3); 1903 putCR321( 1904 n, 1905 unop( Iop_32to8, 1906 binop( Iop_Or32, 1907 /* old value with field masked out */ 1908 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1909 mkU32(~(1 << off))), 1910 /* new value in the right place */ 1911 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1912 ) 1913 ) 1914 ); 1915 } 1916 } 1917 1918 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1919 return it somewhere in an I32; it does not matter where, but 1920 whichever bit it is, all other bits are guaranteed to be zero. In 1921 other words, the I32-typed expression will be zero if the bit is 1922 zero and nonzero if the bit is 1. Write into *where the index 1923 of where the bit will be. */ 1924 1925 static 1926 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1927 { 1928 UInt n = bi / 4; 1929 UInt off = bi % 4; 1930 vassert(bi < 32); 1931 if (off == 3) { 1932 /* Fetch the SO bit for this CR field */ 1933 /* Note: And32 is redundant paranoia iff guest state only has 0 1934 or 1 in that slot. */ 1935 *where = 0; 1936 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1937 } else { 1938 /* Fetch the <, > or == bit for this CR field */ 1939 *where = 3-off; 1940 return binop( Iop_And32, 1941 unop(Iop_8Uto32, getCR321(n)), 1942 mkU32(1 << (3-off)) ); 1943 } 1944 } 1945 1946 /* Set the CR0 flags following an arithmetic operation. 1947 (Condition Register CR0 Field Definition, PPC32 p60) 1948 */ 1949 static IRExpr* getXER_SO ( void ); 1950 static void set_CR0 ( IRExpr* result ) 1951 { 1952 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1953 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1954 if (mode64) { 1955 putCR321( 0, unop(Iop_64to8, 1956 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1957 } else { 1958 putCR321( 0, unop(Iop_32to8, 1959 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1960 } 1961 putCR0( 0, getXER_SO() ); 1962 } 1963 1964 1965 /* Set the CR6 flags following an AltiVec compare operation. 1966 * NOTE: This also works for VSX single-precision compares. 1967 * */ 1968 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1969 { 1970 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1971 all_ones = (v[0] && v[1] && v[2] && v[3]) 1972 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1973 */ 1974 IRTemp v0 = newTemp(Ity_V128); 1975 IRTemp v1 = newTemp(Ity_V128); 1976 IRTemp v2 = newTemp(Ity_V128); 1977 IRTemp v3 = newTemp(Ity_V128); 1978 IRTemp rOnes = newTemp(Ity_I8); 1979 IRTemp rZeros = newTemp(Ity_I8); 1980 1981 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1982 1983 assign( v0, result ); 1984 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1985 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1986 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1987 1988 assign( rZeros, unop(Iop_1Uto8, 1989 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1990 unop(Iop_Not32, 1991 unop(Iop_V128to32, 1992 binop(Iop_OrV128, 1993 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1994 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1995 ))) ); 1996 1997 if (test_all_ones) { 1998 assign( rOnes, unop(Iop_1Uto8, 1999 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2000 unop(Iop_V128to32, 2001 binop(Iop_AndV128, 2002 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 2003 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 2004 ))) ); 2005 putCR321( 6, binop(Iop_Or8, 2006 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 2007 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 2008 } else { 2009 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2010 } 2011 putCR0( 6, mkU8(0) ); 2012 } 2013 2014 2015 2016 /*------------------------------------------------------------*/ 2017 /*--- Helpers for XER flags. ---*/ 2018 /*------------------------------------------------------------*/ 2019 2020 static void putXER_SO ( IRExpr* e ) 2021 { 2022 IRExpr* so; 2023 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2024 so = binop(Iop_And8, e, mkU8(1)); 2025 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2026 } 2027 2028 static void putXER_OV ( IRExpr* e ) 2029 { 2030 IRExpr* ov; 2031 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2032 ov = binop(Iop_And8, e, mkU8(1)); 2033 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2034 } 2035 2036 static void putXER_CA ( IRExpr* e ) 2037 { 2038 IRExpr* ca; 2039 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2040 ca = binop(Iop_And8, e, mkU8(1)); 2041 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2042 } 2043 2044 static void putXER_BC ( IRExpr* e ) 2045 { 2046 IRExpr* bc; 2047 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2048 bc = binop(Iop_And8, e, mkU8(0x7F)); 2049 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2050 } 2051 2052 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2053 { 2054 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2055 } 2056 2057 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 2058 { 2059 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2060 } 2061 2062 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2063 { 2064 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2065 } 2066 2067 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 2068 { 2069 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2070 } 2071 2072 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 2073 { 2074 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2075 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2076 } 2077 2078 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2079 { 2080 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2081 } 2082 2083 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 2084 { 2085 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2086 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2087 } 2088 2089 2090 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2091 %XER.SO accordingly. */ 2092 2093 static void set_XER_OV_32( UInt op, IRExpr* res, 2094 IRExpr* argL, IRExpr* argR ) 2095 { 2096 IRTemp t64; 2097 IRExpr* xer_ov; 2098 vassert(op < PPCG_FLAG_OP_NUMBER); 2099 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2100 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2101 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2102 2103 # define INT32_MIN 0x80000000 2104 2105 # define XOR2(_aa,_bb) \ 2106 binop(Iop_Xor32,(_aa),(_bb)) 2107 2108 # define XOR3(_cc,_dd,_ee) \ 2109 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2110 2111 # define AND3(_ff,_gg,_hh) \ 2112 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2113 2114 #define NOT(_jj) \ 2115 unop(Iop_Not32, (_jj)) 2116 2117 switch (op) { 2118 case /* 0 */ PPCG_FLAG_OP_ADD: 2119 case /* 1 */ PPCG_FLAG_OP_ADDE: 2120 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2121 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2122 xer_ov 2123 = AND3( XOR3(argL,argR,mkU32(-1)), 2124 XOR2(argL,res), 2125 mkU32(INT32_MIN) ); 2126 /* xer_ov can only be 0 or 1<<31 */ 2127 xer_ov 2128 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2129 break; 2130 2131 case /* 2 */ PPCG_FLAG_OP_DIVW: 2132 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2133 xer_ov 2134 = mkOR1( 2135 mkAND1( 2136 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2137 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2138 ), 2139 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2140 ); 2141 xer_ov 2142 = unop(Iop_1Uto32, xer_ov); 2143 break; 2144 2145 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2146 /* argR == 0 */ 2147 xer_ov 2148 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2149 break; 2150 2151 case /* 4 */ PPCG_FLAG_OP_MULLW: 2152 /* OV true if result can't be represented in 32 bits 2153 i.e sHi != sign extension of sLo */ 2154 t64 = newTemp(Ity_I64); 2155 assign( t64, binop(Iop_MullS32, argL, argR) ); 2156 xer_ov 2157 = binop( Iop_CmpNE32, 2158 unop(Iop_64HIto32, mkexpr(t64)), 2159 binop( Iop_Sar32, 2160 unop(Iop_64to32, mkexpr(t64)), 2161 mkU8(31)) 2162 ); 2163 xer_ov 2164 = unop(Iop_1Uto32, xer_ov); 2165 break; 2166 2167 case /* 5 */ PPCG_FLAG_OP_NEG: 2168 /* argL == INT32_MIN */ 2169 xer_ov 2170 = unop( Iop_1Uto32, 2171 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2172 break; 2173 2174 case /* 6 */ PPCG_FLAG_OP_SUBF: 2175 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2176 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2177 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2178 xer_ov 2179 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2180 XOR2(NOT(argL),res), 2181 mkU32(INT32_MIN) ); 2182 /* xer_ov can only be 0 or 1<<31 */ 2183 xer_ov 2184 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2185 break; 2186 2187 case PPCG_FLAG_OP_DIVWEU: 2188 xer_ov 2189 = binop( Iop_Or32, 2190 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2191 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2192 break; 2193 2194 case PPCG_FLAG_OP_DIVWE: 2195 2196 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2197 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2198 * an overflow is implied. 2199 */ 2200 xer_ov = binop( Iop_Or32, 2201 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2202 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2203 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2204 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2205 break; 2206 2207 2208 2209 default: 2210 vex_printf("set_XER_OV: op = %u\n", op); 2211 vpanic("set_XER_OV(ppc)"); 2212 } 2213 2214 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2215 putXER_OV( unop(Iop_32to8, xer_ov) ); 2216 2217 /* Update the summary overflow */ 2218 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2219 2220 # undef INT32_MIN 2221 # undef AND3 2222 # undef XOR3 2223 # undef XOR2 2224 # undef NOT 2225 } 2226 2227 static void set_XER_OV_64( UInt op, IRExpr* res, 2228 IRExpr* argL, IRExpr* argR ) 2229 { 2230 IRExpr* xer_ov; 2231 vassert(op < PPCG_FLAG_OP_NUMBER); 2232 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2233 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2234 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2235 2236 # define INT64_MIN 0x8000000000000000ULL 2237 2238 # define XOR2(_aa,_bb) \ 2239 binop(Iop_Xor64,(_aa),(_bb)) 2240 2241 # define XOR3(_cc,_dd,_ee) \ 2242 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2243 2244 # define AND3(_ff,_gg,_hh) \ 2245 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2246 2247 #define NOT(_jj) \ 2248 unop(Iop_Not64, (_jj)) 2249 2250 switch (op) { 2251 case /* 0 */ PPCG_FLAG_OP_ADD: 2252 case /* 1 */ PPCG_FLAG_OP_ADDE: 2253 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2254 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2255 xer_ov 2256 = AND3( XOR3(argL,argR,mkU64(-1)), 2257 XOR2(argL,res), 2258 mkU64(INT64_MIN) ); 2259 /* xer_ov can only be 0 or 1<<63 */ 2260 xer_ov 2261 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2262 break; 2263 2264 case /* 2 */ PPCG_FLAG_OP_DIVW: 2265 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2266 xer_ov 2267 = mkOR1( 2268 mkAND1( 2269 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2270 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2271 ), 2272 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2273 ); 2274 break; 2275 2276 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2277 /* argR == 0 */ 2278 xer_ov 2279 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2280 break; 2281 2282 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2283 /* OV true if result can't be represented in 64 bits 2284 i.e sHi != sign extension of sLo */ 2285 xer_ov 2286 = binop( Iop_CmpNE32, 2287 unop(Iop_64HIto32, res), 2288 binop( Iop_Sar32, 2289 unop(Iop_64to32, res), 2290 mkU8(31)) 2291 ); 2292 break; 2293 } 2294 2295 case /* 5 */ PPCG_FLAG_OP_NEG: 2296 /* argL == INT64_MIN */ 2297 xer_ov 2298 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2299 break; 2300 2301 case /* 6 */ PPCG_FLAG_OP_SUBF: 2302 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2303 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2304 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2305 xer_ov 2306 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2307 XOR2(NOT(argL),res), 2308 mkU64(INT64_MIN) ); 2309 /* xer_ov can only be 0 or 1<<63 */ 2310 xer_ov 2311 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2312 break; 2313 2314 case PPCG_FLAG_OP_DIVDE: 2315 2316 /* If argR == 0, we must set the OV bit. But there's another condition 2317 * where we can get overflow set for divde . . . when the 2318 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2319 * both dividend and divisor are non-zero, it implies an overflow. 2320 */ 2321 xer_ov 2322 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2323 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2324 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2325 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2326 break; 2327 2328 case PPCG_FLAG_OP_DIVDEU: 2329 /* If argR == 0 or if argL >= argR, set OV. */ 2330 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2331 binop( Iop_CmpLE64U, argR, argL ) ); 2332 break; 2333 2334 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2335 IRTemp t128; 2336 /* OV true if result can't be represented in 64 bits 2337 i.e sHi != sign extension of sLo */ 2338 t128 = newTemp(Ity_I128); 2339 assign( t128, binop(Iop_MullS64, argL, argR) ); 2340 xer_ov 2341 = binop( Iop_CmpNE64, 2342 unop(Iop_128HIto64, mkexpr(t128)), 2343 binop( Iop_Sar64, 2344 unop(Iop_128to64, mkexpr(t128)), 2345 mkU8(63)) 2346 ); 2347 break; 2348 } 2349 2350 default: 2351 vex_printf("set_XER_OV: op = %u\n", op); 2352 vpanic("set_XER_OV(ppc64)"); 2353 } 2354 2355 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2356 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2357 2358 /* Update the summary overflow */ 2359 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2360 2361 # undef INT64_MIN 2362 # undef AND3 2363 # undef XOR3 2364 # undef XOR2 2365 # undef NOT 2366 } 2367 2368 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2369 IRExpr* argL, IRExpr* argR ) 2370 { 2371 if (ty == Ity_I32) 2372 set_XER_OV_32( op, res, argL, argR ); 2373 else 2374 set_XER_OV_64( op, res, argL, argR ); 2375 } 2376 2377 2378 2379 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2380 value being OLDCA. Set %XER.CA accordingly. */ 2381 2382 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2383 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2384 { 2385 IRExpr* xer_ca; 2386 vassert(op < PPCG_FLAG_OP_NUMBER); 2387 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2388 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2389 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2390 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2391 2392 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2393 seems reasonable given that it's always generated by 2394 getXER_CA32(), which masks it accordingly. In any case it being 2395 0 or 1 is an invariant of the ppc guest state representation; 2396 if it has any other value, that invariant has been violated. */ 2397 2398 switch (op) { 2399 case /* 0 */ PPCG_FLAG_OP_ADD: 2400 /* res <u argL */ 2401 xer_ca 2402 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2403 break; 2404 2405 case /* 1 */ PPCG_FLAG_OP_ADDE: 2406 /* res <u argL || (old_ca==1 && res==argL) */ 2407 xer_ca 2408 = mkOR1( 2409 binop(Iop_CmpLT32U, res, argL), 2410 mkAND1( 2411 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2412 binop(Iop_CmpEQ32, res, argL) 2413 ) 2414 ); 2415 xer_ca 2416 = unop(Iop_1Uto32, xer_ca); 2417 break; 2418 2419 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2420 /* res <u argR || (old_ca==1 && res==argR) */ 2421 xer_ca 2422 = mkOR1( 2423 binop(Iop_CmpLT32U, res, argR), 2424 mkAND1( 2425 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2426 binop(Iop_CmpEQ32, res, argR) 2427 ) 2428 ); 2429 xer_ca 2430 = unop(Iop_1Uto32, xer_ca); 2431 break; 2432 2433 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2434 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2435 /* res <=u argR */ 2436 xer_ca 2437 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2438 break; 2439 2440 case /* 10 */ PPCG_FLAG_OP_SRAW: 2441 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2442 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2443 bit of argL. */ 2444 /* This term valid for shift amount < 32 only */ 2445 xer_ca 2446 = binop( 2447 Iop_And32, 2448 binop(Iop_Sar32, argL, mkU8(31)), 2449 binop( Iop_And32, 2450 argL, 2451 binop( Iop_Sub32, 2452 binop(Iop_Shl32, mkU32(1), 2453 unop(Iop_32to8,argR)), 2454 mkU32(1) ) 2455 ) 2456 ); 2457 xer_ca 2458 = IRExpr_ITE( 2459 /* shift amt > 31 ? */ 2460 binop(Iop_CmpLT32U, mkU32(31), argR), 2461 /* yes -- get sign bit of argL */ 2462 binop(Iop_Shr32, argL, mkU8(31)), 2463 /* no -- be like srawi */ 2464 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2465 ); 2466 break; 2467 2468 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2469 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2470 0. Since the shift amount is known to be in the range 2471 0 .. 31 inclusive the following seems viable: 2472 xer.ca == 1 iff the following is nonzero: 2473 (argL >>s 31) -- either all 0s or all 1s 2474 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2475 xer_ca 2476 = binop( 2477 Iop_And32, 2478 binop(Iop_Sar32, argL, mkU8(31)), 2479 binop( Iop_And32, 2480 argL, 2481 binop( Iop_Sub32, 2482 binop(Iop_Shl32, mkU32(1), 2483 unop(Iop_32to8,argR)), 2484 mkU32(1) ) 2485 ) 2486 ); 2487 xer_ca 2488 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2489 break; 2490 2491 default: 2492 vex_printf("set_XER_CA: op = %u\n", op); 2493 vpanic("set_XER_CA(ppc)"); 2494 } 2495 2496 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2497 putXER_CA( unop(Iop_32to8, xer_ca) ); 2498 } 2499 2500 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2501 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2502 { 2503 IRExpr* xer_ca; 2504 vassert(op < PPCG_FLAG_OP_NUMBER); 2505 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2506 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2507 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2508 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2509 2510 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2511 seems reasonable given that it's always generated by 2512 getXER_CA32(), which masks it accordingly. In any case it being 2513 0 or 1 is an invariant of the ppc guest state representation; 2514 if it has any other value, that invariant has been violated. */ 2515 2516 switch (op) { 2517 case /* 0 */ PPCG_FLAG_OP_ADD: 2518 /* res <u argL */ 2519 xer_ca 2520 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2521 break; 2522 2523 case /* 1 */ PPCG_FLAG_OP_ADDE: 2524 /* res <u argL || (old_ca==1 && res==argL) */ 2525 xer_ca 2526 = mkOR1( 2527 binop(Iop_CmpLT64U, res, argL), 2528 mkAND1( 2529 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2530 binop(Iop_CmpEQ64, res, argL) 2531 ) 2532 ); 2533 xer_ca 2534 = unop(Iop_1Uto32, xer_ca); 2535 break; 2536 2537 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2538 /* res <u argR || (old_ca==1 && res==argR) */ 2539 xer_ca 2540 = mkOR1( 2541 binop(Iop_CmpLT64U, res, argR), 2542 mkAND1( 2543 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2544 binop(Iop_CmpEQ64, res, argR) 2545 ) 2546 ); 2547 xer_ca 2548 = unop(Iop_1Uto32, xer_ca); 2549 break; 2550 2551 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2552 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2553 /* res <=u argR */ 2554 xer_ca 2555 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2556 break; 2557 2558 2559 case /* 10 */ PPCG_FLAG_OP_SRAW: 2560 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2561 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2562 bit of argL. */ 2563 /* This term valid for shift amount < 31 only */ 2564 2565 xer_ca 2566 = binop( 2567 Iop_And64, 2568 binop(Iop_Sar64, argL, mkU8(31)), 2569 binop( Iop_And64, 2570 argL, 2571 binop( Iop_Sub64, 2572 binop(Iop_Shl64, mkU64(1), 2573 unop(Iop_64to8,argR)), 2574 mkU64(1) ) 2575 ) 2576 ); 2577 xer_ca 2578 = IRExpr_ITE( 2579 /* shift amt > 31 ? */ 2580 binop(Iop_CmpLT64U, mkU64(31), argR), 2581 /* yes -- get sign bit of argL */ 2582 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2583 /* no -- be like srawi */ 2584 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2585 ); 2586 break; 2587 2588 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2589 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2590 Since the shift amount is known to be in the range 0 .. 31 2591 inclusive the following seems viable: 2592 xer.ca == 1 iff the following is nonzero: 2593 (argL >>s 31) -- either all 0s or all 1s 2594 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2595 2596 xer_ca 2597 = binop( 2598 Iop_And64, 2599 binop(Iop_Sar64, argL, mkU8(31)), 2600 binop( Iop_And64, 2601 argL, 2602 binop( Iop_Sub64, 2603 binop(Iop_Shl64, mkU64(1), 2604 unop(Iop_64to8,argR)), 2605 mkU64(1) ) 2606 ) 2607 ); 2608 xer_ca 2609 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2610 break; 2611 2612 2613 case /* 12 */ PPCG_FLAG_OP_SRAD: 2614 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2615 If it is <= 63, behave like SRADI; else XER.CA is the sign 2616 bit of argL. */ 2617 /* This term valid for shift amount < 63 only */ 2618 2619 xer_ca 2620 = binop( 2621 Iop_And64, 2622 binop(Iop_Sar64, argL, mkU8(63)), 2623 binop( Iop_And64, 2624 argL, 2625 binop( Iop_Sub64, 2626 binop(Iop_Shl64, mkU64(1), 2627 unop(Iop_64to8,argR)), 2628 mkU64(1) ) 2629 ) 2630 ); 2631 xer_ca 2632 = IRExpr_ITE( 2633 /* shift amt > 63 ? */ 2634 binop(Iop_CmpLT64U, mkU64(63), argR), 2635 /* yes -- get sign bit of argL */ 2636 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2637 /* no -- be like sradi */ 2638 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2639 ); 2640 break; 2641 2642 2643 case /* 13 */ PPCG_FLAG_OP_SRADI: 2644 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2645 Since the shift amount is known to be in the range 0 .. 63 2646 inclusive, the following seems viable: 2647 xer.ca == 1 iff the following is nonzero: 2648 (argL >>s 63) -- either all 0s or all 1s 2649 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2650 2651 xer_ca 2652 = binop( 2653 Iop_And64, 2654 binop(Iop_Sar64, argL, mkU8(63)), 2655 binop( Iop_And64, 2656 argL, 2657 binop( Iop_Sub64, 2658 binop(Iop_Shl64, mkU64(1), 2659 unop(Iop_64to8,argR)), 2660 mkU64(1) ) 2661 ) 2662 ); 2663 xer_ca 2664 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2665 break; 2666 2667 default: 2668 vex_printf("set_XER_CA: op = %u\n", op); 2669 vpanic("set_XER_CA(ppc64)"); 2670 } 2671 2672 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2673 putXER_CA( unop(Iop_32to8, xer_ca) ); 2674 } 2675 2676 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2677 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2678 { 2679 if (ty == Ity_I32) 2680 set_XER_CA_32( op, res, argL, argR, oldca ); 2681 else 2682 set_XER_CA_64( op, res, argL, argR, oldca ); 2683 } 2684 2685 2686 2687 /*------------------------------------------------------------*/ 2688 /*--- Read/write to guest-state --- */ 2689 /*------------------------------------------------------------*/ 2690 2691 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2692 { 2693 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2694 switch (reg) { 2695 case PPC_GST_SPRG3_RO: 2696 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2697 2698 case PPC_GST_CIA: 2699 return IRExpr_Get( OFFB_CIA, ty ); 2700 2701 case PPC_GST_LR: 2702 return IRExpr_Get( OFFB_LR, ty ); 2703 2704 case PPC_GST_CTR: 2705 return IRExpr_Get( OFFB_CTR, ty ); 2706 2707 case PPC_GST_VRSAVE: 2708 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2709 2710 case PPC_GST_VSCR: 2711 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2712 mkU32(MASK_VSCR_VALID)); 2713 2714 case PPC_GST_CR: { 2715 /* Synthesise the entire CR into a single word. Expensive. */ 2716 # define FIELD(_n) \ 2717 binop(Iop_Shl32, \ 2718 unop(Iop_8Uto32, \ 2719 binop(Iop_Or8, \ 2720 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2721 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2722 ) \ 2723 ), \ 2724 mkU8(4 * (7-(_n))) \ 2725 ) 2726 return binop(Iop_Or32, 2727 binop(Iop_Or32, 2728 binop(Iop_Or32, FIELD(0), FIELD(1)), 2729 binop(Iop_Or32, FIELD(2), FIELD(3)) 2730 ), 2731 binop(Iop_Or32, 2732 binop(Iop_Or32, FIELD(4), FIELD(5)), 2733 binop(Iop_Or32, FIELD(6), FIELD(7)) 2734 ) 2735 ); 2736 # undef FIELD 2737 } 2738 2739 case PPC_GST_XER: 2740 return binop(Iop_Or32, 2741 binop(Iop_Or32, 2742 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2743 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2744 binop(Iop_Or32, 2745 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2746 getXER_BC32())); 2747 2748 case PPC_GST_TFHAR: 2749 return IRExpr_Get( OFFB_TFHAR, ty ); 2750 2751 case PPC_GST_TEXASR: 2752 return IRExpr_Get( OFFB_TEXASR, ty ); 2753 2754 case PPC_GST_TEXASRU: 2755 return IRExpr_Get( OFFB_TEXASRU, ty ); 2756 2757 case PPC_GST_TFIAR: 2758 return IRExpr_Get( OFFB_TFIAR, ty ); 2759 2760 case PPC_GST_PPR: 2761 return IRExpr_Get( OFFB_PPR, ty ); 2762 2763 case PPC_GST_PPR32: 2764 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) ); 2765 2766 case PPC_GST_PSPB: 2767 return IRExpr_Get( OFFB_PSPB, ty ); 2768 2769 default: 2770 vex_printf("getGST(ppc): reg = %u", reg); 2771 vpanic("getGST(ppc)"); 2772 } 2773 } 2774 2775 /* Get a masked word from the given reg */ 2776 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2777 { 2778 IRTemp val = newTemp(Ity_I32); 2779 vassert( reg < PPC_GST_MAX ); 2780 2781 switch (reg) { 2782 2783 case PPC_GST_FPSCR: { 2784 /* Vex-generated code expects the FPSCR to be set as follows: 2785 all exceptions masked, round-to-nearest. 2786 This corresponds to a FPSCR value of 0x0. */ 2787 2788 /* In the lower 32 bits of FPSCR, we're only keeping track of 2789 * the binary floating point rounding mode, so if the mask isn't 2790 * asking for this, just return 0x0. 2791 */ 2792 if (mask & MASK_FPSCR_RN) { 2793 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2794 } else { 2795 assign( val, mkU32(0x0) ); 2796 } 2797 break; 2798 } 2799 2800 default: 2801 vex_printf("getGST_masked(ppc): reg = %u", reg); 2802 vpanic("getGST_masked(ppc)"); 2803 } 2804 2805 if (mask != 0xFFFFFFFF) { 2806 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2807 } else { 2808 return mkexpr(val); 2809 } 2810 } 2811 2812 /* Get a masked word from the given reg */ 2813 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2814 IRExpr * val; 2815 vassert( reg < PPC_GST_MAX ); 2816 2817 switch (reg) { 2818 2819 case PPC_GST_FPSCR: { 2820 /* In the upper 32 bits of FPSCR, we're only keeping track 2821 * of the decimal floating point rounding mode, so if the mask 2822 * isn't asking for this, just return 0x0. 2823 */ 2824 if (mask & MASK_FPSCR_DRN) { 2825 val = binop( Iop_And32, 2826 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2827 unop( Iop_64HIto32, mkU64( mask ) ) ); 2828 } else { 2829 val = mkU32( 0x0ULL ); 2830 } 2831 break; 2832 } 2833 2834 default: 2835 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2836 vpanic( "getGST_masked_upper(ppc)" ); 2837 } 2838 return val; 2839 } 2840 2841 2842 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2843 and return it at the bottom of an I32; the top 27 bits are 2844 guaranteed to be zero. */ 2845 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2846 { 2847 UInt shft, mask; 2848 2849 vassert( fld < 8 ); 2850 vassert( reg < PPC_GST_MAX ); 2851 2852 shft = 4*(7-fld); 2853 mask = 0xF<<shft; 2854 2855 switch (reg) { 2856 case PPC_GST_XER: 2857 vassert(fld ==7); 2858 return binop(Iop_Or32, 2859 binop(Iop_Or32, 2860 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2861 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2862 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2863 break; 2864 2865 default: 2866 if (shft == 0) 2867 return getGST_masked( reg, mask ); 2868 else 2869 return binop(Iop_Shr32, 2870 getGST_masked( reg, mask ), 2871 mkU8(toUChar( shft ))); 2872 } 2873 } 2874 2875 static void putGST ( PPC_GST reg, IRExpr* src ) 2876 { 2877 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2878 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2879 vassert( reg < PPC_GST_MAX ); 2880 switch (reg) { 2881 case PPC_GST_IP_AT_SYSCALL: 2882 vassert( ty_src == ty ); 2883 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2884 break; 2885 case PPC_GST_CIA: 2886 vassert( ty_src == ty ); 2887 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2888 break; 2889 case PPC_GST_LR: 2890 vassert( ty_src == ty ); 2891 stmt( IRStmt_Put( OFFB_LR, src ) ); 2892 break; 2893 case PPC_GST_CTR: 2894 vassert( ty_src == ty ); 2895 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2896 break; 2897 case PPC_GST_VRSAVE: 2898 vassert( ty_src == Ity_I32 ); 2899 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2900 break; 2901 case PPC_GST_VSCR: 2902 vassert( ty_src == Ity_I32 ); 2903 stmt( IRStmt_Put( OFFB_VSCR, 2904 binop(Iop_And32, src, 2905 mkU32(MASK_VSCR_VALID)) ) ); 2906 break; 2907 case PPC_GST_XER: 2908 vassert( ty_src == Ity_I32 ); 2909 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2910 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2911 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2912 putXER_BC( unop(Iop_32to8, src) ); 2913 break; 2914 2915 case PPC_GST_EMWARN: 2916 vassert( ty_src == Ity_I32 ); 2917 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 2918 break; 2919 2920 case PPC_GST_CMSTART: 2921 vassert( ty_src == ty ); 2922 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 2923 break; 2924 2925 case PPC_GST_CMLEN: 2926 vassert( ty_src == ty ); 2927 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 2928 break; 2929 2930 case PPC_GST_TEXASR: 2931 vassert( ty_src == Ity_I64 ); 2932 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 2933 break; 2934 2935 case PPC_GST_TEXASRU: 2936 vassert( ty_src == Ity_I32 ); 2937 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 2938 break; 2939 2940 case PPC_GST_TFIAR: 2941 vassert( ty_src == Ity_I64 ); 2942 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 2943 break; 2944 case PPC_GST_TFHAR: 2945 vassert( ty_src == Ity_I64 ); 2946 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 2947 break; 2948 2949 case PPC_GST_PPR32: 2950 case PPC_GST_PPR: 2951 { 2952 /* The Program Priority Register (PPR) stores the priority in 2953 * bits [52:50]. The user setable priorities are: 2954 * 2955 * 001 very low 2956 * 010 low 2957 * 011 medium low 2958 * 100 medium 2959 * 101 medium high 2960 * 2961 * If the argument is not between 0b001 and 0b100 the priority is set 2962 * to 0b100. The priority can only be set to 0b101 if the the Problem 2963 * State Boost Register is non-zero. The value of the PPR is not 2964 * changed if the input is not valid. 2965 */ 2966 2967 IRTemp not_valid = newTemp(Ity_I64); 2968 IRTemp has_perm = newTemp(Ity_I64); 2969 IRTemp new_src = newTemp(Ity_I64); 2970 IRTemp PSPB_val = newTemp(Ity_I64); 2971 IRTemp value = newTemp(Ity_I64); 2972 2973 vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 )); 2974 assign( PSPB_val, binop( Iop_32HLto64, 2975 mkU32( 0 ), 2976 IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) ); 2977 if( reg == PPC_GST_PPR32 ) { 2978 vassert( ty_src == Ity_I32 ); 2979 assign( value, binop( Iop_32HLto64, 2980 mkU32(0), 2981 binop( Iop_And32, 2982 binop( Iop_Shr32, src, mkU8( 18 ) ), 2983 mkU32( 0x7 ) ) ) ); 2984 } else { 2985 vassert( ty_src == Ity_I64 ); 2986 assign( value, binop( Iop_And64, 2987 binop( Iop_Shr64, src, mkU8( 50 ) ), 2988 mkU64( 0x7 ) ) ); 2989 } 2990 assign( has_perm, 2991 binop( Iop_And64, 2992 unop( Iop_1Sto64, 2993 binop( Iop_CmpEQ64, 2994 mkexpr( PSPB_val ), 2995 mkU64( 0 ) ) ), 2996 unop( Iop_1Sto64, 2997 binop( Iop_CmpEQ64, 2998 mkU64( 0x5 ), 2999 mkexpr( value ) ) ) ) ); 3000 assign( not_valid, 3001 binop( Iop_Or64, 3002 unop( Iop_1Sto64, 3003 binop( Iop_CmpEQ64, 3004 mkexpr( value ), 3005 mkU64( 0 ) ) ), 3006 unop( Iop_1Sto64, 3007 binop( Iop_CmpLT64U, 3008 mkU64( 0x5 ), 3009 mkexpr( value ) ) ) ) ); 3010 assign( new_src, 3011 binop( Iop_Or64, 3012 binop( Iop_And64, 3013 unop( Iop_Not64, 3014 mkexpr( not_valid ) ), 3015 src ), 3016 binop( Iop_And64, 3017 mkexpr( not_valid ), 3018 binop( Iop_Or64, 3019 binop( Iop_And64, 3020 mkexpr( has_perm), 3021 binop( Iop_Shl64, 3022 mkexpr( value ), 3023 mkU8( 50 ) ) ), 3024 binop( Iop_And64, 3025 IRExpr_Get( OFFB_PPR, ty ), 3026 unop( Iop_Not64, 3027 mkexpr( has_perm ) 3028 ) ) ) ) ) ); 3029 3030 /* make sure we only set the valid bit field [52:50] */ 3031 stmt( IRStmt_Put( OFFB_PPR, 3032 binop( Iop_And64, 3033 mkexpr( new_src ), 3034 mkU64( 0x1C000000000000) ) ) ); 3035 break; 3036 } 3037 default: 3038 vex_printf("putGST(ppc): reg = %u", reg); 3039 vpanic("putGST(ppc)"); 3040 } 3041 } 3042 3043 /* Write masked src to the given reg */ 3044 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 3045 { 3046 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3047 vassert( reg < PPC_GST_MAX ); 3048 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 3049 3050 switch (reg) { 3051 case PPC_GST_FPSCR: { 3052 /* Allow writes to either binary or decimal floating point 3053 Rounding Mode. 3054 */ 3055 /* If any part of |mask| covers FPSCR.RN, update the bits of 3056 FPSCR.RN by copying in |src| for locations where the 3057 corresponding bit in |mask| is 1, and leaving it unchanged 3058 for corresponding |mask| zero bits. */ 3059 if (mask & MASK_FPSCR_RN) { 3060 stmt( 3061 IRStmt_Put( 3062 OFFB_FPROUND, 3063 unop( 3064 Iop_32to8, 3065 binop( 3066 Iop_Or32, 3067 binop( 3068 Iop_And32, 3069 unop(Iop_64to32, src), 3070 mkU32(MASK_FPSCR_RN & mask) 3071 ), 3072 binop( 3073 Iop_And32, 3074 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 3075 mkU32(MASK_FPSCR_RN & ~mask) 3076 ) 3077 ) 3078 ) 3079 ) 3080 ); 3081 } 3082 /* Similarly, update FPSCR.DRN if any bits of |mask| 3083 corresponding to FPSCR.DRN are set. */ 3084 if (mask & MASK_FPSCR_DRN) { 3085 stmt( 3086 IRStmt_Put( 3087 OFFB_DFPROUND, 3088 unop( 3089 Iop_32to8, 3090 binop( 3091 Iop_Or32, 3092 binop( 3093 Iop_And32, 3094 unop(Iop_64HIto32, src), 3095 mkU32((MASK_FPSCR_DRN & mask) >> 32) 3096 ), 3097 binop( 3098 Iop_And32, 3099 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 3100 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 3101 ) 3102 ) 3103 ) 3104 ) 3105 ); 3106 } 3107 3108 /* Give EmNote for attempted writes to: 3109 - Exception Controls 3110 - Non-IEEE Mode 3111 */ 3112 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3113 VexEmNote ew = EmWarn_PPCexns; 3114 3115 /* If any of the src::exception_control bits are actually set, 3116 side-exit to the next insn, reporting the warning, 3117 so that Valgrind's dispatcher sees the warning. */ 3118 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3119 stmt( 3120 IRStmt_Exit( 3121 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3122 Ijk_EmWarn, 3123 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3124 } 3125 3126 /* Ignore all other writes */ 3127 break; 3128 } 3129 3130 default: 3131 vex_printf("putGST_masked(ppc): reg = %u", reg); 3132 vpanic("putGST_masked(ppc)"); 3133 } 3134 } 3135 3136 /* Write the least significant nibble of src to the specified 3137 REG[FLD] (as per IBM/hardware notation). */ 3138 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3139 { 3140 UInt shft; 3141 ULong mask; 3142 3143 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3144 vassert( fld < 16 ); 3145 vassert( reg < PPC_GST_MAX ); 3146 3147 if (fld < 8) 3148 shft = 4*(7-fld); 3149 else 3150 shft = 4*(15-fld); 3151 mask = 0xF; 3152 mask = mask << shft; 3153 3154 switch (reg) { 3155 case PPC_GST_CR: 3156 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3157 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3158 break; 3159 3160 default: 3161 { 3162 IRExpr * src64 = unop( Iop_32Uto64, src ); 3163 3164 if (shft == 0) { 3165 putGST_masked( reg, src64, mask ); 3166 } else { 3167 putGST_masked( reg, 3168 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3169 mask ); 3170 } 3171 } 3172 } 3173 } 3174 3175 /*------------------------------------------------------------*/ 3176 /* Helpers for VSX instructions that do floating point 3177 * operations and need to determine if a src contains a 3178 * special FP value. 3179 * 3180 *------------------------------------------------------------*/ 3181 3182 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3183 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3184 mkexpr( x ), \ 3185 mkU64( NONZERO_FRAC_MASK ) ) 3186 3187 // Returns exponent part of a single precision floating point as I32 3188 static IRExpr * fp_exp_part_sp(IRTemp src) 3189 { 3190 return binop( Iop_And32, 3191 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3192 mkU32( 0xff ) ); 3193 } 3194 3195 // Returns exponent part of floating point as I32 3196 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 3197 { 3198 IRExpr * exp; 3199 if (sp) 3200 return fp_exp_part_sp(src); 3201 3202 if (!mode64) 3203 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 3204 mkexpr( src ) ), 3205 mkU8( 20 ) ), mkU32( 0x7ff ) ); 3206 else 3207 exp = unop( Iop_64to32, 3208 binop( Iop_And64, 3209 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 3210 mkU64( 0x7ff ) ) ); 3211 return exp; 3212 } 3213 3214 static IRExpr * is_Inf_sp(IRTemp src) 3215 { 3216 IRTemp frac_part = newTemp(Ity_I32); 3217 IRExpr * Inf_exp; 3218 3219 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 3220 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 3221 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 3222 } 3223 3224 3225 // Infinity: exp = 7ff and fraction is zero; s = 0/1 3226 static IRExpr * is_Inf(IRTemp src, Bool sp) 3227 { 3228 IRExpr * Inf_exp, * hi32, * low32; 3229 IRTemp frac_part; 3230 3231 if (sp) 3232 return is_Inf_sp(src); 3233 3234 frac_part = newTemp(Ity_I64); 3235 assign( frac_part, FP_FRAC_PART(src) ); 3236 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 3237 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3238 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3239 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3240 mkU32( 0 ) ) ); 3241 } 3242 3243 static IRExpr * is_Zero_sp(IRTemp src) 3244 { 3245 IRTemp sign_less_part = newTemp(Ity_I32); 3246 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 3247 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 3248 } 3249 3250 // Zero: exp is zero and fraction is zero; s = 0/1 3251 static IRExpr * is_Zero(IRTemp src, Bool sp) 3252 { 3253 IRExpr * hi32, * low32; 3254 IRTemp sign_less_part; 3255 if (sp) 3256 return is_Zero_sp(src); 3257 3258 sign_less_part = newTemp(Ity_I64); 3259 3260 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 3261 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 3262 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 3263 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3264 mkU32( 0 ) ); 3265 } 3266 3267 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 3268 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 3269 * This function returns an IRExpr value of '1' for any type of NaN. 3270 */ 3271 static IRExpr * is_NaN(IRTemp src) 3272 { 3273 IRExpr * NaN_exp, * hi32, * low32; 3274 IRTemp frac_part = newTemp(Ity_I64); 3275 3276 assign( frac_part, FP_FRAC_PART(src) ); 3277 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3278 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3279 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 3280 mkU32( 0x7ff ) ); 3281 3282 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 3283 mkU32( 0 ) ) ); 3284 } 3285 3286 /* This function returns an IRExpr value of '1' for any type of NaN. 3287 * The passed 'src' argument is assumed to be Ity_I32. 3288 */ 3289 static IRExpr * is_NaN_32(IRTemp src) 3290 { 3291 #define NONZERO_FRAC_MASK32 0x007fffffULL 3292 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3293 mkexpr( x ), \ 3294 mkU32( NONZERO_FRAC_MASK32 ) ) 3295 3296 IRExpr * frac_part = FP_FRAC_PART32(src); 3297 IRExpr * exp_part = binop( Iop_And32, 3298 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3299 mkU32( 0x0ff ) ); 3300 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 3301 3302 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 3303 } 3304 3305 /* This function takes an Ity_I32 input argument interpreted 3306 * as a single-precision floating point value. If src is a 3307 * SNaN, it is changed to a QNaN and returned; otherwise, 3308 * the original value is returned. 3309 */ 3310 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 3311 { 3312 #define SNAN_MASK32 0x00400000 3313 IRTemp tmp = newTemp(Ity_I32); 3314 IRTemp mask = newTemp(Ity_I32); 3315 IRTemp is_SNAN = newTemp(Ity_I1); 3316 3317 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 3318 assign(tmp, src); 3319 3320 /* check if input is SNaN, if it is convert to QNaN */ 3321 assign( is_SNAN, 3322 mkAND1( is_NaN_32( tmp ), 3323 binop( Iop_CmpEQ32, 3324 binop( Iop_And32, mkexpr( tmp ), 3325 mkU32( SNAN_MASK32 ) ), 3326 mkU32( 0 ) ) ) ); 3327 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 3328 assign ( mask, binop( Iop_And32, 3329 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 3330 mkU32( SNAN_MASK32 ) ) ); 3331 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 3332 } 3333 3334 3335 /* This helper function performs the negation part of operations of the form: 3336 * "Negate Multiply-<op>" 3337 * where "<op>" is either "Add" or "Sub". 3338 * 3339 * This function takes one argument -- the floating point intermediate result (converted to 3340 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 3341 * the operation described above. 3342 */ 3343 static IRTemp getNegatedResult(IRTemp intermediateResult) 3344 { 3345 ULong signbit_mask = 0x8000000000000000ULL; 3346 IRTemp signbit_32 = newTemp(Ity_I32); 3347 IRTemp resultantSignbit = newTemp(Ity_I1); 3348 IRTemp negatedResult = newTemp(Ity_I64); 3349 assign( signbit_32, binop( Iop_Shr32, 3350 unop( Iop_64HIto32, 3351 binop( Iop_And64, mkexpr( intermediateResult ), 3352 mkU64( signbit_mask ) ) ), 3353 mkU8( 31 ) ) ); 3354 /* We negate the signbit if and only if the intermediate result from the 3355 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3356 */ 3357 assign( resultantSignbit, 3358 unop( Iop_Not1, 3359 binop( Iop_CmpEQ32, 3360 binop( Iop_Xor32, 3361 mkexpr( signbit_32 ), 3362 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 3363 mkU32( 1 ) ) ) ); 3364 3365 assign( negatedResult, 3366 binop( Iop_Or64, 3367 binop( Iop_And64, 3368 mkexpr( intermediateResult ), 3369 mkU64( ~signbit_mask ) ), 3370 binop( Iop_32HLto64, 3371 binop( Iop_Shl32, 3372 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3373 mkU8( 31 ) ), 3374 mkU32( 0 ) ) ) ); 3375 3376 return negatedResult; 3377 } 3378 3379 /* This helper function performs the negation part of operations of the form: 3380 * "Negate Multiply-<op>" 3381 * where "<op>" is either "Add" or "Sub". 3382 * 3383 * This function takes one argument -- the floating point intermediate result (converted to 3384 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 3385 * the operation described above. 3386 */ 3387 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 3388 { 3389 UInt signbit_mask = 0x80000000; 3390 IRTemp signbit_32 = newTemp(Ity_I32); 3391 IRTemp resultantSignbit = newTemp(Ity_I1); 3392 IRTemp negatedResult = newTemp(Ity_I32); 3393 assign( signbit_32, binop( Iop_Shr32, 3394 binop( Iop_And32, mkexpr( intermediateResult ), 3395 mkU32( signbit_mask ) ), 3396 mkU8( 31 ) ) ); 3397 /* We negate the signbit if and only if the intermediate result from the 3398 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3399 */ 3400 assign( resultantSignbit, 3401 unop( Iop_Not1, 3402 binop( Iop_CmpEQ32, 3403 binop( Iop_Xor32, 3404 mkexpr( signbit_32 ), 3405 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 3406 mkU32( 1 ) ) ) ); 3407 3408 assign( negatedResult, 3409 binop( Iop_Or32, 3410 binop( Iop_And32, 3411 mkexpr( intermediateResult ), 3412 mkU32( ~signbit_mask ) ), 3413 binop( Iop_Shl32, 3414 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3415 mkU8( 31 ) ) ) ); 3416 3417 return negatedResult; 3418 } 3419 3420 /*------------------------------------------------------------*/ 3421 /* Transactional memory helpers 3422 * 3423 *------------------------------------------------------------*/ 3424 3425 static ULong generate_TMreason( UInt failure_code, 3426 UInt persistant, 3427 UInt nest_overflow, 3428 UInt tm_exact ) 3429 { 3430 ULong tm_err_code = 3431 ( (ULong) 0) << (63-6) /* Failure code */ 3432 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 3433 | ( (ULong) 0) << (63-8) /* Disallowed */ 3434 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 3435 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 3436 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 3437 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 3438 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 3439 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 3440 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 3441 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 3442 | ( (ULong) 0) << (63-30) /* Reserved */ 3443 | ( (ULong) 0) << (63-31) /* Abort */ 3444 | ( (ULong) 0) << (63-32) /* Suspend */ 3445 | ( (ULong) 0) << (63-33) /* Reserved */ 3446 | ( (ULong) 0) << (63-35) /* Privilege */ 3447 | ( (ULong) 0) << (63-36) /* Failure Summary */ 3448 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 3449 | ( (ULong) 0) << (63-38) /* ROT */ 3450 | ( (ULong) 0) << (63-51) /* Reserved */ 3451 | ( (ULong) 0) << (63-63); /* Transaction Level */ 3452 3453 return tm_err_code; 3454 } 3455 3456 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 3457 Addr64 handler_address ) 3458 { 3459 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 3460 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 3461 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 3462 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 3463 } 3464 3465 /*------------------------------------------------------------*/ 3466 /*--- Integer Instruction Translation --- */ 3467 /*------------------------------------------------------------*/ 3468 3469 /* 3470 Integer Arithmetic Instructions 3471 */ 3472 static Bool dis_int_arith ( UInt theInstr ) 3473 { 3474 /* D-Form, XO-Form */ 3475 UChar opc1 = ifieldOPC(theInstr); 3476 UChar rD_addr = ifieldRegDS(theInstr); 3477 UChar rA_addr = ifieldRegA(theInstr); 3478 UInt uimm16 = ifieldUIMM16(theInstr); 3479 UChar rB_addr = ifieldRegB(theInstr); 3480 UChar flag_OE = ifieldBIT10(theInstr); 3481 UInt opc2 = ifieldOPClo9(theInstr); 3482 UChar flag_rC = ifieldBIT0(theInstr); 3483 3484 Long simm16 = extend_s_16to64(uimm16); 3485 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3486 IRTemp rA = newTemp(ty); 3487 IRTemp rB = newTemp(ty); 3488 IRTemp rD = newTemp(ty); 3489 3490 Bool do_rc = False; 3491 3492 assign( rA, getIReg(rA_addr) ); 3493 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3494 3495 switch (opc1) { 3496 /* D-Form */ 3497 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3498 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3499 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3500 mkSzExtendS16(ty, uimm16) ) ); 3501 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3502 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3503 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3504 break; 3505 3506 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3507 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3508 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3509 mkSzExtendS16(ty, uimm16) ) ); 3510 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3511 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3512 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3513 do_rc = True; // Always record to CR 3514 flag_rC = 1; 3515 break; 3516 3517 case 0x0E: // addi (Add Immediate, PPC32 p350) 3518 // li rD,val == addi rD,0,val 3519 // la disp(rA) == addi rD,rA,disp 3520 if ( rA_addr == 0 ) { 3521 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3522 assign( rD, mkSzExtendS16(ty, uimm16) ); 3523 } else { 3524 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3525 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3526 mkSzExtendS16(ty, uimm16) ) ); 3527 } 3528 break; 3529 3530 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3531 // lis rD,val == addis rD,0,val 3532 if ( rA_addr == 0 ) { 3533 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3534 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3535 } else { 3536 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16); 3537 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3538 mkSzExtendS32(ty, uimm16 << 16) ) ); 3539 } 3540 break; 3541 3542 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3543 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3544 if (mode64) 3545 assign( rD, unop(Iop_128to64, 3546 binop(Iop_MullS64, mkexpr(rA), 3547 mkSzExtendS16(ty, uimm16))) ); 3548 else 3549 assign( rD, unop(Iop_64to32, 3550 binop(Iop_MullS32, mkexpr(rA), 3551 mkSzExtendS16(ty, uimm16))) ); 3552 break; 3553 3554 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3555 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3556 // rD = simm16 - rA 3557 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3558 mkSzExtendS16(ty, uimm16), 3559 mkexpr(rA)) ); 3560 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3561 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3562 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3563 break; 3564 3565 /* XO-Form */ 3566 case 0x1F: 3567 do_rc = True; // All below record to CR 3568 3569 switch (opc2) { 3570 case 0x10A: // add (Add, PPC32 p347) 3571 DIP("add%s%s r%u,r%u,r%u\n", 3572 flag_OE ? "o" : "", flag_rC ? ".":"", 3573 rD_addr, rA_addr, rB_addr); 3574 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3575 mkexpr(rA), mkexpr(rB) ) ); 3576 if (flag_OE) { 3577 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3578 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3579 } 3580 break; 3581 3582 case 0x00A: // addc (Add Carrying, PPC32 p348) 3583 DIP("addc%s%s r%u,r%u,r%u\n", 3584 flag_OE ? "o" : "", flag_rC ? ".":"", 3585 rD_addr, rA_addr, rB_addr); 3586 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3587 mkexpr(rA), mkexpr(rB)) ); 3588 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3589 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3590 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3591 if (flag_OE) { 3592 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3593 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3594 } 3595 break; 3596 3597 case 0x08A: { // adde (Add Extended, PPC32 p349) 3598 IRTemp old_xer_ca = newTemp(ty); 3599 DIP("adde%s%s r%u,r%u,r%u\n", 3600 flag_OE ? "o" : "", flag_rC ? ".":"", 3601 rD_addr, rA_addr, rB_addr); 3602 // rD = rA + rB + XER[CA] 3603 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3604 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3605 binop( mkSzOp(ty, Iop_Add8), 3606 mkexpr(rB), mkexpr(old_xer_ca))) ); 3607 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3608 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3609 mkexpr(old_xer_ca) ); 3610 if (flag_OE) { 3611 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3612 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3613 } 3614 break; 3615 } 3616 3617 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3618 IRTemp old_xer_ca = newTemp(ty); 3619 IRExpr *min_one; 3620 if (rB_addr != 0) { 3621 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3622 return False; 3623 } 3624 DIP("addme%s%s r%u,r%u,r%u\n", 3625 flag_OE ? "o" : "", flag_rC ? ".":"", 3626 rD_addr, rA_addr, rB_addr); 3627 // rD = rA + (-1) + XER[CA] 3628 // => Just another form of adde 3629 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3630 min_one = mkSzImm(ty, (Long)-1); 3631 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3632 binop( mkSzOp(ty, Iop_Add8), 3633 min_one, mkexpr(old_xer_ca)) )); 3634 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3635 mkexpr(rD), mkexpr(rA), min_one, 3636 mkexpr(old_xer_ca) ); 3637 if (flag_OE) { 3638 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3639 mkexpr(rD), mkexpr(rA), min_one ); 3640 } 3641 break; 3642 } 3643 3644 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3645 IRTemp old_xer_ca = newTemp(ty); 3646 if (rB_addr != 0) { 3647 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3648 return False; 3649 } 3650 DIP("addze%s%s r%u,r%u,r%u\n", 3651 flag_OE ? "o" : "", flag_rC ? ".":"", 3652 rD_addr, rA_addr, rB_addr); 3653 // rD = rA + (0) + XER[CA] 3654 // => Just another form of adde 3655 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3656 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3657 mkexpr(rA), mkexpr(old_xer_ca)) ); 3658 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3659 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3660 mkexpr(old_xer_ca) ); 3661 if (flag_OE) { 3662 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3663 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3664 } 3665 break; 3666 } 3667 3668 case 0x1EB: // divw (Divide Word, PPC32 p388) 3669 DIP("divw%s%s r%u,r%u,r%u\n", 3670 flag_OE ? "o" : "", flag_rC ? ".":"", 3671 rD_addr, rA_addr, rB_addr); 3672 if (mode64) { 3673 /* Note: 3674 XER settings are mode independent, and reflect the 3675 overflow of the low-order 32bit result 3676 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3677 */ 3678 /* rD[hi32] are undefined: setting them to sign of lo32 3679 - makes set_CR0 happy */ 3680 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3681 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3682 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3683 divisor) ) ); 3684 if (flag_OE) { 3685 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3686 mkexpr(rD), dividend, divisor ); 3687 } 3688 } else { 3689 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3690 if (flag_OE) { 3691 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3692 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3693 } 3694 } 3695 /* Note: 3696 if (0x8000_0000 / -1) or (x / 0) 3697 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3698 => But _no_ exception raised. */ 3699 break; 3700 3701 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3702 DIP("divwu%s%s r%u,r%u,r%u\n", 3703 flag_OE ? "o" : "", flag_rC ? ".":"", 3704 rD_addr, rA_addr, rB_addr); 3705 if (mode64) { 3706 /* Note: 3707 XER settings are mode independent, and reflect the 3708 overflow of the low-order 32bit result 3709 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3710 */ 3711 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3712 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3713 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3714 divisor) ) ); 3715 if (flag_OE) { 3716 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3717 mkexpr(rD), dividend, divisor ); 3718 } 3719 } else { 3720 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3721 if (flag_OE) { 3722 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3723 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3724 } 3725 } 3726 /* Note: ditto comment divw, for (x / 0) */ 3727 break; 3728 3729 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3730 if (flag_OE != 0) { 3731 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3732 return False; 3733 } 3734 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3735 rD_addr, rA_addr, rB_addr); 3736 if (mode64) { 3737 /* rD[hi32] are undefined: setting them to sign of lo32 3738 - makes set_CR0 happy */ 3739 assign( rD, binop(Iop_Sar64, 3740 binop(Iop_Mul64, 3741 mk64lo32Sto64( mkexpr(rA) ), 3742 mk64lo32Sto64( mkexpr(rB) )), 3743 mkU8(32)) ); 3744 } else { 3745 assign( rD, unop(Iop_64HIto32, 3746 binop(Iop_MullS32, 3747 mkexpr(rA), mkexpr(rB))) ); 3748 } 3749 break; 3750 3751 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3752 if (flag_OE != 0) { 3753 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3754 return False; 3755 } 3756 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3757 rD_addr, rA_addr, rB_addr); 3758 if (mode64) { 3759 /* rD[hi32] are undefined: setting them to sign of lo32 3760 - makes set_CR0 happy */ 3761 assign( rD, binop(Iop_Sar64, 3762 binop(Iop_Mul64, 3763 mk64lo32Uto64( mkexpr(rA) ), 3764 mk64lo32Uto64( mkexpr(rB) ) ), 3765 mkU8(32)) ); 3766 } else { 3767 assign( rD, unop(Iop_64HIto32, 3768 binop(Iop_MullU32, 3769 mkexpr(rA), mkexpr(rB))) ); 3770 } 3771 break; 3772 3773 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3774 DIP("mullw%s%s r%u,r%u,r%u\n", 3775 flag_OE ? "o" : "", flag_rC ? ".":"", 3776 rD_addr, rA_addr, rB_addr); 3777 if (mode64) { 3778 /* rD[hi32] are undefined: setting them to sign of lo32 3779 - set_XER_OV() and set_CR0() depend on this */ 3780 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3781 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3782 assign( rD, binop(Iop_MullS32, a, b) ); 3783 if (flag_OE) { 3784 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3785 mkexpr(rD), 3786 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3787 } 3788 } else { 3789 assign( rD, unop(Iop_64to32, 3790 binop(Iop_MullU32, 3791 mkexpr(rA), mkexpr(rB))) ); 3792 if (flag_OE) { 3793 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3794 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3795 } 3796 } 3797 break; 3798 3799 case 0x068: // neg (Negate, PPC32 p493) 3800 if (rB_addr != 0) { 3801 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3802 return False; 3803 } 3804 DIP("neg%s%s r%u,r%u\n", 3805 flag_OE ? "o" : "", flag_rC ? ".":"", 3806 rD_addr, rA_addr); 3807 // rD = (~rA) + 1 3808 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3809 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3810 mkSzImm(ty, 1)) ); 3811 if (flag_OE) { 3812 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3813 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3814 } 3815 break; 3816 3817 case 0x028: // subf (Subtract From, PPC32 p537) 3818 DIP("subf%s%s r%u,r%u,r%u\n", 3819 flag_OE ? "o" : "", flag_rC ? ".":"", 3820 rD_addr, rA_addr, rB_addr); 3821 // rD = rB - rA 3822 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3823 mkexpr(rB), mkexpr(rA)) ); 3824 if (flag_OE) { 3825 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3826 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3827 } 3828 break; 3829 3830 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3831 DIP("subfc%s%s r%u,r%u,r%u\n", 3832 flag_OE ? "o" : "", flag_rC ? ".":"", 3833 rD_addr, rA_addr, rB_addr); 3834 // rD = rB - rA 3835 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3836 mkexpr(rB), mkexpr(rA)) ); 3837 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3838 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3839 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3840 if (flag_OE) { 3841 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3842 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3843 } 3844 break; 3845 3846 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3847 IRTemp old_xer_ca = newTemp(ty); 3848 DIP("subfe%s%s r%u,r%u,r%u\n", 3849 flag_OE ? "o" : "", flag_rC ? ".":"", 3850 rD_addr, rA_addr, rB_addr); 3851 // rD = (log not)rA + rB + XER[CA] 3852 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3853 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3854 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3855 binop( mkSzOp(ty, Iop_Add8), 3856 mkexpr(rB), mkexpr(old_xer_ca))) ); 3857 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3858 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3859 mkexpr(old_xer_ca) ); 3860 if (flag_OE) { 3861 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3862 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3863 } 3864 break; 3865 } 3866 3867 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3868 IRTemp old_xer_ca = newTemp(ty); 3869 IRExpr *min_one; 3870 if (rB_addr != 0) { 3871 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3872 return False; 3873 } 3874 DIP("subfme%s%s r%u,r%u\n", 3875 flag_OE ? "o" : "", flag_rC ? ".":"", 3876 rD_addr, rA_addr); 3877 // rD = (log not)rA + (-1) + XER[CA] 3878 // => Just another form of subfe 3879 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3880 min_one = mkSzImm(ty, (Long)-1); 3881 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3882 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3883 binop( mkSzOp(ty, Iop_Add8), 3884 min_one, mkexpr(old_xer_ca))) ); 3885 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3886 mkexpr(rD), mkexpr(rA), min_one, 3887 mkexpr(old_xer_ca) ); 3888 if (flag_OE) { 3889 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3890 mkexpr(rD), mkexpr(rA), min_one ); 3891 } 3892 break; 3893 } 3894 3895 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3896 IRTemp old_xer_ca = newTemp(ty); 3897 if (rB_addr != 0) { 3898 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3899 return False; 3900 } 3901 DIP("subfze%s%s r%u,r%u\n", 3902 flag_OE ? "o" : "", flag_rC ? ".":"", 3903 rD_addr, rA_addr); 3904 // rD = (log not)rA + (0) + XER[CA] 3905 // => Just another form of subfe 3906 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3907 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3908 unop( mkSzOp(ty, Iop_Not8), 3909 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3910 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3911 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3912 mkexpr(old_xer_ca) ); 3913 if (flag_OE) { 3914 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3915 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3916 } 3917 break; 3918 } 3919 3920 3921 /* 64bit Arithmetic */ 3922 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3923 if (flag_OE != 0) { 3924 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3925 return False; 3926 } 3927 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3928 rD_addr, rA_addr, rB_addr); 3929 assign( rD, unop(Iop_128HIto64, 3930 binop(Iop_MullS64, 3931 mkexpr(rA), mkexpr(rB))) ); 3932 3933 break; 3934 3935 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3936 if (flag_OE != 0) { 3937 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3938 return False; 3939 } 3940 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3941 rD_addr, rA_addr, rB_addr); 3942 assign( rD, unop(Iop_128HIto64, 3943 binop(Iop_MullU64, 3944 mkexpr(rA), mkexpr(rB))) ); 3945 break; 3946 3947 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3948 DIP("mulld%s%s r%u,r%u,r%u\n", 3949 flag_OE ? "o" : "", flag_rC ? ".":"", 3950 rD_addr, rA_addr, rB_addr); 3951 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3952 if (flag_OE) { 3953 set_XER_OV( ty, PPCG_FLAG_OP_MULLD, 3954 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3955 } 3956 break; 3957 3958 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3959 DIP("divd%s%s r%u,r%u,r%u\n", 3960 flag_OE ? "o" : "", flag_rC ? ".":"", 3961 rD_addr, rA_addr, rB_addr); 3962 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3963 if (flag_OE) { 3964 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3965 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3966 } 3967 break; 3968 /* Note: 3969 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3970 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3971 => But _no_ exception raised. */ 3972 3973 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3974 DIP("divdu%s%s r%u,r%u,r%u\n", 3975 flag_OE ? "o" : "", flag_rC ? ".":"", 3976 rD_addr, rA_addr, rB_addr); 3977 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3978 if (flag_OE) { 3979 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3980 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3981 } 3982 break; 3983 /* Note: ditto comment divd, for (x / 0) */ 3984 3985 case 0x18B: // divweu (Divide Word Extended Unsigned) 3986 { 3987 /* 3988 * If (RA) >= (RB), or if an attempt is made to perform the division 3989 * <anything> / 0 3990 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3991 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3992 * to 1. 3993 */ 3994 IRTemp res = newTemp(Ity_I32); 3995 IRExpr * dividend, * divisor; 3996 DIP("divweu%s%s r%u,r%u,r%u\n", 3997 flag_OE ? "o" : "", flag_rC ? ".":"", 3998 rD_addr, rA_addr, rB_addr); 3999 if (mode64) { 4000 dividend = unop( Iop_64to32, mkexpr( rA ) ); 4001 divisor = unop( Iop_64to32, mkexpr( rB ) ); 4002 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 4003 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 4004 } else { 4005 dividend = mkexpr( rA ); 4006 divisor = mkexpr( rB ); 4007 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 4008 assign( rD, mkexpr( res) ); 4009 } 4010 4011 if (flag_OE) { 4012 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 4013 mkexpr(res), dividend, divisor ); 4014 } 4015 break; 4016 } 4017 4018 case 0x1AB: // divwe (Divide Word Extended) 4019 { 4020 /* 4021 * If the quotient cannot be represented in 32 bits, or if an 4022 * attempt is made to perform the division 4023 * <anything> / 0 4024 * then the contents of register RD are undefined as are (if 4025 * Rc=1) the contents of the LT, GT, and EQ bits of CR 4026 * Field 0. In these cases, if OE=1 then OV is set to 1. 4027 */ 4028 4029 IRTemp res = newTemp(Ity_I32); 4030 IRExpr * dividend, * divisor; 4031 DIP("divwe%s%s r%u,r%u,r%u\n", 4032 flag_OE ? "o" : "", flag_rC ? ".":"", 4033 rD_addr, rA_addr, rB_addr); 4034 if (mode64) { 4035 dividend = unop( Iop_64to32, mkexpr( rA ) ); 4036 divisor = unop( Iop_64to32, mkexpr( rB ) ); 4037 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 4038 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 4039 } else { 4040 dividend = mkexpr( rA ); 4041 divisor = mkexpr( rB ); 4042 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 4043 assign( rD, mkexpr( res) ); 4044 } 4045 4046 if (flag_OE) { 4047 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 4048 mkexpr(res), dividend, divisor ); 4049 } 4050 break; 4051 } 4052 4053 4054 case 0x1A9: // divde (Divide Doubleword Extended) 4055 /* 4056 * If the quotient cannot be represented in 64 bits, or if an 4057 * attempt is made to perform the division 4058 * <anything> / 0 4059 * then the contents of register RD are undefined as are (if 4060 * Rc=1) the contents of the LT, GT, and EQ bits of CR 4061 * Field 0. In these cases, if OE=1 then OV is set to 1. 4062 */ 4063 DIP("divde%s%s r%u,r%u,r%u\n", 4064 flag_OE ? "o" : "", flag_rC ? ".":"", 4065 rD_addr, rA_addr, rB_addr); 4066 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 4067 if (flag_OE) { 4068 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 4069 mkexpr( rA ), mkexpr( rB ) ); 4070 } 4071 break; 4072 4073 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 4074 // Same CR and OV rules as given for divweu above 4075 DIP("divdeu%s%s r%u,r%u,r%u\n", 4076 flag_OE ? "o" : "", flag_rC ? ".":"", 4077 rD_addr, rA_addr, rB_addr); 4078 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 4079 if (flag_OE) { 4080 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 4081 mkexpr( rA ), mkexpr( rB ) ); 4082 } 4083 break; 4084 4085 default: 4086 vex_printf("dis_int_arith(ppc)(opc2)\n"); 4087 return False; 4088 } 4089 break; 4090 4091 default: 4092 vex_printf("dis_int_arith(ppc)(opc1)\n"); 4093 return False; 4094 } 4095 4096 putIReg( rD_addr, mkexpr(rD) ); 4097 4098 if (do_rc && flag_rC) { 4099 set_CR0( mkexpr(rD) ); 4100 } 4101 return True; 4102 } 4103 4104 4105 4106 /* 4107 Integer Compare Instructions 4108 */ 4109 static Bool dis_int_cmp ( UInt theInstr ) 4110 { 4111 /* D-Form, X-Form */ 4112 UChar opc1 = ifieldOPC(theInstr); 4113 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 4114 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 4115 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 4116 UChar rA_addr = ifieldRegA(theInstr); 4117 UInt uimm16 = ifieldUIMM16(theInstr); 4118 UChar rB_addr = ifieldRegB(theInstr); 4119 UInt opc2 = ifieldOPClo10(theInstr); 4120 UChar b0 = ifieldBIT0(theInstr); 4121 4122 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4123 IRExpr *a = getIReg(rA_addr); 4124 IRExpr *b; 4125 4126 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 4127 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 4128 return False; 4129 } 4130 4131 if (b22 != 0) { 4132 vex_printf("dis_int_cmp(ppc)(b22)\n"); 4133 return False; 4134 } 4135 4136 switch (opc1) { 4137 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 4138 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 4139 (Int)extend_s_16to32(uimm16)); 4140 b = mkSzExtendS16( ty, uimm16 ); 4141 if (flag_L == 1) { 4142 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4143 } else { 4144 a = mkNarrowTo32( ty, a ); 4145 b = mkNarrowTo32( ty, b ); 4146 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 4147 } 4148 putCR0( crfD, getXER_SO() ); 4149 break; 4150 4151 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 4152 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 4153 b = mkSzImm( ty, uimm16 ); 4154 if (flag_L == 1) { 4155 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4156 } else { 4157 a = mkNarrowTo32( ty, a ); 4158 b = mkNarrowTo32( ty, b ); 4159 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4160 } 4161 putCR0( crfD, getXER_SO() ); 4162 break; 4163 4164 /* X Form */ 4165 case 0x1F: 4166 if (b0 != 0) { 4167 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 4168 return False; 4169 } 4170 b = getIReg(rB_addr); 4171 4172 switch (opc2) { 4173 case 0x000: // cmp (Compare, PPC32 p367) 4174 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4175 /* Comparing a reg with itself produces a result which 4176 doesn't depend on the contents of the reg. Therefore 4177 remove the false dependency, which has been known to cause 4178 memcheck to produce false errors. */ 4179 if (rA_addr == rB_addr) 4180 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4181 ? mkU64(0) : mkU32(0); 4182 if (flag_L == 1) { 4183 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4184 } else { 4185 a = mkNarrowTo32( ty, a ); 4186 b = mkNarrowTo32( ty, b ); 4187 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 4188 } 4189 putCR0( crfD, getXER_SO() ); 4190 break; 4191 4192 case 0x020: // cmpl (Compare Logical, PPC32 p369) 4193 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4194 /* Comparing a reg with itself produces a result which 4195 doesn't depend on the contents of the reg. Therefore 4196 remove the false dependency, which has been known to cause 4197 memcheck to produce false errors. */ 4198 if (rA_addr == rB_addr) 4199 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4200 ? mkU64(0) : mkU32(0); 4201 if (flag_L == 1) { 4202 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4203 } else { 4204 a = mkNarrowTo32( ty, a ); 4205 b = mkNarrowTo32( ty, b ); 4206 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4207 } 4208 putCR0( crfD, getXER_SO() ); 4209 break; 4210 4211 default: 4212 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 4213 return False; 4214 } 4215 break; 4216 4217 default: 4218 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 4219 return False; 4220 } 4221 4222 return True; 4223 } 4224 4225 4226 /* 4227 Integer Logical Instructions 4228 */ 4229 static Bool dis_int_logic ( UInt theInstr ) 4230 { 4231 /* D-Form, X-Form */ 4232 UChar opc1 = ifieldOPC(theInstr); 4233 UChar rS_addr = ifieldRegDS(theInstr); 4234 UChar rA_addr = ifieldRegA(theInstr); 4235 UInt uimm16 = ifieldUIMM16(theInstr); 4236 UChar rB_addr = ifieldRegB(theInstr); 4237 UInt opc2 = ifieldOPClo10(theInstr); 4238 UChar flag_rC = ifieldBIT0(theInstr); 4239 4240 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4241 IRTemp rS = newTemp(ty); 4242 IRTemp rA = newTemp(ty); 4243 IRTemp rB = newTemp(ty); 4244 IRExpr* irx; 4245 Bool do_rc = False; 4246 4247 assign( rS, getIReg(rS_addr) ); 4248 assign( rB, getIReg(rB_addr) ); 4249 4250 switch (opc1) { 4251 case 0x1C: // andi. (AND Immediate, PPC32 p358) 4252 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4253 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4254 mkSzImm(ty, uimm16)) ); 4255 do_rc = True; // Always record to CR 4256 flag_rC = 1; 4257 break; 4258 4259 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 4260 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4261 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4262 mkSzImm(ty, uimm16 << 16)) ); 4263 do_rc = True; // Always record to CR 4264 flag_rC = 1; 4265 break; 4266 4267 case 0x18: // ori (OR Immediate, PPC32 p497) 4268 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4269 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4270 mkSzImm(ty, uimm16)) ); 4271 break; 4272 4273 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 4274 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4275 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4276 mkSzImm(ty, uimm16 << 16)) ); 4277 break; 4278 4279 case 0x1A: // xori (XOR Immediate, PPC32 p550) 4280 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4281 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4282 mkSzImm(ty, uimm16)) ); 4283 break; 4284 4285 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 4286 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4287 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4288 mkSzImm(ty, uimm16 << 16)) ); 4289 break; 4290 4291 /* X Form */ 4292 case 0x1F: 4293 do_rc = True; // All below record to CR, except for where we return at case end. 4294 4295 switch (opc2) { 4296 case 0x01C: // and (AND, PPC32 p356) 4297 DIP("and%s r%u,r%u,r%u\n", 4298 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4299 assign(rA, binop( mkSzOp(ty, Iop_And8), 4300 mkexpr(rS), mkexpr(rB))); 4301 break; 4302 4303 case 0x03C: // andc (AND with Complement, PPC32 p357) 4304 DIP("andc%s r%u,r%u,r%u\n", 4305 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4306 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4307 unop( mkSzOp(ty, Iop_Not8), 4308 mkexpr(rB)))); 4309 break; 4310 4311 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 4312 IRExpr* lo32; 4313 if (rB_addr!=0) { 4314 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 4315 return False; 4316 } 4317 DIP("cntlzw%s r%u,r%u\n", 4318 flag_rC ? ".":"", rA_addr, rS_addr); 4319 4320 // mode64: count in low word only 4321 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 4322 4323 // Iop_Clz32 undefined for arg==0, so deal with that case: 4324 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 4325 assign(rA, mkWidenFrom32(ty, 4326 IRExpr_ITE( irx, 4327 unop(Iop_Clz32, lo32), 4328 mkU32(32)), 4329 False)); 4330 4331 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 4332 break; 4333 } 4334 4335 case 0x11C: // eqv (Equivalent, PPC32 p396) 4336 DIP("eqv%s r%u,r%u,r%u\n", 4337 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4338 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4339 binop( mkSzOp(ty, Iop_Xor8), 4340 mkexpr(rS), mkexpr(rB))) ); 4341 break; 4342 4343 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 4344 if (rB_addr!=0) { 4345 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 4346 return False; 4347 } 4348 DIP("extsb%s r%u,r%u\n", 4349 flag_rC ? ".":"", rA_addr, rS_addr); 4350 if (mode64) 4351 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 4352 else 4353 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 4354 break; 4355 4356 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 4357 if (rB_addr!=0) { 4358 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 4359 return False; 4360 } 4361 DIP("extsh%s r%u,r%u\n", 4362 flag_rC ? ".":"", rA_addr, rS_addr); 4363 if (mode64) 4364 assign( rA, unop(Iop_16Sto64, 4365 unop(Iop_64to16, mkexpr(rS))) ); 4366 else 4367 assign( rA, unop(Iop_16Sto32, 4368 unop(Iop_32to16, mkexpr(rS))) ); 4369 break; 4370 4371 case 0x1DC: // nand (NAND, PPC32 p492) 4372 DIP("nand%s r%u,r%u,r%u\n", 4373 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4374 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4375 binop( mkSzOp(ty, Iop_And8), 4376 mkexpr(rS), mkexpr(rB))) ); 4377 break; 4378 4379 case 0x07C: // nor (NOR, PPC32 p494) 4380 DIP("nor%s r%u,r%u,r%u\n", 4381 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4382 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4383 binop( mkSzOp(ty, Iop_Or8), 4384 mkexpr(rS), mkexpr(rB))) ); 4385 break; 4386 4387 case 0x1BC: // or (OR, PPC32 p495) 4388 if ((!flag_rC) && rS_addr == rB_addr) { 4389 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 4390 assign( rA, mkexpr(rS) ); 4391 } else { 4392 DIP("or%s r%u,r%u,r%u\n", 4393 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4394 assign( rA, binop( mkSzOp(ty, Iop_Or8), 4395 mkexpr(rS), mkexpr(rB)) ); 4396 } 4397 break; 4398 4399 case 0x19C: // orc (OR with Complement, PPC32 p496) 4400 DIP("orc%s r%u,r%u,r%u\n", 4401 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4402 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4403 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 4404 break; 4405 4406 case 0x13C: // xor (XOR, PPC32 p549) 4407 DIP("xor%s r%u,r%u,r%u\n", 4408 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4409 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 4410 mkexpr(rS), mkexpr(rB)) ); 4411 break; 4412 4413 4414 /* 64bit Integer Logical Instructions */ 4415 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 4416 if (rB_addr!=0) { 4417 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 4418 return False; 4419 } 4420 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 4421 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 4422 break; 4423 4424 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 4425 if (rB_addr!=0) { 4426 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 4427 return False; 4428 } 4429 DIP("cntlzd%s r%u,r%u\n", 4430 flag_rC ? ".":"", rA_addr, rS_addr); 4431 // Iop_Clz64 undefined for arg==0, so deal with that case: 4432 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 4433 assign(rA, IRExpr_ITE( irx, 4434 unop(Iop_Clz64, mkexpr(rS)), 4435 mkU64(64) )); 4436 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 4437 break; 4438 4439 case 0x1FC: // cmpb (Power6: compare bytes) 4440 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4441 4442 if (mode64) 4443 assign( rA, unop( Iop_V128to64, 4444 binop( Iop_CmpEQ8x16, 4445 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 4446 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 4447 )) ); 4448 else 4449 assign( rA, unop( Iop_V128to32, 4450 binop( Iop_CmpEQ8x16, 4451 unop( Iop_32UtoV128, mkexpr(rS) ), 4452 unop( Iop_32UtoV128, mkexpr(rB) ) 4453 )) ); 4454 break; 4455 4456 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 4457 IRTemp frB = newTemp(Ity_F64); 4458 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 4459 4460 assign( frB, getFReg(rB_addr)); // always F64 4461 if (mode64) 4462 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 4463 else 4464 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 4465 4466 putIReg( rS_addr, mkexpr(rA)); 4467 return True; 4468 } 4469 4470 case 0x25F: { // mffgpr (move floating-point from general purpose register) 4471 IRTemp frA = newTemp(Ity_F64); 4472 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 4473 4474 if (mode64) 4475 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 4476 else 4477 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 4478 4479 putFReg( rS_addr, mkexpr(frA)); 4480 return True; 4481 } 4482 case 0x1FA: // popcntd (population count doubleword 4483 { 4484 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4485 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 4486 putIReg( rA_addr, mkexpr(result) ); 4487 return True; 4488 } 4489 case 0x17A: // popcntw (Population Count Words) 4490 { 4491 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4492 if (mode64) { 4493 IRTemp resultHi, resultLo; 4494 IRTemp argLo = newTemp(Ity_I32); 4495 IRTemp argHi = newTemp(Ity_I32); 4496 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4497 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4498 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 4499 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 4500 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4501 } else { 4502 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 4503 putIReg( rA_addr, mkexpr(result) ); 4504 } 4505 return True; 4506 } 4507 case 0x7A: // popcntb (Population Count Byte) 4508 { 4509 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4510 4511 if (mode64) { 4512 IRTemp resultHi, resultLo; 4513 IRTemp argLo = newTemp(Ity_I32); 4514 IRTemp argHi = newTemp(Ity_I32); 4515 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4516 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4517 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 4518 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 4519 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4520 mkexpr(resultLo))); 4521 } else { 4522 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 4523 putIReg( rA_addr, mkexpr(result) ); 4524 } 4525 return True; 4526 } 4527 case 0x0FC: // bpermd (Bit Permute Doubleword) 4528 { 4529 /* This is a lot of rigmarole to emulate bpermd like this, as it 4530 * could be done much faster by implementing a call to the native 4531 * instruction. However, where possible I want to avoid using new 4532 * native instructions so that we can use valgrind to emulate those 4533 * instructions on older PPC64 hardware. 4534 */ 4535 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4536 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4537 int i; 4538 IRExpr * rS_expr = mkexpr(rS); 4539 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4540 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4541 for (i = 0; i < 8; i++) { 4542 IRTemp idx_tmp = newTemp( Ity_I64 ); 4543 IRTemp perm_bit = newTemp( Ity_I64 ); 4544 IRTemp idx = newTemp( Ity_I8 ); 4545 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4546 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4547 4548 assign( idx_tmp, 4549 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4550 assign( idx_LT64, 4551 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4552 assign( idx, 4553 binop( Iop_And8, 4554 unop( Iop_1Sto8, 4555 mkexpr(idx_LT64) ), 4556 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4557 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4558 * to determine which bit of rB to use for the perm bit, and then we shift 4559 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4560 * to set the final perm bit. 4561 */ 4562 assign( idx_LT64_ity64, 4563 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4564 assign( perm_bit, 4565 binop( Iop_And64, 4566 mkexpr( idx_LT64_ity64 ), 4567 binop( Iop_Shr64, 4568 binop( Iop_And64, 4569 mkU64( BPERMD_BIT_MASK ), 4570 binop( Iop_Shl64, 4571 mkexpr( rB ), 4572 mkexpr( idx ) ) ), 4573 mkU8( 63 ) ) ) ); 4574 res = binop( Iop_Or64, 4575 res, 4576 binop( Iop_Shl64, 4577 mkexpr( perm_bit ), 4578 mkU8( i ) ) ); 4579 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4580 } 4581 putIReg(rA_addr, res); 4582 return True; 4583 } 4584 4585 default: 4586 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4587 return False; 4588 } 4589 break; 4590 4591 default: 4592 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4593 return False; 4594 } 4595 4596 putIReg( rA_addr, mkexpr(rA) ); 4597 4598 if (do_rc && flag_rC) { 4599 set_CR0( mkexpr(rA) ); 4600 } 4601 return True; 4602 } 4603 4604 /* 4605 Integer Parity Instructions 4606 */ 4607 static Bool dis_int_parity ( UInt theInstr ) 4608 { 4609 /* X-Form */ 4610 UChar opc1 = ifieldOPC(theInstr); 4611 UChar rS_addr = ifieldRegDS(theInstr); 4612 UChar rA_addr = ifieldRegA(theInstr); 4613 UChar rB_addr = ifieldRegB(theInstr); 4614 UInt opc2 = ifieldOPClo10(theInstr); 4615 UChar b0 = ifieldBIT0(theInstr); 4616 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4617 4618 IRTemp rS = newTemp(ty); 4619 IRTemp rA = newTemp(ty); 4620 IRTemp iTot1 = newTemp(Ity_I32); 4621 IRTemp iTot2 = newTemp(Ity_I32); 4622 IRTemp iTot3 = newTemp(Ity_I32); 4623 IRTemp iTot4 = newTemp(Ity_I32); 4624 IRTemp iTot5 = newTemp(Ity_I32); 4625 IRTemp iTot6 = newTemp(Ity_I32); 4626 IRTemp iTot7 = newTemp(Ity_I32); 4627 IRTemp iTot8 = newTemp(Ity_I32); 4628 IRTemp rS1 = newTemp(ty); 4629 IRTemp rS2 = newTemp(ty); 4630 IRTemp rS3 = newTemp(ty); 4631 IRTemp rS4 = newTemp(ty); 4632 IRTemp rS5 = newTemp(ty); 4633 IRTemp rS6 = newTemp(ty); 4634 IRTemp rS7 = newTemp(ty); 4635 IRTemp iHi = newTemp(Ity_I32); 4636 IRTemp iLo = newTemp(Ity_I32); 4637 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4638 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4639 4640 if (opc1 != 0x1f || rB_addr || b0) { 4641 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4642 return False; 4643 } 4644 4645 assign( rS, getIReg(rS_addr) ); 4646 4647 switch (opc2) { 4648 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4649 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4650 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4651 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4652 assign( iTot2, binop(Iop_Add32, 4653 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4654 mkexpr(iTot1)) ); 4655 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4656 assign( iTot3, binop(Iop_Add32, 4657 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4658 mkexpr(iTot2)) ); 4659 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4660 assign( iTot4, binop(Iop_Add32, 4661 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4662 mkexpr(iTot3)) ); 4663 if (mode64) { 4664 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4665 assign( iTot5, binop(Iop_Add32, 4666 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4667 mkexpr(iTot4)) ); 4668 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4669 assign( iTot6, binop(Iop_Add32, 4670 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4671 mkexpr(iTot5)) ); 4672 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4673 assign( iTot7, binop(Iop_Add32, 4674 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4675 mkexpr(iTot6)) ); 4676 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4677 assign( iTot8, binop(Iop_Add32, 4678 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4679 mkexpr(iTot7)) ); 4680 assign( rA, unop(Iop_32Uto64, 4681 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4682 } else 4683 assign( rA, mkexpr(iTot4) ); 4684 4685 break; 4686 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4687 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4688 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4689 assign( iTot2, binop(Iop_Add32, 4690 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4691 mkexpr(iTot1)) ); 4692 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4693 assign( iTot3, binop(Iop_Add32, 4694 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4695 mkexpr(iTot2)) ); 4696 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4697 assign( iTot4, binop(Iop_Add32, 4698 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4699 mkexpr(iTot3)) ); 4700 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4701 4702 if (mode64) { 4703 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4704 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4705 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4706 assign( iTot6, binop(Iop_Add32, 4707 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4708 mkexpr(iTot5)) ); 4709 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4710 assign( iTot7, binop(Iop_Add32, 4711 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4712 mkexpr(iTot6)) ); 4713 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4714 assign( iTot8, binop(Iop_Add32, 4715 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4716 mkexpr(iTot7)) ); 4717 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4718 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4719 } else 4720 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4721 break; 4722 default: 4723 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4724 return False; 4725 } 4726 4727 putIReg( rA_addr, mkexpr(rA) ); 4728 4729 return True; 4730 } 4731 4732 4733 /* 4734 Integer Rotate Instructions 4735 */ 4736 static Bool dis_int_rot ( UInt theInstr ) 4737 { 4738 /* M-Form, MDS-Form */ 4739 UChar opc1 = ifieldOPC(theInstr); 4740 UChar rS_addr = ifieldRegDS(theInstr); 4741 UChar rA_addr = ifieldRegA(theInstr); 4742 UChar rB_addr = ifieldRegB(theInstr); 4743 UChar sh_imm = rB_addr; 4744 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4745 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4746 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4747 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4748 UChar b1 = ifieldBIT1(theInstr); 4749 UChar flag_rC = ifieldBIT0(theInstr); 4750 4751 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4752 IRTemp rS = newTemp(ty); 4753 IRTemp rA = newTemp(ty); 4754 IRTemp rB = newTemp(ty); 4755 IRTemp rot = newTemp(ty); 4756 IRExpr *r; 4757 UInt mask32; 4758 ULong mask64; 4759 4760 assign( rS, getIReg(rS_addr) ); 4761 assign( rB, getIReg(rB_addr) ); 4762 4763 switch (opc1) { 4764 case 0x14: { 4765 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4766 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4767 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4768 if (mode64) { 4769 // tmp32 = (ROTL(rS_Lo32, Imm) 4770 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4771 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4772 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4773 r = unop(Iop_32Uto64, r); 4774 assign( rot, binop(Iop_Or64, r, 4775 binop(Iop_Shl64, r, mkU8(32))) ); 4776 assign( rA, 4777 binop(Iop_Or64, 4778 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4779 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4780 } 4781 else { 4782 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4783 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4784 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4785 assign( rA, 4786 binop(Iop_Or32, 4787 binop(Iop_And32, mkU32(mask32), r), 4788 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4789 } 4790 break; 4791 } 4792 4793 case 0x15: { 4794 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4795 vassert(MaskBeg < 32); 4796 vassert(MaskEnd < 32); 4797 vassert(sh_imm < 32); 4798 4799 if (mode64) { 4800 IRTemp rTmp = newTemp(Ity_I64); 4801 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4802 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4803 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4804 // tmp32 = (ROTL(rS_Lo32, Imm) 4805 // rA = ((tmp32 || tmp32) & mask64) 4806 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4807 r = unop(Iop_32Uto64, r); 4808 assign( rTmp, r ); 4809 r = NULL; 4810 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4811 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4812 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4813 } 4814 else { 4815 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4816 /* Special-case the ,n,0,31-n form as that is just n-bit 4817 shift left, PPC32 p501 */ 4818 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4819 rA_addr, rS_addr, sh_imm); 4820 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4821 } 4822 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4823 /* Special-case the ,32-n,n,31 form as that is just n-bit 4824 unsigned shift right, PPC32 p501 */ 4825 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4826 rA_addr, rS_addr, MaskBeg); 4827 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4828 } 4829 else { 4830 /* General case. */ 4831 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4832 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4833 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4834 // rA = ROTL(rS, Imm) & mask 4835 assign( rA, binop(Iop_And32, 4836 ROTL(mkexpr(rS), mkU8(sh_imm)), 4837 mkU32(mask32)) ); 4838 } 4839 } 4840 break; 4841 } 4842 4843 case 0x17: { 4844 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4845 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4846 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4847 if (mode64) { 4848 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4849 /* weird insn alert! 4850 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4851 rA = ((tmp32 || tmp32) & mask64) 4852 */ 4853 // note, ROTL does the masking, so we don't do it here 4854 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4855 unop(Iop_64to8, mkexpr(rB)) ); 4856 r = unop(Iop_32Uto64, r); 4857 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4858 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4859 } else { 4860 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4861 // rA = ROTL(rS, rB[0-4]) & mask 4862 // note, ROTL does the masking, so we don't do it here 4863 assign( rA, binop(Iop_And32, 4864 ROTL(mkexpr(rS), 4865 unop(Iop_32to8, mkexpr(rB))), 4866 mkU32(mask32)) ); 4867 } 4868 break; 4869 } 4870 4871 /* 64bit Integer Rotates */ 4872 case 0x1E: { 4873 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4874 sh_imm |= b1 << 5; 4875 4876 vassert( msk_imm < 64 ); 4877 vassert( sh_imm < 64 ); 4878 4879 switch (opc2) { 4880 case 0x4: { 4881 /* r = ROTL64( rS, rB_lo6) */ 4882 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4883 4884 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4885 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4886 rA_addr, rS_addr, rB_addr, msk_imm); 4887 // note, ROTL does the masking, so we don't do it here 4888 mask64 = MASK64(0, 63-msk_imm); 4889 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4890 break; 4891 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4892 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4893 rA_addr, rS_addr, rB_addr, msk_imm); 4894 mask64 = MASK64(63-msk_imm, 63); 4895 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4896 break; 4897 } 4898 break; 4899 } 4900 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4901 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4902 rA_addr, rS_addr, sh_imm, msk_imm); 4903 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4904 mask64 = MASK64(sh_imm, 63-msk_imm); 4905 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4906 break; 4907 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4908 /* 4909 Hmm... looks like this'll do the job more simply: 4910 r = SHL(rS, sh_imm) 4911 m = ~(1 << (63-msk_imm)) 4912 assign(rA, r & m); 4913 */ 4914 4915 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4916 if (mode64 4917 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4918 /* special-case the ,64-n,n form as that is just 4919 unsigned shift-right by n */ 4920 DIP("srdi%s r%u,r%u,%u\n", 4921 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4922 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4923 } else { 4924 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4925 rA_addr, rS_addr, sh_imm, msk_imm); 4926 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4927 mask64 = MASK64(0, 63-msk_imm); 4928 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4929 } 4930 break; 4931 4932 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4933 if (mode64 4934 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4935 /* special-case the ,n,63-n form as that is just 4936 shift-left by n */ 4937 DIP("sldi%s r%u,r%u,%u\n", 4938 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4939 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4940 } else { 4941 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4942 rA_addr, rS_addr, sh_imm, msk_imm); 4943 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4944 mask64 = MASK64(63-msk_imm, 63); 4945 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4946 } 4947 break; 4948 4949 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4950 IRTemp rA_orig = newTemp(ty); 4951 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4952 rA_addr, rS_addr, sh_imm, msk_imm); 4953 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4954 mask64 = MASK64(sh_imm, 63-msk_imm); 4955 assign( rA_orig, getIReg(rA_addr) ); 4956 assign( rA, binop(Iop_Or64, 4957 binop(Iop_And64, mkU64(mask64), r), 4958 binop(Iop_And64, mkU64(~mask64), 4959 mkexpr(rA_orig))) ); 4960 break; 4961 } 4962 default: 4963 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4964 return False; 4965 } 4966 break; 4967 } 4968 4969 default: 4970 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4971 return False; 4972 } 4973 4974 putIReg( rA_addr, mkexpr(rA) ); 4975 4976 if (flag_rC) { 4977 set_CR0( mkexpr(rA) ); 4978 } 4979 return True; 4980 } 4981 4982 4983 /* 4984 Integer Load Instructions 4985 */ 4986 static Bool dis_int_load ( UInt theInstr ) 4987 { 4988 /* D-Form, X-Form, DS-Form */ 4989 UChar opc1 = ifieldOPC(theInstr); 4990 UChar rD_addr = ifieldRegDS(theInstr); 4991 UChar rA_addr = ifieldRegA(theInstr); 4992 UInt uimm16 = ifieldUIMM16(theInstr); 4993 UChar rB_addr = ifieldRegB(theInstr); 4994 UInt opc2 = ifieldOPClo10(theInstr); 4995 UChar b1 = ifieldBIT1(theInstr); 4996 UChar b0 = ifieldBIT0(theInstr); 4997 4998 Int simm16 = extend_s_16to32(uimm16); 4999 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5000 IRTemp EA = newTemp(ty); 5001 IRExpr* val; 5002 5003 switch (opc1) { 5004 case 0x1F: // register offset 5005 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5006 break; 5007 case 0x38: // immediate offset: 64bit: lq: maskoff 5008 // lowest 4 bits of immediate before forming EA 5009 simm16 = simm16 & 0xFFFFFFF0; 5010 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5011 break; 5012 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 5013 // lowest 2 bits of immediate before forming EA 5014 simm16 = simm16 & 0xFFFFFFFC; 5015 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5016 break; 5017 default: // immediate offset 5018 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5019 break; 5020 } 5021 5022 switch (opc1) { 5023 case 0x22: // lbz (Load B & Zero, PPC32 p433) 5024 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5025 val = load(Ity_I8, mkexpr(EA)); 5026 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5027 break; 5028 5029 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 5030 if (rA_addr == 0 || rA_addr == rD_addr) { 5031 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 5032 return False; 5033 } 5034 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5035 val = load(Ity_I8, mkexpr(EA)); 5036 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5037 putIReg( rA_addr, mkexpr(EA) ); 5038 break; 5039 5040 case 0x2A: // lha (Load HW Alg, PPC32 p445) 5041 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5042 val = load(Ity_I16, mkexpr(EA)); 5043 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5044 break; 5045 5046 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 5047 if (rA_addr == 0 || rA_addr == rD_addr) { 5048 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 5049 return False; 5050 } 5051 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5052 val = load(Ity_I16, mkexpr(EA)); 5053 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5054 putIReg( rA_addr, mkexpr(EA) ); 5055 break; 5056 5057 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 5058 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5059 val = load(Ity_I16, mkexpr(EA)); 5060 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5061 break; 5062 5063 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 5064 if (rA_addr == 0 || rA_addr == rD_addr) { 5065 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 5066 return False; 5067 } 5068 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5069 val = load(Ity_I16, mkexpr(EA)); 5070 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5071 putIReg( rA_addr, mkexpr(EA) ); 5072 break; 5073 5074 case 0x20: // lwz (Load W & Zero, PPC32 p460) 5075 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5076 val = load(Ity_I32, mkexpr(EA)); 5077 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5078 break; 5079 5080 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 5081 if (rA_addr == 0 || rA_addr == rD_addr) { 5082 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 5083 return False; 5084 } 5085 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5086 val = load(Ity_I32, mkexpr(EA)); 5087 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5088 putIReg( rA_addr, mkexpr(EA) ); 5089 break; 5090 5091 /* X Form */ 5092 case 0x1F: 5093 if (b0 != 0) { 5094 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 5095 return False; 5096 } 5097 5098 switch (opc2) { 5099 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 5100 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5101 if (rA_addr == 0 || rA_addr == rD_addr) { 5102 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5103 return False; 5104 } 5105 val = load(Ity_I8, mkexpr(EA)); 5106 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5107 putIReg( rA_addr, mkexpr(EA) ); 5108 break; 5109 5110 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 5111 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5112 val = load(Ity_I8, mkexpr(EA)); 5113 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5114 break; 5115 5116 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 5117 if (rA_addr == 0 || rA_addr == rD_addr) { 5118 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 5119 return False; 5120 } 5121 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5122 val = load(Ity_I16, mkexpr(EA)); 5123 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5124 putIReg( rA_addr, mkexpr(EA) ); 5125 break; 5126 5127 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 5128 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5129 val = load(Ity_I16, mkexpr(EA)); 5130 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5131 break; 5132 5133 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 5134 if (rA_addr == 0 || rA_addr == rD_addr) { 5135 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 5136 return False; 5137 } 5138 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5139 val = load(Ity_I16, mkexpr(EA)); 5140 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5141 putIReg( rA_addr, mkexpr(EA) ); 5142 break; 5143 5144 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 5145 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5146 val = load(Ity_I16, mkexpr(EA)); 5147 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5148 break; 5149 5150 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 5151 if (rA_addr == 0 || rA_addr == rD_addr) { 5152 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5153 return False; 5154 } 5155 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5156 val = load(Ity_I32, mkexpr(EA)); 5157 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5158 putIReg( rA_addr, mkexpr(EA) ); 5159 break; 5160 5161 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 5162 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5163 val = load(Ity_I32, mkexpr(EA)); 5164 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5165 break; 5166 5167 5168 /* 64bit Loads */ 5169 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 5170 if (rA_addr == 0 || rA_addr == rD_addr) { 5171 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 5172 return False; 5173 } 5174 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5175 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5176 putIReg( rA_addr, mkexpr(EA) ); 5177 break; 5178 5179 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 5180 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5181 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5182 break; 5183 5184 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 5185 if (rA_addr == 0 || rA_addr == rD_addr) { 5186 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 5187 return False; 5188 } 5189 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5190 putIReg( rD_addr, 5191 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5192 putIReg( rA_addr, mkexpr(EA) ); 5193 break; 5194 5195 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 5196 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5197 putIReg( rD_addr, 5198 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5199 break; 5200 5201 default: 5202 vex_printf("dis_int_load(ppc)(opc2)\n"); 5203 return False; 5204 } 5205 break; 5206 5207 /* DS Form - 64bit Loads. In each case EA will have been formed 5208 with the lowest 2 bits masked off the immediate offset. */ 5209 case 0x3A: 5210 switch ((b1<<1) | b0) { 5211 case 0x0: // ld (Load DWord, PPC64 p472) 5212 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5213 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5214 break; 5215 5216 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 5217 if (rA_addr == 0 || rA_addr == rD_addr) { 5218 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 5219 return False; 5220 } 5221 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5222 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5223 putIReg( rA_addr, mkexpr(EA) ); 5224 break; 5225 5226 case 0x2: // lwa (Load Word Alg, PPC64 p499) 5227 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5228 putIReg( rD_addr, 5229 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5230 break; 5231 5232 default: 5233 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5234 return False; 5235 } 5236 break; 5237 5238 case 0x38: { 5239 IRTemp high = newTemp(ty); 5240 IRTemp low = newTemp(ty); 5241 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 5242 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5243 /* NOTE: there are some changes to XER[41:42] that have not been 5244 * implemented. 5245 */ 5246 // trap if EA misaligned on 16 byte address 5247 if (mode64) { 5248 if (host_endness == VexEndnessBE) { 5249 assign(high, load(ty, mkexpr( EA ) ) ); 5250 assign(low, load(ty, binop( Iop_Add64, 5251 mkexpr( EA ), 5252 mkU64( 8 ) ) ) ); 5253 } else { 5254 assign(low, load(ty, mkexpr( EA ) ) ); 5255 assign(high, load(ty, binop( Iop_Add64, 5256 mkexpr( EA ), 5257 mkU64( 8 ) ) ) ); 5258 } 5259 } else { 5260 assign(high, load(ty, binop( Iop_Add32, 5261 mkexpr( EA ), 5262 mkU32( 4 ) ) ) ); 5263 assign(low, load(ty, binop( Iop_Add32, 5264 mkexpr( EA ), 5265 mkU32( 12 ) ) ) ); 5266 } 5267 gen_SIGBUS_if_misaligned( EA, 16 ); 5268 putIReg( rD_addr, mkexpr( high) ); 5269 putIReg( rD_addr+1, mkexpr( low) ); 5270 break; 5271 } 5272 default: 5273 vex_printf("dis_int_load(ppc)(opc1)\n"); 5274 return False; 5275 } 5276 return True; 5277 } 5278 5279 5280 5281 /* 5282 Integer Store Instructions 5283 */ 5284 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 5285 { 5286 /* D-Form, X-Form, DS-Form */ 5287 UChar opc1 = ifieldOPC(theInstr); 5288 UInt rS_addr = ifieldRegDS(theInstr); 5289 UInt rA_addr = ifieldRegA(theInstr); 5290 UInt uimm16 = ifieldUIMM16(theInstr); 5291 UInt rB_addr = ifieldRegB(theInstr); 5292 UInt opc2 = ifieldOPClo10(theInstr); 5293 UChar b1 = ifieldBIT1(theInstr); 5294 UChar b0 = ifieldBIT0(theInstr); 5295 5296 Int simm16 = extend_s_16to32(uimm16); 5297 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5298 IRTemp rS = newTemp(ty); 5299 IRTemp rB = newTemp(ty); 5300 IRTemp EA = newTemp(ty); 5301 5302 assign( rB, getIReg(rB_addr) ); 5303 assign( rS, getIReg(rS_addr) ); 5304 5305 switch (opc1) { 5306 case 0x1F: // register offset 5307 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5308 break; 5309 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 5310 // lowest 2 bits of immediate before forming EA 5311 simm16 = simm16 & 0xFFFFFFFC; 5312 default: // immediate offset 5313 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5314 break; 5315 } 5316 5317 switch (opc1) { 5318 case 0x26: // stb (Store B, PPC32 p509) 5319 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5320 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5321 break; 5322 5323 case 0x27: // stbu (Store B, Update, PPC32 p510) 5324 if (rA_addr == 0 ) { 5325 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 5326 return False; 5327 } 5328 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5329 putIReg( rA_addr, mkexpr(EA) ); 5330 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5331 break; 5332 5333 case 0x2C: // sth (Store HW, PPC32 p522) 5334 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5335 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5336 break; 5337 5338 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 5339 if (rA_addr == 0) { 5340 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 5341 return False; 5342 } 5343 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5344 putIReg( rA_addr, mkexpr(EA) ); 5345 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5346 break; 5347 5348 case 0x24: // stw (Store W, PPC32 p530) 5349 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5350 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5351 break; 5352 5353 case 0x25: // stwu (Store W, Update, PPC32 p534) 5354 if (rA_addr == 0) { 5355 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 5356 return False; 5357 } 5358 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5359 putIReg( rA_addr, mkexpr(EA) ); 5360 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5361 break; 5362 5363 /* X Form : all these use EA_indexed */ 5364 case 0x1F: 5365 if (b0 != 0) { 5366 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 5367 return False; 5368 } 5369 5370 switch (opc2) { 5371 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 5372 if (rA_addr == 0) { 5373 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 5374 return False; 5375 } 5376 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5377 putIReg( rA_addr, mkexpr(EA) ); 5378 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5379 break; 5380 5381 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 5382 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5383 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5384 break; 5385 5386 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 5387 if (rA_addr == 0) { 5388 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 5389 return False; 5390 } 5391 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5392 putIReg( rA_addr, mkexpr(EA) ); 5393 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5394 break; 5395 5396 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 5397 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5398 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5399 break; 5400 5401 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 5402 if (rA_addr == 0) { 5403 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 5404 return False; 5405 } 5406 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5407 putIReg( rA_addr, mkexpr(EA) ); 5408 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5409 break; 5410 5411 case 0x097: // stwx (Store W Indexed, PPC32 p536) 5412 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5413 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5414 break; 5415 5416 5417 /* 64bit Stores */ 5418 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 5419 if (rA_addr == 0) { 5420 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 5421 return False; 5422 } 5423 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5424 putIReg( rA_addr, mkexpr(EA) ); 5425 store( mkexpr(EA), mkexpr(rS) ); 5426 break; 5427 5428 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 5429 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5430 store( mkexpr(EA), mkexpr(rS) ); 5431 break; 5432 5433 default: 5434 vex_printf("dis_int_store(ppc)(opc2)\n"); 5435 return False; 5436 } 5437 break; 5438 5439 /* DS Form - 64bit Stores. In each case EA will have been formed 5440 with the lowest 2 bits masked off the immediate offset. */ 5441 case 0x3E: 5442 switch ((b1<<1) | b0) { 5443 case 0x0: // std (Store DWord, PPC64 p580) 5444 if (!mode64) 5445 return False; 5446 5447 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5448 store( mkexpr(EA), mkexpr(rS) ); 5449 break; 5450 5451 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 5452 if (!mode64) 5453 return False; 5454 5455 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5456 putIReg( rA_addr, mkexpr(EA) ); 5457 store( mkexpr(EA), mkexpr(rS) ); 5458 break; 5459 5460 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 5461 IRTemp EA_hi = newTemp(ty); 5462 IRTemp EA_lo = newTemp(ty); 5463 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5464 5465 if (mode64) { 5466 if (host_endness == VexEndnessBE) { 5467 5468 /* upper 64-bits */ 5469 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 5470 5471 /* lower 64-bits */ 5472 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5473 } else { 5474 /* upper 64-bits */ 5475 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5476 5477 /* lower 64-bits */ 5478 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 5479 } 5480 } else { 5481 /* upper half of upper 64-bits */ 5482 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 5483 5484 /* lower half of upper 64-bits */ 5485 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 5486 } 5487 store( mkexpr(EA_hi), mkexpr(rS) ); 5488 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 5489 break; 5490 } 5491 default: 5492 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5493 return False; 5494 } 5495 break; 5496 5497 default: 5498 vex_printf("dis_int_store(ppc)(opc1)\n"); 5499 return False; 5500 } 5501 return True; 5502 } 5503 5504 5505 5506 /* 5507 Integer Load/Store Multiple Instructions 5508 */ 5509 static Bool dis_int_ldst_mult ( UInt theInstr ) 5510 { 5511 /* D-Form */ 5512 UChar opc1 = ifieldOPC(theInstr); 5513 UChar rD_addr = ifieldRegDS(theInstr); 5514 UChar rS_addr = rD_addr; 5515 UChar rA_addr = ifieldRegA(theInstr); 5516 UInt uimm16 = ifieldUIMM16(theInstr); 5517 5518 Int simm16 = extend_s_16to32(uimm16); 5519 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5520 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 5521 IRTemp EA = newTemp(ty); 5522 UInt r = 0; 5523 UInt ea_off = 0; 5524 IRExpr* irx_addr; 5525 5526 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5527 5528 switch (opc1) { 5529 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 5530 if (rA_addr >= rD_addr) { 5531 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 5532 return False; 5533 } 5534 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5535 for (r = rD_addr; r <= 31; r++) { 5536 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5537 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 5538 False) ); 5539 ea_off += 4; 5540 } 5541 break; 5542 5543 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 5544 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5545 for (r = rS_addr; r <= 31; r++) { 5546 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5547 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 5548 ea_off += 4; 5549 } 5550 break; 5551 5552 default: 5553 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 5554 return False; 5555 } 5556 return True; 5557 } 5558 5559 5560 5561 /* 5562 Integer Load/Store String Instructions 5563 */ 5564 static 5565 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5566 IRTemp EA, // EA 5567 Int rD, // first dst register 5568 Int maxBytes ) // 32 or 128 5569 { 5570 Int i, shift = 24; 5571 IRExpr* e_nbytes = mkexpr(tNBytes); 5572 IRExpr* e_EA = mkexpr(EA); 5573 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5574 5575 vassert(rD >= 0 && rD < 32); 5576 rD--; if (rD < 0) rD = 31; 5577 5578 for (i = 0; i < maxBytes; i++) { 5579 /* if (nBytes < (i+1)) goto NIA; */ 5580 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5581 Ijk_Boring, 5582 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5583 /* when crossing into a new dest register, set it to zero. */ 5584 if ((i % 4) == 0) { 5585 rD++; if (rD == 32) rD = 0; 5586 putIReg(rD, mkSzImm(ty, 0)); 5587 shift = 24; 5588 } 5589 /* rD |= (8Uto32(*(EA+i))) << shift */ 5590 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5591 putIReg( 5592 rD, 5593 mkWidenFrom32( 5594 ty, 5595 binop( 5596 Iop_Or32, 5597 mkNarrowTo32(ty, getIReg(rD)), 5598 binop( 5599 Iop_Shl32, 5600 unop( 5601 Iop_8Uto32, 5602 load( Ity_I8, 5603 binop( mkSzOp(ty,Iop_Add8), 5604 e_EA, mkSzImm(ty,i))) 5605 ), 5606 mkU8(toUChar(shift)) 5607 ) 5608 ), 5609 /*Signed*/False 5610 ) 5611 ); 5612 shift -= 8; 5613 } 5614 } 5615 5616 static 5617 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5618 IRTemp EA, // EA 5619 Int rS, // first src register 5620 Int maxBytes ) // 32 or 128 5621 { 5622 Int i, shift = 24; 5623 IRExpr* e_nbytes = mkexpr(tNBytes); 5624 IRExpr* e_EA = mkexpr(EA); 5625 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5626 5627 vassert(rS >= 0 && rS < 32); 5628 rS--; if (rS < 0) rS = 31; 5629 5630 for (i = 0; i < maxBytes; i++) { 5631 /* if (nBytes < (i+1)) goto NIA; */ 5632 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5633 Ijk_Boring, 5634 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5635 /* check for crossing into a new src register. */ 5636 if ((i % 4) == 0) { 5637 rS++; if (rS == 32) rS = 0; 5638 shift = 24; 5639 } 5640 /* *(EA+i) = 32to8(rS >> shift) */ 5641 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5642 store( 5643 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5644 unop( Iop_32to8, 5645 binop( Iop_Shr32, 5646 mkNarrowTo32( ty, getIReg(rS) ), 5647 mkU8( toUChar(shift) ))) 5648 ); 5649 shift -= 8; 5650 } 5651 } 5652 5653 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5654 { 5655 /* X-Form */ 5656 UChar opc1 = ifieldOPC(theInstr); 5657 UChar rD_addr = ifieldRegDS(theInstr); 5658 UChar rS_addr = rD_addr; 5659 UChar rA_addr = ifieldRegA(theInstr); 5660 UChar rB_addr = ifieldRegB(theInstr); 5661 UChar NumBytes = rB_addr; 5662 UInt opc2 = ifieldOPClo10(theInstr); 5663 UChar b0 = ifieldBIT0(theInstr); 5664 5665 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5666 IRTemp t_EA = newTemp(ty); 5667 IRTemp t_nbytes = IRTemp_INVALID; 5668 5669 *stopHere = False; 5670 5671 if (opc1 != 0x1F || b0 != 0) { 5672 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5673 return False; 5674 } 5675 5676 switch (opc2) { 5677 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5678 /* NB: does not reject the case where RA is in the range of 5679 registers to be loaded. It should. */ 5680 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5681 assign( t_EA, ea_rAor0(rA_addr) ); 5682 if (NumBytes == 8 && !mode64) { 5683 /* Special case hack */ 5684 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5685 putIReg( rD_addr, 5686 load(Ity_I32, mkexpr(t_EA)) ); 5687 putIReg( (rD_addr+1) % 32, 5688 load(Ity_I32, 5689 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5690 } else { 5691 t_nbytes = newTemp(Ity_I32); 5692 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5693 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5694 *stopHere = True; 5695 } 5696 return True; 5697 5698 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5699 /* NB: does not reject the case where RA is in the range of 5700 registers to be loaded. It should. Although considering 5701 that that can only be detected at run time, it's not easy to 5702 do so. */ 5703 if (rD_addr == rA_addr || rD_addr == rB_addr) 5704 return False; 5705 if (rD_addr == 0 && rA_addr == 0) 5706 return False; 5707 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5708 t_nbytes = newTemp(Ity_I32); 5709 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5710 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5711 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5712 *stopHere = True; 5713 return True; 5714 5715 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5716 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5717 assign( t_EA, ea_rAor0(rA_addr) ); 5718 if (NumBytes == 8 && !mode64) { 5719 /* Special case hack */ 5720 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5721 store( mkexpr(t_EA), 5722 getIReg(rD_addr) ); 5723 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5724 getIReg((rD_addr+1) % 32) ); 5725 } else { 5726 t_nbytes = newTemp(Ity_I32); 5727 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5728 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5729 *stopHere = True; 5730 } 5731 return True; 5732 5733 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5734 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5735 t_nbytes = newTemp(Ity_I32); 5736 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5737 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5738 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5739 *stopHere = True; 5740 return True; 5741 5742 default: 5743 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5744 return False; 5745 } 5746 return True; 5747 } 5748 5749 5750 /* ------------------------------------------------------------------ 5751 Integer Branch Instructions 5752 ------------------------------------------------------------------ */ 5753 5754 /* 5755 Branch helper function 5756 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5757 Returns an I32 which is 0x00000000 if the ctr condition failed 5758 and 0xFFFFFFFF otherwise. 5759 */ 5760 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5761 { 5762 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5763 IRTemp ok = newTemp(Ity_I32); 5764 5765 if ((BO >> 2) & 1) { // independent of ctr 5766 assign( ok, mkU32(0xFFFFFFFF) ); 5767 } else { 5768 if ((BO >> 1) & 1) { // ctr == 0 ? 5769 assign( ok, unop( Iop_1Sto32, 5770 binop( mkSzOp(ty, Iop_CmpEQ8), 5771 getGST( PPC_GST_CTR ), 5772 mkSzImm(ty,0))) ); 5773 } else { // ctr != 0 ? 5774 assign( ok, unop( Iop_1Sto32, 5775 binop( mkSzOp(ty, Iop_CmpNE8), 5776 getGST( PPC_GST_CTR ), 5777 mkSzImm(ty,0))) ); 5778 } 5779 } 5780 return mkexpr(ok); 5781 } 5782 5783 5784 /* 5785 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5786 Returns an I32 which is either 0 if the condition failed or 5787 some arbitrary nonzero value otherwise. */ 5788 5789 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5790 { 5791 Int where; 5792 IRTemp res = newTemp(Ity_I32); 5793 IRTemp cr_bi = newTemp(Ity_I32); 5794 5795 if ((BO >> 4) & 1) { 5796 assign( res, mkU32(1) ); 5797 } else { 5798 // ok = (CR[BI] == BO[3]) Note, the following relies on 5799 // getCRbit_anywhere returning a value which 5800 // is either zero or has exactly 1 bit set. 5801 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5802 5803 if ((BO >> 3) & 1) { 5804 /* We can use cr_bi as-is. */ 5805 assign( res, mkexpr(cr_bi) ); 5806 } else { 5807 /* We have to invert the sense of the information held in 5808 cr_bi. For that we need to know which bit 5809 getCRbit_anywhere regards as significant. */ 5810 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5811 mkU32(1<<where)) ); 5812 } 5813 } 5814 return mkexpr(res); 5815 } 5816 5817 5818 /* 5819 Integer Branch Instructions 5820 */ 5821 static Bool dis_branch ( UInt theInstr, 5822 const VexAbiInfo* vbi, 5823 /*OUT*/DisResult* dres, 5824 Bool (*resteerOkFn)(void*,Addr), 5825 void* callback_opaque ) 5826 { 5827 UChar opc1 = ifieldOPC(theInstr); 5828 UChar BO = ifieldRegDS(theInstr); 5829 UChar BI = ifieldRegA(theInstr); 5830 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5831 UChar b11to15 = ifieldRegB(theInstr); 5832 UInt opc2 = ifieldOPClo10(theInstr); 5833 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5834 UChar flag_AA = ifieldBIT1(theInstr); 5835 UChar flag_LK = ifieldBIT0(theInstr); 5836 5837 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5838 Addr64 tgt = 0; 5839 UInt BD = extend_s_16to32(BD_u16); 5840 IRTemp do_branch = newTemp(Ity_I32); 5841 IRTemp ctr_ok = newTemp(Ity_I32); 5842 IRTemp cond_ok = newTemp(Ity_I32); 5843 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5844 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5845 IRTemp lr_old = newTemp(ty); 5846 5847 /* Hack to pass through code that just wants to read the PC */ 5848 if (theInstr == 0x429F0005) { 5849 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5850 putGST( PPC_GST_LR, e_nia ); 5851 return True; 5852 } 5853 5854 /* The default what-next. Individual cases can override it. */ 5855 dres->whatNext = Dis_StopHere; 5856 vassert(dres->jk_StopHere == Ijk_INVALID); 5857 5858 switch (opc1) { 5859 case 0x12: // b (Branch, PPC32 p360) 5860 if (flag_AA) { 5861 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5862 } else { 5863 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5864 (Long)extend_s_26to64(LI_u26) ); 5865 } 5866 if (mode64) { 5867 DIP("b%s%s 0x%llx\n", 5868 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5869 } else { 5870 DIP("b%s%s 0x%x\n", 5871 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5872 } 5873 5874 if (flag_LK) { 5875 putGST( PPC_GST_LR, e_nia ); 5876 if (vbi->guest_ppc_zap_RZ_at_bl 5877 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5878 IRTemp t_tgt = newTemp(ty); 5879 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5880 make_redzone_AbiHint( vbi, t_tgt, 5881 "branch-and-link (unconditional call)" ); 5882 } 5883 } 5884 5885 if (resteerOkFn( callback_opaque, tgt )) { 5886 dres->whatNext = Dis_ResteerU; 5887 dres->continueAt = tgt; 5888 } else { 5889 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5890 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5891 } 5892 break; 5893 5894 case 0x10: // bc (Branch Conditional, PPC32 p361) 5895 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5896 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5897 5898 if (!(BO & 0x4)) { 5899 putGST( PPC_GST_CTR, 5900 binop(mkSzOp(ty, Iop_Sub8), 5901 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5902 } 5903 5904 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5905 cond_ok is either zero or nonzero, since that's the cheapest 5906 way to compute it. Anding them together gives a value which 5907 is either zero or non zero and so that's what we must test 5908 for in the IRStmt_Exit. */ 5909 assign( ctr_ok, branch_ctr_ok( BO ) ); 5910 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5911 assign( do_branch, 5912 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5913 5914 if (flag_AA) { 5915 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5916 } else { 5917 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5918 (Long)extend_s_16to64(BD_u16)); 5919 } 5920 if (flag_LK) 5921 putGST( PPC_GST_LR, e_nia ); 5922 5923 stmt( IRStmt_Exit( 5924 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5925 flag_LK ? Ijk_Call : Ijk_Boring, 5926 mkSzConst(ty, tgt), OFFB_CIA ) ); 5927 5928 dres->jk_StopHere = Ijk_Boring; 5929 putGST( PPC_GST_CIA, e_nia ); 5930 break; 5931 5932 case 0x13: 5933 /* For bclr and bcctr, it appears that the lowest two bits of 5934 b11to15 are a branch hint, and so we only need to ensure it's 5935 of the form 000XX. */ 5936 if ((b11to15 & ~3) != 0) { 5937 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15); 5938 return False; 5939 } 5940 5941 switch (opc2) { 5942 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5943 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5944 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5945 return False; 5946 } 5947 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5948 5949 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5950 5951 /* FIXME: this is confusing. lr_old holds the old value 5952 of ctr, not lr :-) */ 5953 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5954 5955 if (flag_LK) 5956 putGST( PPC_GST_LR, e_nia ); 5957 5958 stmt( IRStmt_Exit( 5959 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5960 Ijk_Boring, 5961 c_nia, OFFB_CIA )); 5962 5963 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5964 make_redzone_AbiHint( vbi, lr_old, 5965 "b-ctr-l (indirect call)" ); 5966 } 5967 5968 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5969 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5970 break; 5971 5972 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5973 Bool vanilla_return = False; 5974 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5975 DIP("blr\n"); 5976 vanilla_return = True; 5977 } else { 5978 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5979 } 5980 5981 if (!(BO & 0x4)) { 5982 putGST( PPC_GST_CTR, 5983 binop(mkSzOp(ty, Iop_Sub8), 5984 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5985 } 5986 5987 /* See comments above for 'bc' about this */ 5988 assign( ctr_ok, branch_ctr_ok( BO ) ); 5989 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5990 assign( do_branch, 5991 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5992 5993 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5994 5995 if (flag_LK) 5996 putGST( PPC_GST_LR, e_nia ); 5997 5998 stmt( IRStmt_Exit( 5999 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 6000 Ijk_Boring, 6001 c_nia, OFFB_CIA )); 6002 6003 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 6004 make_redzone_AbiHint( vbi, lr_old, 6005 "branch-to-lr (unconditional return)" ); 6006 } 6007 6008 /* blrl is pretty strange; it's like a return that sets the 6009 return address of its caller to the insn following this 6010 one. Mark it as a return. */ 6011 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 6012 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 6013 break; 6014 } 6015 default: 6016 vex_printf("dis_int_branch(ppc)(opc2)\n"); 6017 return False; 6018 } 6019 break; 6020 6021 default: 6022 vex_printf("dis_int_branch(ppc)(opc1)\n"); 6023 return False; 6024 } 6025 6026 return True; 6027 } 6028 6029 6030 6031 /* 6032 Condition Register Logical Instructions 6033 */ 6034 static Bool dis_cond_logic ( UInt theInstr ) 6035 { 6036 /* XL-Form */ 6037 UChar opc1 = ifieldOPC(theInstr); 6038 UChar crbD_addr = ifieldRegDS(theInstr); 6039 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 6040 UChar crbA_addr = ifieldRegA(theInstr); 6041 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 6042 UChar crbB_addr = ifieldRegB(theInstr); 6043 UInt opc2 = ifieldOPClo10(theInstr); 6044 UChar b0 = ifieldBIT0(theInstr); 6045 6046 IRTemp crbD = newTemp(Ity_I32); 6047 IRTemp crbA = newTemp(Ity_I32); 6048 IRTemp crbB = newTemp(Ity_I32); 6049 6050 if (opc1 != 19 || b0 != 0) { 6051 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 6052 return False; 6053 } 6054 6055 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 6056 if (((crbD_addr & 0x3) != 0) || 6057 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 6058 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 6059 return False; 6060 } 6061 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 6062 putCR0( crfD_addr, getCR0( crfS_addr) ); 6063 putCR321( crfD_addr, getCR321(crfS_addr) ); 6064 } else { 6065 assign( crbA, getCRbit(crbA_addr) ); 6066 if (crbA_addr == crbB_addr) 6067 crbB = crbA; 6068 else 6069 assign( crbB, getCRbit(crbB_addr) ); 6070 6071 switch (opc2) { 6072 case 0x101: // crand (Cond Reg AND, PPC32 p372) 6073 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6074 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 6075 break; 6076 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 6077 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6078 assign( crbD, binop(Iop_And32, 6079 mkexpr(crbA), 6080 unop(Iop_Not32, mkexpr(crbB))) ); 6081 break; 6082 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 6083 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6084 assign( crbD, unop(Iop_Not32, 6085 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 6086 break; 6087 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 6088 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6089 assign( crbD, unop(Iop_Not32, 6090 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 6091 break; 6092 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 6093 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6094 assign( crbD, unop(Iop_Not32, 6095 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 6096 break; 6097 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 6098 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6099 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 6100 break; 6101 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 6102 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6103 assign( crbD, binop(Iop_Or32, 6104 mkexpr(crbA), 6105 unop(Iop_Not32, mkexpr(crbB))) ); 6106 break; 6107 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 6108 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6109 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 6110 break; 6111 default: 6112 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 6113 return False; 6114 } 6115 6116 putCRbit( crbD_addr, mkexpr(crbD) ); 6117 } 6118 return True; 6119 } 6120 6121 6122 /* 6123 Trap instructions 6124 */ 6125 6126 /* Do the code generation for a trap. Returned Bool is true iff 6127 this is an unconditional trap. If the two arg IRExpr*s are 6128 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 6129 then they are 64-bit, and we must be disassembling 64-bit 6130 instructions. */ 6131 static Bool do_trap ( UChar TO, 6132 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 6133 { 6134 IRTemp argL, argR; 6135 IRExpr *argLe, *argRe, *cond, *tmp; 6136 6137 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 6138 6139 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 6140 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 6141 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 6142 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 6143 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 6144 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 6145 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 6146 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 6147 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 6148 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 6149 6150 const UChar b11100 = 0x1C; 6151 const UChar b00111 = 0x07; 6152 6153 if (is32bit) { 6154 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 6155 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 6156 } else { 6157 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 6158 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 6159 vassert( mode64 ); 6160 } 6161 6162 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 6163 /* Unconditional trap. Just do the exit without 6164 testing the arguments. */ 6165 stmt( IRStmt_Exit( 6166 binop(opCMPEQ, const0, const0), 6167 Ijk_SigTRAP, 6168 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6169 OFFB_CIA 6170 )); 6171 return True; /* unconditional trap */ 6172 } 6173 6174 if (is32bit) { 6175 argL = newTemp(Ity_I32); 6176 argR = newTemp(Ity_I32); 6177 } else { 6178 argL = newTemp(Ity_I64); 6179 argR = newTemp(Ity_I64); 6180 } 6181 6182 assign( argL, argL0 ); 6183 assign( argR, argR0 ); 6184 6185 argLe = mkexpr(argL); 6186 argRe = mkexpr(argR); 6187 6188 cond = const0; 6189 if (TO & 16) { // L <s R 6190 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 6191 cond = binop(opOR, tmp, cond); 6192 } 6193 if (TO & 8) { // L >s R 6194 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 6195 cond = binop(opOR, tmp, cond); 6196 } 6197 if (TO & 4) { // L == R 6198 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 6199 cond = binop(opOR, tmp, cond); 6200 } 6201 if (TO & 2) { // L <u R 6202 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 6203 cond = binop(opOR, tmp, cond); 6204 } 6205 if (TO & 1) { // L >u R 6206 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 6207 cond = binop(opOR, tmp, cond); 6208 } 6209 stmt( IRStmt_Exit( 6210 binop(opCMPNE, cond, const0), 6211 Ijk_SigTRAP, 6212 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6213 OFFB_CIA 6214 )); 6215 return False; /* not an unconditional trap */ 6216 } 6217 6218 static Bool dis_trapi ( UInt theInstr, 6219 /*OUT*/DisResult* dres ) 6220 { 6221 /* D-Form */ 6222 UChar opc1 = ifieldOPC(theInstr); 6223 UChar TO = ifieldRegDS(theInstr); 6224 UChar rA_addr = ifieldRegA(theInstr); 6225 UInt uimm16 = ifieldUIMM16(theInstr); 6226 ULong simm16 = extend_s_16to64(uimm16); 6227 Addr64 cia = guest_CIA_curr_instr; 6228 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6229 Bool uncond = False; 6230 6231 switch (opc1) { 6232 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 6233 uncond = do_trap( TO, 6234 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6235 : getIReg(rA_addr), 6236 mkU32( (UInt)simm16 ), 6237 cia ); 6238 if (TO == 4) { 6239 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16); 6240 } else { 6241 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16); 6242 } 6243 break; 6244 case 0x02: // tdi 6245 if (!mode64) 6246 return False; 6247 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 6248 if (TO == 4) { 6249 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16); 6250 } else { 6251 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16); 6252 } 6253 break; 6254 default: 6255 return False; 6256 } 6257 6258 if (uncond) { 6259 /* If the trap shows signs of being unconditional, don't 6260 continue decoding past it. */ 6261 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6262 dres->jk_StopHere = Ijk_Boring; 6263 dres->whatNext = Dis_StopHere; 6264 } 6265 6266 return True; 6267 } 6268 6269 static Bool dis_trap ( UInt theInstr, 6270 /*OUT*/DisResult* dres ) 6271 { 6272 /* X-Form */ 6273 UInt opc2 = ifieldOPClo10(theInstr); 6274 UChar TO = ifieldRegDS(theInstr); 6275 UChar rA_addr = ifieldRegA(theInstr); 6276 UChar rB_addr = ifieldRegB(theInstr); 6277 Addr64 cia = guest_CIA_curr_instr; 6278 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6279 Bool uncond = False; 6280 6281 if (ifieldBIT0(theInstr) != 0) 6282 return False; 6283 6284 switch (opc2) { 6285 case 0x004: // tw (Trap Word, PPC64 p540) 6286 uncond = do_trap( TO, 6287 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6288 : getIReg(rA_addr), 6289 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 6290 : getIReg(rB_addr), 6291 cia ); 6292 if (TO == 4) { 6293 DIP("tweq r%u,r%u\n", rA_addr, rB_addr); 6294 } else { 6295 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr); 6296 } 6297 break; 6298 case 0x044: // td (Trap Doubleword, PPC64 p534) 6299 if (!mode64) 6300 return False; 6301 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 6302 if (TO == 4) { 6303 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr); 6304 } else { 6305 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr); 6306 } 6307 break; 6308 default: 6309 return False; 6310 } 6311 6312 if (uncond) { 6313 /* If the trap shows signs of being unconditional, don't 6314 continue decoding past it. */ 6315 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6316 dres->jk_StopHere = Ijk_Boring; 6317 dres->whatNext = Dis_StopHere; 6318 } 6319 6320 return True; 6321 } 6322 6323 6324 /* 6325 System Linkage Instructions 6326 */ 6327 static Bool dis_syslink ( UInt theInstr, 6328 const VexAbiInfo* abiinfo, DisResult* dres ) 6329 { 6330 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6331 6332 if (theInstr != 0x44000002) { 6333 vex_printf("dis_syslink(ppc)(theInstr)\n"); 6334 return False; 6335 } 6336 6337 // sc (System Call, PPC32 p504) 6338 DIP("sc\n"); 6339 6340 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 6341 Valgrind can back the guest up to this instruction if it needs 6342 to restart the syscall. */ 6343 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 6344 6345 /* It's important that all ArchRegs carry their up-to-date value 6346 at this point. So we declare an end-of-block here, which 6347 forces any TempRegs caching ArchRegs to be flushed. */ 6348 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6349 6350 dres->whatNext = Dis_StopHere; 6351 dres->jk_StopHere = Ijk_Sys_syscall; 6352 return True; 6353 } 6354 6355 6356 /* 6357 Memory Synchronization Instructions 6358 6359 Note on Reservations: 6360 We rely on the assumption that V will in fact only allow one thread at 6361 once to run. In effect, a thread can make a reservation, but we don't 6362 check any stores it does. Instead, the reservation is cancelled when 6363 the scheduler switches to another thread (run_thread_for_a_while()). 6364 */ 6365 static Bool dis_memsync ( UInt theInstr ) 6366 { 6367 /* X-Form, XL-Form */ 6368 UChar opc1 = ifieldOPC(theInstr); 6369 UInt b11to25 = IFIELD(theInstr, 11, 15); 6370 UChar flag_L = ifieldRegDS(theInstr); 6371 UInt b11to20 = IFIELD(theInstr, 11, 10); 6372 UInt M0 = IFIELD(theInstr, 11, 5); 6373 UChar rD_addr = ifieldRegDS(theInstr); 6374 UChar rS_addr = rD_addr; 6375 UChar rA_addr = ifieldRegA(theInstr); 6376 UChar rB_addr = ifieldRegB(theInstr); 6377 UInt opc2 = ifieldOPClo10(theInstr); 6378 UChar b0 = ifieldBIT0(theInstr); 6379 6380 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6381 IRTemp EA = newTemp(ty); 6382 6383 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6384 6385 switch (opc1) { 6386 /* XL-Form */ 6387 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 6388 if (opc2 != 0x096) { 6389 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 6390 return False; 6391 } 6392 if (b11to25 != 0 || b0 != 0) { 6393 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 6394 return False; 6395 } 6396 DIP("isync\n"); 6397 stmt( IRStmt_MBE(Imbe_Fence) ); 6398 break; 6399 6400 /* X-Form */ 6401 case 0x1F: 6402 switch (opc2) { 6403 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394) 6404 if (M0 == 0) { 6405 if (b11to20 != 0 || b0 != 0) { 6406 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n"); 6407 return False; 6408 } 6409 DIP("eieio\n"); 6410 } else { 6411 if (b11to20 != 0 || b0 != 0) { 6412 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n"); 6413 return False; 6414 } 6415 DIP("mbar %d\n", M0); 6416 } 6417 /* Insert a memory fence, just to be on the safe side. */ 6418 stmt( IRStmt_MBE(Imbe_Fence) ); 6419 break; 6420 6421 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 6422 IRTemp res; 6423 /* According to the PowerPC ISA version 2.05, b0 (called EH 6424 in the documentation) is merely a hint bit to the 6425 hardware, I think as to whether or not contention is 6426 likely. So we can just ignore it. */ 6427 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6428 6429 // trap if misaligned 6430 gen_SIGBUS_if_misaligned( EA, 4 ); 6431 6432 // and actually do the load 6433 res = newTemp(Ity_I32); 6434 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6435 6436 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 6437 break; 6438 } 6439 6440 case 0x034: { // lbarx (Load Word and Reserve Indexed) 6441 IRTemp res; 6442 /* According to the PowerPC ISA version 2.05, b0 (called EH 6443 in the documentation) is merely a hint bit to the 6444 hardware, I think as to whether or not contention is 6445 likely. So we can just ignore it. */ 6446 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6447 6448 // and actually do the load 6449 res = newTemp(Ity_I8); 6450 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6451 6452 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 6453 break; 6454 } 6455 6456 case 0x074: { // lharx (Load Word and Reserve Indexed) 6457 IRTemp res; 6458 /* According to the PowerPC ISA version 2.05, b0 (called EH 6459 in the documentation) is merely a hint bit to the 6460 hardware, I think as to whether or not contention is 6461 likely. So we can just ignore it. */ 6462 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6463 6464 // trap if misaligned 6465 gen_SIGBUS_if_misaligned( EA, 2 ); 6466 6467 // and actually do the load 6468 res = newTemp(Ity_I16); 6469 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6470 6471 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 6472 break; 6473 } 6474 6475 case 0x096: { 6476 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 6477 // Note this has to handle stwcx. in both 32- and 64-bit modes, 6478 // so isn't quite as straightforward as it might otherwise be. 6479 IRTemp rS = newTemp(Ity_I32); 6480 IRTemp resSC; 6481 if (b0 != 1) { 6482 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6483 return False; 6484 } 6485 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6486 6487 // trap if misaligned 6488 gen_SIGBUS_if_misaligned( EA, 4 ); 6489 6490 // Get the data to be stored, and narrow to 32 bits if necessary 6491 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6492 6493 // Do the store, and get success/failure bit into resSC 6494 resSC = newTemp(Ity_I1); 6495 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6496 6497 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6498 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6499 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6500 putCR0(0, getXER_SO()); 6501 6502 /* Note: 6503 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6504 whether rS is stored is dependent on that value. */ 6505 /* So I guess we can just ignore this case? */ 6506 break; 6507 } 6508 6509 case 0x2B6: { 6510 // stbcx. (Store Byte Conditional Indexed) 6511 // Note this has to handle stbcx. in both 32- and 64-bit modes, 6512 // so isn't quite as straightforward as it might otherwise be. 6513 IRTemp rS = newTemp(Ity_I8); 6514 IRTemp resSC; 6515 if (b0 != 1) { 6516 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 6517 return False; 6518 } 6519 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6520 6521 // Get the data to be stored, and narrow to 32 bits if necessary 6522 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 6523 6524 // Do the store, and get success/failure bit into resSC 6525 resSC = newTemp(Ity_I1); 6526 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6527 6528 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6529 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6530 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6531 putCR0(0, getXER_SO()); 6532 6533 /* Note: 6534 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 6535 whether rS is stored is dependent on that value. */ 6536 /* So I guess we can just ignore this case? */ 6537 break; 6538 } 6539 6540 case 0x2D6: { 6541 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 6542 // Note this has to handle sthcx. in both 32- and 64-bit modes, 6543 // so isn't quite as straightforward as it might otherwise be. 6544 IRTemp rS = newTemp(Ity_I16); 6545 IRTemp resSC; 6546 if (b0 != 1) { 6547 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6548 return False; 6549 } 6550 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6551 6552 // trap if misaligned 6553 gen_SIGBUS_if_misaligned( EA, 2 ); 6554 6555 // Get the data to be stored, and narrow to 16 bits if necessary 6556 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 6557 6558 // Do the store, and get success/failure bit into resSC 6559 resSC = newTemp(Ity_I1); 6560 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6561 6562 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6563 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6564 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6565 putCR0(0, getXER_SO()); 6566 6567 /* Note: 6568 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 6569 whether rS is stored is dependent on that value. */ 6570 /* So I guess we can just ignore this case? */ 6571 break; 6572 } 6573 6574 case 0x256: // sync (Synchronize, PPC32 p543), 6575 // also lwsync (L==1), ptesync (L==2) 6576 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 6577 6578 The PowerPC architecture used in IBM chips has expanded 6579 the sync instruction into two variants: lightweight sync 6580 and heavyweight sync. The original sync instruction is 6581 the new heavyweight sync and lightweight sync is a strict 6582 subset of the heavyweight sync functionality. This allows 6583 the programmer to specify a less expensive operation on 6584 high-end systems when the full sync functionality is not 6585 necessary. 6586 6587 The basic "sync" mnemonic now utilizes an operand. "sync" 6588 without an operand now becomes a extended mnemonic for 6589 heavyweight sync. Processors without the lwsync 6590 instruction will not decode the L field and will perform a 6591 heavyweight sync. Everything is backward compatible. 6592 6593 sync = sync 0 6594 lwsync = sync 1 6595 ptesync = sync 2 *** TODO - not implemented *** 6596 */ 6597 if (b11to20 != 0 || b0 != 0) { 6598 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 6599 return False; 6600 } 6601 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 6602 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 6603 return False; 6604 } 6605 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 6606 /* Insert a memory fence. It's sometimes important that these 6607 are carried through to the generated code. */ 6608 stmt( IRStmt_MBE(Imbe_Fence) ); 6609 break; 6610 6611 /* 64bit Memsync */ 6612 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 6613 IRTemp res; 6614 /* According to the PowerPC ISA version 2.05, b0 (called EH 6615 in the documentation) is merely a hint bit to the 6616 hardware, I think as to whether or not contention is 6617 likely. So we can just ignore it. */ 6618 if (!mode64) 6619 return False; 6620 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6621 6622 // trap if misaligned 6623 gen_SIGBUS_if_misaligned( EA, 8 ); 6624 6625 // and actually do the load 6626 res = newTemp(Ity_I64); 6627 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 6628 6629 putIReg( rD_addr, mkexpr(res) ); 6630 break; 6631 } 6632 6633 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 6634 // A marginally simplified version of the stwcx. case 6635 IRTemp rS = newTemp(Ity_I64); 6636 IRTemp resSC; 6637 if (b0 != 1) { 6638 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 6639 return False; 6640 } 6641 if (!mode64) 6642 return False; 6643 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6644 6645 // trap if misaligned 6646 gen_SIGBUS_if_misaligned( EA, 8 ); 6647 6648 // Get the data to be stored 6649 assign( rS, getIReg(rS_addr) ); 6650 6651 // Do the store, and get success/failure bit into resSC 6652 resSC = newTemp(Ity_I1); 6653 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6654 6655 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6656 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6657 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6658 putCR0(0, getXER_SO()); 6659 6660 /* Note: 6661 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6662 whether rS is stored is dependent on that value. */ 6663 /* So I guess we can just ignore this case? */ 6664 break; 6665 } 6666 6667 /* 128bit Memsync */ 6668 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 6669 IRTemp res_hi = newTemp(ty); 6670 IRTemp res_lo = newTemp(ty); 6671 6672 /* According to the PowerPC ISA version 2.07, b0 (called EH 6673 in the documentation) is merely a hint bit to the 6674 hardware, I think as to whether or not contention is 6675 likely. So we can just ignore it. */ 6676 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6677 6678 // trap if misaligned 6679 gen_SIGBUS_if_misaligned( EA, 16 ); 6680 6681 // and actually do the load 6682 if (mode64) { 6683 if (host_endness == VexEndnessBE) { 6684 stmt( stmt_load( res_hi, 6685 mkexpr(EA), NULL/*this is a load*/) ); 6686 stmt( stmt_load( res_lo, 6687 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6688 NULL/*this is a load*/) ); 6689 } else { 6690 stmt( stmt_load( res_lo, 6691 mkexpr(EA), NULL/*this is a load*/) ); 6692 stmt( stmt_load( res_hi, 6693 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6694 NULL/*this is a load*/) ); 6695 } 6696 } else { 6697 stmt( stmt_load( res_hi, 6698 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 6699 NULL/*this is a load*/) ); 6700 stmt( stmt_load( res_lo, 6701 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 6702 NULL/*this is a load*/) ); 6703 } 6704 putIReg( rD_addr, mkexpr(res_hi) ); 6705 putIReg( rD_addr+1, mkexpr(res_lo) ); 6706 break; 6707 } 6708 6709 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 6710 // A marginally simplified version of the stwcx. case 6711 IRTemp rS_hi = newTemp(ty); 6712 IRTemp rS_lo = newTemp(ty); 6713 IRTemp resSC; 6714 if (b0 != 1) { 6715 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 6716 return False; 6717 } 6718 6719 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6720 6721 // trap if misaligned 6722 gen_SIGBUS_if_misaligned( EA, 16 ); 6723 // Get the data to be stored 6724 assign( rS_hi, getIReg(rS_addr) ); 6725 assign( rS_lo, getIReg(rS_addr+1) ); 6726 6727 // Do the store, and get success/failure bit into resSC 6728 resSC = newTemp(Ity_I1); 6729 6730 if (mode64) { 6731 if (host_endness == VexEndnessBE) { 6732 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 6733 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6734 mkexpr(rS_lo) ); 6735 } else { 6736 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 6737 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6738 mkexpr(rS_hi) ); 6739 } 6740 } else { 6741 stmt( stmt_load( resSC, binop( Iop_Add32, 6742 mkexpr(EA), 6743 mkU32(4) ), 6744 mkexpr(rS_hi) ) ); 6745 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 6746 } 6747 6748 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6749 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6750 putCR321(0, binop( Iop_Shl8, 6751 unop(Iop_1Uto8, mkexpr(resSC) ), 6752 mkU8(1))); 6753 putCR0(0, getXER_SO()); 6754 break; 6755 } 6756 6757 default: 6758 vex_printf("dis_memsync(ppc)(opc2)\n"); 6759 return False; 6760 } 6761 break; 6762 6763 default: 6764 vex_printf("dis_memsync(ppc)(opc1)\n"); 6765 return False; 6766 } 6767 return True; 6768 } 6769 6770 6771 6772 /* 6773 Integer Shift Instructions 6774 */ 6775 static Bool dis_int_shift ( UInt theInstr ) 6776 { 6777 /* X-Form, XS-Form */ 6778 UChar opc1 = ifieldOPC(theInstr); 6779 UChar rS_addr = ifieldRegDS(theInstr); 6780 UChar rA_addr = ifieldRegA(theInstr); 6781 UChar rB_addr = ifieldRegB(theInstr); 6782 UChar sh_imm = rB_addr; 6783 UInt opc2 = ifieldOPClo10(theInstr); 6784 UChar b1 = ifieldBIT1(theInstr); 6785 UChar flag_rC = ifieldBIT0(theInstr); 6786 6787 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6788 IRTemp rA = newTemp(ty); 6789 IRTemp rS = newTemp(ty); 6790 IRTemp rB = newTemp(ty); 6791 IRTemp outofrange = newTemp(Ity_I1); 6792 IRTemp rS_lo32 = newTemp(Ity_I32); 6793 IRTemp rB_lo32 = newTemp(Ity_I32); 6794 IRExpr* e_tmp; 6795 6796 assign( rS, getIReg(rS_addr) ); 6797 assign( rB, getIReg(rB_addr) ); 6798 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6799 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6800 6801 if (opc1 == 0x1F) { 6802 switch (opc2) { 6803 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6804 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6805 rA_addr, rS_addr, rB_addr); 6806 /* rA = rS << rB */ 6807 /* ppc32 semantics are: 6808 slw(x,y) = (x << (y & 31)) -- primary result 6809 & ~((y << 26) >>s 31) -- make result 0 6810 for y in 32 .. 63 6811 */ 6812 e_tmp = 6813 binop( Iop_And32, 6814 binop( Iop_Shl32, 6815 mkexpr(rS_lo32), 6816 unop( Iop_32to8, 6817 binop(Iop_And32, 6818 mkexpr(rB_lo32), mkU32(31)))), 6819 unop( Iop_Not32, 6820 binop( Iop_Sar32, 6821 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6822 mkU8(31))) ); 6823 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6824 break; 6825 } 6826 6827 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6828 IRTemp sh_amt = newTemp(Ity_I32); 6829 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6830 rA_addr, rS_addr, rB_addr); 6831 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6832 amt = rB & 63 6833 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6834 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6835 */ 6836 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6837 mkexpr(rB_lo32)) ); 6838 assign( outofrange, 6839 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 6840 e_tmp = binop( Iop_Sar32, 6841 mkexpr(rS_lo32), 6842 unop( Iop_32to8, 6843 IRExpr_ITE( mkexpr(outofrange), 6844 mkU32(31), 6845 mkexpr(sh_amt)) ) ); 6846 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6847 6848 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6849 mkexpr(rA), 6850 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6851 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6852 mkWidenFrom32(ty, getXER_CA32(), True) ); 6853 break; 6854 } 6855 6856 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6857 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6858 rA_addr, rS_addr, sh_imm); 6859 vassert(sh_imm < 32); 6860 if (mode64) { 6861 assign( rA, binop(Iop_Sar64, 6862 binop(Iop_Shl64, getIReg(rS_addr), 6863 mkU8(32)), 6864 mkU8(32 + sh_imm)) ); 6865 } else { 6866 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6867 mkU8(sh_imm)) ); 6868 } 6869 6870 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6871 mkexpr(rA), 6872 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6873 mkSzImm(ty, sh_imm), 6874 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6875 break; 6876 6877 case 0x218: // srw (Shift Right Word, PPC32 p508) 6878 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6879 rA_addr, rS_addr, rB_addr); 6880 /* rA = rS >>u rB */ 6881 /* ppc32 semantics are: 6882 srw(x,y) = (x >>u (y & 31)) -- primary result 6883 & ~((y << 26) >>s 31) -- make result 0 6884 for y in 32 .. 63 6885 */ 6886 e_tmp = 6887 binop( 6888 Iop_And32, 6889 binop( Iop_Shr32, 6890 mkexpr(rS_lo32), 6891 unop( Iop_32to8, 6892 binop(Iop_And32, mkexpr(rB_lo32), 6893 mkU32(31)))), 6894 unop( Iop_Not32, 6895 binop( Iop_Sar32, 6896 binop(Iop_Shl32, mkexpr(rB_lo32), 6897 mkU8(26)), 6898 mkU8(31)))); 6899 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6900 break; 6901 6902 6903 /* 64bit Shifts */ 6904 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6905 DIP("sld%s r%u,r%u,r%u\n", 6906 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6907 /* rA = rS << rB */ 6908 /* ppc64 semantics are: 6909 slw(x,y) = (x << (y & 63)) -- primary result 6910 & ~((y << 57) >>s 63) -- make result 0 6911 for y in 64 .. 6912 */ 6913 assign( rA, 6914 binop( 6915 Iop_And64, 6916 binop( Iop_Shl64, 6917 mkexpr(rS), 6918 unop( Iop_64to8, 6919 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6920 unop( Iop_Not64, 6921 binop( Iop_Sar64, 6922 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6923 mkU8(63)))) ); 6924 break; 6925 6926 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6927 IRTemp sh_amt = newTemp(Ity_I64); 6928 DIP("srad%s r%u,r%u,r%u\n", 6929 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6930 /* amt = rB & 127 6931 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6932 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6933 */ 6934 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6935 assign( outofrange, 6936 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 6937 assign( rA, 6938 binop( Iop_Sar64, 6939 mkexpr(rS), 6940 unop( Iop_64to8, 6941 IRExpr_ITE( mkexpr(outofrange), 6942 mkU64(63), 6943 mkexpr(sh_amt)) )) 6944 ); 6945 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6946 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6947 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6948 break; 6949 } 6950 6951 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6952 sh_imm |= b1<<5; 6953 vassert(sh_imm < 64); 6954 DIP("sradi%s r%u,r%u,%u\n", 6955 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6956 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6957 6958 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6959 mkexpr(rA), 6960 getIReg(rS_addr), 6961 mkU64(sh_imm), 6962 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6963 break; 6964 6965 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6966 DIP("srd%s r%u,r%u,r%u\n", 6967 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6968 /* rA = rS >>u rB */ 6969 /* ppc semantics are: 6970 srw(x,y) = (x >>u (y & 63)) -- primary result 6971 & ~((y << 57) >>s 63) -- make result 0 6972 for y in 64 .. 127 6973 */ 6974 assign( rA, 6975 binop( 6976 Iop_And64, 6977 binop( Iop_Shr64, 6978 mkexpr(rS), 6979 unop( Iop_64to8, 6980 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6981 unop( Iop_Not64, 6982 binop( Iop_Sar64, 6983 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6984 mkU8(63)))) ); 6985 break; 6986 6987 default: 6988 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6989 return False; 6990 } 6991 } else { 6992 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6993 return False; 6994 } 6995 6996 putIReg( rA_addr, mkexpr(rA) ); 6997 6998 if (flag_rC) { 6999 set_CR0( mkexpr(rA) ); 7000 } 7001 return True; 7002 } 7003 7004 7005 7006 /* 7007 Integer Load/Store Reverse Instructions 7008 */ 7009 /* Generates code to swap the byte order in an Ity_I32. */ 7010 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 7011 { 7012 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 7013 return 7014 binop(Iop_Or32, 7015 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 7016 binop(Iop_Or32, 7017 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 7018 mkU32(0x00FF0000)), 7019 binop(Iop_Or32, 7020 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 7021 mkU32(0x0000FF00)), 7022 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 7023 mkU32(0x000000FF) ) 7024 ))); 7025 } 7026 7027 /* Generates code to swap the byte order in the lower half of an Ity_I32, 7028 and zeroes the upper half. */ 7029 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 7030 { 7031 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 7032 return 7033 binop(Iop_Or32, 7034 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 7035 mkU32(0x0000FF00)), 7036 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 7037 mkU32(0x000000FF)) 7038 ); 7039 } 7040 7041 static Bool dis_int_ldst_rev ( UInt theInstr ) 7042 { 7043 /* X-Form */ 7044 UChar opc1 = ifieldOPC(theInstr); 7045 UChar rD_addr = ifieldRegDS(theInstr); 7046 UChar rS_addr = rD_addr; 7047 UChar rA_addr = ifieldRegA(theInstr); 7048 UChar rB_addr = ifieldRegB(theInstr); 7049 UInt opc2 = ifieldOPClo10(theInstr); 7050 UChar b0 = ifieldBIT0(theInstr); 7051 7052 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7053 IRTemp EA = newTemp(ty); 7054 IRTemp w1 = newTemp(Ity_I32); 7055 IRTemp w2 = newTemp(Ity_I32); 7056 7057 if (opc1 != 0x1F || b0 != 0) { 7058 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 7059 return False; 7060 } 7061 7062 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7063 7064 switch (opc2) { 7065 7066 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 7067 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7068 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 7069 assign( w2, gen_byterev16(w1) ); 7070 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 7071 /* Signed */False) ); 7072 break; 7073 7074 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 7075 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7076 assign( w1, load(Ity_I32, mkexpr(EA)) ); 7077 assign( w2, gen_byterev32(w1) ); 7078 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 7079 /* Signed */False) ); 7080 break; 7081 7082 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 7083 { 7084 IRExpr * nextAddr; 7085 IRTemp w3 = newTemp( Ity_I32 ); 7086 IRTemp w4 = newTemp( Ity_I32 ); 7087 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7088 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 7089 assign( w2, gen_byterev32( w1 ) ); 7090 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 7091 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 7092 assign( w3, load( Ity_I32, nextAddr ) ); 7093 assign( w4, gen_byterev32( w3 ) ); 7094 if (host_endness == VexEndnessLE) 7095 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 7096 else 7097 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 7098 break; 7099 } 7100 7101 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 7102 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7103 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 7104 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 7105 break; 7106 7107 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 7108 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7109 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 7110 store( mkexpr(EA), gen_byterev32(w1) ); 7111 break; 7112 7113 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 7114 { 7115 IRTemp lo = newTemp(Ity_I32); 7116 IRTemp hi = newTemp(Ity_I32); 7117 IRTemp rS = newTemp(Ity_I64); 7118 assign( rS, getIReg( rS_addr ) ); 7119 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7120 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 7121 assign(hi, unop(Iop_64to32, mkexpr(rS))); 7122 store( mkexpr( EA ), 7123 binop( Iop_32HLto64, gen_byterev32( hi ), 7124 gen_byterev32( lo ) ) ); 7125 break; 7126 } 7127 7128 default: 7129 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 7130 return False; 7131 } 7132 return True; 7133 } 7134 7135 7136 7137 /* 7138 Processor Control Instructions 7139 */ 7140 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 7141 { 7142 UChar opc1 = ifieldOPC(theInstr); 7143 7144 /* X-Form */ 7145 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7146 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7147 UChar rD_addr = ifieldRegDS(theInstr); 7148 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 7149 7150 /* XFX-Form */ 7151 UChar rS_addr = rD_addr; 7152 UInt SPR = b11to20; 7153 UInt TBR = b11to20; 7154 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 7155 UInt CRM = IFIELD( theInstr, 12, 8 ); 7156 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 7157 7158 UInt opc2 = ifieldOPClo10(theInstr); 7159 UChar b0 = ifieldBIT0(theInstr); 7160 7161 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7162 IRTemp rS = newTemp(ty); 7163 assign( rS, getIReg(rS_addr) ); 7164 7165 /* Reorder SPR field as per PPC32 p470 */ 7166 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 7167 /* Reorder TBR field as per PPC32 p475 */ 7168 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 7169 7170 /* b0 = 0, inst is treated as floating point inst for reservation purposes 7171 * b0 = 1, inst is treated as vector inst for reservation purposes 7172 */ 7173 if (opc1 != 0x1F) { 7174 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 7175 return False; 7176 } 7177 7178 switch (opc2) { 7179 /* X-Form */ 7180 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 7181 if (b21to22 != 0 || b11to20 != 0) { 7182 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 7183 return False; 7184 } 7185 DIP("mcrxr crf%d\n", crfD); 7186 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 7187 putGST_field( PPC_GST_CR, 7188 getGST_field( PPC_GST_XER, 7 ), 7189 crfD ); 7190 7191 // Clear XER[0-3] 7192 putXER_SO( mkU8(0) ); 7193 putXER_OV( mkU8(0) ); 7194 putXER_CA( mkU8(0) ); 7195 break; 7196 } 7197 7198 case 0x013: 7199 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 7200 // b20==1 & b11==0: mfocrf (Move from One CR Field) 7201 // However it seems that the 'mfcr' behaviour is an acceptable 7202 // implementation of mfocr (from the 2.02 arch spec) 7203 if (b11to20 == 0) { 7204 DIP("mfcr r%u\n", rD_addr); 7205 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7206 /* Signed */False) ); 7207 break; 7208 } 7209 if (b20 == 1 && b11 == 0) { 7210 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 7211 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7212 /* Signed */False) ); 7213 break; 7214 } 7215 /* not decodable */ 7216 return False; 7217 7218 /* XFX-Form */ 7219 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 7220 7221 switch (SPR) { // Choose a register... 7222 case 0x1: 7223 DIP("mfxer r%u\n", rD_addr); 7224 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 7225 /* Signed */False) ); 7226 break; 7227 case 0x8: 7228 DIP("mflr r%u\n", rD_addr); 7229 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 7230 break; 7231 case 0x9: 7232 DIP("mfctr r%u\n", rD_addr); 7233 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 7234 break; 7235 case 0x80: // 128 7236 DIP("mfspr r%u (TFHAR)\n", rD_addr); 7237 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 7238 break; 7239 case 0x81: // 129 7240 DIP("mfspr r%u (TFIAR)\n", rD_addr); 7241 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 7242 break; 7243 case 0x82: // 130 7244 DIP("mfspr r%u (TEXASR)\n", rD_addr); 7245 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 7246 break; 7247 case 0x83: // 131 7248 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 7249 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 7250 break; 7251 case 0x9F: // 159 7252 DIP("mfspr r%u (PSPB)\n", rD_addr); 7253 putIReg( rD_addr, getGST( PPC_GST_PSPB) ); 7254 break; 7255 case 0x380: // 896 7256 DIP("mfspr r%u (PPR)\n", rD_addr); 7257 putIReg( rD_addr, getGST( PPC_GST_PPR) ); 7258 break; 7259 case 0x382: // 898 7260 DIP("mfspr r%u (PPR)32\n", rD_addr); 7261 putIReg( rD_addr, getGST( PPC_GST_PPR32) ); 7262 break; 7263 case 0x100: 7264 DIP("mfvrsave r%u\n", rD_addr); 7265 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 7266 /* Signed */False) ); 7267 break; 7268 7269 case 0x103: 7270 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 7271 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 7272 break; 7273 7274 /* Even a lowly PPC7400 can run the associated helper, so no 7275 obvious need for feature testing at this point. */ 7276 case 268 /* 0x10C */: 7277 case 269 /* 0x10D */: { 7278 UInt arg = SPR==268 ? 0 : 1; 7279 IRTemp val = newTemp(Ity_I32); 7280 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 7281 IRDirty* d = unsafeIRDirty_1_N( 7282 val, 7283 0/*regparms*/, 7284 "ppc32g_dirtyhelper_MFSPR_268_269", 7285 fnptr_to_fnentry 7286 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 7287 args 7288 ); 7289 /* execute the dirty call, dumping the result in val. */ 7290 stmt( IRStmt_Dirty(d) ); 7291 putIReg( rD_addr, 7292 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7293 DIP("mfspr r%u,%u", rD_addr, SPR); 7294 break; 7295 } 7296 7297 /* Again, runs natively on PPC7400 (7447, really). Not 7298 bothering with a feature test. */ 7299 case 287: /* 0x11F */ { 7300 IRTemp val = newTemp(Ity_I32); 7301 IRExpr** args = mkIRExprVec_0(); 7302 IRDirty* d = unsafeIRDirty_1_N( 7303 val, 7304 0/*regparms*/, 7305 "ppc32g_dirtyhelper_MFSPR_287", 7306 fnptr_to_fnentry 7307 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 7308 args 7309 ); 7310 /* execute the dirty call, dumping the result in val. */ 7311 stmt( IRStmt_Dirty(d) ); 7312 putIReg( rD_addr, 7313 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7314 DIP("mfspr r%u,%u", rD_addr, SPR); 7315 break; 7316 } 7317 7318 default: 7319 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 7320 return False; 7321 } 7322 break; 7323 7324 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 7325 IRTemp val = newTemp(Ity_I64); 7326 IRExpr** args = mkIRExprVec_0(); 7327 IRDirty* d = unsafeIRDirty_1_N( 7328 val, 7329 0/*regparms*/, 7330 "ppcg_dirtyhelper_MFTB", 7331 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 7332 args ); 7333 /* execute the dirty call, dumping the result in val. */ 7334 stmt( IRStmt_Dirty(d) ); 7335 7336 switch (TBR) { 7337 case 269: 7338 DIP("mftbu r%u", rD_addr); 7339 putIReg( rD_addr, 7340 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 7341 /* Signed */False) ); 7342 break; 7343 case 268: 7344 DIP("mftb r%u", rD_addr); 7345 putIReg( rD_addr, (mode64) ? mkexpr(val) : 7346 unop(Iop_64to32, mkexpr(val)) ); 7347 break; 7348 default: 7349 return False; /* illegal instruction */ 7350 } 7351 break; 7352 } 7353 7354 case 0x090: { 7355 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 7356 // b20==1: mtocrf (Move to One Cond Reg Field) 7357 Int cr; 7358 UChar shft; 7359 if (b11 != 0) 7360 return False; 7361 if (b20 == 1) { 7362 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 7363 1 field is written. It seems more robust to decline to 7364 decode the insn if so. */ 7365 switch (CRM) { 7366 case 0x01: case 0x02: case 0x04: case 0x08: 7367 case 0x10: case 0x20: case 0x40: case 0x80: 7368 break; 7369 default: 7370 return False; 7371 } 7372 } 7373 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 7374 CRM, rS_addr); 7375 /* Write to each field specified by CRM */ 7376 for (cr = 0; cr < 8; cr++) { 7377 if ((CRM & (1 << (7-cr))) == 0) 7378 continue; 7379 shft = 4*(7-cr); 7380 putGST_field( PPC_GST_CR, 7381 binop(Iop_Shr32, 7382 mkNarrowTo32(ty, mkexpr(rS)), 7383 mkU8(shft)), cr ); 7384 } 7385 break; 7386 } 7387 7388 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 7389 7390 switch (SPR) { // Choose a register... 7391 case 0x1: 7392 DIP("mtxer r%u\n", rS_addr); 7393 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 7394 break; 7395 case 0x8: 7396 DIP("mtlr r%u\n", rS_addr); 7397 putGST( PPC_GST_LR, mkexpr(rS) ); 7398 break; 7399 case 0x9: 7400 DIP("mtctr r%u\n", rS_addr); 7401 putGST( PPC_GST_CTR, mkexpr(rS) ); 7402 break; 7403 case 0x100: 7404 DIP("mtvrsave r%u\n", rS_addr); 7405 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 7406 break; 7407 case 0x80: // 128 7408 DIP("mtspr r%u (TFHAR)\n", rS_addr); 7409 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 7410 break; 7411 case 0x81: // 129 7412 DIP("mtspr r%u (TFIAR)\n", rS_addr); 7413 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 7414 break; 7415 case 0x82: // 130 7416 DIP("mtspr r%u (TEXASR)\n", rS_addr); 7417 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 7418 break; 7419 case 0x9F: // 159 7420 DIP("mtspr r%u (PSPB)\n", rS_addr); 7421 putGST( PPC_GST_PSPB, mkexpr(rS) ); 7422 break; 7423 case 0x380: // 896 7424 DIP("mtspr r%u (PPR)\n", rS_addr); 7425 putGST( PPC_GST_PPR, mkexpr(rS) ); 7426 break; 7427 case 0x382: // 898 7428 DIP("mtspr r%u (PPR32)\n", rS_addr); 7429 putGST( PPC_GST_PPR32, mkexpr(rS) ); 7430 break; 7431 default: 7432 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 7433 return False; 7434 } 7435 break; 7436 7437 case 0x33: // mfvsrd 7438 { 7439 UChar XS = ifieldRegXS( theInstr ); 7440 UChar rA_addr = ifieldRegA(theInstr); 7441 IRExpr * high64; 7442 IRTemp vS = newTemp( Ity_V128 ); 7443 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS); 7444 7445 /* XS = SX || S 7446 * For SX=0, mfvsrd is treated as a Floating-Point 7447 * instruction in terms of resource availability. 7448 * For SX=1, mfvsrd is treated as a Vector instruction in 7449 * terms of resource availability. 7450 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7451 */ 7452 assign( vS, getVSReg( XS ) ); 7453 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7454 putIReg( rA_addr, (mode64) ? high64 : 7455 unop( Iop_64to32, high64 ) ); 7456 break; 7457 } 7458 7459 case 0x73: // mfvsrwz 7460 { 7461 UChar XS = ifieldRegXS( theInstr ); 7462 UChar rA_addr = ifieldRegA(theInstr); 7463 IRExpr * high64; 7464 IRTemp vS = newTemp( Ity_V128 ); 7465 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS); 7466 /* XS = SX || S 7467 * For SX=0, mfvsrwz is treated as a Floating-Point 7468 * instruction in terms of resource availability. 7469 * For SX=1, mfvsrwz is treated as a Vector instruction in 7470 * terms of resource availability. 7471 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7472 */ 7473 7474 assign( vS, getVSReg( XS ) ); 7475 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7476 /* move value to the destination setting the upper 32-bits to zero */ 7477 putIReg( rA_addr, (mode64) ? 7478 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 7479 unop( Iop_64to32, 7480 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 7481 break; 7482 } 7483 7484 case 0xB3: // mtvsrd 7485 { 7486 UChar XT = ifieldRegXT( theInstr ); 7487 UChar rA_addr = ifieldRegA(theInstr); 7488 IRTemp rA = newTemp(ty); 7489 DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr); 7490 /* XS = SX || S 7491 * For SX=0, mfvsrd is treated as a Floating-Point 7492 * instruction in terms of resource availability. 7493 * For SX=1, mfvsrd is treated as a Vector instruction in 7494 * terms of resource availability. 7495 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7496 */ 7497 assign( rA, getIReg(rA_addr) ); 7498 7499 if (mode64) 7500 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 7501 else 7502 putVSReg( XT, binop( Iop_64HLtoV128, 7503 binop( Iop_32HLto64, 7504 mkU32( 0 ), 7505 mkexpr( rA ) ), 7506 mkU64( 0 ) ) ); 7507 break; 7508 } 7509 7510 case 0xD3: // mtvsrwa 7511 { 7512 UChar XT = ifieldRegXT( theInstr ); 7513 UChar rA_addr = ifieldRegA(theInstr); 7514 IRTemp rA = newTemp( Ity_I32 ); 7515 DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr); 7516 /* XS = SX || S 7517 * For SX=0, mtvsrwa is treated as a Floating-Point 7518 * instruction in terms of resource availability. 7519 * For SX=1, mtvsrwa is treated as a Vector instruction in 7520 * terms of resource availability. 7521 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7522 */ 7523 if (mode64) 7524 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7525 else 7526 assign( rA, getIReg(rA_addr) ); 7527 7528 putVSReg( XT, binop( Iop_64HLtoV128, 7529 unop( Iop_32Sto64, mkexpr( rA ) ), 7530 mkU64( 0 ) ) ); 7531 break; 7532 } 7533 7534 case 0xF3: // mtvsrwz 7535 { 7536 UChar XT = ifieldRegXT( theInstr ); 7537 UChar rA_addr = ifieldRegA(theInstr); 7538 IRTemp rA = newTemp( Ity_I32 ); 7539 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT); 7540 /* XS = SX || S 7541 * For SX=0, mtvsrwz is treated as a Floating-Point 7542 * instruction in terms of resource availability. 7543 * For SX=1, mtvsrwz is treated as a Vector instruction in 7544 * terms of resource availability. 7545 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7546 */ 7547 if (mode64) 7548 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7549 else 7550 assign( rA, getIReg(rA_addr) ); 7551 7552 putVSReg( XT, binop( Iop_64HLtoV128, 7553 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 7554 mkU64( 0 ) ) ); 7555 break; 7556 } 7557 7558 default: 7559 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 7560 return False; 7561 } 7562 return True; 7563 } 7564 7565 7566 /* 7567 Cache Management Instructions 7568 */ 7569 static Bool dis_cache_manage ( UInt theInstr, 7570 DisResult* dres, 7571 const VexArchInfo* guest_archinfo ) 7572 { 7573 /* X-Form */ 7574 UChar opc1 = ifieldOPC(theInstr); 7575 UChar b21to25 = ifieldRegDS(theInstr); 7576 UChar rA_addr = ifieldRegA(theInstr); 7577 UChar rB_addr = ifieldRegB(theInstr); 7578 UInt opc2 = ifieldOPClo10(theInstr); 7579 UChar b0 = ifieldBIT0(theInstr); 7580 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 7581 Bool is_dcbzl = False; 7582 7583 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7584 7585 // Check for valid hint values for dcbt and dcbtst as currently described in 7586 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 7587 // means of modeling the hint anyway. 7588 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 7589 if (b21to25 == 0x10 || b21to25 < 0x10) 7590 b21to25 = 0; 7591 } 7592 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 7593 b21to25 = 0; 7594 7595 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 7596 if (b21to25 == 1) { 7597 is_dcbzl = True; 7598 b21to25 = 0; 7599 if (!(guest_archinfo->ppc_dcbzl_szB)) { 7600 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 7601 return False; 7602 } 7603 } 7604 } 7605 7606 if (opc1 != 0x1F || b0 != 0) { 7607 if (0) vex_printf("dis_cache_manage %d %d\n", 7608 opc1, b0); 7609 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n"); 7610 return False; 7611 } 7612 7613 /* stay sane .. */ 7614 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 7615 7616 switch (opc2) { 7617 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 7618 //zz vassert(0); /* AWAITING TEST CASE */ 7619 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 7620 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 7621 //zz break; 7622 7623 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 7624 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 7625 /* nop as far as vex is concerned */ 7626 break; 7627 7628 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 7629 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 7630 /* nop as far as vex is concerned */ 7631 break; 7632 7633 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 7634 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 7635 /* nop as far as vex is concerned */ 7636 break; 7637 7638 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 7639 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 7640 /* nop as far as vex is concerned */ 7641 break; 7642 7643 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 7644 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 7645 /* Clear all bytes in cache block at (rA|0) + rB. */ 7646 IRTemp EA = newTemp(ty); 7647 IRTemp addr = newTemp(ty); 7648 IRExpr* irx_addr; 7649 UInt i; 7650 UInt clearszB; 7651 if (is_dcbzl) { 7652 clearszB = guest_archinfo->ppc_dcbzl_szB; 7653 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 7654 } 7655 else { 7656 clearszB = guest_archinfo->ppc_dcbz_szB; 7657 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 7658 } 7659 7660 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7661 7662 if (mode64) { 7663 /* Round EA down to the start of the containing block. */ 7664 assign( addr, binop( Iop_And64, 7665 mkexpr(EA), 7666 mkU64( ~((ULong)clearszB-1) )) ); 7667 7668 for (i = 0; i < clearszB / 8; i++) { 7669 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 7670 store( irx_addr, mkU64(0) ); 7671 } 7672 } else { 7673 /* Round EA down to the start of the containing block. */ 7674 assign( addr, binop( Iop_And32, 7675 mkexpr(EA), 7676 mkU32( ~(clearszB-1) )) ); 7677 7678 for (i = 0; i < clearszB / 4; i++) { 7679 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 7680 store( irx_addr, mkU32(0) ); 7681 } 7682 } 7683 break; 7684 } 7685 7686 case 0x3D6: { 7687 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 7688 /* Invalidate all translations containing code from the cache 7689 block at (rA|0) + rB. */ 7690 IRTemp EA = newTemp(ty); 7691 IRTemp addr = newTemp(ty); 7692 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 7693 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7694 7695 /* Round EA down to the start of the containing block. */ 7696 assign( addr, binop( mkSzOp(ty, Iop_And8), 7697 mkexpr(EA), 7698 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 7699 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 7700 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 7701 7702 /* be paranoid ... */ 7703 stmt( IRStmt_MBE(Imbe_Fence) ); 7704 7705 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 7706 dres->jk_StopHere = Ijk_InvalICache; 7707 dres->whatNext = Dis_StopHere; 7708 break; 7709 } 7710 7711 default: 7712 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 7713 return False; 7714 } 7715 return True; 7716 } 7717 7718 7719 /*------------------------------------------------------------*/ 7720 /*--- Floating Point Helpers ---*/ 7721 /*------------------------------------------------------------*/ 7722 7723 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 7724 /* Produces a value in 0 .. 3, which is encoded as per the type 7725 IRRoundingMode. PPCRoundingMode encoding is different to 7726 IRRoundingMode, so need to map it. 7727 */ 7728 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 7729 { 7730 /* 7731 rounding mode | PPC | IR 7732 ------------------------ 7733 to nearest | 00 | 00 7734 to zero | 01 | 11 7735 to +infinity | 10 | 10 7736 to -infinity | 11 | 01 7737 */ 7738 IRTemp rm_PPC32 = newTemp(Ity_I32); 7739 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 7740 7741 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7742 return binop( Iop_Xor32, 7743 mkexpr(rm_PPC32), 7744 binop( Iop_And32, 7745 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 7746 mkU32(2) )); 7747 } 7748 7749 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 7750 * mapping would still work with the extended three bit DFP rounding 7751 * mode designator. 7752 7753 * rounding mode | PPC | IR 7754 * ----------------------------------------------- 7755 * to nearest, ties to even | 000 | 000 7756 * to zero | 001 | 011 7757 * to +infinity | 010 | 010 7758 * to -infinity | 011 | 001 7759 * to nearest, ties away from 0 | 100 | 100 7760 * to nearest, ties toward 0 | 101 | 111 7761 * to away from 0 | 110 | 110 7762 * to prepare for shorter precision | 111 | 101 7763 */ 7764 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 7765 { 7766 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 7767 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 7768 7769 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7770 return binop( Iop_Xor32, 7771 mkexpr( rm_PPC32 ), 7772 binop( Iop_And32, 7773 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 7774 mkU32( 2 ) ) ); 7775 } 7776 7777 #define NANmaskSingle 0x7F800000 7778 #define NANmaskDouble 0x7FF00000 7779 7780 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 7781 { 7782 IRTemp exp_zero = newTemp(Ity_I8); 7783 IRTemp frac_mask = newTemp(Ity_I32); 7784 IRTemp frac_not_zero = newTemp(Ity_I8); 7785 7786 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 7787 * The input value is always 64-bits, for single precision values, the 7788 * lower 32 bits must be zero. 7789 * 7790 * Single Pricision 7791 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 7792 * [53:32] fraction field is zero for Infinity and non-zero for NAN 7793 * [31:0] unused for single precision representation 7794 * 7795 * Double Pricision 7796 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 7797 * [50:0] fraction field is zero for Infinity and non-zero for NAN 7798 * 7799 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 7800 */ 7801 assign( frac_mask, unop( Iop_Not32, 7802 binop( Iop_Or32, 7803 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 7804 7805 assign( exp_zero, 7806 unop( Iop_1Sto8, 7807 binop( Iop_CmpEQ32, 7808 binop( Iop_And32, 7809 unop( Iop_64HIto32, 7810 unop( Iop_ReinterpF64asI64, 7811 value ) ), 7812 Hi32Mask ), 7813 Hi32Mask ) ) ); 7814 assign( frac_not_zero, 7815 binop( Iop_Or8, 7816 unop( Iop_1Sto8, 7817 binop( Iop_CmpNE32, 7818 binop( Iop_And32, 7819 unop( Iop_64HIto32, 7820 unop( Iop_ReinterpF64asI64, 7821 value ) ), 7822 mkexpr( frac_mask ) ), 7823 mkU32( 0x0 ) ) ), 7824 unop( Iop_1Sto8, 7825 binop( Iop_CmpNE32, 7826 binop( Iop_And32, 7827 unop( Iop_64to32, 7828 unop( Iop_ReinterpF64asI64, 7829 value ) ), 7830 mkU32( 0xFFFFFFFF ) ), 7831 mkU32( 0x0 ) ) ) ) ); 7832 return unop( Iop_8Sto32, 7833 binop( Iop_And8, 7834 mkexpr( exp_zero ), 7835 mkexpr( frac_not_zero ) ) ); 7836 } 7837 7838 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 7839 { 7840 /* This function will only complement the 64-bit floating point value if it 7841 * is not Nan. NaN is not a signed value. Need to do computations using 7842 * 32-bit operands to ensure it will run in 32-bit mode. 7843 */ 7844 return binop( Iop_32HLto64, 7845 binop( Iop_Or32, 7846 binop( Iop_And32, 7847 nan_mask, 7848 unop( Iop_64HIto32, 7849 unop( Iop_ReinterpF64asI64, 7850 value ) ) ), 7851 binop( Iop_And32, 7852 unop( Iop_Not32, 7853 nan_mask ), 7854 unop( Iop_64HIto32, 7855 unop( Iop_ReinterpF64asI64, 7856 unop( Iop_NegF64, 7857 value ) ) ) ) ), 7858 unop( Iop_64to32, 7859 unop( Iop_ReinterpF64asI64, value ) ) ); 7860 } 7861 7862 /*------------------------------------------------------------*/ 7863 /*--- Floating Point Instruction Translation ---*/ 7864 /*------------------------------------------------------------*/ 7865 7866 /* 7867 Floating Point Load Instructions 7868 */ 7869 static Bool dis_fp_load ( UInt theInstr ) 7870 { 7871 /* X-Form, D-Form */ 7872 UChar opc1 = ifieldOPC(theInstr); 7873 UChar frD_addr = ifieldRegDS(theInstr); 7874 UChar rA_addr = ifieldRegA(theInstr); 7875 UChar rB_addr = ifieldRegB(theInstr); 7876 UInt opc2 = ifieldOPClo10(theInstr); 7877 UChar b0 = ifieldBIT0(theInstr); 7878 UInt uimm16 = ifieldUIMM16(theInstr); 7879 7880 Int simm16 = extend_s_16to32(uimm16); 7881 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7882 IRTemp EA = newTemp(ty); 7883 IRTemp rA = newTemp(ty); 7884 IRTemp rB = newTemp(ty); 7885 IRTemp iHi = newTemp(Ity_I32); 7886 IRTemp iLo = newTemp(Ity_I32); 7887 7888 assign( rA, getIReg(rA_addr) ); 7889 assign( rB, getIReg(rB_addr) ); 7890 7891 /* These are completely straightforward from a rounding and status 7892 bits perspective: no rounding involved and no funny status or CR 7893 bits affected. */ 7894 7895 switch (opc1) { 7896 case 0x30: // lfs (Load Float Single, PPC32 p441) 7897 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7898 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7899 putFReg( frD_addr, 7900 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7901 break; 7902 7903 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 7904 if (rA_addr == 0) 7905 return False; 7906 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7907 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7908 putFReg( frD_addr, 7909 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7910 putIReg( rA_addr, mkexpr(EA) ); 7911 break; 7912 7913 case 0x32: // lfd (Load Float Double, PPC32 p437) 7914 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7915 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7916 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7917 break; 7918 7919 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 7920 if (rA_addr == 0) 7921 return False; 7922 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7923 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7924 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7925 putIReg( rA_addr, mkexpr(EA) ); 7926 break; 7927 7928 case 0x1F: 7929 if (b0 != 0) { 7930 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 7931 return False; 7932 } 7933 7934 switch(opc2) { 7935 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7936 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7937 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7938 putFReg( frD_addr, unop( Iop_F32toF64, 7939 load(Ity_F32, mkexpr(EA))) ); 7940 break; 7941 7942 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7943 if (rA_addr == 0) 7944 return False; 7945 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7946 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7947 putFReg( frD_addr, 7948 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7949 putIReg( rA_addr, mkexpr(EA) ); 7950 break; 7951 7952 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7953 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7954 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7955 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7956 break; 7957 7958 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7959 if (rA_addr == 0) 7960 return False; 7961 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7962 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7963 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7964 putIReg( rA_addr, mkexpr(EA) ); 7965 break; 7966 7967 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7968 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7969 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7970 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7971 assign( iHi, binop(Iop_Sub32, 7972 mkU32(0), 7973 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7974 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7975 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7976 break; 7977 7978 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7979 { 7980 IRTemp dw = newTemp( Ity_I64 ); 7981 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7982 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7983 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7984 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7985 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7986 break; 7987 } 7988 7989 default: 7990 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7991 return False; 7992 } 7993 break; 7994 7995 default: 7996 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7997 return False; 7998 } 7999 return True; 8000 } 8001 8002 8003 8004 /* 8005 Floating Point Store Instructions 8006 */ 8007 static Bool dis_fp_store ( UInt theInstr ) 8008 { 8009 /* X-Form, D-Form */ 8010 UChar opc1 = ifieldOPC(theInstr); 8011 UChar frS_addr = ifieldRegDS(theInstr); 8012 UChar rA_addr = ifieldRegA(theInstr); 8013 UChar rB_addr = ifieldRegB(theInstr); 8014 UInt opc2 = ifieldOPClo10(theInstr); 8015 UChar b0 = ifieldBIT0(theInstr); 8016 Int uimm16 = ifieldUIMM16(theInstr); 8017 8018 Int simm16 = extend_s_16to32(uimm16); 8019 IRTemp frS = newTemp(Ity_F64); 8020 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8021 IRTemp EA = newTemp(ty); 8022 IRTemp rA = newTemp(ty); 8023 IRTemp rB = newTemp(ty); 8024 8025 assign( frS, getFReg(frS_addr) ); 8026 assign( rA, getIReg(rA_addr) ); 8027 assign( rB, getIReg(rB_addr) ); 8028 8029 /* These are straightforward from a status bits perspective: no 8030 funny status or CR bits affected. For single precision stores, 8031 the values are truncated and denormalised (not rounded) to turn 8032 them into single precision values. */ 8033 8034 switch (opc1) { 8035 8036 case 0x34: // stfs (Store Float Single, PPC32 p518) 8037 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8038 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 8039 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 8040 the value to be stored in the correct way, without any 8041 rounding. */ 8042 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8043 break; 8044 8045 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 8046 if (rA_addr == 0) 8047 return False; 8048 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8049 assign( EA, ea_rA_simm(rA_addr, simm16) ); 8050 /* See comment for stfs */ 8051 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8052 putIReg( rA_addr, mkexpr(EA) ); 8053 break; 8054 8055 case 0x36: // stfd (Store Float Double, PPC32 p513) 8056 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8057 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 8058 store( mkexpr(EA), mkexpr(frS) ); 8059 break; 8060 8061 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 8062 if (rA_addr == 0) 8063 return False; 8064 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8065 assign( EA, ea_rA_simm(rA_addr, simm16) ); 8066 store( mkexpr(EA), mkexpr(frS) ); 8067 putIReg( rA_addr, mkexpr(EA) ); 8068 break; 8069 8070 case 0x1F: 8071 if (b0 != 0) { 8072 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 8073 return False; 8074 } 8075 switch(opc2) { 8076 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 8077 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8078 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8079 /* See note for stfs */ 8080 store( mkexpr(EA), 8081 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8082 break; 8083 8084 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 8085 if (rA_addr == 0) 8086 return False; 8087 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8088 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 8089 /* See note for stfs */ 8090 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8091 putIReg( rA_addr, mkexpr(EA) ); 8092 break; 8093 8094 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 8095 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8096 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8097 store( mkexpr(EA), mkexpr(frS) ); 8098 break; 8099 8100 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 8101 if (rA_addr == 0) 8102 return False; 8103 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8104 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 8105 store( mkexpr(EA), mkexpr(frS) ); 8106 putIReg( rA_addr, mkexpr(EA) ); 8107 break; 8108 8109 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 8110 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8111 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8112 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8113 store( mkexpr(EA), 8114 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 8115 break; 8116 8117 default: 8118 vex_printf("dis_fp_store(ppc)(opc2)\n"); 8119 return False; 8120 } 8121 break; 8122 8123 default: 8124 vex_printf("dis_fp_store(ppc)(opc1)\n"); 8125 return False; 8126 } 8127 return True; 8128 } 8129 8130 8131 8132 /* 8133 Floating Point Arith Instructions 8134 */ 8135 static Bool dis_fp_arith ( UInt theInstr ) 8136 { 8137 /* A-Form */ 8138 UChar opc1 = ifieldOPC(theInstr); 8139 UChar frD_addr = ifieldRegDS(theInstr); 8140 UChar frA_addr = ifieldRegA(theInstr); 8141 UChar frB_addr = ifieldRegB(theInstr); 8142 UChar frC_addr = ifieldRegC(theInstr); 8143 UChar opc2 = ifieldOPClo5(theInstr); 8144 UChar flag_rC = ifieldBIT0(theInstr); 8145 8146 IRTemp frD = newTemp(Ity_F64); 8147 IRTemp frA = newTemp(Ity_F64); 8148 IRTemp frB = newTemp(Ity_F64); 8149 IRTemp frC = newTemp(Ity_F64); 8150 IRExpr* rm = get_IR_roundingmode(); 8151 8152 /* By default, we will examine the results of the operation and set 8153 fpscr[FPRF] accordingly. */ 8154 Bool set_FPRF = True; 8155 8156 /* By default, if flag_RC is set, we will clear cr1 after the 8157 operation. In reality we should set cr1 to indicate the 8158 exception status of the operation, but since we're not 8159 simulating exceptions, the exception status will appear to be 8160 zero. Hence cr1 should be cleared if this is a . form insn. */ 8161 Bool clear_CR1 = True; 8162 8163 assign( frA, getFReg(frA_addr)); 8164 assign( frB, getFReg(frB_addr)); 8165 assign( frC, getFReg(frC_addr)); 8166 8167 switch (opc1) { 8168 case 0x3B: 8169 switch (opc2) { 8170 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 8171 if (frC_addr != 0) 8172 return False; 8173 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8174 frD_addr, frA_addr, frB_addr); 8175 assign( frD, triop( Iop_DivF64r32, 8176 rm, mkexpr(frA), mkexpr(frB) )); 8177 break; 8178 8179 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 8180 if (frC_addr != 0) 8181 return False; 8182 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8183 frD_addr, frA_addr, frB_addr); 8184 assign( frD, triop( Iop_SubF64r32, 8185 rm, mkexpr(frA), mkexpr(frB) )); 8186 break; 8187 8188 case 0x15: // fadds (Floating Add Single, PPC32 p401) 8189 if (frC_addr != 0) 8190 return False; 8191 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8192 frD_addr, frA_addr, frB_addr); 8193 assign( frD, triop( Iop_AddF64r32, 8194 rm, mkexpr(frA), mkexpr(frB) )); 8195 break; 8196 8197 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 8198 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8199 if (frA_addr != 0 || frC_addr != 0) 8200 return False; 8201 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 8202 frD_addr, frB_addr); 8203 // however illogically, on ppc970 this insn behaves identically 8204 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 8205 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 8206 break; 8207 8208 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 8209 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8210 if (frA_addr != 0 || frC_addr != 0) 8211 return False; 8212 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 8213 frD_addr, frB_addr); 8214 { IRExpr* ieee_one 8215 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8216 assign( frD, triop( Iop_DivF64r32, 8217 rm, 8218 ieee_one, mkexpr(frB) )); 8219 } 8220 break; 8221 8222 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 8223 if (frB_addr != 0) 8224 return False; 8225 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8226 frD_addr, frA_addr, frC_addr); 8227 assign( frD, triop( Iop_MulF64r32, 8228 rm, mkexpr(frA), mkexpr(frC) )); 8229 break; 8230 8231 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 8232 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8233 // Undocumented instruction? 8234 if (frA_addr != 0 || frC_addr != 0) 8235 return False; 8236 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 8237 frD_addr, frB_addr); 8238 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8239 break; 8240 8241 default: 8242 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 8243 return False; 8244 } 8245 break; 8246 8247 case 0x3F: 8248 switch (opc2) { 8249 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 8250 if (frC_addr != 0) 8251 return False; 8252 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8253 frD_addr, frA_addr, frB_addr); 8254 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 8255 break; 8256 8257 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 8258 if (frC_addr != 0) 8259 return False; 8260 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8261 frD_addr, frA_addr, frB_addr); 8262 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 8263 break; 8264 8265 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 8266 if (frC_addr != 0) 8267 return False; 8268 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8269 frD_addr, frA_addr, frB_addr); 8270 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 8271 break; 8272 8273 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 8274 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8275 if (frA_addr != 0 || frC_addr != 0) 8276 return False; 8277 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 8278 frD_addr, frB_addr); 8279 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 8280 break; 8281 8282 case 0x17: { // fsel (Floating Select, PPC32 p426) 8283 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8284 IRTemp cc = newTemp(Ity_I32); 8285 IRTemp cc_b0 = newTemp(Ity_I32); 8286 8287 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8288 frD_addr, frA_addr, frC_addr, frB_addr); 8289 8290 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 8291 // => GT|EQ == (cc & 0x1 == 0) 8292 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 8293 IRExpr_Const(IRConst_F64(0))) ); 8294 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 8295 8296 // frD = (frA >= 0.0) ? frC : frB 8297 // = (cc_b0 == 0) ? frC : frB 8298 assign( frD, 8299 IRExpr_ITE( 8300 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 8301 mkexpr(frC), 8302 mkexpr(frB) )); 8303 8304 /* One of the rare ones which don't mess with FPRF */ 8305 set_FPRF = False; 8306 break; 8307 } 8308 8309 case 0x18: // fre (Floating Reciprocal Estimate) 8310 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8311 // Note: unclear whether this insn really exists or not 8312 // ppc970 doesn't have it, but POWER5 does 8313 if (frA_addr != 0 || frC_addr != 0) 8314 return False; 8315 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 8316 frD_addr, frB_addr); 8317 { IRExpr* ieee_one 8318 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8319 assign( frD, triop( Iop_DivF64, 8320 rm, 8321 ieee_one, mkexpr(frB) )); 8322 } 8323 break; 8324 8325 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 8326 if (frB_addr != 0) 8327 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 8328 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8329 frD_addr, frA_addr, frC_addr); 8330 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 8331 break; 8332 8333 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 8334 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8335 if (frA_addr != 0 || frC_addr != 0) 8336 return False; 8337 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 8338 frD_addr, frB_addr); 8339 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8340 break; 8341 8342 default: 8343 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 8344 return False; 8345 } 8346 break; 8347 8348 default: 8349 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 8350 return False; 8351 } 8352 8353 putFReg( frD_addr, mkexpr(frD) ); 8354 8355 if (set_FPRF) { 8356 // XXX XXX XXX FIXME 8357 // set FPRF from frD 8358 } 8359 8360 if (flag_rC && clear_CR1) { 8361 putCR321( 1, mkU8(0) ); 8362 putCR0( 1, mkU8(0) ); 8363 } 8364 8365 return True; 8366 } 8367 8368 8369 8370 /* 8371 Floating Point Mult-Add Instructions 8372 */ 8373 static Bool dis_fp_multadd ( UInt theInstr ) 8374 { 8375 /* A-Form */ 8376 UChar opc1 = ifieldOPC(theInstr); 8377 UChar frD_addr = ifieldRegDS(theInstr); 8378 UChar frA_addr = ifieldRegA(theInstr); 8379 UChar frB_addr = ifieldRegB(theInstr); 8380 UChar frC_addr = ifieldRegC(theInstr); 8381 UChar opc2 = ifieldOPClo5(theInstr); 8382 UChar flag_rC = ifieldBIT0(theInstr); 8383 8384 IRTemp frD = newTemp(Ity_F64); 8385 IRTemp frA = newTemp(Ity_F64); 8386 IRTemp frB = newTemp(Ity_F64); 8387 IRTemp frC = newTemp(Ity_F64); 8388 IRTemp rmt = newTemp(Ity_I32); 8389 IRTemp tmp = newTemp(Ity_F64); 8390 IRTemp sign_tmp = newTemp(Ity_I64); 8391 IRTemp nan_mask = newTemp(Ity_I32); 8392 IRExpr* rm; 8393 8394 /* By default, we will examine the results of the operation and set 8395 fpscr[FPRF] accordingly. */ 8396 Bool set_FPRF = True; 8397 8398 /* By default, if flag_RC is set, we will clear cr1 after the 8399 operation. In reality we should set cr1 to indicate the 8400 exception status of the operation, but since we're not 8401 simulating exceptions, the exception status will appear to be 8402 zero. Hence cr1 should be cleared if this is a . form insn. */ 8403 Bool clear_CR1 = True; 8404 8405 /* Bind the rounding mode expression to a temp; there's no 8406 point in creating gratuitous CSEs, as we know we'll need 8407 to use it twice. */ 8408 assign( rmt, get_IR_roundingmode() ); 8409 rm = mkexpr(rmt); 8410 8411 assign( frA, getFReg(frA_addr)); 8412 assign( frB, getFReg(frB_addr)); 8413 assign( frC, getFReg(frC_addr)); 8414 8415 /* The rounding in this is all a bit dodgy. The idea is to only do 8416 one rounding. That clearly isn't achieveable without dedicated 8417 four-input IR primops, although in the single precision case we 8418 can sort-of simulate it by doing the inner multiply in double 8419 precision. 8420 8421 In the negated cases, the negation happens after rounding. */ 8422 8423 switch (opc1) { 8424 case 0x3B: 8425 switch (opc2) { 8426 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 8427 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8428 frD_addr, frA_addr, frC_addr, frB_addr); 8429 assign( frD, qop( Iop_MSubF64r32, rm, 8430 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8431 break; 8432 8433 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 8434 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8435 frD_addr, frA_addr, frC_addr, frB_addr); 8436 assign( frD, qop( Iop_MAddF64r32, rm, 8437 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8438 break; 8439 8440 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 8441 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 8442 8443 if (opc2 == 0x1E) { 8444 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8445 frD_addr, frA_addr, frC_addr, frB_addr); 8446 assign( tmp, qop( Iop_MSubF64r32, rm, 8447 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8448 } else { 8449 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8450 frD_addr, frA_addr, frC_addr, frB_addr); 8451 assign( tmp, qop( Iop_MAddF64r32, rm, 8452 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8453 } 8454 8455 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8456 mkU32( NANmaskSingle ) ) ); 8457 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8458 mkexpr( nan_mask ) ) ); 8459 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8460 break; 8461 8462 default: 8463 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 8464 return False; 8465 } 8466 break; 8467 8468 case 0x3F: 8469 switch (opc2) { 8470 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 8471 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8472 frD_addr, frA_addr, frC_addr, frB_addr); 8473 assign( frD, qop( Iop_MSubF64, rm, 8474 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8475 break; 8476 8477 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 8478 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8479 frD_addr, frA_addr, frC_addr, frB_addr); 8480 assign( frD, qop( Iop_MAddF64, rm, 8481 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8482 break; 8483 8484 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 8485 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 8486 8487 if (opc2 == 0x1E) { 8488 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8489 frD_addr, frA_addr, frC_addr, frB_addr); 8490 assign( tmp, qop( Iop_MSubF64, rm, 8491 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8492 } else { 8493 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8494 frD_addr, frA_addr, frC_addr, frB_addr); 8495 assign( tmp, qop( Iop_MAddF64, rm, 8496 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8497 } 8498 8499 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8500 mkU32( NANmaskDouble ) ) ); 8501 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8502 mkexpr( nan_mask ) ) ); 8503 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8504 break; 8505 8506 default: 8507 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 8508 return False; 8509 } 8510 break; 8511 8512 default: 8513 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 8514 return False; 8515 } 8516 8517 putFReg( frD_addr, mkexpr(frD) ); 8518 8519 if (set_FPRF) { 8520 // XXX XXX XXX FIXME 8521 // set FPRF from frD 8522 } 8523 8524 if (flag_rC && clear_CR1) { 8525 putCR321( 1, mkU8(0) ); 8526 putCR0( 1, mkU8(0) ); 8527 } 8528 8529 return True; 8530 } 8531 8532 /* 8533 * fe_flag is set to 1 if any of the following conditions occurs: 8534 * - The floating-point operand in register FRB is a Zero, a 8535 * NaN, an Infinity, or a negative value. 8536 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 8537 * Otherwise fe_flag is set to 0. 8538 * 8539 * fg_flag is set to 1 if either of the following conditions occurs. 8540 * - The floating-point operand in register FRB is a Zero, an 8541 * Infinity, or a denormalized value. 8542 * Otherwise fg_flag is set to 0. 8543 * 8544 */ 8545 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8546 { 8547 // The following temps are for holding intermediate results 8548 IRTemp e_b = newTemp(Ity_I32); 8549 IRExpr * fe_flag, * fg_flag; 8550 IRTemp frB_exp_shR = newTemp(Ity_I32); 8551 UInt bias = sp? 127 : 1023; 8552 IRExpr * frbNaN, * frbDenorm, * frBNeg; 8553 IRExpr * eb_LTE; 8554 IRTemp frbZero_tmp = newTemp(Ity_I1); 8555 IRTemp frbInf_tmp = newTemp(Ity_I1); 8556 *fe_flag_tmp = newTemp(Ity_I32); 8557 *fg_flag_tmp = newTemp(Ity_I32); 8558 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 8559 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8560 8561 ////////////////// fe_flag tests BEGIN ////////////////////// 8562 /* We first do all tests that may result in setting fe_flag to '1'. 8563 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 8564 * for details.) 8565 */ 8566 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 8567 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 8568 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 8569 { 8570 // Test_value = -970 for double precision 8571 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 8572 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 8573 } 8574 frBNeg = binop( Iop_CmpEQ32, 8575 binop( Iop_Shr32, 8576 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 8577 mkU8( 31 ) ), 8578 mkU32( 1 ) ); 8579 ////////////////// fe_flag tests END ////////////////////// 8580 8581 ////////////////// fg_flag tests BEGIN ////////////////////// 8582 /* 8583 * The following tests were already performed above in the fe_flag 8584 * tests. So these conditions will result in both fe_ and fg_ flags 8585 * being set. 8586 * - Test if FRB is Zero 8587 * - Test if FRB is an Infinity 8588 */ 8589 8590 /* 8591 * Test if FRB holds a denormalized value. A denormalized value is one where 8592 * the exp is 0 and the fraction is non-zero. 8593 */ 8594 if (sp) { 8595 IRTemp frac_part = newTemp(Ity_I32); 8596 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 8597 frbDenorm 8598 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8599 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 8600 } else { 8601 IRExpr * hi32, * low32, * fraction_is_nonzero; 8602 IRTemp frac_part = newTemp(Ity_I64); 8603 8604 assign( frac_part, FP_FRAC_PART(frB_Int) ); 8605 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8606 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8607 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8608 mkU32( 0 ) ); 8609 frbDenorm 8610 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8611 fraction_is_nonzero ); 8612 } 8613 ////////////////// fg_flag tests END ////////////////////// 8614 8615 ///////////////////////// 8616 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 8617 mkOR1( frbNaN, 8618 mkOR1( mkexpr( frbInf_tmp ), 8619 mkOR1( frBNeg, eb_LTE ) ) ) ); 8620 8621 fe_flag = unop(Iop_1Uto32, fe_flag); 8622 8623 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 8624 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 8625 fg_flag = unop(Iop_1Uto32, fg_flag); 8626 assign (*fg_flag_tmp, fg_flag); 8627 assign (*fe_flag_tmp, fe_flag); 8628 } 8629 /* 8630 * fe_flag is set to 1 if any of the following conditions occurs: 8631 * - The double-precision floating-point operand in register FRA is a NaN or an 8632 * Infinity. 8633 * - The double-precision floating-point operand in register FRB is a Zero, a 8634 * NaN, or an Infinity. 8635 * - e_b is less than or equal to -1022. 8636 * - e_b is greater than or equal to 1021. 8637 * - The double-precision floating-point operand in register FRA is not a zero 8638 * and the difference, e_a - e_b, is greater than or equal to 1023. 8639 * - The double-precision floating-point operand in register FRA is not a zero 8640 * and the difference, e_a - e_b, is less than or equal to -1021. 8641 * - The double-precision floating-point operand in register FRA is not a zero 8642 * and e_a is less than or equal to -970 8643 * Otherwise fe_flag is set to 0. 8644 * 8645 * fg_flag is set to 1 if either of the following conditions occurs. 8646 * - The double-precision floating-point operand in register FRA is an Infinity. 8647 * - The double-precision floating-point operand in register FRB is a Zero, an 8648 * Infinity, or a denormalized value. 8649 * Otherwise fg_flag is set to 0. 8650 * 8651 */ 8652 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8653 { 8654 // The following temps are for holding intermediate results 8655 IRTemp e_a = newTemp(Ity_I32); 8656 IRTemp e_b = newTemp(Ity_I32); 8657 IRTemp frA_exp_shR = newTemp(Ity_I32); 8658 IRTemp frB_exp_shR = newTemp(Ity_I32); 8659 8660 UInt bias = sp? 127 : 1023; 8661 *fe_flag_tmp = newTemp(Ity_I32); 8662 *fg_flag_tmp = newTemp(Ity_I32); 8663 8664 /* The following variables hold boolean results from tests 8665 * that are OR'ed together for setting the fe_ and fg_ flags. 8666 * For some cases, the booleans are used more than once, so 8667 * I make those IRTemp's instead of IRExpr's. 8668 */ 8669 IRExpr * fraNaN, * frbNaN, * frbDenorm; 8670 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 8671 IRTemp fraInf_tmp = newTemp(Ity_I1); 8672 IRTemp frbZero_tmp = newTemp(Ity_I1); 8673 IRTemp frbInf_tmp = newTemp(Ity_I1); 8674 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 8675 8676 /* The following are the flags that are set by OR'ing the results of 8677 * all the tests done for tdiv. These flags are the input to the specified CR. 8678 */ 8679 IRExpr * fe_flag, * fg_flag; 8680 8681 // Create temps that will be used throughout the following tests. 8682 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 8683 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 8684 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 8685 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 8686 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8687 8688 8689 ////////////////// fe_flag tests BEGIN ////////////////////// 8690 /* We first do all tests that may result in setting fe_flag to '1'. */ 8691 8692 /* 8693 * Test if the double-precision floating-point operand in register FRA is 8694 * a NaN: 8695 */ 8696 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 8697 /* 8698 * Test if the double-precision floating-point operand in register FRA is 8699 * an Infinity. 8700 */ 8701 assign(fraInf_tmp, is_Inf(frA_int, sp)); 8702 8703 /* 8704 * Test if the double-precision floating-point operand in register FRB is 8705 * a NaN: 8706 */ 8707 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 8708 /* 8709 * Test if the double-precision floating-point operand in register FRB is 8710 * an Infinity. 8711 */ 8712 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 8713 /* 8714 * Test if the double-precision floating-point operand in register FRB is 8715 * a Zero. 8716 */ 8717 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 8718 8719 /* 8720 * Test if e_b <= -1022 for double precision; 8721 * or e_b <= -126 for single precision 8722 */ 8723 { 8724 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 8725 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 8726 } 8727 8728 /* 8729 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 8730 * or e_b >= -125 (125 < e_b) for single precision 8731 */ 8732 { 8733 Int test_value = sp ? 125 : 1021; 8734 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 8735 } 8736 8737 /* 8738 * Test if FRA != Zero and (e_a - e_b) >= bias 8739 */ 8740 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 8741 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 8742 binop( Iop_CmpLT32S, mkU32( bias ), 8743 binop( Iop_Sub32, mkexpr( e_a ), 8744 mkexpr( e_b ) ) ) ); 8745 8746 /* 8747 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 8748 */ 8749 { 8750 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 8751 8752 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 8753 binop( Iop_CmpLE32S, 8754 binop( Iop_Sub32, 8755 mkexpr( e_a ), 8756 mkexpr( e_b ) ), 8757 mkU32( test_value ) ) ); 8758 } 8759 8760 /* 8761 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 8762 */ 8763 { 8764 UInt test_value = 0xfffffc36; //Int test_value = -970; 8765 8766 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 8767 mkexpr( e_a ), 8768 mkU32( test_value ) ) ); 8769 } 8770 ////////////////// fe_flag tests END ////////////////////// 8771 8772 ////////////////// fg_flag tests BEGIN ////////////////////// 8773 /* 8774 * The following tests were already performed above in the fe_flag 8775 * tests. So these conditions will result in both fe_ and fg_ flags 8776 * being set. 8777 * - Test if FRA is an Infinity 8778 * - Test if FRB ix Zero 8779 * - Test if FRB is an Infinity 8780 */ 8781 8782 /* 8783 * Test if FRB holds a denormalized value. A denormalized value is one where 8784 * the exp is 0 and the fraction is non-zero. 8785 */ 8786 { 8787 IRExpr * fraction_is_nonzero; 8788 8789 if (sp) { 8790 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 8791 mkU32( 0 ) ); 8792 } else { 8793 IRExpr * hi32, * low32; 8794 IRTemp frac_part = newTemp(Ity_I64); 8795 assign( frac_part, FP_FRAC_PART(frB_int) ); 8796 8797 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8798 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8799 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8800 mkU32( 0 ) ); 8801 } 8802 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 8803 mkU32( 0x0 ) ), fraction_is_nonzero ); 8804 8805 } 8806 ////////////////// fg_flag tests END ////////////////////// 8807 8808 fe_flag 8809 = mkOR1( 8810 fraNaN, 8811 mkOR1( 8812 mkexpr( fraInf_tmp ), 8813 mkOR1( 8814 mkexpr( frbZero_tmp ), 8815 mkOR1( 8816 frbNaN, 8817 mkOR1( 8818 mkexpr( frbInf_tmp ), 8819 mkOR1( eb_LTE, 8820 mkOR1( eb_GTE, 8821 mkOR1( ea_eb_GTE, 8822 mkOR1( ea_eb_LTE, 8823 ea_LTE ) ) ) ) ) ) ) ) ); 8824 8825 fe_flag = unop(Iop_1Uto32, fe_flag); 8826 8827 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 8828 mkOR1( mkexpr( frbInf_tmp ), 8829 frbDenorm ) ) ); 8830 fg_flag = unop(Iop_1Uto32, fg_flag); 8831 assign(*fe_flag_tmp, fe_flag); 8832 assign(*fg_flag_tmp, fg_flag); 8833 } 8834 8835 /* See description for _do_fp_tdiv() above. */ 8836 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 8837 { 8838 IRTemp fe_flag, fg_flag; 8839 ///////////////////////// 8840 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8841 * where fl_flag == 1 on ppc64. 8842 */ 8843 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 8844 fe_flag = fg_flag = IRTemp_INVALID; 8845 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 8846 return binop( Iop_Or32, 8847 binop( Iop_Or32, 8848 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 8849 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8850 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 8851 } 8852 8853 static Bool dis_fp_tests ( UInt theInstr ) 8854 { 8855 UChar opc1 = ifieldOPC(theInstr); 8856 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8857 UChar frB_addr = ifieldRegB(theInstr); 8858 UChar b0 = ifieldBIT0(theInstr); 8859 UInt opc2 = ifieldOPClo10(theInstr); 8860 IRTemp frB_I64 = newTemp(Ity_I64); 8861 8862 if (opc1 != 0x3F || b0 != 0 ){ 8863 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8864 return False; 8865 } 8866 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 8867 8868 switch (opc2) { 8869 case 0x080: // ftdiv 8870 { 8871 UChar frA_addr = ifieldRegA(theInstr); 8872 IRTemp frA_I64 = newTemp(Ity_I64); 8873 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8874 if (b21to22 != 0 ) { 8875 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8876 return False; 8877 } 8878 8879 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 8880 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 8881 8882 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8883 break; 8884 } 8885 case 0x0A0: // ftsqrt 8886 { 8887 IRTemp flags = newTemp(Ity_I32); 8888 IRTemp fe_flag, fg_flag; 8889 fe_flag = fg_flag = IRTemp_INVALID; 8890 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 8891 if ( b18to22 != 0) { 8892 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 8893 return False; 8894 } 8895 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 8896 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 8897 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8898 * where fl_flag == 1 on ppc64. 8899 */ 8900 assign( flags, 8901 binop( Iop_Or32, 8902 binop( Iop_Or32, mkU32( 8 ), // fl_flag 8903 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8904 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 8905 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 8906 break; 8907 } 8908 8909 default: 8910 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 8911 return False; 8912 8913 } 8914 return True; 8915 } 8916 8917 /* 8918 Floating Point Compare Instructions 8919 */ 8920 static Bool dis_fp_cmp ( UInt theInstr ) 8921 { 8922 /* X-Form */ 8923 UChar opc1 = ifieldOPC(theInstr); 8924 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8925 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8926 UChar frA_addr = ifieldRegA(theInstr); 8927 UChar frB_addr = ifieldRegB(theInstr); 8928 UInt opc2 = ifieldOPClo10(theInstr); 8929 UChar b0 = ifieldBIT0(theInstr); 8930 8931 IRTemp ccIR = newTemp(Ity_I32); 8932 IRTemp ccPPC32 = newTemp(Ity_I32); 8933 8934 IRTemp frA = newTemp(Ity_F64); 8935 IRTemp frB = newTemp(Ity_F64); 8936 8937 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 8938 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 8939 return False; 8940 } 8941 8942 assign( frA, getFReg(frA_addr)); 8943 assign( frB, getFReg(frB_addr)); 8944 8945 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 8946 8947 /* Map compare result from IR to PPC32 */ 8948 /* 8949 FP cmp result | PPC | IR 8950 -------------------------- 8951 UN | 0x1 | 0x45 8952 EQ | 0x2 | 0x40 8953 GT | 0x4 | 0x00 8954 LT | 0x8 | 0x01 8955 */ 8956 8957 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 8958 // | ((ccIR ^ (ccIR>>6)) & 1) 8959 assign( 8960 ccPPC32, 8961 binop( 8962 Iop_Shl32, 8963 mkU32(1), 8964 unop( 8965 Iop_32to8, 8966 binop( 8967 Iop_Or32, 8968 binop( 8969 Iop_And32, 8970 unop( 8971 Iop_Not32, 8972 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 8973 ), 8974 mkU32(2) 8975 ), 8976 binop( 8977 Iop_And32, 8978 binop( 8979 Iop_Xor32, 8980 mkexpr(ccIR), 8981 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 8982 ), 8983 mkU32(1) 8984 ) 8985 ) 8986 ) 8987 ) 8988 ); 8989 8990 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 8991 8992 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 8993 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 8994 */ 8995 // XXX XXX XXX FIXME 8996 // Also write the result into FPRF (it's not entirely clear how) 8997 8998 /* Note: Differences between fcmpu and fcmpo are only in exception 8999 flag settings, which aren't supported anyway. */ 9000 switch (opc2) { 9001 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 9002 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 9003 break; 9004 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 9005 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 9006 break; 9007 default: 9008 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 9009 return False; 9010 } 9011 return True; 9012 } 9013 9014 9015 9016 /* 9017 Floating Point Rounding/Conversion Instructions 9018 */ 9019 static Bool dis_fp_round ( UInt theInstr ) 9020 { 9021 /* X-Form */ 9022 UChar opc1 = ifieldOPC(theInstr); 9023 UChar b16to20 = ifieldRegA(theInstr); 9024 UChar frD_addr = ifieldRegDS(theInstr); 9025 UChar frB_addr = ifieldRegB(theInstr); 9026 UInt opc2 = ifieldOPClo10(theInstr); 9027 UChar flag_rC = ifieldBIT0(theInstr); 9028 9029 IRTemp frD = newTemp(Ity_F64); 9030 IRTemp frB = newTemp(Ity_F64); 9031 IRTemp r_tmp32 = newTemp(Ity_I32); 9032 IRTemp r_tmp64 = newTemp(Ity_I64); 9033 IRExpr* rm = get_IR_roundingmode(); 9034 9035 /* By default, we will examine the results of the operation and set 9036 fpscr[FPRF] accordingly. */ 9037 Bool set_FPRF = True; 9038 9039 /* By default, if flag_RC is set, we will clear cr1 after the 9040 operation. In reality we should set cr1 to indicate the 9041 exception status of the operation, but since we're not 9042 simulating exceptions, the exception status will appear to be 9043 zero. Hence cr1 should be cleared if this is a . form insn. */ 9044 Bool clear_CR1 = True; 9045 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 9046 vex_printf("dis_fp_round(ppc)(instr)\n"); 9047 return False; 9048 } 9049 9050 assign( frB, getFReg(frB_addr)); 9051 if (opc1 == 0x3B) { 9052 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 9053 * they're very similar to the other instructions handled here, but have 9054 * a different primary opcode. 9055 */ 9056 switch (opc2) { 9057 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 9058 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9059 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9060 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 9061 mkexpr( r_tmp64 ) ) ) ); 9062 goto putFR; 9063 9064 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 9065 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9066 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9067 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 9068 goto putFR; 9069 } 9070 } 9071 9072 9073 switch (opc2) { 9074 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 9075 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9076 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 9077 break; 9078 9079 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 9080 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9081 assign( r_tmp32, 9082 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 9083 assign( frD, unop( Iop_ReinterpI64asF64, 9084 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 9085 /* FPRF is undefined after fctiw. Leave unchanged. */ 9086 set_FPRF = False; 9087 break; 9088 9089 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 9090 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9091 assign( r_tmp32, 9092 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 9093 assign( frD, unop( Iop_ReinterpI64asF64, 9094 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 9095 /* FPRF is undefined after fctiwz. Leave unchanged. */ 9096 set_FPRF = False; 9097 break; 9098 9099 case 0x08F: case 0x08E: // fctiwu[z] 9100 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 9101 flag_rC ? ".":"", frD_addr, frB_addr); 9102 assign( r_tmp32, 9103 binop( Iop_F64toI32U, 9104 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 9105 mkexpr( frB ) ) ); 9106 assign( frD, unop( Iop_ReinterpI64asF64, 9107 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 9108 /* FPRF is undefined after fctiwz. Leave unchanged. */ 9109 set_FPRF = False; 9110 break; 9111 9112 9113 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 9114 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9115 assign( r_tmp64, 9116 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 9117 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 9118 /* FPRF is undefined after fctid. Leave unchanged. */ 9119 set_FPRF = False; 9120 break; 9121 9122 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 9123 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9124 assign( r_tmp64, 9125 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 9126 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 9127 /* FPRF is undefined after fctidz. Leave unchanged. */ 9128 set_FPRF = False; 9129 break; 9130 9131 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 9132 { 9133 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 9134 flag_rC ? ".":"", frD_addr, frB_addr); 9135 assign( r_tmp64, 9136 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 9137 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 9138 /* FPRF is undefined after fctidz. Leave unchanged. */ 9139 set_FPRF = False; 9140 break; 9141 } 9142 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 9143 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9144 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9145 assign( frD, 9146 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 9147 break; 9148 9149 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 9150 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9151 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9152 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 9153 break; 9154 9155 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 9156 switch(opc2) { 9157 case 0x188: // frin (Floating Round to Integer Nearest) 9158 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9159 assign( r_tmp64, 9160 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 9161 break; 9162 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 9163 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9164 assign( r_tmp64, 9165 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 9166 break; 9167 case 0x1C8: // frip (Floating Round to Integer Plus) 9168 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9169 assign( r_tmp64, 9170 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 9171 break; 9172 case 0x1E8: // frim (Floating Round to Integer Minus) 9173 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9174 assign( r_tmp64, 9175 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 9176 break; 9177 } 9178 9179 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 9180 /* F64 has only log10(2**52) significant digits anyway */ 9181 /* need to preserve sign of zero */ 9182 /* frD = (fabs(frB) > 9e18) ? frB : 9183 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 9184 assign(frD, IRExpr_ITE( 9185 binop(Iop_CmpNE8, 9186 unop(Iop_32to8, 9187 binop(Iop_CmpF64, 9188 IRExpr_Const(IRConst_F64(9e18)), 9189 unop(Iop_AbsF64, mkexpr(frB)))), 9190 mkU8(0)), 9191 mkexpr(frB), 9192 IRExpr_ITE( 9193 binop(Iop_CmpNE32, 9194 binop(Iop_Shr32, 9195 unop(Iop_64HIto32, 9196 unop(Iop_ReinterpF64asI64, 9197 mkexpr(frB))), 9198 mkU8(31)), 9199 mkU32(0)), 9200 unop(Iop_NegF64, 9201 unop( Iop_AbsF64, 9202 binop(Iop_I64StoF64, mkU32(0), 9203 mkexpr(r_tmp64)) )), 9204 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 9205 ) 9206 )); 9207 break; 9208 9209 default: 9210 vex_printf("dis_fp_round(ppc)(opc2)\n"); 9211 return False; 9212 } 9213 putFR: 9214 putFReg( frD_addr, mkexpr(frD) ); 9215 9216 if (set_FPRF) { 9217 // XXX XXX XXX FIXME 9218 // set FPRF from frD 9219 } 9220 9221 if (flag_rC && clear_CR1) { 9222 putCR321( 1, mkU8(0) ); 9223 putCR0( 1, mkU8(0) ); 9224 } 9225 9226 return True; 9227 } 9228 9229 /* 9230 Floating Point Pair Instructions 9231 */ 9232 static Bool dis_fp_pair ( UInt theInstr ) 9233 { 9234 /* X-Form/DS-Form */ 9235 UChar opc1 = ifieldOPC(theInstr); 9236 UChar frT_hi_addr = ifieldRegDS(theInstr); 9237 UChar frT_lo_addr = frT_hi_addr + 1; 9238 UChar rA_addr = ifieldRegA(theInstr); 9239 UChar rB_addr = ifieldRegB(theInstr); 9240 UInt uimm16 = ifieldUIMM16(theInstr); 9241 Int simm16 = extend_s_16to32(uimm16); 9242 UInt opc2 = ifieldOPClo10(theInstr); 9243 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9244 IRTemp EA_hi = newTemp(ty); 9245 IRTemp EA_lo = newTemp(ty); 9246 IRTemp frT_hi = newTemp(Ity_F64); 9247 IRTemp frT_lo = newTemp(Ity_F64); 9248 UChar b0 = ifieldBIT0(theInstr); 9249 Bool is_load = 0; 9250 9251 if ((frT_hi_addr %2) != 0) { 9252 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 9253 return False; 9254 } 9255 9256 switch (opc1) { 9257 case 0x1F: // register offset 9258 switch(opc2) { 9259 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 9260 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9261 is_load = 1; 9262 break; 9263 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 9264 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9265 break; 9266 default: 9267 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 9268 return False; 9269 } 9270 9271 if (b0 != 0) { 9272 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 9273 return False; 9274 } 9275 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 9276 break; 9277 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 9278 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9279 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9280 is_load = 1; 9281 break; 9282 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 9283 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9284 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9285 break; 9286 default: // immediate offset 9287 vex_printf("dis_fp_pair(ppc)(instr)\n"); 9288 return False; 9289 } 9290 9291 if (mode64) 9292 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 9293 else 9294 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 9295 9296 assign( frT_hi, getFReg(frT_hi_addr) ); 9297 assign( frT_lo, getFReg(frT_lo_addr) ); 9298 9299 if (is_load) { 9300 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) ); 9301 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) ); 9302 } else { 9303 store( mkexpr(EA_hi), mkexpr(frT_hi) ); 9304 store( mkexpr(EA_lo), mkexpr(frT_lo) ); 9305 } 9306 9307 return True; 9308 } 9309 9310 9311 /* 9312 Floating Point Merge Instructions 9313 */ 9314 static Bool dis_fp_merge ( UInt theInstr ) 9315 { 9316 /* X-Form */ 9317 UInt opc2 = ifieldOPClo10(theInstr); 9318 UChar frD_addr = ifieldRegDS(theInstr); 9319 UChar frA_addr = ifieldRegA(theInstr); 9320 UChar frB_addr = ifieldRegB(theInstr); 9321 9322 IRTemp frD = newTemp(Ity_F64); 9323 IRTemp frA = newTemp(Ity_F64); 9324 IRTemp frB = newTemp(Ity_F64); 9325 9326 assign( frA, getFReg(frA_addr)); 9327 assign( frB, getFReg(frB_addr)); 9328 9329 switch (opc2) { 9330 case 0x3c6: // fmrgew floating merge even word 9331 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9332 9333 assign( frD, unop( Iop_ReinterpI64asF64, 9334 binop( Iop_32HLto64, 9335 unop( Iop_64HIto32, 9336 unop( Iop_ReinterpF64asI64, 9337 mkexpr(frA) ) ), 9338 unop( Iop_64HIto32, 9339 unop( Iop_ReinterpF64asI64, 9340 mkexpr(frB) ) ) ) ) ); 9341 break; 9342 9343 case 0x346: // fmrgow floating merge odd word 9344 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9345 9346 assign( frD, unop( Iop_ReinterpI64asF64, 9347 binop( Iop_32HLto64, 9348 unop( Iop_64to32, 9349 unop( Iop_ReinterpF64asI64, 9350 mkexpr(frA) ) ), 9351 unop( Iop_64to32, 9352 unop( Iop_ReinterpF64asI64, 9353 mkexpr(frB) ) ) ) ) ); 9354 break; 9355 9356 default: 9357 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 9358 return False; 9359 } 9360 9361 putFReg( frD_addr, mkexpr(frD) ); 9362 return True; 9363 } 9364 9365 /* 9366 Floating Point Move Instructions 9367 */ 9368 static Bool dis_fp_move ( UInt theInstr ) 9369 { 9370 /* X-Form */ 9371 UChar opc1 = ifieldOPC(theInstr); 9372 UChar frD_addr = ifieldRegDS(theInstr); 9373 UChar frA_addr = ifieldRegA(theInstr); 9374 UChar frB_addr = ifieldRegB(theInstr); 9375 UInt opc2 = ifieldOPClo10(theInstr); 9376 UChar flag_rC = ifieldBIT0(theInstr); 9377 9378 IRTemp frD = newTemp(Ity_F64); 9379 IRTemp frB = newTemp(Ity_F64); 9380 IRTemp itmpB = newTemp(Ity_F64); 9381 IRTemp frA; 9382 IRTemp signA; 9383 IRTemp hiD; 9384 9385 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 9386 vex_printf("dis_fp_move(ppc)(instr)\n"); 9387 return False; 9388 } 9389 9390 assign( frB, getFReg(frB_addr)); 9391 9392 switch (opc2) { 9393 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 9394 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 9395 frB_addr); 9396 signA = newTemp(Ity_I32); 9397 hiD = newTemp(Ity_I32); 9398 itmpB = newTemp(Ity_I64); 9399 frA = newTemp(Ity_F64); 9400 assign( frA, getFReg(frA_addr) ); 9401 9402 /* get A's sign bit */ 9403 assign(signA, binop(Iop_And32, 9404 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 9405 mkexpr(frA))), 9406 mkU32(0x80000000)) ); 9407 9408 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 9409 9410 /* mask off B's sign bit and or in A's sign bit */ 9411 assign(hiD, binop(Iop_Or32, 9412 binop(Iop_And32, 9413 unop(Iop_64HIto32, 9414 mkexpr(itmpB)), /* frB's high 32 bits */ 9415 mkU32(0x7fffffff)), 9416 mkexpr(signA)) ); 9417 9418 /* combine hiD/loB into frD */ 9419 assign( frD, unop(Iop_ReinterpI64asF64, 9420 binop(Iop_32HLto64, 9421 mkexpr(hiD), 9422 unop(Iop_64to32, 9423 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 9424 break; 9425 9426 case 0x028: // fneg (Floating Negate, PPC32 p416) 9427 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9428 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 9429 break; 9430 9431 case 0x048: // fmr (Floating Move Register, PPC32 p410) 9432 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9433 assign( frD, mkexpr(frB) ); 9434 break; 9435 9436 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 9437 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9438 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 9439 break; 9440 9441 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 9442 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9443 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 9444 break; 9445 9446 default: 9447 vex_printf("dis_fp_move(ppc)(opc2)\n"); 9448 return False; 9449 } 9450 9451 putFReg( frD_addr, mkexpr(frD) ); 9452 9453 /* None of these change FPRF. cr1 is set in the usual way though, 9454 if flag_rC is set. */ 9455 9456 if (flag_rC) { 9457 putCR321( 1, mkU8(0) ); 9458 putCR0( 1, mkU8(0) ); 9459 } 9460 9461 return True; 9462 } 9463 9464 9465 9466 /* 9467 Floating Point Status/Control Register Instructions 9468 */ 9469 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 9470 { 9471 /* Many forms - see each switch case */ 9472 UChar opc1 = ifieldOPC(theInstr); 9473 UInt opc2 = ifieldOPClo10(theInstr); 9474 UChar flag_rC = ifieldBIT0(theInstr); 9475 9476 if (opc1 != 0x3F) { 9477 vex_printf("dis_fp_scr(ppc)(instr)\n"); 9478 return False; 9479 } 9480 9481 switch (opc2) { 9482 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 9483 // Bit crbD of the FPSCR is set. 9484 UChar crbD = ifieldRegDS(theInstr); 9485 UInt b11to20 = IFIELD(theInstr, 11, 10); 9486 9487 if (b11to20 != 0) { 9488 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 9489 return False; 9490 } 9491 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 9492 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 9493 1ULL << ( 31 - crbD ) ); 9494 break; 9495 } 9496 9497 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 9498 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9499 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9500 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 9501 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 9502 IRTemp tmp = newTemp(Ity_I32); 9503 IRExpr* fpscr_all; 9504 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 9505 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 9506 return False; 9507 } 9508 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 9509 vassert(crfD < 8); 9510 vassert(crfS < 8); 9511 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9512 assign( tmp, binop(Iop_And32, 9513 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 9514 mkU32(0xF)) ); 9515 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 9516 break; 9517 } 9518 9519 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 9520 // Bit crbD of the FPSCR is cleared. 9521 UChar crbD = ifieldRegDS(theInstr); 9522 UInt b11to20 = IFIELD(theInstr, 11, 10); 9523 9524 if (b11to20 != 0) { 9525 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 9526 return False; 9527 } 9528 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 9529 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 9530 break; 9531 } 9532 9533 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 9534 UInt crfD = IFIELD( theInstr, 23, 3 ); 9535 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 9536 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 9537 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9538 UChar Wbit; 9539 9540 if (b16to22 != 0 || b11 != 0) { 9541 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 9542 return False; 9543 } 9544 DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM); 9545 if (GX_level) { 9546 /* This implies that Decimal Floating Point is supported, and the 9547 * FPSCR must be managed as a 64-bit register. 9548 */ 9549 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9550 } else { 9551 Wbit = 0; 9552 } 9553 crfD = crfD + (8 * (1 - Wbit) ); 9554 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 9555 break; 9556 } 9557 9558 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 9559 UChar frD_addr = ifieldRegDS(theInstr); 9560 UInt b11to20 = IFIELD(theInstr, 11, 10); 9561 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9562 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, 9563 MASK_FPSCR_DRN ); 9564 9565 if (b11to20 != 0) { 9566 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 9567 return False; 9568 } 9569 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 9570 putFReg( frD_addr, 9571 unop( Iop_ReinterpI64asF64, 9572 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 9573 break; 9574 } 9575 9576 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 9577 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 9578 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 9579 UChar frB_addr = ifieldRegB(theInstr); 9580 IRTemp frB = newTemp(Ity_F64); 9581 IRTemp rB_64 = newTemp( Ity_I64 ); 9582 Int i; 9583 ULong mask; 9584 UChar Wbit; 9585 #define BFP_MASK_SEED 0x3000000000000000ULL 9586 #define DFP_MASK_SEED 0x7000000000000000ULL 9587 9588 if (GX_level) { 9589 /* This implies that Decimal Floating Point is supported, and the 9590 * FPSCR must be managed as a 64-bit register. 9591 */ 9592 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9593 } else { 9594 Wbit = 0; 9595 } 9596 9597 if (b25 == 1) { 9598 /* new 64 bit move variant for power 6. If L field (bit 25) is 9599 * a one do a full 64 bit move. Note, the FPSCR is not really 9600 * properly modeled. This instruciton only changes the value of 9601 * the rounding mode. The HW exception bits do not get set in 9602 * the simulator. 1/12/09 9603 */ 9604 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 9605 mask = 0xFF; 9606 9607 } else { 9608 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 9609 // Build 32bit mask from FM: 9610 mask = 0; 9611 for (i=0; i<8; i++) { 9612 if ((FM & (1<<(7-i))) == 1) { 9613 /* FPSCR field k is set to the contents of the corresponding 9614 * field of register FRB, where k = i+8x(1-W). In the Power 9615 * ISA, register field numbering is from left to right, so field 9616 * 15 is the least significant field in a 64-bit register. To 9617 * generate the mask, we set all the appropriate rounding mode 9618 * bits in the highest order nibble (field 0) and shift right 9619 * 'k x nibble length'. 9620 */ 9621 if (Wbit) 9622 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9623 else 9624 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9625 } 9626 } 9627 } 9628 assign( frB, getFReg(frB_addr)); 9629 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 9630 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 9631 break; 9632 } 9633 9634 default: 9635 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 9636 return False; 9637 } 9638 return True; 9639 } 9640 9641 /*------------------------------------------------------------*/ 9642 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 9643 /*------------------------------------------------------------*/ 9644 #define DFP_LONG 1 9645 #define DFP_EXTND 2 9646 #define DFP_LONG_BIAS 398 9647 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 9648 #define DFP_EXTND_BIAS 6176 9649 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 9650 #define DFP_LONG_EXP_MSK 0XFF 9651 #define DFP_EXTND_EXP_MSK 0XFFF 9652 9653 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 9654 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 9655 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 9656 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 9657 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 9658 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 9659 #define DFP_LONG_EXP_MAX 369 // biased max 9660 #define DFP_LONG_EXP_MIN 0 // biased min 9661 #define DFP_EXTND_EXP_MAX 6111 // biased max 9662 #define DFP_EXTND_EXP_MIN 0 // biased min 9663 #define DFP_LONG_MAX_SIG_DIGITS 16 9664 #define DFP_EXTND_MAX_SIG_DIGITS 34 9665 #define MAX_DIGITS_IN_STRING 8 9666 9667 9668 #define AND(x, y) binop( Iop_And32, x, y ) 9669 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 9670 #define OR(x, y) binop( Iop_Or32, x, y ) 9671 #define OR3(x, y, z) OR( x, OR( y, z ) ) 9672 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 9673 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 9674 9675 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 9676 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 9677 9678 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 9679 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 9680 ((_b1) << 1) | ((_b0) << 0)) 9681 9682 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 9683 { 9684 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9685 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 9686 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 9687 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 9688 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 9689 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 9690 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9691 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9692 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9693 9694 /* The encodig is as follows: 9695 * lmd - left most digit 9696 * lme - left most 2-bits of the exponent 9697 * 9698 * lmd 9699 * 0 - 7 (lmexp << 3) | lmd 9700 * 8 0b11000 (24 decimal) if lme=0b00; 9701 * 0b11010 (26 decimal) if lme=0b01; 9702 * 0b11100 (28 decimal) if lme=0b10; 9703 * 9 0b11001 (25 decimal) if lme=0b00; 9704 * 0b11011 (27 decimal) if lme=0b01; 9705 * 0b11101 (29 decimal) if lme=0b10; 9706 */ 9707 9708 /* Generate the masks for each condition */ 9709 assign( lmd_07_mask, 9710 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 9711 assign( lmd_8_mask, 9712 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 9713 assign( lmd_9_mask, 9714 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 9715 assign( lmexp_00_mask, 9716 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 9717 assign( lmexp_01_mask, 9718 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 9719 assign( lmexp_10_mask, 9720 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 9721 9722 /* Generate the values for each LMD condition, assuming the condition 9723 * is TRUE. 9724 */ 9725 assign( lmd_07_val, 9726 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 9727 assign( lmd_8_val, 9728 binop( Iop_Or32, 9729 binop( Iop_Or32, 9730 binop( Iop_And32, 9731 mkexpr( lmexp_00_mask ), 9732 mkU32( 24 ) ), 9733 binop( Iop_And32, 9734 mkexpr( lmexp_01_mask ), 9735 mkU32( 26 ) ) ), 9736 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 9737 assign( lmd_9_val, 9738 binop( Iop_Or32, 9739 binop( Iop_Or32, 9740 binop( Iop_And32, 9741 mkexpr( lmexp_00_mask ), 9742 mkU32( 25 ) ), 9743 binop( Iop_And32, 9744 mkexpr( lmexp_01_mask ), 9745 mkU32( 27 ) ) ), 9746 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 9747 9748 /* generate the result from the possible LMD values */ 9749 return binop( Iop_Or32, 9750 binop( Iop_Or32, 9751 binop( Iop_And32, 9752 mkexpr( lmd_07_mask ), 9753 mkexpr( lmd_07_val ) ), 9754 binop( Iop_And32, 9755 mkexpr( lmd_8_mask ), 9756 mkexpr( lmd_8_val ) ) ), 9757 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 9758 } 9759 9760 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 9761 { 9762 /* Extract the exponent and the left most digit of the mantissa 9763 * from the G field bits [0:4]. 9764 */ 9765 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9766 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 9767 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 9768 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 9769 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 9770 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 9771 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 9772 9773 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9774 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9775 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9776 9777 /* The left most digit (LMD) encoding is as follows: 9778 * lmd 9779 * 0 - 7 (lmexp << 3) | lmd 9780 * 8 0b11000 (24 decimal) if lme=0b00; 9781 * 0b11010 (26 decimal) if lme=0b01; 9782 * 0b11100 (28 decimal) if lme=0b10 9783 * 9 0b11001 (25 decimal) if lme=0b00; 9784 * 0b11011 (27 decimal) if lme=0b01; 9785 * 0b11101 (29 decimal) if lme=0b10; 9786 */ 9787 9788 /* Generate the masks for each condition of LMD and exponent bits */ 9789 assign( lmd_07_mask, 9790 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 9791 gfield_0_4, 9792 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 9793 assign( lmd_8_00_mask, 9794 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9795 gfield_0_4, 9796 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 9797 assign( lmd_8_01_mask, 9798 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9799 gfield_0_4, 9800 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 9801 assign( lmd_8_10_mask, 9802 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9803 gfield_0_4, 9804 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 9805 assign( lmd_9_00_mask, 9806 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9807 gfield_0_4, 9808 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 9809 assign( lmd_9_01_mask, 9810 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9811 gfield_0_4, 9812 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 9813 assign( lmd_9_10_mask, 9814 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9815 gfield_0_4, 9816 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 9817 9818 /* Generate the values for each LMD condition, assuming the condition 9819 * is TRUE. 9820 */ 9821 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 9822 assign( lmd_8_val, mkU32( 0x8 ) ); 9823 assign( lmd_9_val, mkU32( 0x9 ) ); 9824 9825 assign( *lmd, 9826 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 9827 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 9828 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 9829 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 9830 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 9831 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 9832 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 9833 ) ) ); 9834 } 9835 9836 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 9837 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 9838 #define DIGIT3_SHR 12 9839 #define DIGIT4_SHR 16 9840 #define DIGIT5_SHR 20 9841 #define DIGIT6_SHR 24 9842 #define DIGIT7_SHR 28 9843 9844 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 9845 { 9846 /* 60-bit BCD string stored in two 32-bit values. Check that each, 9847 * digit is a valid BCD number, i.e. less then 9. 9848 */ 9849 IRTemp valid = newTemp( Ity_I32 ); 9850 9851 assign( valid, 9852 AND4( AND4 ( unop( Iop_1Sto32, 9853 binop( Iop_CmpLE32U, 9854 binop( Iop_And32, 9855 bcd_l, 9856 mkU32 ( 0xF ) ), 9857 mkU32( 0x9 ) ) ), 9858 unop( Iop_1Sto32, 9859 binop( Iop_CmpLE32U, 9860 binop( Iop_And32, 9861 binop( Iop_Shr32, 9862 bcd_l, 9863 mkU8 ( DIGIT1_SHR ) ), 9864 mkU32 ( 0xF ) ), 9865 mkU32( 0x9 ) ) ), 9866 unop( Iop_1Sto32, 9867 binop( Iop_CmpLE32U, 9868 binop( Iop_And32, 9869 binop( Iop_Shr32, 9870 bcd_l, 9871 mkU8 ( DIGIT2_SHR ) ), 9872 mkU32 ( 0xF ) ), 9873 mkU32( 0x9 ) ) ), 9874 unop( Iop_1Sto32, 9875 binop( Iop_CmpLE32U, 9876 binop( Iop_And32, 9877 binop( Iop_Shr32, 9878 bcd_l, 9879 mkU8 ( DIGIT3_SHR ) ), 9880 mkU32 ( 0xF ) ), 9881 mkU32( 0x9 ) ) ) ), 9882 AND4 ( unop( Iop_1Sto32, 9883 binop( Iop_CmpLE32U, 9884 binop( Iop_And32, 9885 binop( Iop_Shr32, 9886 bcd_l, 9887 mkU8 ( DIGIT4_SHR ) ), 9888 mkU32 ( 0xF ) ), 9889 mkU32( 0x9 ) ) ), 9890 unop( Iop_1Sto32, 9891 binop( Iop_CmpLE32U, 9892 binop( Iop_And32, 9893 binop( Iop_Shr32, 9894 bcd_l, 9895 mkU8 ( DIGIT5_SHR ) ), 9896 mkU32 ( 0xF ) ), 9897 mkU32( 0x9 ) ) ), 9898 unop( Iop_1Sto32, 9899 binop( Iop_CmpLE32U, 9900 binop( Iop_And32, 9901 binop( Iop_Shr32, 9902 bcd_l, 9903 mkU8 ( DIGIT6_SHR ) ), 9904 mkU32 ( 0xF ) ), 9905 mkU32( 0x9 ) ) ), 9906 unop( Iop_1Sto32, 9907 binop( Iop_CmpLE32U, 9908 binop( Iop_And32, 9909 binop( Iop_Shr32, 9910 bcd_l, 9911 mkU8 ( DIGIT7_SHR ) ), 9912 mkU32 ( 0xF ) ), 9913 mkU32( 0x9 ) ) ) ), 9914 AND4( unop( Iop_1Sto32, 9915 binop( Iop_CmpLE32U, 9916 binop( Iop_And32, 9917 bcd_u, 9918 mkU32 ( 0xF ) ), 9919 mkU32( 0x9 ) ) ), 9920 unop( Iop_1Sto32, 9921 binop( Iop_CmpLE32U, 9922 binop( Iop_And32, 9923 binop( Iop_Shr32, 9924 bcd_u, 9925 mkU8 ( DIGIT1_SHR ) ), 9926 mkU32 ( 0xF ) ), 9927 mkU32( 0x9 ) ) ), 9928 unop( Iop_1Sto32, 9929 binop( Iop_CmpLE32U, 9930 binop( Iop_And32, 9931 binop( Iop_Shr32, 9932 bcd_u, 9933 mkU8 ( DIGIT2_SHR ) ), 9934 mkU32 ( 0xF ) ), 9935 mkU32( 0x9 ) ) ), 9936 unop( Iop_1Sto32, 9937 binop( Iop_CmpLE32U, 9938 binop( Iop_And32, 9939 binop( Iop_Shr32, 9940 bcd_u, 9941 mkU8 ( DIGIT3_SHR ) ), 9942 mkU32 ( 0xF ) ), 9943 mkU32( 0x9 ) ) ) ), 9944 AND4( unop( Iop_1Sto32, 9945 binop( Iop_CmpLE32U, 9946 binop( Iop_And32, 9947 binop( Iop_Shr32, 9948 bcd_u, 9949 mkU8 ( DIGIT4_SHR ) ), 9950 mkU32 ( 0xF ) ), 9951 mkU32( 0x9 ) ) ), 9952 unop( Iop_1Sto32, 9953 binop( Iop_CmpLE32U, 9954 binop( Iop_And32, 9955 binop( Iop_Shr32, 9956 bcd_u, 9957 mkU8 ( DIGIT5_SHR ) ), 9958 mkU32 ( 0xF ) ), 9959 mkU32( 0x9 ) ) ), 9960 unop( Iop_1Sto32, 9961 binop( Iop_CmpLE32U, 9962 binop( Iop_And32, 9963 binop( Iop_Shr32, 9964 bcd_u, 9965 mkU8 ( DIGIT6_SHR ) ), 9966 mkU32 ( 0xF ) ), 9967 mkU32( 0x9 ) ) ), 9968 unop( Iop_1Sto32, 9969 binop( Iop_CmpLE32U, 9970 binop( Iop_And32, 9971 binop( Iop_Shr32, 9972 bcd_u, 9973 mkU8 ( DIGIT7_SHR ) ), 9974 mkU32 ( 0xF ) ), 9975 mkU32( 0x9 ) ) ) ) ) ); 9976 9977 return unop( Iop_Not32, mkexpr( valid ) ); 9978 } 9979 #undef DIGIT1_SHR 9980 #undef DIGIT2_SHR 9981 #undef DIGIT3_SHR 9982 #undef DIGIT4_SHR 9983 #undef DIGIT5_SHR 9984 #undef DIGIT6_SHR 9985 #undef DIGIT7_SHR 9986 9987 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 9988 { 9989 return binop( Iop_Or32, 9990 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 9991 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 9992 ); 9993 } 9994 9995 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 9996 { 9997 return binop( Iop_Or32, 9998 binop( Iop_Or32, 9999 unop( Iop_1Sto32, 10000 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 10001 unop( Iop_1Sto32, 10002 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 10003 binop( Iop_Or32, 10004 unop( Iop_1Sto32, 10005 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 10006 unop( Iop_1Sto32, 10007 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 10008 } 10009 10010 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 10011 IRExpr * neg_sign_mask ) 10012 { 10013 return binop( Iop_Or32, 10014 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 10015 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 10016 } 10017 10018 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 10019 IRExpr * pos_sign_mask, 10020 IRExpr * neg_sign_mask ) 10021 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 10022 { 10023 return binop( Iop_Or32, 10024 invalid_bcd_mask, 10025 unop( Iop_1Sto32, 10026 binop( Iop_CmpEQ32, 10027 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 10028 mkU32( 0x0 ) ) ) ); 10029 } 10030 10031 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 10032 IRTemp * top_12_l, IRTemp * mid_60_u, 10033 IRTemp * mid_60_l, IRTemp * low_60_u, 10034 IRTemp * low_60_l) 10035 { 10036 IRTemp tmplow60 = newTemp( Ity_I64 ); 10037 IRTemp tmpmid60 = newTemp( Ity_I64 ); 10038 IRTemp tmptop12 = newTemp( Ity_I64 ); 10039 IRTemp low_50 = newTemp( Ity_I64 ); 10040 IRTemp mid_50 = newTemp( Ity_I64 ); 10041 IRTemp top_10 = newTemp( Ity_I64 ); 10042 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 10043 10044 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 10045 10046 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 10047 assign( low_50, 10048 binop( Iop_32HLto64, 10049 binop( Iop_And32, 10050 unop( Iop_64HIto32, frBI64_lo ), 10051 mkU32( 0x3FFFF ) ), 10052 unop( Iop_64to32, frBI64_lo ) ) ); 10053 10054 /* Convert the 50 bit densely packed BCD string to a 60 bit 10055 * BCD string. 10056 */ 10057 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 10058 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 10059 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 10060 10061 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 10062 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 10063 */ 10064 assign( mid_50, 10065 binop( Iop_32HLto64, 10066 binop( Iop_Or32, 10067 binop( Iop_Shl32, 10068 binop( Iop_And32, 10069 unop( Iop_64HIto32, frBI64_hi ), 10070 mkU32( 0xF ) ), 10071 mkU8( 14 ) ), 10072 binop( Iop_Shr32, 10073 unop( Iop_64to32, frBI64_hi ), 10074 mkU8( 18 ) ) ), 10075 binop( Iop_Or32, 10076 binop( Iop_Shl32, 10077 unop( Iop_64to32, frBI64_hi ), 10078 mkU8( 14 ) ), 10079 binop( Iop_Shr32, 10080 unop( Iop_64HIto32, frBI64_lo ), 10081 mkU8( 18 ) ) ) ) ); 10082 10083 /* Convert the 50 bit densely packed BCD string to a 60 bit 10084 * BCD string. 10085 */ 10086 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 10087 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 10088 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 10089 10090 /* top_10[49:0] = frBI64_hi[45:36]) | */ 10091 assign( top_10, 10092 binop( Iop_32HLto64, 10093 mkU32( 0 ), 10094 binop( Iop_And32, 10095 binop( Iop_Shr32, 10096 unop( Iop_64HIto32, frBI64_hi ), 10097 mkU8( 4 ) ), 10098 mkU32( 0x3FF ) ) ) ); 10099 10100 /* Convert the 10 bit densely packed BCD string to a 12 bit 10101 * BCD string. 10102 */ 10103 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 10104 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 10105 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 10106 } 10107 10108 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 10109 IRTemp * final_cnt, IRTemp * final_flag, 10110 IRExpr * string ) 10111 { 10112 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 10113 int digits = MAX_DIGITS_IN_STRING; 10114 int i; 10115 10116 cnt[start-1] = newTemp( Ity_I8 ); 10117 flag[start-1] = newTemp( Ity_I8 ); 10118 assign( cnt[start-1], init_cnt); 10119 assign( flag[start-1], init_flag); 10120 10121 for ( i = start; i <= digits; i++) { 10122 cnt[i] = newTemp( Ity_I8 ); 10123 flag[i] = newTemp( Ity_I8 ); 10124 assign( cnt[i], 10125 binop( Iop_Add8, 10126 mkexpr( cnt[i-1] ), 10127 binop(Iop_And8, 10128 unop( Iop_1Uto8, 10129 binop(Iop_CmpEQ32, 10130 binop(Iop_And32, 10131 string, 10132 mkU32( 0xF << 10133 ( ( digits - i ) * 4) ) ), 10134 mkU32( 0 ) ) ), 10135 binop( Iop_Xor8, /* complement flag */ 10136 mkexpr( flag[i - 1] ), 10137 mkU8( 0xFF ) ) ) ) ); 10138 10139 /* set flag to 1 if digit was not a zero */ 10140 assign( flag[i], 10141 binop(Iop_Or8, 10142 unop( Iop_1Sto8, 10143 binop(Iop_CmpNE32, 10144 binop(Iop_And32, 10145 string, 10146 mkU32( 0xF << 10147 ( (digits - i) * 4) ) ), 10148 mkU32( 0 ) ) ), 10149 mkexpr( flag[i - 1] ) ) ); 10150 } 10151 10152 *final_cnt = cnt[digits]; 10153 *final_flag = flag[digits]; 10154 } 10155 10156 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 10157 IRExpr * low_32 ) 10158 { 10159 IRTemp num_lmd = newTemp( Ity_I8 ); 10160 IRTemp num_upper = newTemp( Ity_I8 ); 10161 IRTemp num_low = newTemp( Ity_I8 ); 10162 IRTemp lmd_flag = newTemp( Ity_I8 ); 10163 IRTemp upper_flag = newTemp( Ity_I8 ); 10164 IRTemp low_flag = newTemp( Ity_I8 ); 10165 10166 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10167 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10168 10169 Count_zeros( 2, 10170 mkexpr( num_lmd ), 10171 mkexpr( lmd_flag ), 10172 &num_upper, 10173 &upper_flag, 10174 upper_28 ); 10175 10176 Count_zeros( 1, 10177 mkexpr( num_upper ), 10178 mkexpr( upper_flag ), 10179 &num_low, 10180 &low_flag, 10181 low_32 ); 10182 10183 return mkexpr( num_low ); 10184 } 10185 10186 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 10187 IRExpr * mid_60_u, IRExpr * mid_60_l, 10188 IRExpr * low_60_u, IRExpr * low_60_l) 10189 { 10190 IRTemp num_lmd = newTemp( Ity_I8 ); 10191 IRTemp num_top = newTemp( Ity_I8 ); 10192 IRTemp num_mid_u = newTemp( Ity_I8 ); 10193 IRTemp num_mid_l = newTemp( Ity_I8 ); 10194 IRTemp num_low_u = newTemp( Ity_I8 ); 10195 IRTemp num_low_l = newTemp( Ity_I8 ); 10196 10197 IRTemp lmd_flag = newTemp( Ity_I8 ); 10198 IRTemp top_flag = newTemp( Ity_I8 ); 10199 IRTemp mid_u_flag = newTemp( Ity_I8 ); 10200 IRTemp mid_l_flag = newTemp( Ity_I8 ); 10201 IRTemp low_u_flag = newTemp( Ity_I8 ); 10202 IRTemp low_l_flag = newTemp( Ity_I8 ); 10203 10204 /* Check the LMD, digit 16, to see if it is zero. */ 10205 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10206 10207 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10208 10209 Count_zeros( 6, 10210 mkexpr( num_lmd ), 10211 mkexpr( lmd_flag ), 10212 &num_top, 10213 &top_flag, 10214 top_12_l ); 10215 10216 Count_zeros( 1, 10217 mkexpr( num_top ), 10218 mkexpr( top_flag ), 10219 &num_mid_u, 10220 &mid_u_flag, 10221 binop( Iop_Or32, 10222 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 10223 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 10224 10225 Count_zeros( 2, 10226 mkexpr( num_mid_u ), 10227 mkexpr( mid_u_flag ), 10228 &num_mid_l, 10229 &mid_l_flag, 10230 mid_60_l ); 10231 10232 Count_zeros( 1, 10233 mkexpr( num_mid_l ), 10234 mkexpr( mid_l_flag ), 10235 &num_low_u, 10236 &low_u_flag, 10237 binop( Iop_Or32, 10238 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 10239 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 10240 10241 Count_zeros( 2, 10242 mkexpr( num_low_u ), 10243 mkexpr( low_u_flag ), 10244 &num_low_l, 10245 &low_l_flag, 10246 low_60_l ); 10247 10248 return mkexpr( num_low_l ); 10249 } 10250 10251 static IRExpr * Check_unordered(IRExpr * val) 10252 { 10253 IRTemp gfield0to5 = newTemp( Ity_I32 ); 10254 10255 /* Extract G[0:4] */ 10256 assign( gfield0to5, 10257 binop( Iop_And32, 10258 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 10259 mkU32( 0x1F ) ) ); 10260 10261 /* Check for unordered, return all 1'x if true */ 10262 return binop( Iop_Or32, /* QNaN check */ 10263 unop( Iop_1Sto32, 10264 binop( Iop_CmpEQ32, 10265 mkexpr( gfield0to5 ), 10266 mkU32( 0x1E ) ) ), 10267 unop( Iop_1Sto32, /* SNaN check */ 10268 binop( Iop_CmpEQ32, 10269 mkexpr( gfield0to5 ), 10270 mkU32( 0x1F ) ) ) ); 10271 } 10272 10273 #undef AND 10274 #undef AND4 10275 #undef OR 10276 #undef OR3 10277 #undef OR4 10278 #undef NOT 10279 #undef SHR 10280 #undef SHL 10281 #undef BITS5 10282 10283 /*------------------------------------------------------------*/ 10284 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 10285 /*------------------------------------------------------------*/ 10286 10287 /* DFP Arithmetic instructions */ 10288 static Bool dis_dfp_arith(UInt theInstr) 10289 { 10290 UInt opc2 = ifieldOPClo10( theInstr ); 10291 UChar frS_addr = ifieldRegDS( theInstr ); 10292 UChar frA_addr = ifieldRegA( theInstr ); 10293 UChar frB_addr = ifieldRegB( theInstr ); 10294 UChar flag_rC = ifieldBIT0( theInstr ); 10295 10296 IRTemp frA = newTemp( Ity_D64 ); 10297 IRTemp frB = newTemp( Ity_D64 ); 10298 IRTemp frS = newTemp( Ity_D64 ); 10299 IRExpr* round = get_IR_roundingmode_DFP(); 10300 10301 /* By default, if flag_RC is set, we will clear cr1 after the 10302 * operation. In reality we should set cr1 to indicate the 10303 * exception status of the operation, but since we're not 10304 * simulating exceptions, the exception status will appear to be 10305 * zero. Hence cr1 should be cleared if this is a . form insn. 10306 */ 10307 Bool clear_CR1 = True; 10308 10309 assign( frA, getDReg( frA_addr ) ); 10310 assign( frB, getDReg( frB_addr ) ); 10311 10312 switch (opc2) { 10313 case 0x2: // dadd 10314 DIP( "dadd%s fr%u,fr%u,fr%u\n", 10315 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10316 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10317 break; 10318 case 0x202: // dsub 10319 DIP( "dsub%s fr%u,fr%u,fr%u\n", 10320 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10321 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10322 break; 10323 case 0x22: // dmul 10324 DIP( "dmul%s fr%u,fr%u,fr%u\n", 10325 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10326 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10327 break; 10328 case 0x222: // ddiv 10329 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 10330 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10331 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10332 break; 10333 } 10334 10335 putDReg( frS_addr, mkexpr( frS ) ); 10336 10337 if (flag_rC && clear_CR1) { 10338 putCR321( 1, mkU8( 0 ) ); 10339 putCR0( 1, mkU8( 0 ) ); 10340 } 10341 10342 return True; 10343 } 10344 10345 /* Quad DFP Arithmetic instructions */ 10346 static Bool dis_dfp_arithq(UInt theInstr) 10347 { 10348 UInt opc2 = ifieldOPClo10( theInstr ); 10349 UChar frS_addr = ifieldRegDS( theInstr ); 10350 UChar frA_addr = ifieldRegA( theInstr ); 10351 UChar frB_addr = ifieldRegB( theInstr ); 10352 UChar flag_rC = ifieldBIT0( theInstr ); 10353 10354 IRTemp frA = newTemp( Ity_D128 ); 10355 IRTemp frB = newTemp( Ity_D128 ); 10356 IRTemp frS = newTemp( Ity_D128 ); 10357 IRExpr* round = get_IR_roundingmode_DFP(); 10358 10359 /* By default, if flag_RC is set, we will clear cr1 after the 10360 * operation. In reality we should set cr1 to indicate the 10361 * exception status of the operation, but since we're not 10362 * simulating exceptions, the exception status will appear to be 10363 * zero. Hence cr1 should be cleared if this is a . form insn. 10364 */ 10365 Bool clear_CR1 = True; 10366 10367 assign( frA, getDReg_pair( frA_addr ) ); 10368 assign( frB, getDReg_pair( frB_addr ) ); 10369 10370 switch (opc2) { 10371 case 0x2: // daddq 10372 DIP( "daddq%s fr%u,fr%u,fr%u\n", 10373 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10374 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10375 break; 10376 case 0x202: // dsubq 10377 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 10378 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10379 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10380 break; 10381 case 0x22: // dmulq 10382 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 10383 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10384 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10385 break; 10386 case 0x222: // ddivq 10387 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 10388 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10389 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10390 break; 10391 } 10392 10393 putDReg_pair( frS_addr, mkexpr( frS ) ); 10394 10395 if (flag_rC && clear_CR1) { 10396 putCR321( 1, mkU8( 0 ) ); 10397 putCR0( 1, mkU8( 0 ) ); 10398 } 10399 10400 return True; 10401 } 10402 10403 /* DFP 64-bit logical shift instructions */ 10404 static Bool dis_dfp_shift(UInt theInstr) { 10405 UInt opc2 = ifieldOPClo9( theInstr ); 10406 UChar frS_addr = ifieldRegDS( theInstr ); 10407 UChar frA_addr = ifieldRegA( theInstr ); 10408 UChar shift_val = IFIELD(theInstr, 10, 6); 10409 UChar flag_rC = ifieldBIT0( theInstr ); 10410 10411 IRTemp frA = newTemp( Ity_D64 ); 10412 IRTemp frS = newTemp( Ity_D64 ); 10413 Bool clear_CR1 = True; 10414 10415 assign( frA, getDReg( frA_addr ) ); 10416 10417 switch (opc2) { 10418 case 0x42: // dscli 10419 DIP( "dscli%s fr%u,fr%u,%u\n", 10420 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10421 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10422 break; 10423 case 0x62: // dscri 10424 DIP( "dscri%s fr%u,fr%u,%u\n", 10425 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10426 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10427 break; 10428 } 10429 10430 putDReg( frS_addr, mkexpr( frS ) ); 10431 10432 if (flag_rC && clear_CR1) { 10433 putCR321( 1, mkU8( 0 ) ); 10434 putCR0( 1, mkU8( 0 ) ); 10435 } 10436 10437 return True; 10438 } 10439 10440 /* Quad DFP logical shift instructions */ 10441 static Bool dis_dfp_shiftq(UInt theInstr) { 10442 UInt opc2 = ifieldOPClo9( theInstr ); 10443 UChar frS_addr = ifieldRegDS( theInstr ); 10444 UChar frA_addr = ifieldRegA( theInstr ); 10445 UChar shift_val = IFIELD(theInstr, 10, 6); 10446 UChar flag_rC = ifieldBIT0( theInstr ); 10447 10448 IRTemp frA = newTemp( Ity_D128 ); 10449 IRTemp frS = newTemp( Ity_D128 ); 10450 Bool clear_CR1 = True; 10451 10452 assign( frA, getDReg_pair( frA_addr ) ); 10453 10454 switch (opc2) { 10455 case 0x42: // dscliq 10456 DIP( "dscliq%s fr%u,fr%u,%u\n", 10457 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10458 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10459 break; 10460 case 0x62: // dscriq 10461 DIP( "dscriq%s fr%u,fr%u,%u\n", 10462 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10463 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10464 break; 10465 } 10466 10467 putDReg_pair( frS_addr, mkexpr( frS ) ); 10468 10469 if (flag_rC && clear_CR1) { 10470 putCR321( 1, mkU8( 0 ) ); 10471 putCR0( 1, mkU8( 0 ) ); 10472 } 10473 10474 return True; 10475 } 10476 10477 /* DFP 64-bit format conversion instructions */ 10478 static Bool dis_dfp_fmt_conv(UInt theInstr) { 10479 UInt opc2 = ifieldOPClo10( theInstr ); 10480 UChar frS_addr = ifieldRegDS( theInstr ); 10481 UChar frB_addr = ifieldRegB( theInstr ); 10482 IRExpr* round = get_IR_roundingmode_DFP(); 10483 UChar flag_rC = ifieldBIT0( theInstr ); 10484 IRTemp frB; 10485 IRTemp frS; 10486 Bool clear_CR1 = True; 10487 10488 switch (opc2) { 10489 case 0x102: //dctdp 10490 DIP( "dctdp%s fr%u,fr%u\n", 10491 flag_rC ? ".":"", frS_addr, frB_addr ); 10492 10493 frB = newTemp( Ity_D32 ); 10494 frS = newTemp( Ity_D64 ); 10495 assign( frB, getDReg32( frB_addr ) ); 10496 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 10497 putDReg( frS_addr, mkexpr( frS ) ); 10498 break; 10499 case 0x302: // drsp 10500 DIP( "drsp%s fr%u,fr%u\n", 10501 flag_rC ? ".":"", frS_addr, frB_addr ); 10502 frB = newTemp( Ity_D64 ); 10503 frS = newTemp( Ity_D32 ); 10504 assign( frB, getDReg( frB_addr ) ); 10505 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 10506 putDReg32( frS_addr, mkexpr( frS ) ); 10507 break; 10508 case 0x122: // dctfix 10509 { 10510 IRTemp tmp = newTemp( Ity_I64 ); 10511 10512 DIP( "dctfix%s fr%u,fr%u\n", 10513 flag_rC ? ".":"", frS_addr, frB_addr ); 10514 frB = newTemp( Ity_D64 ); 10515 frS = newTemp( Ity_D64 ); 10516 assign( frB, getDReg( frB_addr ) ); 10517 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 10518 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10519 putDReg( frS_addr, mkexpr( frS ) ); 10520 } 10521 break; 10522 case 0x322: // dcffix 10523 DIP( "dcffix%s fr%u,fr%u\n", 10524 flag_rC ? ".":"", frS_addr, frB_addr ); 10525 frB = newTemp( Ity_D64 ); 10526 frS = newTemp( Ity_D64 ); 10527 assign( frB, getDReg( frB_addr ) ); 10528 assign( frS, binop( Iop_I64StoD64, 10529 round, 10530 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 10531 putDReg( frS_addr, mkexpr( frS ) ); 10532 break; 10533 } 10534 10535 if (flag_rC && clear_CR1) { 10536 putCR321( 1, mkU8( 0 ) ); 10537 putCR0( 1, mkU8( 0 ) ); 10538 } 10539 10540 return True; 10541 } 10542 10543 /* Quad DFP format conversion instructions */ 10544 static Bool dis_dfp_fmt_convq(UInt theInstr) { 10545 UInt opc2 = ifieldOPClo10( theInstr ); 10546 UChar frS_addr = ifieldRegDS( theInstr ); 10547 UChar frB_addr = ifieldRegB( theInstr ); 10548 IRExpr* round = get_IR_roundingmode_DFP(); 10549 IRTemp frB64 = newTemp( Ity_D64 ); 10550 IRTemp frB128 = newTemp( Ity_D128 ); 10551 IRTemp frS64 = newTemp( Ity_D64 ); 10552 IRTemp frS128 = newTemp( Ity_D128 ); 10553 UChar flag_rC = ifieldBIT0( theInstr ); 10554 Bool clear_CR1 = True; 10555 10556 switch (opc2) { 10557 case 0x102: // dctqpq 10558 DIP( "dctqpq%s fr%u,fr%u\n", 10559 flag_rC ? ".":"", frS_addr, frB_addr ); 10560 assign( frB64, getDReg( frB_addr ) ); 10561 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 10562 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10563 break; 10564 case 0x122: // dctfixq 10565 { 10566 IRTemp tmp = newTemp( Ity_I64 ); 10567 10568 DIP( "dctfixq%s fr%u,fr%u\n", 10569 flag_rC ? ".":"", frS_addr, frB_addr ); 10570 assign( frB128, getDReg_pair( frB_addr ) ); 10571 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 10572 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10573 putDReg( frS_addr, mkexpr( frS64 ) ); 10574 } 10575 break; 10576 case 0x302: //drdpq 10577 DIP( "drdpq%s fr%u,fr%u\n", 10578 flag_rC ? ".":"", frS_addr, frB_addr ); 10579 assign( frB128, getDReg_pair( frB_addr ) ); 10580 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 10581 putDReg( frS_addr, mkexpr( frS64 ) ); 10582 break; 10583 case 0x322: // dcffixq 10584 { 10585 /* Have to introduce an IOP for this instruction so it will work 10586 * on POWER 6 because emulating the instruction requires a POWER 7 10587 * DFP instruction in the emulation code. 10588 */ 10589 DIP( "dcffixq%s fr%u,fr%u\n", 10590 flag_rC ? ".":"", frS_addr, frB_addr ); 10591 assign( frB64, getDReg( frB_addr ) ); 10592 assign( frS128, unop( Iop_I64StoD128, 10593 unop( Iop_ReinterpD64asI64, 10594 mkexpr( frB64 ) ) ) ); 10595 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10596 break; 10597 } 10598 } 10599 10600 if (flag_rC && clear_CR1) { 10601 putCR321( 1, mkU8( 0 ) ); 10602 putCR0( 1, mkU8( 0 ) ); 10603 } 10604 10605 return True; 10606 } 10607 10608 static Bool dis_dfp_round( UInt theInstr ) { 10609 UChar frS_addr = ifieldRegDS(theInstr); 10610 UChar R = IFIELD(theInstr, 16, 1); 10611 UChar RMC = IFIELD(theInstr, 9, 2); 10612 UChar frB_addr = ifieldRegB( theInstr ); 10613 UChar flag_rC = ifieldBIT0( theInstr ); 10614 IRTemp frB = newTemp( Ity_D64 ); 10615 IRTemp frS = newTemp( Ity_D64 ); 10616 UInt opc2 = ifieldOPClo8( theInstr ); 10617 Bool clear_CR1 = True; 10618 10619 switch (opc2) { 10620 /* drintn, is the same as drintx. The only difference is this 10621 * instruction does not generate an exception for an inexact operation. 10622 * Currently not supporting inexact exceptions. 10623 */ 10624 case 0x63: // drintx 10625 case 0xE3: // drintn 10626 DIP( "drintx/drintn%s fr%u,fr%u\n", 10627 flag_rC ? ".":"", frS_addr, frB_addr ); 10628 10629 /* NOTE, this instruction takes a DFP value and rounds to the 10630 * neares floating point integer value, i.e. fractional part 10631 * is zero. The result is a floating point number. 10632 */ 10633 /* pass the value of R and RMC in the same field */ 10634 assign( frB, getDReg( frB_addr ) ); 10635 assign( frS, binop( Iop_RoundD64toInt, 10636 mkU32( ( R << 3 ) | RMC ), 10637 mkexpr( frB ) ) ); 10638 putDReg( frS_addr, mkexpr( frS ) ); 10639 break; 10640 default: 10641 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 10642 return False; 10643 } 10644 10645 if (flag_rC && clear_CR1) { 10646 putCR321( 1, mkU8( 0 ) ); 10647 putCR0( 1, mkU8( 0 ) ); 10648 } 10649 10650 return True; 10651 } 10652 10653 static Bool dis_dfp_roundq(UInt theInstr) { 10654 UChar frS_addr = ifieldRegDS( theInstr ); 10655 UChar frB_addr = ifieldRegB( theInstr ); 10656 UChar R = IFIELD(theInstr, 16, 1); 10657 UChar RMC = IFIELD(theInstr, 9, 2); 10658 UChar flag_rC = ifieldBIT0( theInstr ); 10659 IRTemp frB = newTemp( Ity_D128 ); 10660 IRTemp frS = newTemp( Ity_D128 ); 10661 Bool clear_CR1 = True; 10662 UInt opc2 = ifieldOPClo8( theInstr ); 10663 10664 switch (opc2) { 10665 /* drintnq, is the same as drintxq. The only difference is this 10666 * instruction does not generate an exception for an inexact operation. 10667 * Currently not supporting inexact exceptions. 10668 */ 10669 case 0x63: // drintxq 10670 case 0xE3: // drintnq 10671 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 10672 flag_rC ? ".":"", frS_addr, frB_addr ); 10673 10674 /* pass the value of R and RMC in the same field */ 10675 assign( frB, getDReg_pair( frB_addr ) ); 10676 assign( frS, binop( Iop_RoundD128toInt, 10677 mkU32( ( R << 3 ) | RMC ), 10678 mkexpr( frB ) ) ); 10679 putDReg_pair( frS_addr, mkexpr( frS ) ); 10680 break; 10681 default: 10682 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 10683 return False; 10684 } 10685 10686 if (flag_rC && clear_CR1) { 10687 putCR321( 1, mkU8( 0 ) ); 10688 putCR0( 1, mkU8( 0 ) ); 10689 } 10690 10691 return True; 10692 } 10693 10694 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 10695 UInt opc2 = ifieldOPClo8( theInstr ); 10696 UChar frS_addr = ifieldRegDS( theInstr ); 10697 UChar frA_addr = ifieldRegA( theInstr ); 10698 UChar frB_addr = ifieldRegB( theInstr ); 10699 UChar flag_rC = ifieldBIT0( theInstr ); 10700 UInt TE_value = IFIELD(theInstr, 16, 4); 10701 UInt TE_sign = IFIELD(theInstr, 20, 1); 10702 UInt RMC = IFIELD(theInstr, 9, 2); 10703 IRTemp frA = newTemp( Ity_D64 ); 10704 IRTemp frB = newTemp( Ity_D64 ); 10705 IRTemp frS = newTemp( Ity_D64 ); 10706 Bool clear_CR1 = True; 10707 10708 assign( frB, getDReg( frB_addr ) ); 10709 10710 switch (opc2) { 10711 case 0x43: // dquai 10712 DIP( "dquai%s fr%u,fr%u,fr%u\n", 10713 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10714 IRTemp TE_I64 = newTemp( Ity_I64 ); 10715 10716 /* Generate a reference DFP value frA with the desired exponent 10717 * given by TE using significand from frB. Need to add the bias 10718 * 398 to TE. TE is stored as a 2's complement number. 10719 */ 10720 if (TE_sign == 1) { 10721 /* Take 2's complement of the 5-bit value and subtract from bias. 10722 * Bias is adjusted for the +1 required when taking 2's complement. 10723 */ 10724 assign( TE_I64, 10725 unop( Iop_32Uto64, 10726 binop( Iop_Sub32, mkU32( 397 ), 10727 binop( Iop_And32, mkU32( 0xF ), 10728 unop( Iop_Not32, mkU32( TE_value ) ) 10729 ) ) ) ); 10730 10731 } else { 10732 assign( TE_I64, 10733 unop( Iop_32Uto64, 10734 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 10735 ) ); 10736 } 10737 10738 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 10739 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 10740 10741 assign( frS, triop( Iop_QuantizeD64, 10742 mkU32( RMC ), 10743 mkexpr( frA ), 10744 mkexpr( frB ) ) ); 10745 break; 10746 10747 case 0x3: // dqua 10748 DIP( "dqua%s fr%u,fr%u,fr%u\n", 10749 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10750 assign( frA, getDReg( frA_addr ) ); 10751 assign( frS, triop( Iop_QuantizeD64, 10752 mkU32( RMC ), 10753 mkexpr( frA ), 10754 mkexpr( frB ) ) ); 10755 break; 10756 case 0x23: // drrnd 10757 { 10758 IRTemp tmp = newTemp( Ity_I8 ); 10759 10760 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 10761 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10762 assign( frA, getDReg( frA_addr ) ); 10763 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 10764 assign( tmp, unop( Iop_32to8, 10765 unop( Iop_64to32, 10766 unop( Iop_ReinterpD64asI64, 10767 mkexpr( frA ) ) ) ) ); 10768 assign( frS, triop( Iop_SignificanceRoundD64, 10769 mkU32( RMC ), 10770 mkexpr( tmp ), 10771 mkexpr( frB ) ) ); 10772 } 10773 break; 10774 default: 10775 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 10776 return False; 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_quantize_sig_rrndq(UInt theInstr) { 10789 UInt opc2 = ifieldOPClo8( 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 UInt TE_value = IFIELD(theInstr, 16, 4); 10795 UInt TE_sign = IFIELD(theInstr, 20, 1); 10796 UInt RMC = IFIELD(theInstr, 9, 2); 10797 IRTemp frA = newTemp( Ity_D128 ); 10798 IRTemp frB = newTemp( Ity_D128 ); 10799 IRTemp frS = newTemp( Ity_D128 ); 10800 Bool clear_CR1 = True; 10801 10802 assign( frB, getDReg_pair( frB_addr ) ); 10803 10804 switch (opc2) { 10805 case 0x43: // dquaiq 10806 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10807 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10808 IRTemp TE_I64 = newTemp( Ity_I64 ); 10809 10810 /* Generate a reference DFP value frA with the desired exponent 10811 * given by TE using significand of 1. Need to add the bias 10812 * 6176 to TE. 10813 */ 10814 if (TE_sign == 1) { 10815 /* Take 2's complement of the 5-bit value and subtract from bias. 10816 * Bias adjusted for the +1 required when taking 2's complement. 10817 */ 10818 assign( TE_I64, 10819 unop( Iop_32Uto64, 10820 binop( Iop_Sub32, mkU32( 6175 ), 10821 binop( Iop_And32, mkU32( 0xF ), 10822 unop( Iop_Not32, mkU32( TE_value ) ) 10823 ) ) ) ); 10824 10825 } else { 10826 assign( TE_I64, 10827 unop( Iop_32Uto64, 10828 binop( Iop_Add32, 10829 mkU32( 6176 ), 10830 mkU32( TE_value ) ) ) ); 10831 } 10832 10833 assign( frA, 10834 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 10835 unop( Iop_D64toD128, 10836 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 10837 assign( frS, triop( Iop_QuantizeD128, 10838 mkU32( RMC ), 10839 mkexpr( frA ), 10840 mkexpr( frB ) ) ); 10841 break; 10842 case 0x3: // dquaq 10843 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10844 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10845 assign( frA, getDReg_pair( frA_addr ) ); 10846 assign( frS, triop( Iop_QuantizeD128, 10847 mkU32( RMC ), 10848 mkexpr( frA ), 10849 mkexpr( frB ) ) ); 10850 break; 10851 case 0x23: // drrndq 10852 { 10853 IRTemp tmp = newTemp( Ity_I8 ); 10854 10855 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 10856 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10857 assign( frA, getDReg_pair( frA_addr ) ); 10858 assign( tmp, unop( Iop_32to8, 10859 unop( Iop_64to32, 10860 unop( Iop_ReinterpD64asI64, 10861 unop( Iop_D128HItoD64, 10862 mkexpr( frA ) ) ) ) ) ); 10863 assign( frS, triop( Iop_SignificanceRoundD128, 10864 mkU32( RMC ), 10865 mkexpr( tmp ), 10866 mkexpr( frB ) ) ); 10867 } 10868 break; 10869 default: 10870 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 10871 return False; 10872 } 10873 putDReg_pair( frS_addr, mkexpr( frS ) ); 10874 10875 if (flag_rC && clear_CR1) { 10876 putCR321( 1, mkU8( 0 ) ); 10877 putCR0( 1, mkU8( 0 ) ); 10878 } 10879 10880 return True; 10881 } 10882 10883 static Bool dis_dfp_extract_insert(UInt theInstr) { 10884 UInt opc2 = ifieldOPClo10( theInstr ); 10885 UChar frS_addr = ifieldRegDS( theInstr ); 10886 UChar frA_addr = ifieldRegA( theInstr ); 10887 UChar frB_addr = ifieldRegB( theInstr ); 10888 UChar flag_rC = ifieldBIT0( theInstr ); 10889 Bool clear_CR1 = True; 10890 10891 IRTemp frA = newTemp( Ity_D64 ); 10892 IRTemp frB = newTemp( Ity_D64 ); 10893 IRTemp frS = newTemp( Ity_D64 ); 10894 IRTemp tmp = newTemp( Ity_I64 ); 10895 10896 assign( frA, getDReg( frA_addr ) ); 10897 assign( frB, getDReg( frB_addr ) ); 10898 10899 switch (opc2) { 10900 case 0x162: // dxex 10901 DIP( "dxex%s fr%u,fr%u,fr%u\n", 10902 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10903 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 10904 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10905 break; 10906 case 0x362: // diex 10907 DIP( "diex%s fr%u,fr%u,fr%u\n", 10908 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10909 assign( frS, binop( Iop_InsertExpD64, 10910 unop( Iop_ReinterpD64asI64, 10911 mkexpr( frA ) ), 10912 mkexpr( frB ) ) ); 10913 break; 10914 default: 10915 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 10916 return False; 10917 } 10918 10919 putDReg( frS_addr, mkexpr( frS ) ); 10920 10921 if (flag_rC && clear_CR1) { 10922 putCR321( 1, mkU8( 0 ) ); 10923 putCR0( 1, mkU8( 0 ) ); 10924 } 10925 10926 return True; 10927 } 10928 10929 static Bool dis_dfp_extract_insertq(UInt theInstr) { 10930 UInt opc2 = ifieldOPClo10( theInstr ); 10931 UChar frS_addr = ifieldRegDS( theInstr ); 10932 UChar frA_addr = ifieldRegA( theInstr ); 10933 UChar frB_addr = ifieldRegB( theInstr ); 10934 UChar flag_rC = ifieldBIT0( theInstr ); 10935 10936 IRTemp frA = newTemp( Ity_D64 ); 10937 IRTemp frB = newTemp( Ity_D128 ); 10938 IRTemp frS64 = newTemp( Ity_D64 ); 10939 IRTemp frS = newTemp( Ity_D128 ); 10940 IRTemp tmp = newTemp( Ity_I64 ); 10941 Bool clear_CR1 = True; 10942 10943 assign( frB, getDReg_pair( frB_addr ) ); 10944 10945 switch (opc2) { 10946 case 0x162: // dxexq 10947 DIP( "dxexq%s fr%u,fr%u\n", 10948 flag_rC ? ".":"", frS_addr, frB_addr ); 10949 /* Instruction actually returns a 64-bit result. So as to be 10950 * consistent and not have to add a new struct, the emulation returns 10951 * the 64-bit result in the upper and lower register. 10952 */ 10953 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 10954 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10955 putDReg( frS_addr, mkexpr( frS64 ) ); 10956 break; 10957 case 0x362: // diexq 10958 DIP( "diexq%s fr%u,fr%u,fr%u\n", 10959 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10960 assign( frA, getDReg( frA_addr ) ); 10961 assign( frS, binop( Iop_InsertExpD128, 10962 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 10963 mkexpr( frB ) ) ); 10964 putDReg_pair( frS_addr, mkexpr( frS ) ); 10965 break; 10966 default: 10967 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 10968 return False; 10969 } 10970 10971 if (flag_rC && clear_CR1) { 10972 putCR321( 1, mkU8( 0 ) ); 10973 putCR0( 1, mkU8( 0 ) ); 10974 } 10975 10976 return True; 10977 } 10978 10979 /* DFP 64-bit comparison instructions */ 10980 static Bool dis_dfp_compare(UInt theInstr) { 10981 /* X-Form */ 10982 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10983 UChar frA_addr = ifieldRegA( theInstr ); 10984 UChar frB_addr = ifieldRegB( theInstr ); 10985 UInt opc1 = ifieldOPC( theInstr ); 10986 IRTemp frA; 10987 IRTemp frB; 10988 10989 IRTemp ccIR = newTemp( Ity_I32 ); 10990 IRTemp ccPPC32 = newTemp( Ity_I32 ); 10991 10992 10993 /* Note: Differences between dcmpu and dcmpo are only in exception 10994 flag settings, which aren't supported anyway. */ 10995 switch (opc1) { 10996 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 10997 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10998 frA = newTemp( Ity_D64 ); 10999 frB = newTemp( Ity_D64 ); 11000 11001 assign( frA, getDReg( frA_addr ) ); 11002 assign( frB, getDReg( frB_addr ) ); 11003 11004 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 11005 break; 11006 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 11007 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 11008 frA = newTemp( Ity_D128 ); 11009 frB = newTemp( Ity_D128 ); 11010 11011 assign( frA, getDReg_pair( frA_addr ) ); 11012 assign( frB, getDReg_pair( frB_addr ) ); 11013 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 11014 break; 11015 default: 11016 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 11017 return False; 11018 } 11019 11020 /* Map compare result from IR to PPC32 */ 11021 /* 11022 FP cmp result | PPC | IR 11023 -------------------------- 11024 UN | 0x1 | 0x45 11025 EQ | 0x2 | 0x40 11026 GT | 0x4 | 0x00 11027 LT | 0x8 | 0x01 11028 */ 11029 11030 assign( ccPPC32, 11031 binop( Iop_Shl32, 11032 mkU32( 1 ), 11033 unop( Iop_32to8, 11034 binop( Iop_Or32, 11035 binop( Iop_And32, 11036 unop( Iop_Not32, 11037 binop( Iop_Shr32, 11038 mkexpr( ccIR ), 11039 mkU8( 5 ) ) ), 11040 mkU32( 2 ) ), 11041 binop( Iop_And32, 11042 binop( Iop_Xor32, 11043 mkexpr( ccIR ), 11044 binop( Iop_Shr32, 11045 mkexpr( ccIR ), 11046 mkU8( 6 ) ) ), 11047 mkU32( 1 ) ) ) ) ) ); 11048 11049 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 11050 return True; 11051 } 11052 11053 /* Test class/group/exponent/significance instructions. */ 11054 static Bool dis_dfp_exponent_test ( UInt theInstr ) 11055 { 11056 UChar frA_addr = ifieldRegA( theInstr ); 11057 UChar frB_addr = ifieldRegB( theInstr ); 11058 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11059 IRTemp frA = newTemp( Ity_D64 ); 11060 IRTemp frB = newTemp( Ity_D64 ); 11061 IRTemp frA128 = newTemp( Ity_D128 ); 11062 IRTemp frB128 = newTemp( Ity_D128 ); 11063 UInt opc1 = ifieldOPC( theInstr ); 11064 IRTemp gfield_A = newTemp( Ity_I32 ); 11065 IRTemp gfield_B = newTemp( Ity_I32 ); 11066 IRTemp gfield_mask = newTemp( Ity_I32 ); 11067 IRTemp exponent_A = newTemp( Ity_I32 ); 11068 IRTemp exponent_B = newTemp( Ity_I32 ); 11069 IRTemp A_NaN_true = newTemp( Ity_I32 ); 11070 IRTemp B_NaN_true = newTemp( Ity_I32 ); 11071 IRTemp A_inf_true = newTemp( Ity_I32 ); 11072 IRTemp B_inf_true = newTemp( Ity_I32 ); 11073 IRTemp A_equals_B = newTemp( Ity_I32 ); 11074 IRTemp finite_number = newTemp( Ity_I32 ); 11075 IRTemp cc0 = newTemp( Ity_I32 ); 11076 IRTemp cc1 = newTemp( Ity_I32 ); 11077 IRTemp cc2 = newTemp( Ity_I32 ); 11078 IRTemp cc3 = newTemp( Ity_I32 ); 11079 11080 /* The dtstex and dtstexg instructions only differ in the size of the 11081 * exponent field. The following switch statement takes care of the size 11082 * specific setup. Once the value of the exponents, the G-field shift 11083 * and mask is setup the remaining code is identical. 11084 */ 11085 switch (opc1) { 11086 case 0x3b: // dtstex Extended instruction setup 11087 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 11088 assign( frA, getDReg( frA_addr ) ); 11089 assign( frB, getDReg( frB_addr ) ); 11090 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 11091 assign(exponent_A, unop( Iop_64to32, 11092 unop( Iop_ExtractExpD64, 11093 mkexpr( frA ) ) ) ); 11094 assign(exponent_B, unop( Iop_64to32, 11095 unop( Iop_ExtractExpD64, 11096 mkexpr( frB ) ) ) ); 11097 break; 11098 11099 case 0x3F: // dtstexq Quad instruction setup 11100 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 11101 assign( frA128, getDReg_pair( frA_addr ) ); 11102 assign( frB128, getDReg_pair( frB_addr ) ); 11103 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 11104 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 11105 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 11106 assign( exponent_A, unop( Iop_64to32, 11107 unop( Iop_ExtractExpD128, 11108 mkexpr( frA128 ) ) ) ); 11109 assign( exponent_B, unop( Iop_64to32, 11110 unop( Iop_ExtractExpD128, 11111 mkexpr( frB128 ) ) ) ); 11112 break; 11113 default: 11114 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 11115 return False; 11116 } 11117 11118 /* Extract the Gfield */ 11119 assign( gfield_A, binop( Iop_And32, 11120 mkexpr( gfield_mask ), 11121 unop( Iop_64HIto32, 11122 unop( Iop_ReinterpD64asI64, 11123 mkexpr(frA) ) ) ) ); 11124 11125 assign( gfield_B, binop( Iop_And32, 11126 mkexpr( gfield_mask ), 11127 unop( Iop_64HIto32, 11128 unop( Iop_ReinterpD64asI64, 11129 mkexpr(frB) ) ) ) ); 11130 11131 /* check for NAN */ 11132 assign( A_NaN_true, binop(Iop_Or32, 11133 unop( Iop_1Sto32, 11134 binop( Iop_CmpEQ32, 11135 mkexpr( gfield_A ), 11136 mkU32( 0x7C000000 ) ) ), 11137 unop( Iop_1Sto32, 11138 binop( Iop_CmpEQ32, 11139 mkexpr( gfield_A ), 11140 mkU32( 0x7E000000 ) ) 11141 ) ) ); 11142 assign( B_NaN_true, binop(Iop_Or32, 11143 unop( Iop_1Sto32, 11144 binop( Iop_CmpEQ32, 11145 mkexpr( gfield_B ), 11146 mkU32( 0x7C000000 ) ) ), 11147 unop( Iop_1Sto32, 11148 binop( Iop_CmpEQ32, 11149 mkexpr( gfield_B ), 11150 mkU32( 0x7E000000 ) ) 11151 ) ) ); 11152 11153 /* check for infinity */ 11154 assign( A_inf_true, 11155 unop( Iop_1Sto32, 11156 binop( Iop_CmpEQ32, 11157 mkexpr( gfield_A ), 11158 mkU32( 0x78000000 ) ) ) ); 11159 11160 assign( B_inf_true, 11161 unop( Iop_1Sto32, 11162 binop( Iop_CmpEQ32, 11163 mkexpr( gfield_B ), 11164 mkU32( 0x78000000 ) ) ) ); 11165 11166 assign( finite_number, 11167 unop( Iop_Not32, 11168 binop( Iop_Or32, 11169 binop( Iop_Or32, 11170 mkexpr( A_NaN_true ), 11171 mkexpr( B_NaN_true ) ), 11172 binop( Iop_Or32, 11173 mkexpr( A_inf_true ), 11174 mkexpr( B_inf_true ) ) ) ) ); 11175 11176 /* Calculate the condition code bits 11177 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 11178 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 11179 * cc0, cc1 and cc0 reflect the results of the comparisons. 11180 */ 11181 assign( A_equals_B, 11182 binop( Iop_Or32, 11183 unop( Iop_1Uto32, 11184 binop( Iop_CmpEQ32, 11185 mkexpr( exponent_A ), 11186 mkexpr( exponent_B ) ) ), 11187 binop( Iop_Or32, 11188 binop( Iop_And32, 11189 mkexpr( A_inf_true ), 11190 mkexpr( B_inf_true ) ), 11191 binop( Iop_And32, 11192 mkexpr( A_NaN_true ), 11193 mkexpr( B_NaN_true ) ) ) ) ); 11194 11195 assign( cc0, binop( Iop_And32, 11196 mkexpr( finite_number ), 11197 binop( Iop_Shl32, 11198 unop( Iop_1Uto32, 11199 binop( Iop_CmpLT32U, 11200 mkexpr( exponent_A ), 11201 mkexpr( exponent_B ) ) ), 11202 mkU8( 3 ) ) ) ); 11203 11204 assign( cc1, binop( Iop_And32, 11205 mkexpr( finite_number ), 11206 binop( Iop_Shl32, 11207 unop( Iop_1Uto32, 11208 binop( Iop_CmpLT32U, 11209 mkexpr( exponent_B ), 11210 mkexpr( exponent_A ) ) ), 11211 mkU8( 2 ) ) ) ); 11212 11213 assign( cc2, binop( Iop_Shl32, 11214 binop( Iop_And32, 11215 mkexpr( A_equals_B ), 11216 mkU32( 1 ) ), 11217 mkU8( 1 ) ) ); 11218 11219 assign( cc3, binop( Iop_And32, 11220 unop( Iop_Not32, mkexpr( A_equals_B ) ), 11221 binop( Iop_And32, 11222 mkU32( 0x1 ), 11223 binop( Iop_Or32, 11224 binop( Iop_Or32, 11225 mkexpr ( A_inf_true ), 11226 mkexpr ( B_inf_true ) ), 11227 binop( Iop_Or32, 11228 mkexpr ( A_NaN_true ), 11229 mkexpr ( B_NaN_true ) ) ) 11230 ) ) ); 11231 11232 /* store the condition code */ 11233 putGST_field( PPC_GST_CR, 11234 binop( Iop_Or32, 11235 mkexpr( cc0 ), 11236 binop( Iop_Or32, 11237 mkexpr( cc1 ), 11238 binop( Iop_Or32, 11239 mkexpr( cc2 ), 11240 mkexpr( cc3 ) ) ) ), 11241 crfD ); 11242 return True; 11243 } 11244 11245 /* Test class/group/exponent/significance instructions. */ 11246 static Bool dis_dfp_class_test ( UInt theInstr ) 11247 { 11248 UChar frA_addr = ifieldRegA( theInstr ); 11249 IRTemp frA = newTemp( Ity_D64 ); 11250 IRTemp abs_frA = newTemp( Ity_D64 ); 11251 IRTemp frAI64_hi = newTemp( Ity_I64 ); 11252 IRTemp frAI64_lo = newTemp( Ity_I64 ); 11253 UInt opc1 = ifieldOPC( theInstr ); 11254 UInt opc2 = ifieldOPClo9( theInstr ); 11255 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 11256 UInt DCM = IFIELD( theInstr, 10, 6 ); 11257 IRTemp DCM_calc = newTemp( Ity_I32 ); 11258 UInt max_exp = 0; 11259 UInt min_exp = 0; 11260 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 11261 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 11262 IRTemp significand64 = newTemp( Ity_D64 ); 11263 IRTemp significand128 = newTemp( Ity_D128 ); 11264 IRTemp exp_min_normal = newTemp( Ity_I64 ); 11265 IRTemp exponent = newTemp( Ity_I32 ); 11266 11267 IRTemp infinity_true = newTemp( Ity_I32 ); 11268 IRTemp SNaN_true = newTemp( Ity_I32 ); 11269 IRTemp QNaN_true = newTemp( Ity_I32 ); 11270 IRTemp subnormal_true = newTemp( Ity_I32 ); 11271 IRTemp normal_true = newTemp( Ity_I32 ); 11272 IRTemp extreme_true = newTemp( Ity_I32 ); 11273 IRTemp lmd = newTemp( Ity_I32 ); 11274 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 11275 IRTemp zero_true = newTemp( Ity_I32 ); 11276 IRTemp sign = newTemp( Ity_I32 ); 11277 IRTemp field = newTemp( Ity_I32 ); 11278 IRTemp ccIR_zero = newTemp( Ity_I32 ); 11279 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 11280 11281 /* UInt size = DFP_LONG; JRS:unused */ 11282 IRTemp gfield = newTemp( Ity_I32 ); 11283 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 11284 IRTemp gfield_mask = newTemp( Ity_I32 ); 11285 IRTemp dcm0 = newTemp( Ity_I32 ); 11286 IRTemp dcm1 = newTemp( Ity_I32 ); 11287 IRTemp dcm2 = newTemp( Ity_I32 ); 11288 IRTemp dcm3 = newTemp( Ity_I32 ); 11289 IRTemp dcm4 = newTemp( Ity_I32 ); 11290 IRTemp dcm5 = newTemp( Ity_I32 ); 11291 11292 /* The only difference between the dtstdc and dtstdcq instructions is 11293 * size of the T and G fields. The calculation of the 4 bit field 11294 * is the same. Setup the parameters and values that are DFP size 11295 * specific. The rest of the code is independent of the DFP size. 11296 * 11297 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 11298 * The interpretation of the ccIR values is as follows: 11299 * 11300 * DFP cmp result | IR 11301 * -------------------------- 11302 * UN | 0x45 11303 * EQ | 0x40 11304 * GT | 0x00 11305 * LT | 0x01 11306 */ 11307 11308 assign( frA, getDReg( frA_addr ) ); 11309 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 11310 11311 assign( abs_frA, unop( Iop_ReinterpI64asD64, 11312 binop( Iop_And64, 11313 unop( Iop_ReinterpD64asI64, 11314 mkexpr( frA ) ), 11315 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 11316 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 11317 switch (opc1) { 11318 case 0x3b: // dtstdc, dtstdg 11319 DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 11320 crfD, frA_addr, DCM); 11321 /* setup the parameters for the long format of the two instructions */ 11322 assign( frAI64_lo, mkU64( 0 ) ); 11323 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 11324 max_exp = DFP_LONG_EXP_MAX; 11325 min_exp = DFP_LONG_EXP_MIN; 11326 11327 assign( exponent, unop( Iop_64to32, 11328 unop( Iop_ExtractExpD64, 11329 mkexpr( frA ) ) ) ); 11330 assign( significand64, 11331 unop( Iop_ReinterpI64asD64, 11332 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 11333 assign( exp_min_normal,mkU64( 398 - 383 ) ); 11334 assign( min_subnormalD64, 11335 binop( Iop_InsertExpD64, 11336 mkexpr( exp_min_normal ), 11337 mkexpr( significand64 ) ) ); 11338 11339 assign( ccIR_subnormal, 11340 binop( Iop_CmpD64, 11341 mkexpr( abs_frA ), 11342 mkexpr( min_subnormalD64 ) ) ); 11343 11344 /* compare absolute value of frA with zero */ 11345 assign( ccIR_zero, 11346 binop( Iop_CmpD64, 11347 mkexpr( abs_frA ), 11348 unop( Iop_ReinterpI64asD64, 11349 mkU64( 0x2238000000000000ULL ) ) ) ); 11350 11351 /* size = DFP_LONG; JRS: unused */ 11352 break; 11353 11354 case 0x3F: // dtstdcq, dtstdgq 11355 DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 11356 crfD, frA_addr, DCM); 11357 /* setup the parameters for the extended format of the 11358 * two instructions 11359 */ 11360 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 11361 getDReg( frA_addr+1 ) ) ); 11362 11363 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 11364 max_exp = DFP_EXTND_EXP_MAX; 11365 min_exp = DFP_EXTND_EXP_MIN; 11366 assign( exponent, unop( Iop_64to32, 11367 unop( Iop_ExtractExpD128, 11368 getDReg_pair( frA_addr) ) ) ); 11369 11370 /* create quand exponent for minimum normal number */ 11371 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 11372 assign( significand128, 11373 unop( Iop_D64toD128, 11374 unop( Iop_ReinterpI64asD64, 11375 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 11376 11377 assign( min_subnormalD128, 11378 binop( Iop_InsertExpD128, 11379 mkexpr( exp_min_normal ), 11380 mkexpr( significand128 ) ) ); 11381 11382 assign( ccIR_subnormal, 11383 binop( Iop_CmpD128, 11384 binop( Iop_D64HLtoD128, 11385 unop( Iop_ReinterpI64asD64, 11386 binop( Iop_And64, 11387 unop( Iop_ReinterpD64asI64, 11388 mkexpr( frA ) ), 11389 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 11390 getDReg( frA_addr+1 ) ), 11391 mkexpr( min_subnormalD128 ) ) ); 11392 assign( ccIR_zero, 11393 binop( Iop_CmpD128, 11394 binop( Iop_D64HLtoD128, 11395 mkexpr( abs_frA ), 11396 getDReg( frA_addr+1 ) ), 11397 unop( Iop_D64toD128, 11398 unop( Iop_ReinterpI64asD64, 11399 mkU64( 0x0ULL ) ) ) ) ); 11400 11401 /* size = DFP_EXTND; JRS:unused */ 11402 break; 11403 default: 11404 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 11405 return False; 11406 } 11407 11408 /* The G-field is in the upper 32-bits. The I64 logical operations 11409 * do not seem to be supported in 32-bit mode so keep things as 32-bit 11410 * operations. 11411 */ 11412 assign( gfield, binop( Iop_And32, 11413 mkexpr( gfield_mask ), 11414 unop( Iop_64HIto32, 11415 mkexpr(frAI64_hi) ) ) ); 11416 11417 /* There is a lot of code that is the same to do the class and group 11418 * instructions. Later there is an if statement to handle the specific 11419 * instruction. 11420 * 11421 * Will be using I32 values, compares, shifts and logical operations for 11422 * this code as the 64-bit compare, shifts, logical operations are not 11423 * supported in 32-bit mode. 11424 */ 11425 11426 /* Check the bits for Infinity, QNaN or Signaling NaN */ 11427 assign( infinity_true, 11428 unop( Iop_1Sto32, 11429 binop( Iop_CmpEQ32, 11430 binop( Iop_And32, 11431 mkU32( 0x7C000000 ), 11432 mkexpr( gfield ) ), 11433 mkU32( 0x78000000 ) ) ) ); 11434 11435 assign( SNaN_true, 11436 unop( Iop_1Sto32, 11437 binop( Iop_CmpEQ32, 11438 binop( Iop_And32, 11439 mkU32( 0x7E000000 ), 11440 mkexpr( gfield ) ), 11441 mkU32( 0x7E000000 ) ) ) ); 11442 11443 assign( QNaN_true, 11444 binop( Iop_And32, 11445 unop( Iop_1Sto32, 11446 binop( Iop_CmpEQ32, 11447 binop( Iop_And32, 11448 mkU32( 0x7E000000 ), 11449 mkexpr( gfield ) ), 11450 mkU32( 0x7C000000 ) ) ), 11451 unop( Iop_Not32, 11452 mkexpr( SNaN_true ) ) ) ); 11453 11454 assign( zero_true, 11455 binop( Iop_And32, 11456 unop(Iop_1Sto32, 11457 binop( Iop_CmpEQ32, 11458 mkexpr( ccIR_zero ), 11459 mkU32( 0x40 ) ) ), // ccIR code for Equal 11460 unop( Iop_Not32, 11461 binop( Iop_Or32, 11462 mkexpr( infinity_true ), 11463 binop( Iop_Or32, 11464 mkexpr( QNaN_true ), 11465 mkexpr( SNaN_true ) ) ) ) ) ); 11466 11467 /* Do compare of frA the minimum normal value. Comparison is size 11468 * depenent and was done above to get the ccIR value. 11469 */ 11470 assign( subnormal_true, 11471 binop( Iop_And32, 11472 binop( Iop_Or32, 11473 unop( Iop_1Sto32, 11474 binop( Iop_CmpEQ32, 11475 mkexpr( ccIR_subnormal ), 11476 mkU32( 0x40 ) ) ), // ccIR code for Equal 11477 unop( Iop_1Sto32, 11478 binop( Iop_CmpEQ32, 11479 mkexpr( ccIR_subnormal ), 11480 mkU32( 0x1 ) ) ) ), // ccIR code for LT 11481 unop( Iop_Not32, 11482 binop( Iop_Or32, 11483 binop( Iop_Or32, 11484 mkexpr( infinity_true ), 11485 mkexpr( zero_true) ), 11486 binop( Iop_Or32, 11487 mkexpr( QNaN_true ), 11488 mkexpr( SNaN_true ) ) ) ) ) ); 11489 11490 /* Normal number is not subnormal, infinity, NaN or Zero */ 11491 assign( normal_true, 11492 unop( Iop_Not32, 11493 binop( Iop_Or32, 11494 binop( Iop_Or32, 11495 mkexpr( infinity_true ), 11496 mkexpr( zero_true ) ), 11497 binop( Iop_Or32, 11498 mkexpr( subnormal_true ), 11499 binop( Iop_Or32, 11500 mkexpr( QNaN_true ), 11501 mkexpr( SNaN_true ) ) ) ) ) ); 11502 11503 /* Calculate the DCM bit field based on the tests for the specific 11504 * instruction 11505 */ 11506 if (opc2 == 0xC2) { // dtstdc, dtstdcq 11507 /* DCM[0:5] Bit Data Class definition 11508 * 0 Zero 11509 * 1 Subnormal 11510 * 2 Normal 11511 * 3 Infinity 11512 * 4 Quiet NaN 11513 * 5 Signaling NaN 11514 */ 11515 11516 assign( dcm0, binop( Iop_Shl32, 11517 mkexpr( zero_true ), 11518 mkU8( 5 ) ) ); 11519 assign( dcm1, binop( Iop_Shl32, 11520 binop( Iop_And32, 11521 mkexpr( subnormal_true ), 11522 mkU32( 1 ) ), 11523 mkU8( 4 ) ) ); 11524 assign( dcm2, binop( Iop_Shl32, 11525 binop( Iop_And32, 11526 mkexpr( normal_true ), 11527 mkU32( 1 ) ), 11528 mkU8( 3 ) ) ); 11529 assign( dcm3, binop( Iop_Shl32, 11530 binop( Iop_And32, 11531 mkexpr( infinity_true), 11532 mkU32( 1 ) ), 11533 mkU8( 2 ) ) ); 11534 assign( dcm4, binop( Iop_Shl32, 11535 binop( Iop_And32, 11536 mkexpr( QNaN_true ), 11537 mkU32( 1 ) ), 11538 mkU8( 1 ) ) ); 11539 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 11540 11541 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 11542 /* check if the exponent is extreme */ 11543 assign( extreme_true, binop( Iop_Or32, 11544 unop( Iop_1Sto32, 11545 binop( Iop_CmpEQ32, 11546 mkexpr( exponent ), 11547 mkU32( max_exp ) ) ), 11548 unop( Iop_1Sto32, 11549 binop( Iop_CmpEQ32, 11550 mkexpr( exponent ), 11551 mkU32( min_exp ) ) ) ) ); 11552 11553 /* Check if LMD is zero */ 11554 Get_lmd( &lmd, binop( Iop_Shr32, 11555 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 11556 11557 assign( lmd_zero_true, unop( Iop_1Sto32, 11558 binop( Iop_CmpEQ32, 11559 mkexpr( lmd ), 11560 mkU32( 0 ) ) ) ); 11561 11562 /* DCM[0:5] Bit Data Class definition 11563 * 0 Zero with non-extreme exponent 11564 * 1 Zero with extreme exponent 11565 * 2 Subnormal or (Normal with extreme exponent) 11566 * 3 Normal with non-extreme exponent and 11567 * leftmost zero digit in significand 11568 * 4 Normal with non-extreme exponent and 11569 * leftmost nonzero digit in significand 11570 * 5 Special symbol (Infinity, QNaN, or SNaN) 11571 */ 11572 assign( dcm0, binop( Iop_Shl32, 11573 binop( Iop_And32, 11574 binop( Iop_And32, 11575 unop( Iop_Not32, 11576 mkexpr( extreme_true ) ), 11577 mkexpr( zero_true ) ), 11578 mkU32( 0x1 ) ), 11579 mkU8( 5 ) ) ); 11580 11581 assign( dcm1, binop( Iop_Shl32, 11582 binop( Iop_And32, 11583 binop( Iop_And32, 11584 mkexpr( extreme_true ), 11585 mkexpr( zero_true ) ), 11586 mkU32( 0x1 ) ), 11587 mkU8( 4 ) ) ); 11588 11589 assign( dcm2, binop( Iop_Shl32, 11590 binop( Iop_And32, 11591 binop( Iop_Or32, 11592 binop( Iop_And32, 11593 mkexpr( extreme_true ), 11594 mkexpr( normal_true ) ), 11595 mkexpr( subnormal_true ) ), 11596 mkU32( 0x1 ) ), 11597 mkU8( 3 ) ) ); 11598 11599 assign( dcm3, binop( Iop_Shl32, 11600 binop( Iop_And32, 11601 binop( Iop_And32, 11602 binop( Iop_And32, 11603 unop( Iop_Not32, 11604 mkexpr( extreme_true ) ), 11605 mkexpr( normal_true ) ), 11606 unop( Iop_1Sto32, 11607 binop( Iop_CmpEQ32, 11608 mkexpr( lmd ), 11609 mkU32( 0 ) ) ) ), 11610 mkU32( 0x1 ) ), 11611 mkU8( 2 ) ) ); 11612 11613 assign( dcm4, binop( Iop_Shl32, 11614 binop( Iop_And32, 11615 binop( Iop_And32, 11616 binop( Iop_And32, 11617 unop( Iop_Not32, 11618 mkexpr( extreme_true ) ), 11619 mkexpr( normal_true ) ), 11620 unop( Iop_1Sto32, 11621 binop( Iop_CmpNE32, 11622 mkexpr( lmd ), 11623 mkU32( 0 ) ) ) ), 11624 mkU32( 0x1 ) ), 11625 mkU8( 1 ) ) ); 11626 11627 assign( dcm5, binop( Iop_And32, 11628 binop( Iop_Or32, 11629 mkexpr( SNaN_true), 11630 binop( Iop_Or32, 11631 mkexpr( QNaN_true), 11632 mkexpr( infinity_true) ) ), 11633 mkU32( 0x1 ) ) ); 11634 } 11635 11636 /* create DCM field */ 11637 assign( DCM_calc, 11638 binop( Iop_Or32, 11639 mkexpr( dcm0 ), 11640 binop( Iop_Or32, 11641 mkexpr( dcm1 ), 11642 binop( Iop_Or32, 11643 mkexpr( dcm2 ), 11644 binop( Iop_Or32, 11645 mkexpr( dcm3 ), 11646 binop( Iop_Or32, 11647 mkexpr( dcm4 ), 11648 mkexpr( dcm5 ) ) ) ) ) ) ); 11649 11650 /* Get the sign of the DFP number, ignore sign for QNaN */ 11651 assign( sign, 11652 unop( Iop_1Uto32, 11653 binop( Iop_CmpEQ32, 11654 binop( Iop_Shr32, 11655 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 11656 mkU8( 63 - 32 ) ), 11657 mkU32( 1 ) ) ) ); 11658 11659 /* This instruction generates a four bit field to be stored in the 11660 * condition code register. The condition code register consists of 7 11661 * fields. The field to be written to is specified by the BF (AKA crfD) 11662 * field. 11663 * 11664 * The field layout is as follows: 11665 * 11666 * Field Meaning 11667 * 0000 Operand positive with no match 11668 * 0100 Operand positive with at least one match 11669 * 0001 Operand negative with no match 11670 * 0101 Operand negative with at least one match 11671 */ 11672 assign( field, binop( Iop_Or32, 11673 binop( Iop_Shl32, 11674 mkexpr( sign ), 11675 mkU8( 3 ) ), 11676 binop( Iop_Shl32, 11677 unop( Iop_1Uto32, 11678 binop( Iop_CmpNE32, 11679 binop( Iop_And32, 11680 mkU32( DCM ), 11681 mkexpr( DCM_calc ) ), 11682 mkU32( 0 ) ) ), 11683 mkU8( 1 ) ) ) ); 11684 11685 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 11686 return True; 11687 } 11688 11689 static Bool dis_dfp_bcd(UInt theInstr) { 11690 UInt opc2 = ifieldOPClo10( theInstr ); 11691 ULong sp = IFIELD(theInstr, 19, 2); 11692 ULong s = IFIELD(theInstr, 20, 1); 11693 UChar frT_addr = ifieldRegDS( theInstr ); 11694 UChar frB_addr = ifieldRegB( theInstr ); 11695 IRTemp frB = newTemp( Ity_D64 ); 11696 IRTemp frBI64 = newTemp( Ity_I64 ); 11697 IRTemp result = newTemp( Ity_I64 ); 11698 IRTemp resultD64 = newTemp( Ity_D64 ); 11699 IRTemp bcd64 = newTemp( Ity_I64 ); 11700 IRTemp bcd_u = newTemp( Ity_I32 ); 11701 IRTemp bcd_l = newTemp( Ity_I32 ); 11702 IRTemp dbcd_u = newTemp( Ity_I32 ); 11703 IRTemp dbcd_l = newTemp( Ity_I32 ); 11704 IRTemp lmd = newTemp( Ity_I32 ); 11705 11706 assign( frB, getDReg( frB_addr ) ); 11707 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11708 11709 switch ( opc2 ) { 11710 case 0x142: // ddedpd DFP Decode DPD to BCD 11711 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11712 11713 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11714 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 11715 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 11716 11717 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11718 /* Unsigned BCD string */ 11719 Get_lmd( &lmd, 11720 binop( Iop_Shr32, 11721 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11722 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11723 11724 assign( result, 11725 binop( Iop_32HLto64, 11726 binop( Iop_Or32, 11727 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 11728 mkexpr( bcd_u ) ), 11729 mkexpr( bcd_l ) ) ); 11730 11731 } else { 11732 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11733 * the positive and negative values are encoded in the least 11734 * significant bits. 11735 */ 11736 IRTemp sign = newTemp( Ity_I32 ); 11737 11738 if (sp == 2) { 11739 /* Positive sign = 0xC, negative sign = 0xD */ 11740 11741 assign( sign, 11742 binop( Iop_Or32, 11743 binop( Iop_Shr32, 11744 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11745 mkU8( 31 ) ), 11746 mkU32( 0xC ) ) ); 11747 11748 } else if ( sp == 3 ) { 11749 /* Positive sign = 0xF, negative sign = 0xD */ 11750 IRTemp tmp32 = newTemp( Ity_I32 ); 11751 11752 /* Complement sign bit then OR into bit position 1 */ 11753 assign( tmp32, 11754 binop( Iop_Xor32, 11755 binop( Iop_Shr32, 11756 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11757 mkU8( 30 ) ), 11758 mkU32( 0x2 ) ) ); 11759 11760 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11761 11762 } else { 11763 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11764 } 11765 11766 /* Put sign in bottom 4 bits, move most significant 4-bits from 11767 * bcd_l to bcd_u. 11768 */ 11769 assign( result, 11770 binop( Iop_32HLto64, 11771 binop( Iop_Or32, 11772 binop( Iop_Shr32, 11773 mkexpr( bcd_l ), 11774 mkU8( 28 ) ), 11775 binop( Iop_Shl32, 11776 mkexpr( bcd_u ), 11777 mkU8( 4 ) ) ), 11778 binop( Iop_Or32, 11779 mkexpr( sign ), 11780 binop( Iop_Shl32, 11781 mkexpr( bcd_l ), 11782 mkU8( 4 ) ) ) ) ); 11783 } 11784 11785 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 11786 break; 11787 11788 case 0x342: // denbcd DFP Encode BCD to DPD 11789 { 11790 IRTemp valid_mask = newTemp( Ity_I32 ); 11791 IRTemp invalid_mask = newTemp( Ity_I32 ); 11792 IRTemp without_lmd = newTemp( Ity_I64 ); 11793 IRTemp tmp64 = newTemp( Ity_I64 ); 11794 IRTemp dbcd64 = newTemp( Ity_I64 ); 11795 IRTemp left_exp = newTemp( Ity_I32 ); 11796 IRTemp g0_4 = newTemp( Ity_I32 ); 11797 11798 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11799 11800 if ( s == 0 ) { 11801 /* Unsigned BCD string */ 11802 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 11803 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 11804 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 11805 11806 assign( lmd, 11807 binop( Iop_Shr32, 11808 binop( Iop_And32, 11809 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11810 mkU32( 0xF0000000 ) ), 11811 mkU8( 28 ) ) ); 11812 11813 assign( invalid_mask, 11814 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11815 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 11816 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11817 11818 assign( without_lmd, 11819 unop( Iop_ReinterpD64asI64, 11820 binop( Iop_InsertExpD64, 11821 mkU64( DFP_LONG_BIAS ), 11822 unop( Iop_ReinterpI64asD64, 11823 binop( Iop_32HLto64, 11824 mkexpr( dbcd_u ), 11825 mkexpr( dbcd_l ) ) ) ) ) ); 11826 assign( left_exp, 11827 binop( Iop_Shr32, 11828 binop( Iop_And32, 11829 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 11830 mkU32( 0x60000000 ) ), 11831 mkU8( 29 ) ) ); 11832 11833 assign( g0_4, 11834 binop( Iop_Shl32, 11835 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 11836 mkU8( 26 ) ) ); 11837 11838 assign( tmp64, 11839 binop( Iop_32HLto64, 11840 binop( Iop_Or32, 11841 binop( Iop_And32, 11842 unop( Iop_64HIto32, 11843 mkexpr( without_lmd ) ), 11844 mkU32( 0x83FFFFFF ) ), 11845 mkexpr( g0_4 ) ), 11846 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 11847 11848 } else if ( s == 1 ) { 11849 IRTemp sign = newTemp( Ity_I32 ); 11850 IRTemp sign_bit = newTemp( Ity_I32 ); 11851 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11852 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11853 IRTemp tmp = newTemp( Ity_I64 ); 11854 11855 /* Signed BCD string, least significant 4 bits are sign bits 11856 * positive sign = 0xC, negative sign = 0xD 11857 */ 11858 assign( tmp, unop( Iop_BCDtoDPB, 11859 binop( Iop_32HLto64, 11860 binop( Iop_Shr32, 11861 unop( Iop_64HIto32, 11862 mkexpr( frBI64 ) ), 11863 mkU8( 4 ) ), 11864 binop( Iop_Or32, 11865 binop( Iop_Shr32, 11866 unop( Iop_64to32, 11867 mkexpr( frBI64 ) ), 11868 mkU8( 4 ) ), 11869 binop( Iop_Shl32, 11870 unop( Iop_64HIto32, 11871 mkexpr( frBI64 ) ), 11872 mkU8( 28 ) ) ) ) ) ); 11873 11874 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 11875 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 11876 11877 /* Get the sign of the BCD string. */ 11878 assign( sign, 11879 binop( Iop_And32, 11880 unop( Iop_64to32, mkexpr( frBI64 ) ), 11881 mkU32( 0xF ) ) ); 11882 11883 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11884 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11885 assign( sign_bit, 11886 Generate_sign_bit( mkexpr( pos_sign_mask ), 11887 mkexpr( neg_sign_mask ) ) ); 11888 11889 /* Check for invalid sign and BCD digit. Don't check the bottom 11890 * four bits of bcd_l as that is the sign value. 11891 */ 11892 assign( invalid_mask, 11893 Generate_inv_mask( 11894 bcd_digit_inval( unop( Iop_64HIto32, 11895 mkexpr( frBI64 ) ), 11896 binop( Iop_Shr32, 11897 unop( Iop_64to32, 11898 mkexpr( frBI64 ) ), 11899 mkU8( 4 ) ) ), 11900 mkexpr( pos_sign_mask ), 11901 mkexpr( neg_sign_mask ) ) ); 11902 11903 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11904 11905 /* Generate the result assuming the sign value was valid. */ 11906 assign( tmp64, 11907 unop( Iop_ReinterpD64asI64, 11908 binop( Iop_InsertExpD64, 11909 mkU64( DFP_LONG_BIAS ), 11910 unop( Iop_ReinterpI64asD64, 11911 binop( Iop_32HLto64, 11912 binop( Iop_Or32, 11913 mkexpr( dbcd_u ), 11914 mkexpr( sign_bit ) ), 11915 mkexpr( dbcd_l ) ) ) ) ) ); 11916 } 11917 11918 /* Generate the value to store depending on the validity of the 11919 * sign value and the validity of the BCD digits. 11920 */ 11921 assign( resultD64, 11922 unop( Iop_ReinterpI64asD64, 11923 binop( Iop_32HLto64, 11924 binop( Iop_Or32, 11925 binop( Iop_And32, 11926 mkexpr( valid_mask ), 11927 unop( Iop_64HIto32, 11928 mkexpr( tmp64 ) ) ), 11929 binop( Iop_And32, 11930 mkU32( 0x7C000000 ), 11931 mkexpr( invalid_mask ) ) ), 11932 binop( Iop_Or32, 11933 binop( Iop_And32, 11934 mkexpr( valid_mask ), 11935 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 11936 binop( Iop_And32, 11937 mkU32( 0x0 ), 11938 mkexpr( invalid_mask ) ) ) ) ) ); 11939 putDReg( frT_addr, mkexpr( resultD64 ) ); 11940 } 11941 break; 11942 default: 11943 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 11944 return False; 11945 } 11946 return True; 11947 } 11948 11949 static Bool dis_dfp_bcdq( UInt theInstr ) 11950 { 11951 UInt opc2 = ifieldOPClo10( theInstr ); 11952 ULong sp = IFIELD(theInstr, 19, 2); 11953 ULong s = IFIELD(theInstr, 20, 1); 11954 IRTemp frB_hi = newTemp( Ity_D64 ); 11955 IRTemp frB_lo = newTemp( Ity_D64 ); 11956 IRTemp frBI64_hi = newTemp( Ity_I64 ); 11957 IRTemp frBI64_lo = newTemp( Ity_I64 ); 11958 UChar frT_addr = ifieldRegDS( theInstr ); 11959 UChar frB_addr = ifieldRegB( theInstr ); 11960 11961 IRTemp lmd = newTemp( Ity_I32 ); 11962 IRTemp result_hi = newTemp( Ity_I64 ); 11963 IRTemp result_lo = newTemp( Ity_I64 ); 11964 11965 assign( frB_hi, getDReg( frB_addr ) ); 11966 assign( frB_lo, getDReg( frB_addr + 1 ) ); 11967 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 11968 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 11969 11970 switch ( opc2 ) { 11971 case 0x142: // ddedpdq DFP Decode DPD to BCD 11972 { 11973 IRTemp low_60_u = newTemp( Ity_I32 ); 11974 IRTemp low_60_l = newTemp( Ity_I32 ); 11975 IRTemp mid_60_u = newTemp( Ity_I32 ); 11976 IRTemp mid_60_l = newTemp( Ity_I32 ); 11977 IRTemp top_12_l = newTemp( Ity_I32 ); 11978 11979 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11980 11981 /* Note, instruction only stores the lower 32 BCD digits in 11982 * the result 11983 */ 11984 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 11985 mkexpr( frBI64_lo ), 11986 &top_12_l, 11987 &mid_60_u, 11988 &mid_60_l, 11989 &low_60_u, 11990 &low_60_l ); 11991 11992 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11993 /* Unsigned BCD string */ 11994 assign( result_hi, 11995 binop( Iop_32HLto64, 11996 binop( Iop_Or32, 11997 binop( Iop_Shl32, 11998 mkexpr( top_12_l ), 11999 mkU8( 24 ) ), 12000 binop( Iop_Shr32, 12001 mkexpr( mid_60_u ), 12002 mkU8( 4 ) ) ), 12003 binop( Iop_Or32, 12004 binop( Iop_Shl32, 12005 mkexpr( mid_60_u ), 12006 mkU8( 28 ) ), 12007 binop( Iop_Shr32, 12008 mkexpr( mid_60_l ), 12009 mkU8( 4 ) ) ) ) ); 12010 12011 assign( result_lo, 12012 binop( Iop_32HLto64, 12013 binop( Iop_Or32, 12014 binop( Iop_Shl32, 12015 mkexpr( mid_60_l ), 12016 mkU8( 28 ) ), 12017 mkexpr( low_60_u ) ), 12018 mkexpr( low_60_l ) ) ); 12019 12020 } else { 12021 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 12022 * the positive and negative values are encoded in the least 12023 * significant bits. 12024 */ 12025 IRTemp sign = newTemp( Ity_I32 ); 12026 12027 if ( sp == 2 ) { 12028 /* Positive sign = 0xC, negative sign = 0xD */ 12029 assign( sign, 12030 binop( Iop_Or32, 12031 binop( Iop_Shr32, 12032 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12033 mkU8( 31 ) ), 12034 mkU32( 0xC ) ) ); 12035 12036 } else if ( sp == 3 ) { 12037 IRTemp tmp32 = newTemp( Ity_I32 ); 12038 12039 /* Positive sign = 0xF, negative sign = 0xD. 12040 * Need to complement sign bit then OR into bit position 1. 12041 */ 12042 assign( tmp32, 12043 binop( Iop_Xor32, 12044 binop( Iop_Shr32, 12045 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12046 mkU8( 30 ) ), 12047 mkU32( 0x2 ) ) ); 12048 12049 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 12050 12051 } else { 12052 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 12053 } 12054 12055 assign( result_hi, 12056 binop( Iop_32HLto64, 12057 binop( Iop_Or32, 12058 binop( Iop_Shl32, 12059 mkexpr( top_12_l ), 12060 mkU8( 28 ) ), 12061 mkexpr( mid_60_u ) ), 12062 mkexpr( mid_60_l ) ) ); 12063 12064 assign( result_lo, 12065 binop( Iop_32HLto64, 12066 binop( Iop_Or32, 12067 binop( Iop_Shl32, 12068 mkexpr( low_60_u ), 12069 mkU8( 4 ) ), 12070 binop( Iop_Shr32, 12071 mkexpr( low_60_l ), 12072 mkU8( 28 ) ) ), 12073 binop( Iop_Or32, 12074 binop( Iop_Shl32, 12075 mkexpr( low_60_l ), 12076 mkU8( 4 ) ), 12077 mkexpr( sign ) ) ) ); 12078 } 12079 12080 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 12081 putDReg( frT_addr + 1, 12082 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 12083 } 12084 break; 12085 case 0x342: // denbcdq DFP Encode BCD to DPD 12086 { 12087 IRTemp valid_mask = newTemp( Ity_I32 ); 12088 IRTemp invalid_mask = newTemp( Ity_I32 ); 12089 IRTemp result128 = newTemp( Ity_D128 ); 12090 IRTemp dfp_significand = newTemp( Ity_D128 ); 12091 IRTemp tmp_hi = newTemp( Ity_I64 ); 12092 IRTemp tmp_lo = newTemp( Ity_I64 ); 12093 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 12094 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 12095 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 12096 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 12097 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 12098 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 12099 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 12100 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 12101 IRTemp sign_bit = newTemp( Ity_I32 ); 12102 IRTemp tmptop10 = newTemp( Ity_I64 ); 12103 IRTemp tmpmid50 = newTemp( Ity_I64 ); 12104 IRTemp tmplow50 = newTemp( Ity_I64 ); 12105 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 12106 12107 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 12108 12109 if ( s == 0 ) { 12110 /* Unsigned BCD string */ 12111 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 12112 12113 assign( bcd_top_8, 12114 binop( Iop_32HLto64, 12115 mkU32( 0 ), 12116 binop( Iop_And32, 12117 binop( Iop_Shr32, 12118 unop( Iop_64HIto32, 12119 mkexpr( frBI64_hi ) ), 12120 mkU8( 24 ) ), 12121 mkU32( 0xFF ) ) ) ); 12122 assign( bcd_mid_60, 12123 binop( Iop_32HLto64, 12124 binop( Iop_Or32, 12125 binop( Iop_Shr32, 12126 unop( Iop_64to32, 12127 mkexpr( frBI64_hi ) ), 12128 mkU8( 28 ) ), 12129 binop( Iop_Shl32, 12130 unop( Iop_64HIto32, 12131 mkexpr( frBI64_hi ) ), 12132 mkU8( 4 ) ) ), 12133 binop( Iop_Or32, 12134 binop( Iop_Shl32, 12135 unop( Iop_64to32, 12136 mkexpr( frBI64_hi ) ), 12137 mkU8( 4 ) ), 12138 binop( Iop_Shr32, 12139 unop( Iop_64HIto32, 12140 mkexpr( frBI64_lo ) ), 12141 mkU8( 28 ) ) ) ) ); 12142 12143 /* Note, the various helper functions ignores top 4-bits */ 12144 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 12145 12146 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 12147 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12148 12149 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 12150 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12151 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12152 12153 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12154 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12155 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12156 12157 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 12158 * value is not part of the final result. Only the right most 12159 * BCD digits are stored. 12160 */ 12161 assign( lmd, mkU32( 0 ) ); 12162 12163 assign( invalid_mask, 12164 binop( Iop_Or32, 12165 bcd_digit_inval( mkU32( 0 ), 12166 unop( Iop_64to32, 12167 mkexpr( bcd_top_8 ) ) ), 12168 binop( Iop_Or32, 12169 bcd_digit_inval( unop( Iop_64HIto32, 12170 mkexpr( bcd_mid_60 ) ), 12171 unop( Iop_64to32, 12172 mkexpr( bcd_mid_60 ) ) ), 12173 bcd_digit_inval( unop( Iop_64HIto32, 12174 mkexpr( bcd_low_60 ) ), 12175 unop( Iop_64to32, 12176 mkexpr( bcd_low_60 ) ) 12177 ) ) ) ); 12178 12179 } else if ( s == 1 ) { 12180 IRTemp sign = newTemp( Ity_I32 ); 12181 IRTemp zero = newTemp( Ity_I32 ); 12182 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 12183 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 12184 12185 /* The sign of the BCD string is stored in lower 4 bits */ 12186 assign( sign, 12187 binop( Iop_And32, 12188 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 12189 mkU32( 0xF ) ) ); 12190 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 12191 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 12192 assign( sign_bit, 12193 Generate_sign_bit( mkexpr( pos_sign_mask ), 12194 mkexpr( neg_sign_mask ) ) ); 12195 12196 /* Generate the value assuminig the sign and BCD digits are vaild */ 12197 assign( bcd_top_8, 12198 binop( Iop_32HLto64, 12199 mkU32( 0x0 ), 12200 binop( Iop_Shr32, 12201 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12202 mkU8( 28 ) ) ) ); 12203 12204 /* The various helper routines ignore the upper 4-bits */ 12205 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 12206 12207 /* Remove bottom four sign bits */ 12208 assign( bcd_low_60, 12209 binop( Iop_32HLto64, 12210 binop( Iop_Shr32, 12211 unop( Iop_64HIto32, 12212 mkexpr( frBI64_lo ) ), 12213 mkU8( 4 ) ), 12214 binop( Iop_Or32, 12215 binop( Iop_Shl32, 12216 unop( Iop_64HIto32, 12217 mkexpr( frBI64_lo ) ), 12218 mkU8( 28 ) ), 12219 binop( Iop_Shr32, 12220 unop( Iop_64to32, 12221 mkexpr( frBI64_lo ) ), 12222 mkU8( 4 ) ) ) ) ); 12223 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 12224 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12225 12226 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 12227 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12228 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12229 12230 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12231 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12232 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12233 12234 /* The entire BCD string fits in lower 110-bits. The LMD value 12235 * is not stored in the final result for the DFP Long instruction. 12236 */ 12237 assign( lmd, mkU32( 0 ) ); 12238 12239 /* Check for invalid sign and invalid BCD digit. Don't check the 12240 * bottom four bits of frBI64_lo as that is the sign value. 12241 */ 12242 assign( zero, mkU32( 0 ) ); 12243 assign( inval_bcd_digit_mask, 12244 binop( Iop_Or32, 12245 bcd_digit_inval( mkexpr( zero ), 12246 unop( Iop_64to32, 12247 mkexpr( bcd_top_8 ) ) ), 12248 binop( Iop_Or32, 12249 bcd_digit_inval( unop( Iop_64HIto32, 12250 mkexpr( bcd_mid_60 ) ), 12251 unop( Iop_64to32, 12252 mkexpr( bcd_mid_60 ) ) ), 12253 bcd_digit_inval( unop( Iop_64HIto32, 12254 mkexpr( frBI64_lo ) ), 12255 binop( Iop_Shr32, 12256 unop( Iop_64to32, 12257 mkexpr( frBI64_lo ) ), 12258 mkU8( 4 ) ) ) ) ) ); 12259 assign( invalid_mask, 12260 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 12261 mkexpr( pos_sign_mask ), 12262 mkexpr( neg_sign_mask ) ) ); 12263 12264 } 12265 12266 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 12267 12268 /* Calculate the value of the result assuming sign and BCD digits 12269 * are all valid. 12270 */ 12271 assign( dfp_significand, 12272 binop( Iop_D64HLtoD128, 12273 unop( Iop_ReinterpI64asD64, 12274 binop( Iop_32HLto64, 12275 binop( Iop_Or32, 12276 mkexpr( sign_bit ), 12277 mkexpr( dbcd_top_l ) ), 12278 binop( Iop_Or32, 12279 binop( Iop_Shl32, 12280 mkexpr( dbcd_mid_u ), 12281 mkU8( 18 ) ), 12282 binop( Iop_Shr32, 12283 mkexpr( dbcd_mid_l ), 12284 mkU8( 14 ) ) ) ) ), 12285 unop( Iop_ReinterpI64asD64, 12286 binop( Iop_32HLto64, 12287 binop( Iop_Or32, 12288 mkexpr( dbcd_low_u ), 12289 binop( Iop_Shl32, 12290 mkexpr( dbcd_mid_l ), 12291 mkU8( 18 ) ) ), 12292 mkexpr( dbcd_low_l ) ) ) ) ); 12293 12294 /* Break the result back down to 32-bit chunks and replace chunks. 12295 * If there was an invalid BCD digit or invalid sign value, replace 12296 * the calculated result with the invalid bit string. 12297 */ 12298 assign( result128, 12299 binop( Iop_InsertExpD128, 12300 mkU64( DFP_EXTND_BIAS ), 12301 mkexpr( dfp_significand ) ) ); 12302 12303 assign( tmp_hi, 12304 unop( Iop_ReinterpD64asI64, 12305 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 12306 12307 assign( tmp_lo, 12308 unop( Iop_ReinterpD64asI64, 12309 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 12310 12311 assign( result_hi, 12312 binop( Iop_32HLto64, 12313 binop( Iop_Or32, 12314 binop( Iop_And32, 12315 mkexpr( valid_mask ), 12316 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 12317 binop( Iop_And32, 12318 mkU32( 0x7C000000 ), 12319 mkexpr( invalid_mask ) ) ), 12320 binop( Iop_Or32, 12321 binop( Iop_And32, 12322 mkexpr( valid_mask ), 12323 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 12324 binop( Iop_And32, 12325 mkU32( 0x0 ), 12326 mkexpr( invalid_mask ) ) ) ) ); 12327 12328 assign( result_lo, 12329 binop( Iop_32HLto64, 12330 binop( Iop_Or32, 12331 binop( Iop_And32, 12332 mkexpr( valid_mask ), 12333 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 12334 binop( Iop_And32, 12335 mkU32( 0x0 ), 12336 mkexpr( invalid_mask ) ) ), 12337 binop( Iop_Or32, 12338 binop( Iop_And32, 12339 mkexpr( valid_mask ), 12340 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 12341 binop( Iop_And32, 12342 mkU32( 0x0 ), 12343 mkexpr( invalid_mask ) ) ) ) ); 12344 12345 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 12346 putDReg( frT_addr + 1, 12347 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 12348 12349 } 12350 break; 12351 default: 12352 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 12353 break; 12354 } 12355 return True; 12356 } 12357 12358 static Bool dis_dfp_significant_digits( UInt theInstr ) 12359 { 12360 UChar frA_addr = ifieldRegA( theInstr ); 12361 UChar frB_addr = ifieldRegB( theInstr ); 12362 IRTemp frA = newTemp( Ity_D64 ); 12363 UInt opc1 = ifieldOPC( theInstr ); 12364 IRTemp B_sig = newTemp( Ity_I8 ); 12365 IRTemp K = newTemp( Ity_I8 ); 12366 IRTemp lmd_B = newTemp( Ity_I32 ); 12367 IRTemp field = newTemp( Ity_I32 ); 12368 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 12369 IRTemp Unordered_true = newTemp( Ity_I32 ); 12370 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 12371 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 12372 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 12373 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 12374 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 12375 12376 /* Get the reference singificance stored in frA */ 12377 assign( frA, getDReg( frA_addr ) ); 12378 12379 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 12380 * supported in 32-bit mode. 12381 */ 12382 assign( K, unop( Iop_32to8, 12383 binop( Iop_And32, 12384 unop( Iop_64to32, 12385 unop( Iop_ReinterpD64asI64, 12386 mkexpr( frA ) ) ), 12387 mkU32( 0x3F ) ) ) ); 12388 12389 switch ( opc1 ) { 12390 case 0x3b: // dtstsf DFP Test Significance 12391 { 12392 IRTemp frB = newTemp( Ity_D64 ); 12393 IRTemp frBI64 = newTemp( Ity_I64 ); 12394 IRTemp B_bcd_u = newTemp( Ity_I32 ); 12395 IRTemp B_bcd_l = newTemp( Ity_I32 ); 12396 IRTemp tmp64 = newTemp( Ity_I64 ); 12397 12398 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12399 12400 assign( frB, getDReg( frB_addr ) ); 12401 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 12402 12403 /* Get the BCD string for the value stored in a series of I32 values. 12404 * Count the number of leading zeros. Subtract the number of leading 12405 * zeros from 16 (maximum number of significant digits in DFP 12406 * Long). 12407 */ 12408 Get_lmd( &lmd_B, 12409 binop( Iop_Shr32, 12410 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 12411 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12412 12413 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 12414 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 12415 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 12416 12417 assign( B_sig, 12418 binop( Iop_Sub8, 12419 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 12420 Count_leading_zeros_60( mkexpr( lmd_B ), 12421 mkexpr( B_bcd_u ), 12422 mkexpr( B_bcd_l ) ) ) ); 12423 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) ); 12424 } 12425 break; 12426 case 0x3F: // dtstsfq DFP Test Significance 12427 { 12428 IRTemp frB_hi = newTemp( Ity_D64 ); 12429 IRTemp frB_lo = newTemp( Ity_D64 ); 12430 IRTemp frBI64_hi = newTemp( Ity_I64 ); 12431 IRTemp frBI64_lo = newTemp( Ity_I64 ); 12432 IRTemp B_low_60_u = newTemp( Ity_I32 ); 12433 IRTemp B_low_60_l = newTemp( Ity_I32 ); 12434 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 12435 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 12436 IRTemp B_top_12_l = newTemp( Ity_I32 ); 12437 12438 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12439 12440 assign( frB_hi, getDReg( frB_addr ) ); 12441 assign( frB_lo, getDReg( frB_addr + 1 ) ); 12442 12443 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 12444 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 12445 12446 /* Get the BCD string for the value stored in a series of I32 values. 12447 * Count the number of leading zeros. Subtract the number of leading 12448 * zeros from 32 (maximum number of significant digits in DFP 12449 * extended). 12450 */ 12451 Get_lmd( &lmd_B, 12452 binop( Iop_Shr32, 12453 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12454 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12455 12456 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 12457 mkexpr( frBI64_lo ), 12458 &B_top_12_l, 12459 &B_mid_60_u, 12460 &B_mid_60_l, 12461 &B_low_60_u, 12462 &B_low_60_l ); 12463 12464 assign( B_sig, 12465 binop( Iop_Sub8, 12466 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 12467 Count_leading_zeros_128( mkexpr( lmd_B ), 12468 mkexpr( B_top_12_l ), 12469 mkexpr( B_mid_60_u ), 12470 mkexpr( B_mid_60_l ), 12471 mkexpr( B_low_60_u ), 12472 mkexpr( B_low_60_l ) ) ) ); 12473 12474 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) ); 12475 } 12476 break; 12477 } 12478 12479 /* Compare (16 - cnt[0]) against K and set the condition code field 12480 * accordingly. 12481 * 12482 * The field layout is as follows: 12483 * 12484 * bit[3:0] Description 12485 * 3 K != 0 and K < Number of significant digits if FRB 12486 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 12487 * 1 K != 0 and K = Number of significant digits if FRB 12488 * 0 K ? Number of significant digits if FRB 12489 */ 12490 assign( Eq_true_mask, 12491 unop( Iop_1Sto32, 12492 binop( Iop_CmpEQ32, 12493 unop( Iop_8Uto32, mkexpr( K ) ), 12494 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12495 assign( Lt_true_mask, 12496 unop( Iop_1Sto32, 12497 binop( Iop_CmpLT32U, 12498 unop( Iop_8Uto32, mkexpr( K ) ), 12499 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12500 assign( Gt_true_mask, 12501 unop( Iop_1Sto32, 12502 binop( Iop_CmpLT32U, 12503 unop( Iop_8Uto32, mkexpr( B_sig ) ), 12504 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 12505 12506 assign( KisZero_true_mask, 12507 unop( Iop_1Sto32, 12508 binop( Iop_CmpEQ32, 12509 unop( Iop_8Uto32, mkexpr( K ) ), 12510 mkU32( 0 ) ) ) ); 12511 assign( KisZero_false_mask, 12512 unop( Iop_1Sto32, 12513 binop( Iop_CmpNE32, 12514 unop( Iop_8Uto32, mkexpr( K ) ), 12515 mkU32( 0 ) ) ) ); 12516 12517 assign( field, 12518 binop( Iop_Or32, 12519 binop( Iop_And32, 12520 mkexpr( KisZero_false_mask ), 12521 binop( Iop_Or32, 12522 binop( Iop_And32, 12523 mkexpr( Lt_true_mask ), 12524 mkU32( 0x8 ) ), 12525 binop( Iop_Or32, 12526 binop( Iop_And32, 12527 mkexpr( Gt_true_mask ), 12528 mkU32( 0x4 ) ), 12529 binop( Iop_And32, 12530 mkexpr( Eq_true_mask ), 12531 mkU32( 0x2 ) ) ) ) ), 12532 binop( Iop_And32, 12533 mkexpr( KisZero_true_mask ), 12534 mkU32( 0x4 ) ) ) ); 12535 12536 putGST_field( PPC_GST_CR, 12537 binop( Iop_Or32, 12538 binop( Iop_And32, 12539 mkexpr( Unordered_true ), 12540 mkU32( 0x1 ) ), 12541 binop( Iop_And32, 12542 unop( Iop_Not32, mkexpr( Unordered_true ) ), 12543 mkexpr( field ) ) ), 12544 crfD ); 12545 12546 return True; 12547 } 12548 12549 /*------------------------------------------------------------*/ 12550 /*--- AltiVec Instruction Translation ---*/ 12551 /*------------------------------------------------------------*/ 12552 12553 /* 12554 Altivec Cache Control Instructions (Data Streams) 12555 */ 12556 static Bool dis_av_datastream ( UInt theInstr ) 12557 { 12558 /* X-Form */ 12559 UChar opc1 = ifieldOPC(theInstr); 12560 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 12561 UChar flag_A = flag_T; 12562 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 12563 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 12564 UChar rA_addr = ifieldRegA(theInstr); 12565 UChar rB_addr = ifieldRegB(theInstr); 12566 UInt opc2 = ifieldOPClo10(theInstr); 12567 UChar b0 = ifieldBIT0(theInstr); 12568 12569 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 12570 vex_printf("dis_av_datastream(ppc)(instr)\n"); 12571 return False; 12572 } 12573 12574 switch (opc2) { 12575 case 0x156: // dst (Data Stream Touch, AV p115) 12576 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12577 rA_addr, rB_addr, STRM); 12578 break; 12579 12580 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 12581 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12582 rA_addr, rB_addr, STRM); 12583 break; 12584 12585 case 0x336: // dss (Data Stream Stop, AV p114) 12586 if (rA_addr != 0 || rB_addr != 0) { 12587 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 12588 return False; 12589 } 12590 if (flag_A == 0) { 12591 DIP("dss %d\n", STRM); 12592 } else { 12593 DIP("dssall\n"); 12594 } 12595 break; 12596 12597 default: 12598 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 12599 return False; 12600 } 12601 return True; 12602 } 12603 12604 /* 12605 AltiVec Processor Control Instructions 12606 */ 12607 static Bool dis_av_procctl ( UInt theInstr ) 12608 { 12609 /* VX-Form */ 12610 UChar opc1 = ifieldOPC(theInstr); 12611 UChar vD_addr = ifieldRegDS(theInstr); 12612 UChar vA_addr = ifieldRegA(theInstr); 12613 UChar vB_addr = ifieldRegB(theInstr); 12614 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12615 12616 if (opc1 != 0x4) { 12617 vex_printf("dis_av_procctl(ppc)(instr)\n"); 12618 return False; 12619 } 12620 12621 switch (opc2) { 12622 case 0x604: // mfvscr (Move from VSCR, AV p129) 12623 if (vA_addr != 0 || vB_addr != 0) { 12624 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12625 return False; 12626 } 12627 DIP("mfvscr v%d\n", vD_addr); 12628 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 12629 break; 12630 12631 case 0x644: { // mtvscr (Move to VSCR, AV p130) 12632 IRTemp vB = newTemp(Ity_V128); 12633 if (vD_addr != 0 || vA_addr != 0) { 12634 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12635 return False; 12636 } 12637 DIP("mtvscr v%d\n", vB_addr); 12638 assign( vB, getVReg(vB_addr)); 12639 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 12640 break; 12641 } 12642 default: 12643 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 12644 return False; 12645 } 12646 return True; 12647 } 12648 12649 /* 12650 * VSX scalar and vector convert instructions 12651 */ 12652 static Bool 12653 dis_vx_conv ( UInt theInstr, UInt opc2 ) 12654 { 12655 /* XX2-Form */ 12656 UChar opc1 = ifieldOPC( theInstr ); 12657 UChar XT = ifieldRegXT( theInstr ); 12658 UChar XB = ifieldRegXB( theInstr ); 12659 IRTemp xB, xB2; 12660 IRTemp b3, b2, b1, b0; 12661 xB = xB2 = IRTemp_INVALID; 12662 12663 if (opc1 != 0x3C) { 12664 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 12665 return False; 12666 } 12667 12668 /* Create and assign temps only as needed for the given instruction. */ 12669 switch (opc2) { 12670 // scalar double-precision floating point argument 12671 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090: 12672 xB = newTemp(Ity_F64); 12673 assign( xB, 12674 unop( Iop_ReinterpI64asF64, 12675 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12676 break; 12677 // vector double-precision floating point arguments 12678 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 12679 12680 xB = newTemp(Ity_F64); 12681 xB2 = newTemp(Ity_F64); 12682 assign( xB, 12683 unop( Iop_ReinterpI64asF64, 12684 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12685 assign( xB2, 12686 unop( Iop_ReinterpI64asF64, 12687 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 12688 break; 12689 // vector single precision or [un]signed integer word arguments 12690 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 12691 case 0x1f0: case 0x1d0: 12692 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12693 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 12694 break; 12695 // vector [un]signed integer doubleword argument 12696 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 12697 xB = newTemp(Ity_I64); 12698 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12699 xB2 = newTemp(Ity_I64); 12700 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 12701 break; 12702 // scalar [un]signed integer doubleword argument 12703 case 0x250: case 0x270: case 0x2D0: case 0x2F0: 12704 xB = newTemp(Ity_I64); 12705 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12706 break; 12707 // scalar single precision argument 12708 case 0x292: // xscvspdp 12709 xB = newTemp(Ity_I32); 12710 12711 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32, 12712 unop( Iop_V128HIto64, 12713 getVSReg( XB ) ) ) ) ); 12714 break; 12715 case 0x296: // xscvspdpn (non signaling version of xscvpdp) 12716 xB = newTemp(Ity_I32); 12717 assign( xB, 12718 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12719 break; 12720 12721 /* Certain instructions have their complete implementation in the main switch statement 12722 * that follows this one; thus we have a "do nothing" case for those instructions here. 12723 */ 12724 case 0x170: case 0x150: 12725 break; // do nothing 12726 12727 default: 12728 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12729 return False; 12730 } 12731 12732 12733 switch (opc2) { 12734 case 0x2B0: 12735 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 12736 // to Signed Integer Doubleword format with Saturate) 12737 DIP("xscvdpsxds v%u,v%u\n", XT, XB); 12738 putVSReg( XT, 12739 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 12740 mkU32( Irrm_ZERO ), 12741 mkexpr( xB ) ), mkU64( 0 ) ) ); 12742 break; 12743 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 12744 // Convert to Signed Integer Word format with Saturate) 12745 DIP("xscvdpsxws v%u,v%u\n", XT, XB); 12746 putVSReg( XT, 12747 binop( Iop_64HLtoV128, 12748 unop( Iop_32Sto64, 12749 binop( Iop_F64toI32S, 12750 mkU32( Irrm_ZERO ), 12751 mkexpr( xB ) ) ), 12752 mkU64( 0ULL ) ) ); 12753 break; 12754 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 12755 // to Unsigned Integer Doubleword format with Saturate) 12756 DIP("xscvdpuxds v%u,v%u\n", XT, XB); 12757 putVSReg( XT, 12758 binop( Iop_64HLtoV128, 12759 binop( Iop_F64toI64U, 12760 mkU32( Irrm_ZERO ), 12761 mkexpr( xB ) ), 12762 mkU64( 0ULL ) ) ); 12763 break; 12764 case 0x270: 12765 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword 12766 // to Single-Precision format) 12767 DIP("xscvsxdsp v%u,v%u\n", XT, XB); 12768 putVSReg( XT, 12769 binop( Iop_64HLtoV128, 12770 unop( Iop_ReinterpF64asI64, 12771 binop( Iop_RoundF64toF32, 12772 get_IR_roundingmode(), 12773 binop( Iop_I64StoF64, 12774 get_IR_roundingmode(), 12775 mkexpr( xB ) ) ) ), 12776 mkU64( 0 ) ) ); 12777 break; 12778 case 0x2F0: 12779 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 12780 // Double-Precision format) 12781 DIP("xscvsxddp v%u,v%u\n", XT, XB); 12782 putVSReg( XT, 12783 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12784 binop( Iop_I64StoF64, get_IR_roundingmode(), 12785 mkexpr( xB ) ) ), 12786 mkU64( 0 ) ) ); 12787 break; 12788 case 0x250: 12789 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer 12790 // Doubleword to Singel-Precision format) 12791 DIP("xscvuxdsp v%u,v%u\n", XT, XB); 12792 putVSReg( XT, 12793 binop( Iop_64HLtoV128, 12794 unop( Iop_ReinterpF64asI64, 12795 binop( Iop_RoundF64toF32, 12796 get_IR_roundingmode(), 12797 binop( Iop_I64UtoF64, 12798 get_IR_roundingmode(), 12799 mkexpr( xB ) ) ) ), 12800 mkU64( 0 ) ) ); 12801 break; 12802 case 0x2D0: 12803 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 12804 // Double-Precision format) 12805 DIP("xscvuxddp v%u,v%u\n", XT, XB); 12806 putVSReg( XT, 12807 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12808 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12809 mkexpr( xB ) ) ), 12810 mkU64( 0 ) ) ); 12811 break; 12812 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 12813 // to Signed Integer Word format with Saturate) 12814 { 12815 IRTemp hiResult_32 = newTemp(Ity_I32); 12816 IRTemp loResult_32 = newTemp(Ity_I32); 12817 IRExpr* rmZero = mkU32(Irrm_ZERO); 12818 12819 DIP("xvcvdpsxws v%u,v%u\n", XT, XB); 12820 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 12821 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 12822 putVSReg( XT, 12823 binop( Iop_64HLtoV128, 12824 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 12825 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 12826 break; 12827 } 12828 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 12829 // (VSX Vector truncate Single-Precision to integer and 12830 // Convert to [Un]signed Integer Word format with Saturate) 12831 { 12832 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 12833 IRTemp tempResult = newTemp(Ity_V128); 12834 IRTemp res0 = newTemp(Ity_I32); 12835 IRTemp res1 = newTemp(Ity_I32); 12836 IRTemp res2 = newTemp(Ity_I32); 12837 IRTemp res3 = newTemp(Ity_I32); 12838 IRTemp hi64 = newTemp(Ity_I64); 12839 IRTemp lo64 = newTemp(Ity_I64); 12840 Bool un_signed = (opc2 == 0x110); 12841 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 12842 12843 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB); 12844 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 12845 * then result is set to 0x80000000. */ 12846 assign(tempResult, unop(op, getVSReg(XB))); 12847 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 12848 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 12849 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 12850 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 12851 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 12852 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 12853 12854 b3_result = IRExpr_ITE(is_NaN_32(b3), 12855 // then: result is 0x{8|0}80000000 12856 mkU32(un_signed ? 0x00000000 : 0x80000000), 12857 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12858 mkexpr(res3)); 12859 b2_result = IRExpr_ITE(is_NaN_32(b2), 12860 // then: result is 0x{8|0}80000000 12861 mkU32(un_signed ? 0x00000000 : 0x80000000), 12862 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12863 mkexpr(res2)); 12864 b1_result = IRExpr_ITE(is_NaN_32(b1), 12865 // then: result is 0x{8|0}80000000 12866 mkU32(un_signed ? 0x00000000 : 0x80000000), 12867 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12868 mkexpr(res1)); 12869 b0_result = IRExpr_ITE(is_NaN_32(b0), 12870 // then: result is 0x{8|0}80000000 12871 mkU32(un_signed ? 0x00000000 : 0x80000000), 12872 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12873 mkexpr(res0)); 12874 12875 putVSReg( XT, 12876 binop( Iop_64HLtoV128, 12877 binop( Iop_32HLto64, b3_result, b2_result ), 12878 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 12879 break; 12880 } 12881 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 12882 // Convert to Single-Precision format 12883 DIP("xscvdpsp v%u,v%u\n", XT, XB); 12884 putVSReg( XT, 12885 binop( Iop_64HLtoV128, 12886 binop( Iop_32HLto64, 12887 unop( Iop_ReinterpF32asI32, 12888 unop( Iop_TruncF64asF32, 12889 binop( Iop_RoundF64toF32, 12890 get_IR_roundingmode(), 12891 mkexpr( xB ) ) ) ), 12892 mkU32( 0 ) ), 12893 mkU64( 0ULL ) ) ); 12894 break; 12895 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to 12896 vector Single-Precision non-signalling */ 12897 DIP("xscvdpspn v%u,v%u\n", XT, XB); 12898 putVSReg( XT, 12899 binop( Iop_64HLtoV128, 12900 binop( Iop_32HLto64, 12901 unop( Iop_ReinterpF32asI32, 12902 unop( Iop_TruncF64asF32, 12903 mkexpr( xB ) ) ), 12904 mkU32( 0 ) ), 12905 mkU64( 0ULL ) ) ); 12906 break; 12907 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 12908 // and Convert to Unsigned Integer Word format with Saturate) 12909 DIP("xscvdpuxws v%u,v%u\n", XT, XB); 12910 putVSReg( XT, 12911 binop( Iop_64HLtoV128, 12912 binop( Iop_32HLto64, 12913 mkU32( 0 ), 12914 binop( Iop_F64toI32U, 12915 mkU32( Irrm_ZERO ), 12916 mkexpr( xB ) ) ), 12917 mkU64( 0ULL ) ) ); 12918 break; 12919 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling) 12920 DIP("xscvspdp v%u,v%u\n", XT, XB); 12921 putVSReg( XT, 12922 binop( Iop_64HLtoV128, 12923 unop( Iop_ReinterpF64asI64, 12924 unop( Iop_F32toF64, 12925 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12926 mkU64( 0ULL ) ) ); 12927 break; 12928 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling) 12929 DIP("xscvspdpn v%u,v%u\n", XT, XB); 12930 putVSReg( XT, 12931 binop( Iop_64HLtoV128, 12932 unop( Iop_ReinterpF64asI64, 12933 unop( Iop_F32toF64, 12934 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12935 mkU64( 0ULL ) ) ); 12936 break; 12937 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 12938 // and Convert to Single-Precision format) 12939 DIP("xvcvdpsp v%u,v%u\n", XT, XB); 12940 putVSReg( XT, 12941 binop( Iop_64HLtoV128, 12942 binop( Iop_32HLto64, 12943 unop( Iop_ReinterpF32asI32, 12944 unop( Iop_TruncF64asF32, 12945 binop( Iop_RoundF64toF32, 12946 get_IR_roundingmode(), 12947 mkexpr( xB ) ) ) ), 12948 mkU32( 0 ) ), 12949 binop( Iop_32HLto64, 12950 unop( Iop_ReinterpF32asI32, 12951 unop( Iop_TruncF64asF32, 12952 binop( Iop_RoundF64toF32, 12953 get_IR_roundingmode(), 12954 mkexpr( xB2 ) ) ) ), 12955 mkU32( 0 ) ) ) ); 12956 break; 12957 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 12958 // and Convert to Unsigned Integer Doubleword format 12959 // with Saturate) 12960 DIP("xvcvdpuxds v%u,v%u\n", XT, XB); 12961 putVSReg( XT, 12962 binop( Iop_64HLtoV128, 12963 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12964 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12965 break; 12966 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 12967 // Convert to Unsigned Integer Word format with Saturate) 12968 DIP("xvcvdpuxws v%u,v%u\n", XT, XB); 12969 putVSReg( XT, 12970 binop( Iop_64HLtoV128, 12971 binop( Iop_32HLto64, 12972 binop( Iop_F64toI32U, 12973 mkU32( Irrm_ZERO ), 12974 mkexpr( xB ) ), 12975 mkU32( 0 ) ), 12976 binop( Iop_32HLto64, 12977 binop( Iop_F64toI32U, 12978 mkU32( Irrm_ZERO ), 12979 mkexpr( xB2 ) ), 12980 mkU32( 0 ) ) ) ); 12981 break; 12982 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 12983 DIP("xvcvspdp v%u,v%u\n", XT, XB); 12984 putVSReg( XT, 12985 binop( Iop_64HLtoV128, 12986 unop( Iop_ReinterpF64asI64, 12987 unop( Iop_F32toF64, 12988 unop( Iop_ReinterpI32asF32, 12989 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ), 12990 unop( Iop_ReinterpF64asI64, 12991 unop( Iop_F32toF64, 12992 unop( Iop_ReinterpI32asF32, 12993 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) ); 12994 break; 12995 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 12996 // Convert to Signed Integer Doubleword format with Saturate) 12997 DIP("xvcvspsxds v%u,v%u\n", XT, XB); 12998 putVSReg( XT, 12999 binop( Iop_64HLtoV128, 13000 binop( Iop_F64toI64S, 13001 mkU32( Irrm_ZERO ), 13002 unop( Iop_F32toF64, 13003 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 13004 binop( Iop_F64toI64S, 13005 mkU32( Irrm_ZERO ), 13006 unop( Iop_F32toF64, 13007 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 13008 break; 13009 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 13010 // Convert to Unsigned Integer Doubleword format with Saturate) 13011 DIP("xvcvspuxds v%u,v%u\n", XT, XB); 13012 putVSReg( XT, 13013 binop( Iop_64HLtoV128, 13014 binop( Iop_F64toI64U, 13015 mkU32( Irrm_ZERO ), 13016 unop( Iop_F32toF64, 13017 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 13018 binop( Iop_F64toI64U, 13019 mkU32( Irrm_ZERO ), 13020 unop( Iop_F32toF64, 13021 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 13022 break; 13023 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 13024 // Convert to Signed Integer Doubleword format with Saturate) 13025 DIP("xvcvdpsxds v%u,v%u\n", XT, XB); 13026 putVSReg( XT, 13027 binop( Iop_64HLtoV128, 13028 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 13029 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 13030 break; 13031 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 13032 // to Double-Precision format) 13033 DIP("xvcvsxddp v%u,v%u\n", XT, XB); 13034 putVSReg( XT, 13035 binop( Iop_64HLtoV128, 13036 unop( Iop_ReinterpF64asI64, 13037 binop( Iop_I64StoF64, 13038 get_IR_roundingmode(), 13039 mkexpr( xB ) ) ), 13040 unop( Iop_ReinterpF64asI64, 13041 binop( Iop_I64StoF64, 13042 get_IR_roundingmode(), 13043 mkexpr( xB2 ) ) ) ) ); 13044 break; 13045 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 13046 // to Double-Precision format) 13047 DIP("xvcvuxddp v%u,v%u\n", XT, XB); 13048 putVSReg( XT, 13049 binop( Iop_64HLtoV128, 13050 unop( Iop_ReinterpF64asI64, 13051 binop( Iop_I64UtoF64, 13052 get_IR_roundingmode(), 13053 mkexpr( xB ) ) ), 13054 unop( Iop_ReinterpF64asI64, 13055 binop( Iop_I64UtoF64, 13056 get_IR_roundingmode(), 13057 mkexpr( xB2 ) ) ) ) ); 13058 13059 break; 13060 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 13061 // to Single-Precision format) 13062 DIP("xvcvsxddp v%u,v%u\n", XT, XB); 13063 putVSReg( XT, 13064 binop( Iop_64HLtoV128, 13065 binop( Iop_32HLto64, 13066 unop( Iop_ReinterpF32asI32, 13067 unop( Iop_TruncF64asF32, 13068 binop( Iop_RoundF64toF32, 13069 get_IR_roundingmode(), 13070 binop( Iop_I64StoF64, 13071 get_IR_roundingmode(), 13072 mkexpr( xB ) ) ) ) ), 13073 mkU32( 0 ) ), 13074 binop( Iop_32HLto64, 13075 unop( Iop_ReinterpF32asI32, 13076 unop( Iop_TruncF64asF32, 13077 binop( Iop_RoundF64toF32, 13078 get_IR_roundingmode(), 13079 binop( Iop_I64StoF64, 13080 get_IR_roundingmode(), 13081 mkexpr( xB2 ) ) ) ) ), 13082 mkU32( 0 ) ) ) ); 13083 break; 13084 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 13085 // to Single-Precision format) 13086 DIP("xvcvuxddp v%u,v%u\n", XT, XB); 13087 putVSReg( XT, 13088 binop( Iop_64HLtoV128, 13089 binop( Iop_32HLto64, 13090 unop( Iop_ReinterpF32asI32, 13091 unop( Iop_TruncF64asF32, 13092 binop( Iop_RoundF64toF32, 13093 get_IR_roundingmode(), 13094 binop( Iop_I64UtoF64, 13095 get_IR_roundingmode(), 13096 mkexpr( xB ) ) ) ) ), 13097 mkU32( 0 ) ), 13098 binop( Iop_32HLto64, 13099 unop( Iop_ReinterpF32asI32, 13100 unop( Iop_TruncF64asF32, 13101 binop( Iop_RoundF64toF32, 13102 get_IR_roundingmode(), 13103 binop( Iop_I64UtoF64, 13104 get_IR_roundingmode(), 13105 mkexpr( xB2 ) ) ) ) ), 13106 mkU32( 0 ) ) ) ); 13107 break; 13108 13109 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 13110 DIP("xvcvsxwdp v%u,v%u\n", XT, XB); 13111 putVSReg( XT, 13112 binop( Iop_64HLtoV128, 13113 unop( Iop_ReinterpF64asI64, 13114 binop( Iop_I64StoF64, get_IR_roundingmode(), 13115 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 13116 unop( Iop_ReinterpF64asI64, 13117 binop( Iop_I64StoF64, get_IR_roundingmode(), 13118 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 13119 break; 13120 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 13121 DIP("xvcvuxwdp v%u,v%u\n", XT, XB); 13122 putVSReg( XT, 13123 binop( Iop_64HLtoV128, 13124 unop( Iop_ReinterpF64asI64, 13125 binop( Iop_I64UtoF64, get_IR_roundingmode(), 13126 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 13127 unop( Iop_ReinterpF64asI64, 13128 binop( Iop_I64UtoF64, get_IR_roundingmode(), 13129 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 13130 break; 13131 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 13132 DIP("xvcvsxwsp v%u,v%u\n", XT, XB); 13133 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 13134 break; 13135 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 13136 DIP("xvcvuxwsp v%u,v%u\n", XT, XB); 13137 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 13138 break; 13139 13140 default: 13141 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 13142 return False; 13143 } 13144 return True; 13145 } 13146 13147 /* 13148 * VSX vector Double Precision Floating Point Arithmetic Instructions 13149 */ 13150 static Bool 13151 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 13152 { 13153 /* XX3-Form */ 13154 UChar opc1 = ifieldOPC( theInstr ); 13155 UChar XT = ifieldRegXT( theInstr ); 13156 UChar XA = ifieldRegXA( theInstr ); 13157 UChar XB = ifieldRegXB( theInstr ); 13158 IRExpr* rm = get_IR_roundingmode(); 13159 IRTemp frA = newTemp(Ity_F64); 13160 IRTemp frB = newTemp(Ity_F64); 13161 IRTemp frA2 = newTemp(Ity_F64); 13162 IRTemp frB2 = newTemp(Ity_F64); 13163 13164 if (opc1 != 0x3C) { 13165 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 13166 return False; 13167 } 13168 13169 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 13170 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13171 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 13172 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 13173 13174 switch (opc2) { 13175 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 13176 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 13177 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 13178 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 13179 { 13180 IROp mOp; 13181 const HChar * oper_name; 13182 switch (opc2) { 13183 case 0x1E0: 13184 mOp = Iop_DivF64; 13185 oper_name = "div"; 13186 break; 13187 case 0x1C0: 13188 mOp = Iop_MulF64; 13189 oper_name = "mul"; 13190 break; 13191 case 0x180: 13192 mOp = Iop_AddF64; 13193 oper_name = "add"; 13194 break; 13195 case 0x1A0: 13196 mOp = Iop_SubF64; 13197 oper_name = "sub"; 13198 break; 13199 13200 default: 13201 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 13202 } 13203 IRTemp hiResult = newTemp(Ity_I64); 13204 IRTemp loResult = newTemp(Ity_I64); 13205 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB); 13206 13207 assign( hiResult, 13208 unop( Iop_ReinterpF64asI64, 13209 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 13210 assign( loResult, 13211 unop( Iop_ReinterpF64asI64, 13212 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 13213 putVSReg( XT, 13214 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13215 break; 13216 } 13217 case 0x196: // xvsqrtdp 13218 { 13219 IRTemp hiResult = newTemp(Ity_I64); 13220 IRTemp loResult = newTemp(Ity_I64); 13221 DIP("xvsqrtdp v%d,v%d\n", XT, XB); 13222 13223 assign( hiResult, 13224 unop( Iop_ReinterpF64asI64, 13225 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 13226 assign( loResult, 13227 unop( Iop_ReinterpF64asI64, 13228 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 13229 putVSReg( XT, 13230 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13231 break; 13232 } 13233 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 13234 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 13235 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 13236 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 13237 { 13238 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 13239 * XT == FRC 13240 * XA == FRA 13241 * XB == FRB 13242 * 13243 * and for xvm{add|sub}adp . . . 13244 * XT == FRB 13245 * XA == FRA 13246 * XB == FRC 13247 */ 13248 Bool negate; 13249 IROp mOp = Iop_INVALID; 13250 const HChar * oper_name = NULL; 13251 Bool mdp = False; 13252 13253 switch (opc2) { 13254 case 0x184: case 0x1A4: 13255 case 0x384: case 0x3A4: 13256 mOp = Iop_MAddF64; 13257 oper_name = "add"; 13258 mdp = (opc2 & 0x0FF) == 0x0A4; 13259 break; 13260 13261 case 0x1C4: case 0x1E4: 13262 case 0x3C4: case 0x3E4: 13263 mOp = Iop_MSubF64; 13264 oper_name = "sub"; 13265 mdp = (opc2 & 0x0FF) == 0x0E4; 13266 break; 13267 13268 default: 13269 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13270 } 13271 13272 switch (opc2) { 13273 case 0x384: case 0x3A4: 13274 case 0x3C4: case 0x3E4: 13275 negate = True; 13276 break; 13277 default: 13278 negate = False; 13279 } 13280 IRTemp hiResult = newTemp(Ity_I64); 13281 IRTemp loResult = newTemp(Ity_I64); 13282 IRTemp frT = newTemp(Ity_F64); 13283 IRTemp frT2 = newTemp(Ity_F64); 13284 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 13285 XT, XA, XB); 13286 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 13287 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 13288 13289 assign( hiResult, 13290 unop( Iop_ReinterpF64asI64, 13291 qop( mOp, 13292 rm, 13293 mkexpr( frA ), 13294 mkexpr( mdp ? frT : frB ), 13295 mkexpr( mdp ? frB : frT ) ) ) ); 13296 assign( loResult, 13297 unop( Iop_ReinterpF64asI64, 13298 qop( mOp, 13299 rm, 13300 mkexpr( frA2 ), 13301 mkexpr( mdp ? frT2 : frB2 ), 13302 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 13303 putVSReg( XT, 13304 binop( Iop_64HLtoV128, 13305 mkexpr( negate ? getNegatedResult( hiResult ) 13306 : hiResult ), 13307 mkexpr( negate ? getNegatedResult( loResult ) 13308 : loResult ) ) ); 13309 break; 13310 } 13311 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 13312 { 13313 IRTemp frBHi_I64 = newTemp(Ity_I64); 13314 IRTemp frBLo_I64 = newTemp(Ity_I64); 13315 IRTemp flagsHi = newTemp(Ity_I32); 13316 IRTemp flagsLo = newTemp(Ity_I32); 13317 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13318 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13319 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13320 13321 DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB); 13322 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13323 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13324 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 13325 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 13326 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13327 * where fl_flag == 1 on ppc64. 13328 */ 13329 assign( flagsHi, 13330 binop( Iop_Or32, 13331 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13332 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13333 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13334 assign( flagsLo, 13335 binop( Iop_Or32, 13336 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13337 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13338 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13339 putGST_field( PPC_GST_CR, 13340 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13341 crfD ); 13342 break; 13343 } 13344 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 13345 { 13346 IRTemp frBHi_I64 = newTemp(Ity_I64); 13347 IRTemp frBLo_I64 = newTemp(Ity_I64); 13348 IRTemp frAHi_I64 = newTemp(Ity_I64); 13349 IRTemp frALo_I64 = newTemp(Ity_I64); 13350 IRTemp flagsHi = newTemp(Ity_I32); 13351 IRTemp flagsLo = newTemp(Ity_I32); 13352 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13353 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13354 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13355 13356 DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB); 13357 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 13358 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 13359 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13360 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13361 13362 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 13363 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 13364 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13365 * where fl_flag == 1 on ppc64. 13366 */ 13367 assign( flagsHi, 13368 binop( Iop_Or32, 13369 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13370 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13371 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13372 assign( flagsLo, 13373 binop( Iop_Or32, 13374 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13375 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13376 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13377 putGST_field( PPC_GST_CR, 13378 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13379 crfD ); 13380 break; 13381 } 13382 13383 default: 13384 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 13385 return False; 13386 } 13387 return True; 13388 } 13389 13390 /* 13391 * VSX vector Single Precision Floating Point Arithmetic Instructions 13392 */ 13393 static Bool 13394 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 13395 { 13396 /* XX3-Form */ 13397 UChar opc1 = ifieldOPC( theInstr ); 13398 UChar XT = ifieldRegXT( theInstr ); 13399 UChar XA = ifieldRegXA( theInstr ); 13400 UChar XB = ifieldRegXB( theInstr ); 13401 IRExpr* rm = get_IR_roundingmode(); 13402 IRTemp a3, a2, a1, a0; 13403 IRTemp b3, b2, b1, b0; 13404 IRTemp res0 = newTemp(Ity_I32); 13405 IRTemp res1 = newTemp(Ity_I32); 13406 IRTemp res2 = newTemp(Ity_I32); 13407 IRTemp res3 = newTemp(Ity_I32); 13408 13409 a3 = a2 = a1 = a0 = IRTemp_INVALID; 13410 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13411 13412 if (opc1 != 0x3C) { 13413 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 13414 return False; 13415 } 13416 13417 switch (opc2) { 13418 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 13419 DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB); 13420 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4 13421 putVSReg( XT, triop(Iop_Add32Fx4, rm, 13422 getVSReg( XA ), getVSReg( XB )) ); 13423 break; 13424 13425 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 13426 DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB); 13427 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4 13428 putVSReg( XT, triop(Iop_Mul32Fx4, rm, 13429 getVSReg( XA ), getVSReg( XB )) ); 13430 break; 13431 13432 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 13433 DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB); 13434 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4 13435 putVSReg( XT, triop(Iop_Sub32Fx4, rm, 13436 getVSReg( XA ), getVSReg( XB )) ); 13437 break; 13438 13439 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 13440 { 13441 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 13442 * So there are two choices: 13443 * 1. Implement the xvdivsp with a native insn; or 13444 * 2. Extract the 4 single precision floats from each vector 13445 * register inputs and perform fdivs on each pair 13446 * I will do the latter, due to the general philosophy of 13447 * reusing existing implementations when practical. 13448 */ 13449 DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB); 13450 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13451 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13452 13453 assign( res0, 13454 unop( Iop_ReinterpF32asI32, 13455 unop( Iop_TruncF64asF32, 13456 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 13457 assign( res1, 13458 unop( Iop_ReinterpF32asI32, 13459 unop( Iop_TruncF64asF32, 13460 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 13461 assign( res2, 13462 unop( Iop_ReinterpF32asI32, 13463 unop( Iop_TruncF64asF32, 13464 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 13465 assign( res3, 13466 unop( Iop_ReinterpF32asI32, 13467 unop( Iop_TruncF64asF32, 13468 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 13469 13470 putVSReg( XT, 13471 binop( Iop_64HLtoV128, 13472 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13473 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13474 break; 13475 } 13476 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 13477 { 13478 DIP("xvsqrtsp v%d,v%d\n", XT, XB); 13479 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13480 /* Note: The native xvsqrtsp insruction does not always give the same precision 13481 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 13482 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 13483 * to the actual instruction. 13484 */ 13485 13486 assign( res0, 13487 unop( Iop_ReinterpF32asI32, 13488 unop( Iop_TruncF64asF32, 13489 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 13490 assign( res1, 13491 unop( Iop_ReinterpF32asI32, 13492 unop( Iop_TruncF64asF32, 13493 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 13494 assign( res2, 13495 unop( Iop_ReinterpF32asI32, 13496 unop( Iop_TruncF64asF32, 13497 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 13498 assign( res3, 13499 unop( Iop_ReinterpF32asI32, 13500 unop( Iop_TruncF64asF32, 13501 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 13502 13503 putVSReg( XT, 13504 binop( Iop_64HLtoV128, 13505 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13506 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13507 break; 13508 } 13509 13510 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 13511 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 13512 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 13513 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 13514 { 13515 IRTemp t3, t2, t1, t0; 13516 Bool msp = False; 13517 Bool negate; 13518 const HChar * oper_name = NULL; 13519 IROp mOp = Iop_INVALID; 13520 switch (opc2) { 13521 case 0x104: case 0x124: 13522 case 0x304: case 0x324: 13523 msp = (opc2 & 0x0FF) == 0x024; 13524 mOp = Iop_MAddF64r32; 13525 oper_name = "madd"; 13526 break; 13527 13528 case 0x144: case 0x164: 13529 case 0x344: case 0x364: 13530 msp = (opc2 & 0x0FF) == 0x064; 13531 mOp = Iop_MSubF64r32; 13532 oper_name = "sub"; 13533 break; 13534 13535 default: 13536 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13537 } 13538 13539 switch (opc2) { 13540 case 0x304: case 0x324: 13541 case 0x344: case 0x364: 13542 negate = True; 13543 break; 13544 13545 default: 13546 negate = False; 13547 } 13548 13549 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, 13550 msp ? "msp" : "asp", XT, XA, XB); 13551 13552 t3 = t2 = t1 = t0 = IRTemp_INVALID; 13553 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13554 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13555 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 13556 13557 assign( res0, 13558 unop( Iop_ReinterpF32asI32, 13559 unop( Iop_TruncF64asF32, 13560 qop( mOp, 13561 rm, 13562 mkexpr( a0 ), 13563 mkexpr( msp ? t0 : b0 ), 13564 mkexpr( msp ? b0 : t0 ) ) ) ) ); 13565 assign( res1, 13566 unop( Iop_ReinterpF32asI32, 13567 unop( Iop_TruncF64asF32, 13568 qop( mOp, 13569 rm, 13570 mkexpr( a1 ), 13571 mkexpr( msp ? t1 : b1 ), 13572 mkexpr( msp ? b1 : t1 ) ) ) ) ); 13573 assign( res2, 13574 unop( Iop_ReinterpF32asI32, 13575 unop( Iop_TruncF64asF32, 13576 qop( mOp, 13577 rm, 13578 mkexpr( a2 ), 13579 mkexpr( msp ? t2 : b2 ), 13580 mkexpr( msp ? b2 : t2 ) ) ) ) ); 13581 assign( res3, 13582 unop( Iop_ReinterpF32asI32, 13583 unop( Iop_TruncF64asF32, 13584 qop( mOp, 13585 rm, 13586 mkexpr( a3 ), 13587 mkexpr( msp ? t3 : b3 ), 13588 mkexpr( msp ? b3 : t3 ) ) ) ) ); 13589 13590 putVSReg( XT, 13591 binop( Iop_64HLtoV128, 13592 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 13593 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 13594 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 13595 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 13596 13597 break; 13598 } 13599 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 13600 { 13601 IRTemp flags0 = newTemp(Ity_I32); 13602 IRTemp flags1 = newTemp(Ity_I32); 13603 IRTemp flags2 = newTemp(Ity_I32); 13604 IRTemp flags3 = newTemp(Ity_I32); 13605 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13606 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13607 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13608 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13609 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13610 DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB); 13611 13612 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13613 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13614 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13615 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13616 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13617 13618 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13619 * where fl_flag == 1 on ppc64. 13620 */ 13621 assign( flags0, 13622 binop( Iop_Or32, 13623 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13624 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13625 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13626 assign( flags1, 13627 binop( Iop_Or32, 13628 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13629 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13630 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13631 assign( flags2, 13632 binop( Iop_Or32, 13633 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13634 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13635 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13636 assign( flags3, 13637 binop( Iop_Or32, 13638 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13639 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13640 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13641 putGST_field( PPC_GST_CR, 13642 binop( Iop_Or32, 13643 mkexpr( flags0 ), 13644 binop( Iop_Or32, 13645 mkexpr( flags1 ), 13646 binop( Iop_Or32, 13647 mkexpr( flags2 ), 13648 mkexpr( flags3 ) ) ) ), 13649 crfD ); 13650 13651 break; 13652 } 13653 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 13654 { 13655 IRTemp flags0 = newTemp(Ity_I32); 13656 IRTemp flags1 = newTemp(Ity_I32); 13657 IRTemp flags2 = newTemp(Ity_I32); 13658 IRTemp flags3 = newTemp(Ity_I32); 13659 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13660 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13661 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13662 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13663 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13664 DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB); 13665 13666 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13667 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13668 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13669 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13670 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13671 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13672 13673 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13674 * where fl_flag == 1 on ppc64. 13675 */ 13676 assign( flags0, 13677 binop( Iop_Or32, 13678 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13679 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13680 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13681 assign( flags1, 13682 binop( Iop_Or32, 13683 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13684 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13685 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13686 assign( flags2, 13687 binop( Iop_Or32, 13688 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13689 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13690 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13691 assign( flags3, 13692 binop( Iop_Or32, 13693 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13694 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13695 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13696 putGST_field( PPC_GST_CR, 13697 binop( Iop_Or32, 13698 mkexpr( flags0 ), 13699 binop( Iop_Or32, 13700 mkexpr( flags1 ), 13701 binop( Iop_Or32, 13702 mkexpr( flags2 ), 13703 mkexpr( flags3 ) ) ) ), 13704 crfD ); 13705 13706 break; 13707 } 13708 13709 default: 13710 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 13711 return False; 13712 } 13713 return True; 13714 } 13715 13716 /* 13717 * Vector Population Count/bit matrix transpose 13718 */ 13719 static Bool 13720 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) 13721 { 13722 UChar vRB_addr = ifieldRegB(theInstr); 13723 UChar vRT_addr = ifieldRegDS(theInstr); 13724 UChar opc1 = ifieldOPC( theInstr ); 13725 IRTemp vB = newTemp(Ity_V128); 13726 assign( vB, getVReg(vRB_addr)); 13727 13728 if (opc1 != 0x4) { 13729 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" ); 13730 return False; 13731 } 13732 13733 switch (opc2) { 13734 case 0x702: // vclzb 13735 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr); 13736 putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) ); 13737 break; 13738 13739 case 0x742: // vclzh 13740 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr); 13741 putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) ); 13742 break; 13743 13744 case 0x782: // vclzw 13745 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr); 13746 putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) ); 13747 break; 13748 13749 case 0x7C2: // vclzd 13750 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr); 13751 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) ); 13752 break; 13753 13754 case 0x703: // vpopcntb 13755 { 13756 /* Break vector into 32-bit words and do the population count 13757 * on byte in the words 13758 */ 13759 IRType ty = Ity_I32; 13760 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13761 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13762 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13763 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13764 13765 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr); 13766 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13767 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE); 13768 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE); 13769 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE); 13770 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE); 13771 13772 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13773 cnt_bits32_63, cnt_bits0_31) ); 13774 break; 13775 } 13776 13777 case 0x743: // vpopcnth 13778 { 13779 /* Break vector into 32-bit words and do the population count 13780 * for each half word 13781 */ 13782 IRType ty = Ity_I32; 13783 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13784 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13785 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13786 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13787 13788 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr); 13789 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13790 13791 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD); 13792 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD); 13793 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD); 13794 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD); 13795 13796 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13797 cnt_bits32_63, cnt_bits0_31) ); 13798 break; 13799 } 13800 13801 case 0x783: // vpopcntw 13802 { 13803 /* Break vector into 32-bit words and do the population count 13804 * on each word. 13805 */ 13806 IRType ty = Ity_I32; 13807 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13808 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13809 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13810 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13811 13812 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr); 13813 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13814 13815 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD); 13816 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD); 13817 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD); 13818 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD); 13819 13820 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13821 cnt_bits32_63, cnt_bits0_31) ); 13822 break; 13823 } 13824 13825 case 0x7C3: // vpopcntd 13826 { 13827 if (mode64) { 13828 /* Break vector into 64-bit double words and do the population count 13829 * on each double word. 13830 */ 13831 IRType ty = Ity_I64; 13832 IRTemp bits0_63 = newTemp(Ity_I64); 13833 IRTemp bits64_127 = newTemp(Ity_I64); 13834 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13835 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13836 13837 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13838 13839 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) ); 13840 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 13841 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD); 13842 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD); 13843 13844 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13845 mkexpr( cnt_bits64_127 ), 13846 mkexpr( cnt_bits0_63 ) ) ); 13847 } else { 13848 /* Break vector into 32-bit words and do the population count 13849 * on each doubleword. 13850 */ 13851 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13852 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13853 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13854 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13855 13856 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13857 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13858 13859 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63); 13860 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127); 13861 13862 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13863 mkexpr( cnt_bits64_127 ), 13864 mkexpr( cnt_bits0_63 ) ) ); 13865 } 13866 break; 13867 } 13868 13869 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword 13870 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr); 13871 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) ); 13872 break; 13873 13874 default: 13875 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n"); 13876 return False; 13877 break; 13878 } 13879 return True; 13880 } 13881 13882 typedef enum { 13883 PPC_CMP_EQ = 2, 13884 PPC_CMP_GT = 4, 13885 PPC_CMP_GE = 6, 13886 PPC_CMP_LT = 8 13887 } ppc_cmp_t; 13888 13889 13890 /* 13891 This helper function takes as input the IRExpr returned 13892 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 13893 in IR form. This helper function converts it to PPC form. 13894 13895 Map compare result from IR to PPC 13896 13897 FP cmp result | PPC | IR 13898 -------------------------- 13899 UN | 0x1 | 0x45 13900 EQ | 0x2 | 0x40 13901 GT | 0x4 | 0x00 13902 LT | 0x8 | 0x01 13903 13904 condcode = Shl(1, (~(ccIR>>5) & 2) 13905 | ((ccIR ^ (ccIR>>6)) & 1) 13906 */ 13907 static IRTemp 13908 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 13909 { 13910 IRTemp condcode = newTemp( Ity_I32 ); 13911 IRTemp ccIR = newTemp( Ity_I32 ); 13912 13913 assign(ccIR, ccIR_expr); 13914 assign( condcode, 13915 binop( Iop_Shl32, 13916 mkU32( 1 ), 13917 unop( Iop_32to8, 13918 binop( Iop_Or32, 13919 binop( Iop_And32, 13920 unop( Iop_Not32, 13921 binop( Iop_Shr32, 13922 mkexpr( ccIR ), 13923 mkU8( 5 ) ) ), 13924 mkU32( 2 ) ), 13925 binop( Iop_And32, 13926 binop( Iop_Xor32, 13927 mkexpr( ccIR ), 13928 binop( Iop_Shr32, 13929 mkexpr( ccIR ), 13930 mkU8( 6 ) ) ), 13931 mkU32( 1 ) ) ) ) ) ); 13932 return condcode; 13933 } 13934 13935 /* 13936 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 13937 * following these special rules: 13938 * - The max/min of a QNaN and any value is that value 13939 * (When two QNaNs are being compared, the frA QNaN is the return value.) 13940 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 13941 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 13942 */ 13943 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 13944 { 13945 IRTemp frA_isNaN = newTemp(Ity_I1); 13946 IRTemp frB_isNaN = newTemp(Ity_I1); 13947 IRTemp frA_isSNaN = newTemp(Ity_I1); 13948 IRTemp frB_isSNaN = newTemp(Ity_I1); 13949 IRTemp frA_isQNaN = newTemp(Ity_I1); 13950 IRTemp frB_isQNaN = newTemp(Ity_I1); 13951 13952 assign( frA_isNaN, is_NaN( frA_I64 ) ); 13953 assign( frB_isNaN, is_NaN( frB_I64 ) ); 13954 // If operand is a NAN and bit 12 is '0', then it's an SNaN 13955 assign( frA_isSNaN, 13956 mkAND1( mkexpr(frA_isNaN), 13957 binop( Iop_CmpEQ32, 13958 binop( Iop_And32, 13959 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 13960 mkU32( 0x00080000 ) ), 13961 mkU32( 0 ) ) ) ); 13962 assign( frB_isSNaN, 13963 mkAND1( mkexpr(frB_isNaN), 13964 binop( Iop_CmpEQ32, 13965 binop( Iop_And32, 13966 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 13967 mkU32( 0x00080000 ) ), 13968 mkU32( 0 ) ) ) ); 13969 assign( frA_isQNaN, 13970 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 13971 assign( frB_isQNaN, 13972 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 13973 13974 /* Based on the rules specified in the function prologue, the algorithm is as follows: 13975 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13976 * if frA is a SNaN 13977 * result = frA converted to QNaN 13978 * else if frB is a SNaN 13979 * result = frB converted to QNaN 13980 * else if frB is a QNaN 13981 * result = frA 13982 * // One of frA or frB was a NaN in order for this function to be called, so 13983 * // if we get to this point, we KNOW that frA must be a QNaN. 13984 * else // frA is a QNaN 13985 * result = frB 13986 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13987 */ 13988 13989 #define SNAN_MASK 0x0008000000000000ULL 13990 return 13991 IRExpr_ITE(mkexpr(frA_isSNaN), 13992 /* then: result = frA converted to QNaN */ 13993 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)), 13994 /* else: if frB is a SNaN */ 13995 IRExpr_ITE(mkexpr(frB_isSNaN), 13996 /* then: result = frB converted to QNaN */ 13997 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)), 13998 /* else: if frB is a QNaN */ 13999 IRExpr_ITE(mkexpr(frB_isQNaN), 14000 /* then: result = frA */ 14001 mkexpr(frA_I64), 14002 /* else: frA is a QNaN, so result = frB */ 14003 mkexpr(frB_I64)))); 14004 } 14005 14006 /* 14007 * Helper function for get_max_min_fp. 14008 */ 14009 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 14010 { 14011 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14012 unop( Iop_ReinterpI64asF64, 14013 mkexpr( src1 ) ), 14014 unop( Iop_ReinterpI64asF64, 14015 mkexpr( src2 ) ) ) ); 14016 14017 return IRExpr_ITE( binop( Iop_CmpEQ32, 14018 mkexpr( src1cmpsrc2 ), 14019 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ), 14020 /* then: use src1 */ 14021 mkexpr( src1 ), 14022 /* else: use src2 */ 14023 mkexpr( src2 ) ); 14024 } 14025 14026 /* 14027 * Helper function for "Maximum/Minimum Double Precision" operations. 14028 * Arguments: frA and frb are Ity_I64 14029 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 14030 */ 14031 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 14032 { 14033 /* There are three special cases where get_fp_cmp_CR_val is not helpful 14034 * for ascertaining the maximum between two doubles: 14035 * 1. The max/min of +0 and -0 is +0. 14036 * 2. The max/min of a QNaN and any value is that value. 14037 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 14038 * We perform the check for [+/-]0 here in this function and use the 14039 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 14040 * to do the standard comparison function. 14041 */ 14042 IRTemp anyNaN = newTemp(Ity_I1); 14043 IRTemp frA_isZero = newTemp(Ity_I1); 14044 IRTemp frB_isZero = newTemp(Ity_I1); 14045 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 14046 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 14047 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 14048 #define MINUS_ZERO 0x8000000000000000ULL 14049 14050 return IRExpr_ITE( /* If both arguments are zero . . . */ 14051 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ), 14052 /* then: if frA is -0 and isMin==True, return -0; 14053 * else if frA is +0 and isMin==False; return +0; 14054 * otherwise, simply return frB. */ 14055 IRExpr_ITE( binop( Iop_CmpEQ32, 14056 unop( Iop_64HIto32, 14057 mkexpr( frA_I64 ) ), 14058 mkU32( isMin ? 0x80000000 : 0 ) ), 14059 mkU64( isMin ? MINUS_ZERO : 0ULL ), 14060 mkexpr( frB_I64 ) ), 14061 /* else: check if either input is a NaN*/ 14062 IRExpr_ITE( mkexpr( anyNaN ), 14063 /* then: use "NaN helper" */ 14064 _get_maxmin_fp_NaN( frA_I64, frB_I64 ), 14065 /* else: use "comparison helper" */ 14066 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) )); 14067 } 14068 14069 static const HChar * _get_vsx_rdpi_suffix(UInt opc2) 14070 { 14071 switch (opc2 & 0x7F) { 14072 case 0x72: 14073 return "m"; 14074 case 0x52: 14075 return "p"; 14076 case 0x56: 14077 return "c"; 14078 case 0x32: 14079 return "z"; 14080 case 0x12: 14081 return ""; 14082 14083 default: // Impossible to get here 14084 vex_printf("Unrecognized opcode %x\n", opc2); 14085 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)"); 14086 } 14087 } 14088 14089 /* 14090 * Helper function for vector/scalar double precision fp round to integer instructions. 14091 */ 14092 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) 14093 { 14094 14095 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 14096 IRTemp frB = newTemp(Ity_F64); 14097 IRTemp frD = newTemp(Ity_F64); 14098 IRTemp intermediateResult = newTemp(Ity_I64); 14099 IRTemp is_SNAN = newTemp(Ity_I1); 14100 IRExpr * hi32; 14101 IRExpr * rxpi_rm; 14102 switch (opc2 & 0x7F) { 14103 case 0x72: 14104 rxpi_rm = mkU32(Irrm_NegINF); 14105 break; 14106 case 0x52: 14107 rxpi_rm = mkU32(Irrm_PosINF); 14108 break; 14109 case 0x56: 14110 rxpi_rm = get_IR_roundingmode(); 14111 break; 14112 case 0x32: 14113 rxpi_rm = mkU32(Irrm_ZERO); 14114 break; 14115 case 0x12: 14116 rxpi_rm = mkU32(Irrm_NEAREST); 14117 break; 14118 14119 default: // Impossible to get here 14120 vex_printf("Unrecognized opcode %x\n", opc2); 14121 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)"); 14122 } 14123 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 14124 assign( intermediateResult, 14125 binop( Iop_F64toI64S, rxpi_rm, 14126 mkexpr( frB ) ) ); 14127 14128 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 14129 /* F64 has only log10(2**52) significant digits anyway */ 14130 /* need to preserve sign of zero */ 14131 /* frD = (fabs(frB) > 9e18) ? frB : 14132 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 14133 assign( frD, 14134 IRExpr_ITE( 14135 binop( Iop_CmpNE8, 14136 unop( Iop_32to8, 14137 binop( Iop_CmpF64, 14138 IRExpr_Const( IRConst_F64( 9e18 ) ), 14139 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 14140 mkU8(0) ), 14141 mkexpr( frB ), 14142 IRExpr_ITE( 14143 binop( Iop_CmpNE32, 14144 binop( Iop_Shr32, 14145 unop( Iop_64HIto32, 14146 mkexpr( frB_I64 ) ), 14147 mkU8( 31 ) ), 14148 mkU32(0) ), 14149 unop( Iop_NegF64, 14150 unop( Iop_AbsF64, 14151 binop( Iop_I64StoF64, 14152 mkU32( 0 ), 14153 mkexpr( intermediateResult ) ) ) ), 14154 binop( Iop_I64StoF64, 14155 mkU32( 0 ), 14156 mkexpr( intermediateResult ) ) 14157 ) 14158 ) 14159 ); 14160 14161 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 14162 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 14163 */ 14164 #define SNAN_MASK 0x0008000000000000ULL 14165 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 14166 assign( is_SNAN, 14167 mkAND1( is_NaN( frB_I64 ), 14168 binop( Iop_CmpEQ32, 14169 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 14170 mkU32( 0 ) ) ) ); 14171 14172 return IRExpr_ITE( mkexpr( is_SNAN ), 14173 unop( Iop_ReinterpI64asF64, 14174 binop( Iop_Xor64, 14175 mkU64( SNAN_MASK ), 14176 mkexpr( frB_I64 ) ) ), 14177 mkexpr( frD )); 14178 } 14179 14180 /* 14181 * Miscellaneous VSX vector instructions 14182 */ 14183 static Bool 14184 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 14185 { 14186 /* XX3-Form */ 14187 UChar opc1 = ifieldOPC( theInstr ); 14188 UChar XT = ifieldRegXT( theInstr ); 14189 UChar XB = ifieldRegXB( theInstr ); 14190 14191 if (opc1 != 0x3C) { 14192 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 14193 return False; 14194 } 14195 14196 switch (opc2) { 14197 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 14198 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 14199 // Double-Precision) 14200 { 14201 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14202 IRExpr* rm = get_IR_roundingmode(); 14203 IRTemp frB = newTemp(Ity_I64); 14204 IRTemp frB2 = newTemp(Ity_I64); 14205 Bool redp = opc2 == 0x1B4; 14206 IRTemp sqrtHi = newTemp(Ity_F64); 14207 IRTemp sqrtLo = newTemp(Ity_F64); 14208 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14209 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14210 14211 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB); 14212 if (!redp) { 14213 assign( sqrtHi, 14214 binop( Iop_SqrtF64, 14215 rm, 14216 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 14217 assign( sqrtLo, 14218 binop( Iop_SqrtF64, 14219 rm, 14220 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 14221 } 14222 putVSReg( XT, 14223 binop( Iop_64HLtoV128, 14224 unop( Iop_ReinterpF64asI64, 14225 triop( Iop_DivF64, 14226 rm, 14227 ieee_one, 14228 redp ? unop( Iop_ReinterpI64asF64, 14229 mkexpr( frB ) ) 14230 : mkexpr( sqrtHi ) ) ), 14231 unop( Iop_ReinterpF64asI64, 14232 triop( Iop_DivF64, 14233 rm, 14234 ieee_one, 14235 redp ? unop( Iop_ReinterpI64asF64, 14236 mkexpr( frB2 ) ) 14237 : mkexpr( sqrtLo ) ) ) ) ); 14238 break; 14239 14240 } 14241 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 14242 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 14243 { 14244 IRTemp b3, b2, b1, b0; 14245 IRTemp res0 = newTemp(Ity_I32); 14246 IRTemp res1 = newTemp(Ity_I32); 14247 IRTemp res2 = newTemp(Ity_I32); 14248 IRTemp res3 = newTemp(Ity_I32); 14249 IRTemp sqrt3 = newTemp(Ity_F64); 14250 IRTemp sqrt2 = newTemp(Ity_F64); 14251 IRTemp sqrt1 = newTemp(Ity_F64); 14252 IRTemp sqrt0 = newTemp(Ity_F64); 14253 IRExpr* rm = get_IR_roundingmode(); 14254 Bool resp = opc2 == 0x134; 14255 14256 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14257 14258 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14259 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB); 14260 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14261 14262 if (!resp) { 14263 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 14264 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 14265 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 14266 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 14267 } 14268 14269 assign( res0, 14270 unop( Iop_ReinterpF32asI32, 14271 unop( Iop_TruncF64asF32, 14272 triop( Iop_DivF64r32, 14273 rm, 14274 ieee_one, 14275 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 14276 assign( res1, 14277 unop( Iop_ReinterpF32asI32, 14278 unop( Iop_TruncF64asF32, 14279 triop( Iop_DivF64r32, 14280 rm, 14281 ieee_one, 14282 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 14283 assign( res2, 14284 unop( Iop_ReinterpF32asI32, 14285 unop( Iop_TruncF64asF32, 14286 triop( Iop_DivF64r32, 14287 rm, 14288 ieee_one, 14289 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 14290 assign( res3, 14291 unop( Iop_ReinterpF32asI32, 14292 unop( Iop_TruncF64asF32, 14293 triop( Iop_DivF64r32, 14294 rm, 14295 ieee_one, 14296 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 14297 putVSReg( XT, 14298 binop( Iop_64HLtoV128, 14299 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14300 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14301 break; 14302 } 14303 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 14304 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 14305 { 14306 UChar XA = ifieldRegXA( theInstr ); 14307 IRTemp a3, a2, a1, a0; 14308 IRTemp b3, b2, b1, b0; 14309 IRTemp res0 = newTemp( Ity_I32 ); 14310 IRTemp res1 = newTemp( Ity_I32 ); 14311 IRTemp res2 = newTemp( Ity_I32 ); 14312 IRTemp res3 = newTemp( Ity_I32 ); 14313 IRTemp a0_I64 = newTemp( Ity_I64 ); 14314 IRTemp a1_I64 = newTemp( Ity_I64 ); 14315 IRTemp a2_I64 = newTemp( Ity_I64 ); 14316 IRTemp a3_I64 = newTemp( Ity_I64 ); 14317 IRTemp b0_I64 = newTemp( Ity_I64 ); 14318 IRTemp b1_I64 = newTemp( Ity_I64 ); 14319 IRTemp b2_I64 = newTemp( Ity_I64 ); 14320 IRTemp b3_I64 = newTemp( Ity_I64 ); 14321 14322 Bool isMin = opc2 == 0x320 ? True : False; 14323 14324 a3 = a2 = a1 = a0 = IRTemp_INVALID; 14325 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14326 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB); 14327 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 14328 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14329 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 14330 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 14331 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 14332 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 14333 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 14334 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 14335 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 14336 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 14337 assign( res0, 14338 unop( Iop_ReinterpF32asI32, 14339 unop( Iop_TruncF64asF32, 14340 unop( Iop_ReinterpI64asF64, 14341 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 14342 assign( res1, 14343 unop( Iop_ReinterpF32asI32, 14344 unop( Iop_TruncF64asF32, 14345 unop( Iop_ReinterpI64asF64, 14346 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 14347 assign( res2, 14348 unop( Iop_ReinterpF32asI32, 14349 unop( Iop_TruncF64asF32, 14350 unop( Iop_ReinterpI64asF64, 14351 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 14352 assign( res3, 14353 unop( Iop_ReinterpF32asI32, 14354 unop( Iop_TruncF64asF32, 14355 unop( Iop_ReinterpI64asF64, 14356 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 14357 putVSReg( XT, 14358 binop( Iop_64HLtoV128, 14359 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14360 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14361 break; 14362 } 14363 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 14364 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 14365 { 14366 UChar XA = ifieldRegXA( theInstr ); 14367 IRTemp frA = newTemp(Ity_I64); 14368 IRTemp frB = newTemp(Ity_I64); 14369 IRTemp frA2 = newTemp(Ity_I64); 14370 IRTemp frB2 = newTemp(Ity_I64); 14371 Bool isMin = opc2 == 0x3A0 ? True : False; 14372 14373 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14374 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14375 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14376 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14377 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB); 14378 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 14379 14380 break; 14381 } 14382 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 14383 { 14384 UChar XA = ifieldRegXA( theInstr ); 14385 IRTemp frA = newTemp(Ity_I64); 14386 IRTemp frB = newTemp(Ity_I64); 14387 IRTemp frA2 = newTemp(Ity_I64); 14388 IRTemp frB2 = newTemp(Ity_I64); 14389 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14390 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14391 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14392 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14393 14394 DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB); 14395 putVSReg( XT, 14396 binop( Iop_64HLtoV128, 14397 binop( Iop_Or64, 14398 binop( Iop_And64, 14399 mkexpr( frA ), 14400 mkU64( SIGN_BIT ) ), 14401 binop( Iop_And64, 14402 mkexpr( frB ), 14403 mkU64( SIGN_MASK ) ) ), 14404 binop( Iop_Or64, 14405 binop( Iop_And64, 14406 mkexpr( frA2 ), 14407 mkU64( SIGN_BIT ) ), 14408 binop( Iop_And64, 14409 mkexpr( frB2 ), 14410 mkU64( SIGN_MASK ) ) ) ) ); 14411 break; 14412 } 14413 case 0x340: // xvcpsgnsp 14414 { 14415 UChar XA = ifieldRegXA( theInstr ); 14416 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 14417 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 14418 IRTemp resHi = newTemp(Ity_I64); 14419 IRTemp resLo = newTemp(Ity_I64); 14420 14421 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 14422 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 14423 DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB); 14424 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 14425 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 14426 14427 assign( resHi, 14428 binop( Iop_32HLto64, 14429 binop( Iop_Or32, 14430 binop( Iop_And32, 14431 unop(Iop_64to32, mkexpr( a3_I64 ) ), 14432 mkU32( SIGN_BIT32 ) ), 14433 binop( Iop_And32, 14434 unop(Iop_64to32, mkexpr( b3_I64 ) ), 14435 mkU32( SIGN_MASK32) ) ), 14436 14437 binop( Iop_Or32, 14438 binop( Iop_And32, 14439 unop(Iop_64to32, mkexpr( a2_I64 ) ), 14440 mkU32( SIGN_BIT32 ) ), 14441 binop( Iop_And32, 14442 unop(Iop_64to32, mkexpr( b2_I64 ) ), 14443 mkU32( SIGN_MASK32 ) ) ) ) ); 14444 assign( resLo, 14445 binop( Iop_32HLto64, 14446 binop( Iop_Or32, 14447 binop( Iop_And32, 14448 unop(Iop_64to32, mkexpr( a1_I64 ) ), 14449 mkU32( SIGN_BIT32 ) ), 14450 binop( Iop_And32, 14451 unop(Iop_64to32, mkexpr( b1_I64 ) ), 14452 mkU32( SIGN_MASK32 ) ) ), 14453 14454 binop( Iop_Or32, 14455 binop( Iop_And32, 14456 unop(Iop_64to32, mkexpr( a0_I64 ) ), 14457 mkU32( SIGN_BIT32 ) ), 14458 binop( Iop_And32, 14459 unop(Iop_64to32, mkexpr( b0_I64 ) ), 14460 mkU32( SIGN_MASK32 ) ) ) ) ); 14461 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 14462 break; 14463 } 14464 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 14465 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 14466 { 14467 IRTemp frB = newTemp(Ity_F64); 14468 IRTemp frB2 = newTemp(Ity_F64); 14469 IRTemp abs_resultHi = newTemp(Ity_F64); 14470 IRTemp abs_resultLo = newTemp(Ity_F64); 14471 Bool make_negative = (opc2 == 0x3D2) ? True : False; 14472 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14473 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14474 14475 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB); 14476 if (make_negative) { 14477 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 14478 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 14479 14480 } else { 14481 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 14482 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 14483 } 14484 putVSReg( XT, binop( Iop_64HLtoV128, 14485 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 14486 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 14487 break; 14488 } 14489 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 14490 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 14491 { 14492 /* 14493 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 14494 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 14495 * of this function is so easy using shifts, I choose to emulate this instruction that 14496 * way versus a native instruction method of implementation. 14497 */ 14498 Bool make_negative = (opc2 == 0x352) ? True : False; 14499 IRTemp shiftVector = newTemp(Ity_V128); 14500 IRTemp absVal_vector = newTemp(Ity_V128); 14501 assign( shiftVector, 14502 binop( Iop_64HLtoV128, 14503 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 14504 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 14505 assign( absVal_vector, 14506 binop( Iop_Shr32x4, 14507 binop( Iop_Shl32x4, 14508 getVSReg( XB ), 14509 mkexpr( shiftVector ) ), 14510 mkexpr( shiftVector ) ) ); 14511 if (make_negative) { 14512 IRTemp signBit_vector = newTemp(Ity_V128); 14513 assign( signBit_vector, 14514 binop( Iop_64HLtoV128, 14515 binop( Iop_32HLto64, 14516 mkU32( 0x80000000 ), 14517 mkU32( 0x80000000 ) ), 14518 binop( Iop_32HLto64, 14519 mkU32( 0x80000000 ), 14520 mkU32( 0x80000000 ) ) ) ); 14521 putVSReg( XT, 14522 binop( Iop_OrV128, 14523 mkexpr( absVal_vector ), 14524 mkexpr( signBit_vector ) ) ); 14525 } else { 14526 putVSReg( XT, mkexpr( absVal_vector ) ); 14527 } 14528 break; 14529 } 14530 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 14531 { 14532 IRTemp frB = newTemp(Ity_F64); 14533 IRTemp frB2 = newTemp(Ity_F64); 14534 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14535 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14536 DIP("xvnegdp v%d,v%d\n", XT, XB); 14537 putVSReg( XT, 14538 binop( Iop_64HLtoV128, 14539 unop( Iop_ReinterpF64asI64, 14540 unop( Iop_NegF64, mkexpr( frB ) ) ), 14541 unop( Iop_ReinterpF64asI64, 14542 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 14543 break; 14544 } 14545 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 14546 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 14547 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 14548 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 14549 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 14550 { 14551 IRTemp frBHi_I64 = newTemp(Ity_I64); 14552 IRTemp frBLo_I64 = newTemp(Ity_I64); 14553 IRExpr * frD_fp_roundHi = NULL; 14554 IRExpr * frD_fp_roundLo = NULL; 14555 14556 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 14557 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2); 14558 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 14559 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2); 14560 14561 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB); 14562 putVSReg( XT, 14563 binop( Iop_64HLtoV128, 14564 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 14565 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 14566 break; 14567 } 14568 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 14569 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 14570 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 14571 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 14572 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 14573 { 14574 const HChar * insn_suffix = NULL; 14575 IROp op; 14576 if (opc2 != 0x156) { 14577 // Use pre-defined IRop's for vrfi{m|n|p|z} 14578 switch (opc2) { 14579 case 0x112: 14580 insn_suffix = ""; 14581 op = Iop_RoundF32x4_RN; 14582 break; 14583 case 0x172: 14584 insn_suffix = "m"; 14585 op = Iop_RoundF32x4_RM; 14586 break; 14587 case 0x152: 14588 insn_suffix = "p"; 14589 op = Iop_RoundF32x4_RP; 14590 break; 14591 case 0x132: 14592 insn_suffix = "z"; 14593 op = Iop_RoundF32x4_RZ; 14594 break; 14595 14596 default: 14597 vex_printf("Unrecognized opcode %x\n", opc2); 14598 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n"); 14599 } 14600 DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB); 14601 putVSReg( XT, unop( op, getVSReg(XB) ) ); 14602 } else { 14603 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 14604 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 14605 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 14606 IRTemp b3_I64 = newTemp(Ity_I64); 14607 IRTemp b2_I64 = newTemp(Ity_I64); 14608 IRTemp b1_I64 = newTemp(Ity_I64); 14609 IRTemp b0_I64 = newTemp(Ity_I64); 14610 14611 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 14612 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 14613 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 14614 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 14615 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 14616 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 14617 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 14618 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 14619 _do_vsx_fp_roundToInt(b3_I64, opc2)); 14620 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 14621 _do_vsx_fp_roundToInt(b2_I64, opc2)); 14622 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 14623 _do_vsx_fp_roundToInt(b1_I64, opc2)); 14624 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 14625 _do_vsx_fp_roundToInt(b0_I64, opc2)); 14626 DIP("xvrspic v%d,v%d\n", XT, XB); 14627 putVSReg( XT, 14628 binop( Iop_64HLtoV128, 14629 binop( Iop_32HLto64, 14630 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 14631 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 14632 binop( Iop_32HLto64, 14633 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 14634 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 14635 } 14636 break; 14637 } 14638 14639 default: 14640 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 14641 return False; 14642 } 14643 return True; 14644 } 14645 14646 14647 /* 14648 * VSX Scalar Floating Point Arithmetic Instructions 14649 */ 14650 static Bool 14651 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 14652 { 14653 /* XX3-Form */ 14654 UChar opc1 = ifieldOPC( theInstr ); 14655 UChar XT = ifieldRegXT( theInstr ); 14656 UChar XA = ifieldRegXA( theInstr ); 14657 UChar XB = ifieldRegXB( theInstr ); 14658 IRExpr* rm = get_IR_roundingmode(); 14659 IRTemp frA = newTemp(Ity_F64); 14660 IRTemp frB = newTemp(Ity_F64); 14661 14662 if (opc1 != 0x3C) { 14663 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 14664 return False; 14665 } 14666 14667 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14668 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14669 14670 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 14671 * of VSX[XT] are undefined after the operation; therefore, we can simply set 14672 * element to zero where it makes sense to do so. 14673 */ 14674 switch (opc2) { 14675 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision) 14676 DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB); 14677 putVSReg( XT, binop( Iop_64HLtoV128, 14678 unop( Iop_ReinterpF64asI64, 14679 binop( Iop_RoundF64toF32, rm, 14680 triop( Iop_AddF64, rm, 14681 mkexpr( frA ), 14682 mkexpr( frB ) ) ) ), 14683 mkU64( 0 ) ) ); 14684 break; 14685 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision) 14686 DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB); 14687 putVSReg( XT, binop( Iop_64HLtoV128, 14688 unop( Iop_ReinterpF64asI64, 14689 binop( Iop_RoundF64toF32, rm, 14690 triop( Iop_SubF64, rm, 14691 mkexpr( frA ), 14692 mkexpr( frB ) ) ) ), 14693 mkU64( 0 ) ) ); 14694 break; 14695 case 0x080: // xsadddp (VSX scalar add double-precision) 14696 DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB); 14697 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14698 triop( Iop_AddF64, rm, 14699 mkexpr( frA ), 14700 mkexpr( frB ) ) ), 14701 mkU64( 0 ) ) ); 14702 break; 14703 case 0x060: // xsdivsp (VSX scalar divide single-precision) 14704 DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB); 14705 putVSReg( XT, binop( Iop_64HLtoV128, 14706 unop( Iop_ReinterpF64asI64, 14707 binop( Iop_RoundF64toF32, rm, 14708 triop( Iop_DivF64, rm, 14709 mkexpr( frA ), 14710 mkexpr( frB ) ) ) ), 14711 mkU64( 0 ) ) ); 14712 break; 14713 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 14714 DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB); 14715 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14716 triop( Iop_DivF64, rm, 14717 mkexpr( frA ), 14718 mkexpr( frB ) ) ), 14719 mkU64( 0 ) ) ); 14720 break; 14721 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add 14722 * single-precision) 14723 */ 14724 { 14725 IRTemp frT = newTemp(Ity_F64); 14726 Bool mdp = opc2 == 0x024; 14727 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14728 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14729 getVSReg( XT ) ) ) ); 14730 putVSReg( XT, 14731 binop( Iop_64HLtoV128, 14732 unop( Iop_ReinterpF64asI64, 14733 binop( Iop_RoundF64toF32, rm, 14734 qop( Iop_MAddF64, rm, 14735 mkexpr( frA ), 14736 mkexpr( mdp ? frT : frB ), 14737 mkexpr( mdp ? frB : frT ) ) ) ), 14738 mkU64( 0 ) ) ); 14739 break; 14740 } 14741 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 14742 { 14743 IRTemp frT = newTemp(Ity_F64); 14744 Bool mdp = opc2 == 0x0A4; 14745 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14746 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14747 getVSReg( XT ) ) ) ); 14748 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14749 qop( Iop_MAddF64, rm, 14750 mkexpr( frA ), 14751 mkexpr( mdp ? frT : frB ), 14752 mkexpr( mdp ? frB : frT ) ) ), 14753 mkU64( 0 ) ) ); 14754 break; 14755 } 14756 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar 14757 * multiply-subtract single-precision) 14758 */ 14759 { 14760 IRTemp frT = newTemp(Ity_F64); 14761 Bool mdp = opc2 == 0x064; 14762 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14763 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14764 getVSReg( XT ) ) ) ); 14765 putVSReg( XT, 14766 binop( Iop_64HLtoV128, 14767 unop( Iop_ReinterpF64asI64, 14768 binop( Iop_RoundF64toF32, rm, 14769 qop( Iop_MSubF64, rm, 14770 mkexpr( frA ), 14771 mkexpr( mdp ? frT : frB ), 14772 mkexpr( mdp ? frB : frT ) ) ) ), 14773 mkU64( 0 ) ) ); 14774 break; 14775 } 14776 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 14777 { 14778 IRTemp frT = newTemp(Ity_F64); 14779 Bool mdp = opc2 == 0x0E4; 14780 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14781 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14782 getVSReg( XT ) ) ) ); 14783 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14784 qop( Iop_MSubF64, rm, 14785 mkexpr( frA ), 14786 mkexpr( mdp ? frT : frB ), 14787 mkexpr( mdp ? frB : frT ) ) ), 14788 mkU64( 0 ) ) ); 14789 break; 14790 } 14791 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 14792 { 14793 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 14794 * of fnmadd and use pretty much the same code. However, that code has a bug in the 14795 * way it blindly negates the signbit, even if the floating point result is a NaN. 14796 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 14797 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 14798 * bit for NaN result. 14799 */ 14800 Bool mdp = opc2 == 0x2A4; 14801 IRTemp frT = newTemp(Ity_F64); 14802 IRTemp maddResult = newTemp(Ity_I64); 14803 14804 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14805 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14806 getVSReg( XT ) ) ) ); 14807 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 14808 mkexpr( frA ), 14809 mkexpr( mdp ? frT : frB ), 14810 mkexpr( mdp ? frB : frT ) ) ) ); 14811 14812 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 14813 mkU64( 0 ) ) ); 14814 break; 14815 } 14816 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar 14817 * multiply-add single-precision) 14818 */ 14819 { 14820 Bool mdp = opc2 == 0x224; 14821 IRTemp frT = newTemp(Ity_F64); 14822 IRTemp maddResult = newTemp(Ity_I64); 14823 14824 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14825 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14826 getVSReg( XT ) ) ) ); 14827 assign( maddResult, 14828 unop( Iop_ReinterpF64asI64, 14829 binop( Iop_RoundF64toF32, rm, 14830 qop( Iop_MAddF64, rm, 14831 mkexpr( frA ), 14832 mkexpr( mdp ? frT : frB ), 14833 mkexpr( mdp ? frB : frT ) ) ) ) ); 14834 14835 putVSReg( XT, binop( Iop_64HLtoV128, 14836 mkexpr( getNegatedResult(maddResult) ), 14837 mkU64( 0 ) ) ); 14838 break; 14839 } 14840 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative 14841 * Multiply-Subtract Single-Precision) 14842 */ 14843 { 14844 IRTemp frT = newTemp(Ity_F64); 14845 Bool mdp = opc2 == 0x264; 14846 IRTemp msubResult = newTemp(Ity_I64); 14847 14848 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14849 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14850 getVSReg( XT ) ) ) ); 14851 assign( msubResult, 14852 unop( Iop_ReinterpF64asI64, 14853 binop( Iop_RoundF64toF32, rm, 14854 qop( Iop_MSubF64, rm, 14855 mkexpr( frA ), 14856 mkexpr( mdp ? frT : frB ), 14857 mkexpr( mdp ? frB : frT ) ) ) ) ); 14858 14859 putVSReg( XT, binop( Iop_64HLtoV128, 14860 mkexpr( getNegatedResult(msubResult) ), 14861 mkU64( 0 ) ) ); 14862 14863 break; 14864 } 14865 14866 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 14867 { 14868 IRTemp frT = newTemp(Ity_F64); 14869 Bool mdp = opc2 == 0x2E4; 14870 IRTemp msubResult = newTemp(Ity_I64); 14871 14872 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 14873 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14874 getVSReg( XT ) ) ) ); 14875 assign(msubResult, unop( Iop_ReinterpF64asI64, 14876 qop( Iop_MSubF64, 14877 rm, 14878 mkexpr( frA ), 14879 mkexpr( mdp ? frT : frB ), 14880 mkexpr( mdp ? frB : frT ) ) )); 14881 14882 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 14883 14884 break; 14885 } 14886 14887 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision) 14888 DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB); 14889 putVSReg( XT, binop( Iop_64HLtoV128, 14890 unop( Iop_ReinterpF64asI64, 14891 binop( Iop_RoundF64toF32, rm, 14892 triop( Iop_MulF64, rm, 14893 mkexpr( frA ), 14894 mkexpr( frB ) ) ) ), 14895 mkU64( 0 ) ) ); 14896 break; 14897 14898 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 14899 DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB); 14900 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14901 triop( Iop_MulF64, rm, 14902 mkexpr( frA ), 14903 mkexpr( frB ) ) ), 14904 mkU64( 0 ) ) ); 14905 break; 14906 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 14907 DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB); 14908 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14909 triop( Iop_SubF64, rm, 14910 mkexpr( frA ), 14911 mkexpr( frB ) ) ), 14912 mkU64( 0 ) ) ); 14913 break; 14914 14915 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision) 14916 DIP("xssqrtsp v%d,v%d\n", XT, XB); 14917 putVSReg( XT, 14918 binop( Iop_64HLtoV128, 14919 unop( Iop_ReinterpF64asI64, 14920 binop( Iop_RoundF64toF32, rm, 14921 binop( Iop_SqrtF64, rm, 14922 mkexpr( frB ) ) ) ), 14923 mkU64( 0 ) ) ); 14924 break; 14925 14926 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 14927 DIP("xssqrtdp v%d,v%d\n", XT, XB); 14928 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14929 binop( Iop_SqrtF64, rm, 14930 mkexpr( frB ) ) ), 14931 mkU64( 0 ) ) ); 14932 break; 14933 14934 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 14935 { 14936 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14937 IRTemp frA_I64 = newTemp(Ity_I64); 14938 IRTemp frB_I64 = newTemp(Ity_I64); 14939 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB); 14940 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 14941 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 14942 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 14943 break; 14944 } 14945 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 14946 { 14947 IRTemp frB_I64 = newTemp(Ity_I64); 14948 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14949 IRTemp flags = newTemp(Ity_I32); 14950 IRTemp fe_flag, fg_flag; 14951 fe_flag = fg_flag = IRTemp_INVALID; 14952 DIP("xstsqrtdp v%d,v%d\n", XT, XB); 14953 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 14954 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 14955 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 14956 * where fl_flag == 1 on ppc64. 14957 */ 14958 assign( flags, 14959 binop( Iop_Or32, 14960 binop( Iop_Or32, mkU32( 8 ), // fl_flag 14961 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 14962 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 14963 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 14964 break; 14965 } 14966 14967 default: 14968 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 14969 return False; 14970 } 14971 14972 return True; 14973 } 14974 14975 14976 /* 14977 * VSX Floating Point Compare Instructions 14978 */ 14979 static Bool 14980 dis_vx_cmp( UInt theInstr, UInt opc2 ) 14981 { 14982 /* XX3-Form and XX2-Form */ 14983 UChar opc1 = ifieldOPC( theInstr ); 14984 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14985 IRTemp ccPPC32; 14986 UChar XA = ifieldRegXA ( theInstr ); 14987 UChar XB = ifieldRegXB ( theInstr ); 14988 IRTemp frA = newTemp(Ity_F64); 14989 IRTemp frB = newTemp(Ity_F64); 14990 14991 if (opc1 != 0x3C) { 14992 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 14993 return False; 14994 } 14995 14996 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14997 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14998 switch (opc2) { 14999 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 15000 /* Note: Differences between xscmpudp and xscmpodp are only in 15001 * exception flag settings, which aren't supported anyway. */ 15002 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 15003 crfD, XA, XB); 15004 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 15005 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 15006 break; 15007 15008 default: 15009 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 15010 return False; 15011 } 15012 return True; 15013 } 15014 15015 static void 15016 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 15017 ppc_cmp_t cmp_type ) 15018 { 15019 IRTemp frA_hi = newTemp(Ity_F64); 15020 IRTemp frB_hi = newTemp(Ity_F64); 15021 IRTemp frA_lo = newTemp(Ity_F64); 15022 IRTemp frB_lo = newTemp(Ity_F64); 15023 IRTemp ccPPC32 = newTemp(Ity_I32); 15024 IRTemp ccIR_hi; 15025 IRTemp ccIR_lo; 15026 15027 IRTemp hiResult = newTemp(Ity_I64); 15028 IRTemp loResult = newTemp(Ity_I64); 15029 IRTemp hiEQlo = newTemp(Ity_I1); 15030 IRTemp all_elem_true = newTemp(Ity_I32); 15031 IRTemp all_elem_false = newTemp(Ity_I32); 15032 15033 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 15034 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 15035 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 15036 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 15037 15038 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 15039 mkexpr( frA_hi ), 15040 mkexpr( frB_hi ) ) ); 15041 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 15042 mkexpr( frA_lo ), 15043 mkexpr( frB_lo ) ) ); 15044 15045 if (cmp_type != PPC_CMP_GE) { 15046 assign( hiResult, 15047 unop( Iop_1Sto64, 15048 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 15049 assign( loResult, 15050 unop( Iop_1Sto64, 15051 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 15052 } else { 15053 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 15054 // the other element compare may return "2" (for "equal to"). 15055 IRTemp lo_GE = newTemp(Ity_I1); 15056 IRTemp hi_GE = newTemp(Ity_I1); 15057 15058 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 15059 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 15060 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 15061 15062 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 15063 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 15064 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 15065 } 15066 15067 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 15068 assign( hiEQlo, 15069 binop( Iop_CmpEQ32, 15070 unop( Iop_64to32, mkexpr( hiResult ) ), 15071 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 15072 putVSReg( XT, 15073 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 15074 15075 assign( all_elem_true, 15076 unop( Iop_1Uto32, 15077 mkAND1( mkexpr( hiEQlo ), 15078 binop( Iop_CmpEQ32, 15079 mkU32( 0xffffffff ), 15080 unop( Iop_64to32, 15081 mkexpr( hiResult ) ) ) ) ) ); 15082 15083 assign( all_elem_false, 15084 unop( Iop_1Uto32, 15085 mkAND1( mkexpr( hiEQlo ), 15086 binop( Iop_CmpEQ32, 15087 mkU32( 0 ), 15088 unop( Iop_64to32, 15089 mkexpr( hiResult ) ) ) ) ) ); 15090 assign( ccPPC32, 15091 binop( Iop_Or32, 15092 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 15093 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 15094 15095 if (flag_rC) { 15096 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 15097 } 15098 } 15099 15100 /* 15101 * VSX Vector Compare Instructions 15102 */ 15103 static Bool 15104 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 15105 { 15106 /* XX3-Form */ 15107 UChar opc1 = ifieldOPC( theInstr ); 15108 UChar XT = ifieldRegXT ( theInstr ); 15109 UChar XA = ifieldRegXA ( theInstr ); 15110 UChar XB = ifieldRegXB ( theInstr ); 15111 UChar flag_rC = ifieldBIT10(theInstr); 15112 IRTemp vA = newTemp( Ity_V128 ); 15113 IRTemp vB = newTemp( Ity_V128 ); 15114 15115 if (opc1 != 0x3C) { 15116 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 15117 return False; 15118 } 15119 15120 assign( vA, getVSReg( XA ) ); 15121 assign( vB, getVSReg( XB ) ); 15122 15123 switch (opc2) { 15124 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 15125 { 15126 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15127 XT, XA, XB); 15128 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 15129 break; 15130 } 15131 15132 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 15133 { 15134 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15135 XT, XA, XB); 15136 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 15137 break; 15138 } 15139 15140 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 15141 { 15142 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15143 XT, XA, XB); 15144 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 15145 break; 15146 } 15147 15148 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 15149 { 15150 IRTemp vD = newTemp(Ity_V128); 15151 15152 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15153 XT, XA, XB); 15154 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 15155 putVSReg( XT, mkexpr(vD) ); 15156 if (flag_rC) { 15157 set_AV_CR6( mkexpr(vD), True ); 15158 } 15159 break; 15160 } 15161 15162 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 15163 { 15164 IRTemp vD = newTemp(Ity_V128); 15165 15166 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15167 XT, XA, XB); 15168 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 15169 putVSReg( XT, mkexpr(vD) ); 15170 if (flag_rC) { 15171 set_AV_CR6( mkexpr(vD), True ); 15172 } 15173 break; 15174 } 15175 15176 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 15177 { 15178 IRTemp vD = newTemp(Ity_V128); 15179 15180 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15181 XT, XA, XB); 15182 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 15183 putVSReg( XT, mkexpr(vD) ); 15184 if (flag_rC) { 15185 set_AV_CR6( mkexpr(vD), True ); 15186 } 15187 break; 15188 } 15189 15190 default: 15191 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 15192 return False; 15193 } 15194 return True; 15195 } 15196 /* 15197 * Miscellaneous VSX Scalar Instructions 15198 */ 15199 static Bool 15200 dis_vxs_misc( UInt theInstr, UInt opc2 ) 15201 { 15202 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL 15203 /* XX3-Form and XX2-Form */ 15204 UChar opc1 = ifieldOPC( theInstr ); 15205 UChar XT = ifieldRegXT ( theInstr ); 15206 UChar XA = ifieldRegXA ( theInstr ); 15207 UChar XB = ifieldRegXB ( theInstr ); 15208 IRTemp vA = newTemp( Ity_V128 ); 15209 IRTemp vB = newTemp( Ity_V128 ); 15210 15211 if (opc1 != 0x3C) { 15212 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 15213 return False; 15214 } 15215 15216 assign( vA, getVSReg( XA ) ); 15217 assign( vB, getVSReg( XB ) ); 15218 15219 /* For all the VSX move instructions, the contents of doubleword element 1 15220 * of VSX[XT] are undefined after the operation; therefore, we can simply 15221 * move the entire array element where it makes sense to do so. 15222 */ 15223 15224 switch (opc2) { 15225 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 15226 { 15227 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 15228 IRTemp absVal = newTemp(Ity_V128); 15229 if (host_endness == VexEndnessLE) { 15230 IRTemp hi64 = newTemp(Ity_I64); 15231 IRTemp lo64 = newTemp(Ity_I64); 15232 assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15233 assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) ); 15234 assign( absVal, binop( Iop_64HLtoV128, 15235 binop( Iop_And64, mkexpr(hi64), 15236 mkU64(VG_PPC_SIGN_MASK) ), 15237 mkexpr(lo64) ) ); 15238 } else { 15239 assign(absVal, binop(Iop_ShrV128, 15240 binop(Iop_ShlV128, mkexpr(vB), 15241 mkU8(1)), mkU8(1))); 15242 } 15243 DIP("xsabsdp v%d,v%d\n", XT, XB); 15244 putVSReg(XT, mkexpr(absVal)); 15245 break; 15246 } 15247 case 0x2C0: // xscpsgndp 15248 { 15249 /* Scalar copy sign double-precision */ 15250 IRTemp vecA_signed = newTemp(Ity_I64); 15251 IRTemp vecB_unsigned = newTemp(Ity_I64); 15252 IRTemp vec_result = newTemp(Ity_V128); 15253 DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB); 15254 assign( vecA_signed, binop( Iop_And64, 15255 unop( Iop_V128HIto64, 15256 mkexpr(vA)), 15257 mkU64(~VG_PPC_SIGN_MASK) ) ); 15258 assign( vecB_unsigned, binop( Iop_And64, 15259 unop( Iop_V128HIto64, 15260 mkexpr(vB) ), 15261 mkU64(VG_PPC_SIGN_MASK) ) ); 15262 assign( vec_result, binop( Iop_64HLtoV128, 15263 binop( Iop_Or64, 15264 mkexpr(vecA_signed), 15265 mkexpr(vecB_unsigned) ), 15266 mkU64(0x0ULL))); 15267 putVSReg(XT, mkexpr(vec_result)); 15268 break; 15269 } 15270 case 0x2D2: // xsnabsdp 15271 { 15272 /* Scalar negative absolute value double-precision */ 15273 IRTemp BHi_signed = newTemp(Ity_I64); 15274 DIP("xsnabsdp v%d,v%d\n", XT, XB); 15275 assign( BHi_signed, binop( Iop_Or64, 15276 unop( Iop_V128HIto64, 15277 mkexpr(vB) ), 15278 mkU64(~VG_PPC_SIGN_MASK) ) ); 15279 putVSReg(XT, binop( Iop_64HLtoV128, 15280 mkexpr(BHi_signed), mkU64(0x0ULL) ) ); 15281 break; 15282 } 15283 case 0x2F2: // xsnegdp 15284 { 15285 /* Scalar negate double-precision */ 15286 IRTemp BHi_signed = newTemp(Ity_I64); 15287 IRTemp BHi_unsigned = newTemp(Ity_I64); 15288 IRTemp BHi_negated = newTemp(Ity_I64); 15289 IRTemp BHi_negated_signbit = newTemp(Ity_I1); 15290 IRTemp vec_result = newTemp(Ity_V128); 15291 DIP("xsnabsdp v%d,v%d\n", XT, XB); 15292 assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15293 assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed), 15294 mkU64(VG_PPC_SIGN_MASK) ) ); 15295 assign( BHi_negated_signbit, 15296 unop( Iop_Not1, 15297 unop( Iop_32to1, 15298 binop( Iop_Shr32, 15299 unop( Iop_64HIto32, 15300 binop( Iop_And64, 15301 mkexpr(BHi_signed), 15302 mkU64(~VG_PPC_SIGN_MASK) ) 15303 ), 15304 mkU8(31) ) ) ) ); 15305 assign( BHi_negated, 15306 binop( Iop_Or64, 15307 binop( Iop_32HLto64, 15308 binop( Iop_Shl32, 15309 unop( Iop_1Uto32, 15310 mkexpr(BHi_negated_signbit) ), 15311 mkU8(31) ), 15312 mkU32(0) ), 15313 mkexpr(BHi_unsigned) ) ); 15314 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated), 15315 mkU64(0x0ULL))); 15316 putVSReg( XT, mkexpr(vec_result)); 15317 break; 15318 } 15319 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 15320 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 15321 { 15322 IRTemp frA = newTemp(Ity_I64); 15323 IRTemp frB = newTemp(Ity_I64); 15324 Bool isMin = opc2 == 0x2A0 ? True : False; 15325 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB); 15326 15327 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 15328 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 15329 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 15330 15331 break; 15332 } 15333 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 15334 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 15335 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 15336 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 15337 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 15338 { 15339 IRTemp frB_I64 = newTemp(Ity_I64); 15340 IRExpr * frD_fp_round = NULL; 15341 15342 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 15343 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2); 15344 15345 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB); 15346 putVSReg( XT, 15347 binop( Iop_64HLtoV128, 15348 unop( Iop_ReinterpF64asI64, frD_fp_round), 15349 mkU64( 0 ) ) ); 15350 break; 15351 } 15352 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision) 15353 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate 15354 * single-Precision) 15355 */ 15356 { 15357 IRTemp frB = newTemp(Ity_F64); 15358 IRTemp sqrt = newTemp(Ity_F64); 15359 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15360 IRExpr* rm = get_IR_roundingmode(); 15361 Bool redp = opc2 == 0x034; 15362 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT, 15363 XB); 15364 15365 assign( frB, 15366 unop( Iop_ReinterpI64asF64, 15367 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15368 15369 if (!redp) 15370 assign( sqrt, 15371 binop( Iop_SqrtF64, 15372 rm, 15373 mkexpr(frB) ) ); 15374 putVSReg( XT, 15375 binop( Iop_64HLtoV128, 15376 unop( Iop_ReinterpF64asI64, 15377 binop( Iop_RoundF64toF32, rm, 15378 triop( Iop_DivF64, 15379 rm, 15380 ieee_one, 15381 redp ? mkexpr( frB ) : 15382 mkexpr( sqrt ) ) ) ), 15383 mkU64( 0 ) ) ); 15384 break; 15385 } 15386 15387 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 15388 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 15389 15390 { 15391 IRTemp frB = newTemp(Ity_F64); 15392 IRTemp sqrt = newTemp(Ity_F64); 15393 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15394 IRExpr* rm = get_IR_roundingmode(); 15395 Bool redp = opc2 == 0x0B4; 15396 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB); 15397 assign( frB, 15398 unop( Iop_ReinterpI64asF64, 15399 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15400 15401 if (!redp) 15402 assign( sqrt, 15403 binop( Iop_SqrtF64, 15404 rm, 15405 mkexpr(frB) ) ); 15406 putVSReg( XT, 15407 binop( Iop_64HLtoV128, 15408 unop( Iop_ReinterpF64asI64, 15409 triop( Iop_DivF64, 15410 rm, 15411 ieee_one, 15412 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 15413 mkU64( 0 ) ) ); 15414 break; 15415 } 15416 15417 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision) 15418 { 15419 IRTemp frB = newTemp(Ity_F64); 15420 IRExpr* rm = get_IR_roundingmode(); 15421 DIP("xsrsp v%d, v%d\n", XT, XB); 15422 assign( frB, 15423 unop( Iop_ReinterpI64asF64, 15424 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15425 15426 putVSReg( XT, binop( Iop_64HLtoV128, 15427 unop( Iop_ReinterpF64asI64, 15428 binop( Iop_RoundF64toF32, 15429 rm, 15430 mkexpr( frB ) ) ), 15431 mkU64( 0 ) ) ); 15432 break; 15433 } 15434 15435 default: 15436 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 15437 return False; 15438 } 15439 return True; 15440 } 15441 15442 /* 15443 * VSX Logical Instructions 15444 */ 15445 static Bool 15446 dis_vx_logic ( UInt theInstr, UInt opc2 ) 15447 { 15448 /* XX3-Form */ 15449 UChar opc1 = ifieldOPC( theInstr ); 15450 UChar XT = ifieldRegXT ( theInstr ); 15451 UChar XA = ifieldRegXA ( theInstr ); 15452 UChar XB = ifieldRegXB ( theInstr ); 15453 IRTemp vA = newTemp( Ity_V128 ); 15454 IRTemp vB = newTemp( Ity_V128 ); 15455 15456 if (opc1 != 0x3C) { 15457 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 15458 return False; 15459 } 15460 15461 assign( vA, getVSReg( XA ) ); 15462 assign( vB, getVSReg( XB ) ); 15463 15464 switch (opc2) { 15465 case 0x268: // xxlxor 15466 DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB); 15467 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 15468 break; 15469 case 0x248: // xxlor 15470 DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB); 15471 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 15472 break; 15473 case 0x288: // xxlnor 15474 DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB); 15475 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 15476 mkexpr( vB ) ) ) ); 15477 break; 15478 case 0x208: // xxland 15479 DIP("xxland v%d,v%d,v%d\n", XT, XA, XB); 15480 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 15481 break; 15482 case 0x228: //xxlandc 15483 DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB); 15484 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 15485 mkexpr( vB ) ) ) ); 15486 break; 15487 case 0x2A8: // xxlorc (VSX Logical OR with complement) 15488 DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB); 15489 putVSReg( XT, binop( Iop_OrV128, 15490 mkexpr( vA ), 15491 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 15492 break; 15493 case 0x2C8: // xxlnand (VSX Logical NAND) 15494 DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB); 15495 putVSReg( XT, unop( Iop_NotV128, 15496 binop( Iop_AndV128, mkexpr( vA ), 15497 mkexpr( vB ) ) ) ); 15498 break; 15499 case 0x2E8: // xxleqv (VSX Logical Equivalence) 15500 DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB); 15501 putVSReg( XT, unop( Iop_NotV128, 15502 binop( Iop_XorV128, 15503 mkexpr( vA ), mkexpr( vB ) ) ) ); 15504 break; 15505 default: 15506 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 15507 return False; 15508 } 15509 return True; 15510 } 15511 15512 /* 15513 * VSX Load Instructions 15514 * NOTE: VSX supports word-aligned storage access. 15515 */ 15516 static Bool 15517 dis_vx_load ( UInt theInstr ) 15518 { 15519 /* XX1-Form */ 15520 UChar opc1 = ifieldOPC( theInstr ); 15521 UChar XT = ifieldRegXT ( theInstr ); 15522 UChar rA_addr = ifieldRegA( theInstr ); 15523 UChar rB_addr = ifieldRegB( theInstr ); 15524 UInt opc2 = ifieldOPClo10( theInstr ); 15525 15526 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15527 IRTemp EA = newTemp( ty ); 15528 15529 if (opc1 != 0x1F) { 15530 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 15531 return False; 15532 } 15533 15534 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15535 15536 switch (opc2) { 15537 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) 15538 { 15539 IRExpr * exp; 15540 DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15541 15542 if (host_endness == VexEndnessLE) 15543 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15544 else 15545 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15546 15547 putVSReg( XT, binop( Iop_64HLtoV128, 15548 unop( Iop_32Uto64, exp), 15549 mkU64(0) ) ); 15550 break; 15551 } 15552 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) 15553 { 15554 IRExpr * exp; 15555 DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15556 15557 if (host_endness == VexEndnessLE) 15558 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15559 else 15560 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15561 15562 putVSReg( XT, binop( Iop_64HLtoV128, 15563 unop( Iop_32Sto64, exp), 15564 mkU64(0) ) ); 15565 break; 15566 } 15567 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed) 15568 { 15569 IRExpr * exp; 15570 DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15571 /* Take 32-bit floating point value in the upper half of the fetched 15572 * 64-bit value, convert to 64-bit floating point value and load into 15573 * top word of V128. 15574 */ 15575 exp = unop( Iop_ReinterpF64asI64, 15576 unop( Iop_F32toF64, 15577 unop( Iop_ReinterpI32asF32, 15578 load( Ity_I32, mkexpr( EA ) ) ) ) ); 15579 15580 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); 15581 break; 15582 } 15583 case 0x24C: // lxsdx 15584 { 15585 IRExpr * exp; 15586 DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15587 exp = load( Ity_I64, mkexpr( EA ) ); 15588 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 15589 // we just performed is only a DW. But since the contents of VSR[XT] element 1 15590 // are undefined after this operation, we can just do a splat op. 15591 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 15592 break; 15593 } 15594 case 0x34C: // lxvd2x 15595 { 15596 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 15597 IRExpr * high, *low; 15598 ULong ea_off = 8; 15599 IRExpr* high_addr; 15600 DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15601 high = load( Ity_I64, mkexpr( EA ) ); 15602 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 15603 : mkU32( ea_off ) ); 15604 low = load( Ity_I64, high_addr ); 15605 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 15606 break; 15607 } 15608 case 0x14C: // lxvdsx 15609 { 15610 IRTemp data = newTemp(Ity_I64); 15611 DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15612 assign( data, load( Ity_I64, mkexpr( EA ) ) ); 15613 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 15614 break; 15615 } 15616 case 0x30C: 15617 { 15618 IRExpr *t0; 15619 15620 DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr); 15621 15622 /* The load will result in the data being in BE order. */ 15623 if (host_endness == VexEndnessLE) { 15624 IRExpr *t0_BE; 15625 IRTemp perm_LE = newTemp(Ity_V128); 15626 15627 t0_BE = load( Ity_V128, mkexpr( EA ) ); 15628 15629 /* Permute the data to LE format */ 15630 assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL), 15631 mkU64(0x0405060700010203ULL))); 15632 15633 t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) ); 15634 } else { 15635 t0 = load( Ity_V128, mkexpr( EA ) ); 15636 } 15637 15638 putVSReg( XT, t0 ); 15639 break; 15640 } 15641 default: 15642 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 15643 return False; 15644 } 15645 return True; 15646 } 15647 15648 /* 15649 * VSX Store Instructions 15650 * NOTE: VSX supports word-aligned storage access. 15651 */ 15652 static Bool 15653 dis_vx_store ( UInt theInstr ) 15654 { 15655 /* XX1-Form */ 15656 UChar opc1 = ifieldOPC( theInstr ); 15657 UChar XS = ifieldRegXS( theInstr ); 15658 UChar rA_addr = ifieldRegA( theInstr ); 15659 UChar rB_addr = ifieldRegB( theInstr ); 15660 IRTemp vS = newTemp( Ity_V128 ); 15661 UInt opc2 = ifieldOPClo10( theInstr ); 15662 15663 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15664 IRTemp EA = newTemp( ty ); 15665 15666 if (opc1 != 0x1F) { 15667 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 15668 return False; 15669 } 15670 15671 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15672 assign( vS, getVSReg( XS ) ); 15673 15674 switch (opc2) { 15675 case 0x08C: 15676 { 15677 /* Need the next to the most significant 32-bit word from 15678 * the 128-bit vector. 15679 */ 15680 IRExpr * high64, * low32; 15681 DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr); 15682 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15683 low32 = unop( Iop_64to32, high64 ); 15684 store( mkexpr( EA ), low32 ); 15685 break; 15686 } 15687 case 0x28C: 15688 { 15689 IRTemp high64 = newTemp(Ity_F64); 15690 IRTemp val32 = newTemp(Ity_I32); 15691 DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr); 15692 assign(high64, unop( Iop_ReinterpI64asF64, 15693 unop( Iop_V128HIto64, mkexpr( vS ) ) ) ); 15694 assign(val32, unop( Iop_ReinterpF32asI32, 15695 unop( Iop_TruncF64asF32, 15696 mkexpr(high64) ) ) ); 15697 store( mkexpr( EA ), mkexpr( val32 ) ); 15698 break; 15699 } 15700 case 0x2CC: 15701 { 15702 IRExpr * high64; 15703 DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr); 15704 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15705 store( mkexpr( EA ), high64 ); 15706 break; 15707 } 15708 case 0x3CC: 15709 { 15710 IRExpr * high64, *low64; 15711 DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr); 15712 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15713 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 15714 store( mkexpr( EA ), high64 ); 15715 store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15716 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 ); 15717 break; 15718 } 15719 case 0x38C: 15720 { 15721 UInt ea_off = 0; 15722 IRExpr* irx_addr; 15723 IRTemp hi64 = newTemp( Ity_I64 ); 15724 IRTemp lo64 = newTemp( Ity_I64 ); 15725 15726 DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr); 15727 15728 // This instruction supports word-aligned stores, so EA may not be 15729 // quad-word aligned. Therefore, do 4 individual word-size stores. 15730 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 15731 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 15732 store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 15733 ea_off += 4; 15734 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15735 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15736 store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 15737 ea_off += 4; 15738 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15739 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15740 store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 15741 ea_off += 4; 15742 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15743 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15744 store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 15745 15746 break; 15747 } 15748 default: 15749 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 15750 return False; 15751 } 15752 return True; 15753 } 15754 15755 /* 15756 * VSX permute and other miscealleous instructions 15757 */ 15758 static Bool 15759 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 15760 { 15761 /* XX3-Form */ 15762 UChar opc1 = ifieldOPC( theInstr ); 15763 UChar XT = ifieldRegXT ( theInstr ); 15764 UChar XA = ifieldRegXA ( theInstr ); 15765 UChar XB = ifieldRegXB ( theInstr ); 15766 IRTemp vT = newTemp( Ity_V128 ); 15767 IRTemp vA = newTemp( Ity_V128 ); 15768 IRTemp vB = newTemp( Ity_V128 ); 15769 15770 if (opc1 != 0x3C) { 15771 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 15772 return False; 15773 } 15774 15775 assign( vA, getVSReg( XA ) ); 15776 assign( vB, getVSReg( XB ) ); 15777 15778 switch (opc2) { 15779 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 15780 { 15781 UChar SHW = ifieldSHW ( theInstr ); 15782 IRTemp result = newTemp(Ity_V128); 15783 if ( SHW != 0 ) { 15784 IRTemp hi = newTemp(Ity_V128); 15785 IRTemp lo = newTemp(Ity_V128); 15786 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 15787 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 15788 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 15789 } else 15790 assign ( result, mkexpr(vA) ); 15791 DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW); 15792 putVSReg( XT, mkexpr(result) ); 15793 break; 15794 } 15795 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 15796 { 15797 UChar DM = ifieldDM ( theInstr ); 15798 IRTemp hi = newTemp(Ity_I64); 15799 IRTemp lo = newTemp(Ity_I64); 15800 15801 if (DM & 0x2) 15802 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 15803 else 15804 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 15805 15806 if (DM & 0x1) 15807 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 15808 else 15809 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 15810 15811 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 15812 15813 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM); 15814 putVSReg( XT, mkexpr( vT ) ); 15815 break; 15816 } 15817 case 0x48: // xxmrghw (VSX Merge High Word) 15818 case 0xc8: // xxmrglw (VSX Merge Low Word) 15819 { 15820 const HChar type = (opc2 == 0x48) ? 'h' : 'l'; 15821 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 15822 IRTemp a64 = newTemp(Ity_I64); 15823 IRTemp ahi32 = newTemp(Ity_I32); 15824 IRTemp alo32 = newTemp(Ity_I32); 15825 IRTemp b64 = newTemp(Ity_I64); 15826 IRTemp bhi32 = newTemp(Ity_I32); 15827 IRTemp blo32 = newTemp(Ity_I32); 15828 15829 assign( a64, unop(word_op, mkexpr(vA)) ); 15830 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 15831 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 15832 15833 assign( b64, unop(word_op, mkexpr(vB)) ); 15834 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 15835 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 15836 15837 assign( vT, binop(Iop_64HLtoV128, 15838 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 15839 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 15840 15841 DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB); 15842 putVSReg( XT, mkexpr( vT ) ); 15843 break; 15844 } 15845 case 0x018: // xxsel (VSX Select) 15846 { 15847 UChar XC = ifieldRegXC(theInstr); 15848 IRTemp vC = newTemp( Ity_V128 ); 15849 assign( vC, getVSReg( XC ) ); 15850 DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC); 15851 /* vD = (vA & ~vC) | (vB & vC) */ 15852 putVSReg( XT, binop(Iop_OrV128, 15853 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 15854 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 15855 break; 15856 } 15857 case 0x148: // xxspltw (VSX Splat Word) 15858 { 15859 UChar UIM = ifieldRegA(theInstr) & 3; 15860 UChar sh_uim = (3 - (UIM)) * 32; 15861 DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM); 15862 putVSReg( XT, 15863 unop( Iop_Dup32x4, 15864 unop( Iop_V128to32, 15865 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 15866 break; 15867 } 15868 15869 default: 15870 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 15871 return False; 15872 } 15873 return True; 15874 } 15875 15876 /* 15877 AltiVec Load Instructions 15878 */ 15879 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) 15880 { 15881 /* X-Form */ 15882 UChar opc1 = ifieldOPC(theInstr); 15883 UChar vD_addr = ifieldRegDS(theInstr); 15884 UChar rA_addr = ifieldRegA(theInstr); 15885 UChar rB_addr = ifieldRegB(theInstr); 15886 UInt opc2 = ifieldOPClo10(theInstr); 15887 UChar b0 = ifieldBIT0(theInstr); 15888 15889 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15890 IRTemp EA = newTemp(ty); 15891 IRTemp EA_align16 = newTemp(ty); 15892 15893 if (opc1 != 0x1F || b0 != 0) { 15894 vex_printf("dis_av_load(ppc)(instr)\n"); 15895 return False; 15896 } 15897 15898 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15899 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 15900 15901 switch (opc2) { 15902 15903 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 15904 IRDirty* d; 15905 UInt vD_off = vectorGuestRegOffset(vD_addr); 15906 IRExpr** args_be = mkIRExprVec_5( 15907 IRExpr_BBPTR(), 15908 mkU32(vD_off), 15909 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15910 mkU32(0xF)), 15911 mkU32(0)/*left*/, 15912 mkU32(1)/*Big Endian*/); 15913 IRExpr** args_le = mkIRExprVec_5( 15914 IRExpr_BBPTR(), 15915 mkU32(vD_off), 15916 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15917 mkU32(0xF)), 15918 mkU32(0)/*left*/, 15919 mkU32(0)/*Little Endian*/); 15920 if (!mode64) { 15921 d = unsafeIRDirty_0_N ( 15922 0/*regparms*/, 15923 "ppc32g_dirtyhelper_LVS", 15924 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15925 args_be ); 15926 } else { 15927 if (host_endness == VexEndnessBE) 15928 d = unsafeIRDirty_0_N ( 15929 0/*regparms*/, 15930 "ppc64g_dirtyhelper_LVS", 15931 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15932 args_be ); 15933 else 15934 d = unsafeIRDirty_0_N ( 15935 0/*regparms*/, 15936 "ppc64g_dirtyhelper_LVS", 15937 &ppc64g_dirtyhelper_LVS, 15938 args_le ); 15939 } 15940 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15941 /* declare guest state effects */ 15942 d->nFxState = 1; 15943 vex_bzero(&d->fxState, sizeof(d->fxState)); 15944 d->fxState[0].fx = Ifx_Write; 15945 d->fxState[0].offset = vD_off; 15946 d->fxState[0].size = sizeof(U128); 15947 15948 /* execute the dirty call, side-effecting guest state */ 15949 stmt( IRStmt_Dirty(d) ); 15950 break; 15951 } 15952 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 15953 IRDirty* d; 15954 UInt vD_off = vectorGuestRegOffset(vD_addr); 15955 IRExpr** args_be = mkIRExprVec_5( 15956 IRExpr_BBPTR(), 15957 mkU32(vD_off), 15958 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15959 mkU32(0xF)), 15960 mkU32(1)/*right*/, 15961 mkU32(1)/*Big Endian*/); 15962 IRExpr** args_le = mkIRExprVec_5( 15963 IRExpr_BBPTR(), 15964 mkU32(vD_off), 15965 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15966 mkU32(0xF)), 15967 mkU32(1)/*right*/, 15968 mkU32(0)/*Little Endian*/); 15969 15970 if (!mode64) { 15971 d = unsafeIRDirty_0_N ( 15972 0/*regparms*/, 15973 "ppc32g_dirtyhelper_LVS", 15974 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15975 args_be ); 15976 } else { 15977 if (host_endness == VexEndnessBE) 15978 d = unsafeIRDirty_0_N ( 15979 0/*regparms*/, 15980 "ppc64g_dirtyhelper_LVS", 15981 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15982 args_be ); 15983 else 15984 d = unsafeIRDirty_0_N ( 15985 0/*regparms*/, 15986 "ppc64g_dirtyhelper_LVS", 15987 &ppc64g_dirtyhelper_LVS, 15988 args_le ); 15989 } 15990 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15991 /* declare guest state effects */ 15992 d->nFxState = 1; 15993 vex_bzero(&d->fxState, sizeof(d->fxState)); 15994 d->fxState[0].fx = Ifx_Write; 15995 d->fxState[0].offset = vD_off; 15996 d->fxState[0].size = sizeof(U128); 15997 15998 /* execute the dirty call, side-effecting guest state */ 15999 stmt( IRStmt_Dirty(d) ); 16000 break; 16001 } 16002 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 16003 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 16004 /* loads addressed byte into vector[EA[0:3] 16005 since all other destination bytes are undefined, 16006 can simply load entire vector from 16-aligned EA */ 16007 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 16008 break; 16009 16010 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 16011 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 16012 /* see note for lvebx */ 16013 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 16014 break; 16015 16016 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 16017 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 16018 /* see note for lvebx */ 16019 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 16020 break; 16021 16022 case 0x067: // lvx (Load Vector Indexed, AV p127) 16023 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 16024 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 16025 break; 16026 16027 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 16028 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 16029 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 16030 break; 16031 16032 default: 16033 vex_printf("dis_av_load(ppc)(opc2)\n"); 16034 return False; 16035 } 16036 return True; 16037 } 16038 16039 /* 16040 AltiVec Store Instructions 16041 */ 16042 static Bool dis_av_store ( UInt theInstr ) 16043 { 16044 /* X-Form */ 16045 UChar opc1 = ifieldOPC(theInstr); 16046 UChar vS_addr = ifieldRegDS(theInstr); 16047 UChar rA_addr = ifieldRegA(theInstr); 16048 UChar rB_addr = ifieldRegB(theInstr); 16049 UInt opc2 = ifieldOPClo10(theInstr); 16050 UChar b0 = ifieldBIT0(theInstr); 16051 16052 IRType ty = mode64 ? Ity_I64 : Ity_I32; 16053 IRTemp EA = newTemp(ty); 16054 IRTemp addr_aligned = newTemp(ty); 16055 IRTemp vS = newTemp(Ity_V128); 16056 IRTemp eb = newTemp(Ity_I8); 16057 IRTemp idx = newTemp(Ity_I8); 16058 16059 if (opc1 != 0x1F || b0 != 0) { 16060 vex_printf("dis_av_store(ppc)(instr)\n"); 16061 return False; 16062 } 16063 16064 assign( vS, getVReg(vS_addr)); 16065 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 16066 16067 switch (opc2) { 16068 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 16069 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 16070 assign( eb, binop(Iop_And8, mkU8(0xF), 16071 unop(Iop_32to8, 16072 mkNarrowTo32(ty, mkexpr(EA)) )) ); 16073 if (host_endness == VexEndnessLE) { 16074 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 16075 } else { 16076 assign( idx, binop(Iop_Shl8, 16077 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 16078 mkU8(3)) ); 16079 } 16080 store( mkexpr(EA), 16081 unop( Iop_32to8, unop(Iop_V128to32, 16082 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 16083 break; 16084 } 16085 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 16086 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 16087 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 16088 assign( eb, binop(Iop_And8, mkU8(0xF), 16089 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 16090 if (host_endness == VexEndnessLE) { 16091 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 16092 } else { 16093 assign( idx, binop(Iop_Shl8, 16094 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 16095 mkU8(3)) ); 16096 } 16097 store( mkexpr(addr_aligned), 16098 unop( Iop_32to16, unop(Iop_V128to32, 16099 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 16100 break; 16101 } 16102 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 16103 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 16104 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 16105 assign( eb, binop(Iop_And8, mkU8(0xF), 16106 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 16107 if (host_endness == VexEndnessLE) { 16108 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 16109 } else { 16110 assign( idx, binop(Iop_Shl8, 16111 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 16112 mkU8(3)) ); 16113 } 16114 store( mkexpr( addr_aligned), 16115 unop( Iop_V128to32, 16116 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 16117 break; 16118 } 16119 16120 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 16121 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 16122 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 16123 break; 16124 16125 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 16126 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 16127 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 16128 break; 16129 16130 default: 16131 vex_printf("dis_av_store(ppc)(opc2)\n"); 16132 return False; 16133 } 16134 return True; 16135 } 16136 16137 /* 16138 AltiVec Arithmetic Instructions 16139 */ 16140 static Bool dis_av_arith ( UInt theInstr ) 16141 { 16142 /* VX-Form */ 16143 UChar opc1 = ifieldOPC(theInstr); 16144 UChar vD_addr = ifieldRegDS(theInstr); 16145 UChar vA_addr = ifieldRegA(theInstr); 16146 UChar vB_addr = ifieldRegB(theInstr); 16147 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16148 16149 IRTemp vA = newTemp(Ity_V128); 16150 IRTemp vB = newTemp(Ity_V128); 16151 IRTemp z3 = newTemp(Ity_I64); 16152 IRTemp z2 = newTemp(Ity_I64); 16153 IRTemp z1 = newTemp(Ity_I64); 16154 IRTemp z0 = newTemp(Ity_I64); 16155 IRTemp aEvn, aOdd; 16156 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 16157 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 16158 IRTemp b3, b2, b1, b0; 16159 16160 aEvn = aOdd = IRTemp_INVALID; 16161 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 16162 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 16163 b3 = b2 = b1 = b0 = IRTemp_INVALID; 16164 16165 assign( vA, getVReg(vA_addr)); 16166 assign( vB, getVReg(vB_addr)); 16167 16168 if (opc1 != 0x4) { 16169 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 16170 return False; 16171 } 16172 16173 switch (opc2) { 16174 /* Add */ 16175 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 16176 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16177 /* unsigned_ov(x+y) = (y >u not(x)) */ 16178 putVReg( vD_addr, binop(Iop_ShrN32x4, 16179 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16180 unop(Iop_NotV128, mkexpr(vA))), 16181 mkU8(31)) ); 16182 break; 16183 } 16184 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 16185 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16186 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 16187 break; 16188 16189 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 16190 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16191 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 16192 break; 16193 16194 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 16195 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16196 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 16197 break; 16198 16199 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo) 16200 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16201 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) ); 16202 break; 16203 16204 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 16205 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16206 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 16207 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 16208 break; 16209 16210 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 16211 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16212 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 16213 // TODO: set VSCR[SAT] 16214 break; 16215 16216 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 16217 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16218 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 16219 // TODO: set VSCR[SAT] 16220 break; 16221 16222 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 16223 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16224 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 16225 // TODO: set VSCR[SAT] 16226 break; 16227 16228 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 16229 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16230 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 16231 // TODO: set VSCR[SAT] 16232 break; 16233 16234 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 16235 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16236 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 16237 // TODO: set VSCR[SAT] 16238 break; 16239 16240 16241 /* Subtract */ 16242 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 16243 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16244 /* unsigned_ov(x-y) = (y >u x) */ 16245 putVReg( vD_addr, binop(Iop_ShrN32x4, 16246 unop(Iop_NotV128, 16247 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16248 mkexpr(vA))), 16249 mkU8(31)) ); 16250 break; 16251 } 16252 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 16253 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16254 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 16255 break; 16256 16257 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 16258 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16259 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 16260 break; 16261 16262 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 16263 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16264 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 16265 break; 16266 16267 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo) 16268 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16269 putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) ); 16270 break; 16271 16272 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 16273 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16274 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 16275 // TODO: set VSCR[SAT] 16276 break; 16277 16278 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 16279 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16280 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 16281 // TODO: set VSCR[SAT] 16282 break; 16283 16284 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 16285 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16286 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 16287 // TODO: set VSCR[SAT] 16288 break; 16289 16290 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 16291 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16292 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 16293 // TODO: set VSCR[SAT] 16294 break; 16295 16296 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 16297 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16298 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 16299 // TODO: set VSCR[SAT] 16300 break; 16301 16302 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 16303 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16304 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 16305 // TODO: set VSCR[SAT] 16306 break; 16307 16308 16309 /* Maximum */ 16310 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 16311 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16312 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 16313 break; 16314 16315 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 16316 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16317 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 16318 break; 16319 16320 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 16321 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16322 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 16323 break; 16324 16325 case 0x0C2: // vmaxud (Maximum Unsigned Double word) 16326 DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16327 putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) ); 16328 break; 16329 16330 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 16331 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16332 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 16333 break; 16334 16335 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 16336 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16337 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 16338 break; 16339 16340 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 16341 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16342 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 16343 break; 16344 16345 case 0x1C2: // vmaxsd (Maximum Signed Double word) 16346 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16347 putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) ); 16348 break; 16349 16350 /* Minimum */ 16351 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 16352 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16353 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 16354 break; 16355 16356 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 16357 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16358 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 16359 break; 16360 16361 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 16362 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16363 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 16364 break; 16365 16366 case 0x2C2: // vminud (Minimum Unsigned Double Word) 16367 DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16368 putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) ); 16369 break; 16370 16371 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 16372 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16373 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 16374 break; 16375 16376 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 16377 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16378 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 16379 break; 16380 16381 case 0x382: // vminsw (Minimum Signed Word, AV p190) 16382 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16383 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 16384 break; 16385 16386 case 0x3C2: // vminsd (Minimum Signed Double Word) 16387 DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16388 putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) ); 16389 break; 16390 16391 16392 /* Average */ 16393 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 16394 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16395 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 16396 break; 16397 16398 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 16399 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16400 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 16401 break; 16402 16403 case 0x482: // vavguw (Average Unsigned Word, AV p154) 16404 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16405 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 16406 break; 16407 16408 case 0x502: // vavgsb (Average Signed Byte, AV p149) 16409 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16410 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 16411 break; 16412 16413 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 16414 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16415 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 16416 break; 16417 16418 case 0x582: // vavgsw (Average Signed Word, AV p151) 16419 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16420 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 16421 break; 16422 16423 16424 /* Multiply */ 16425 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 16426 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16427 putVReg( vD_addr, 16428 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 16429 break; 16430 16431 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 16432 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16433 putVReg( vD_addr, 16434 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 16435 break; 16436 16437 case 0x088: // vmulouw (Multiply Odd Unsigned Word) 16438 DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16439 putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) ); 16440 break; 16441 16442 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo) 16443 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16444 putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) ); 16445 break; 16446 16447 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 16448 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16449 putVReg( vD_addr, 16450 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 16451 break; 16452 16453 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 16454 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16455 putVReg( vD_addr, 16456 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 16457 break; 16458 16459 case 0x188: // vmulosw (Multiply Odd Signed Word) 16460 DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16461 putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) ); 16462 break; 16463 16464 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 16465 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16466 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 16467 break; 16468 16469 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 16470 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16471 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 16472 break; 16473 16474 case 0x288: // vmuleuw (Multiply Even Unsigned Word) 16475 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16476 putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) ); 16477 break; 16478 16479 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 16480 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16481 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 16482 break; 16483 16484 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 16485 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16486 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16487 break; 16488 16489 case 0x388: // vmulesw (Multiply Even Signed Word) 16490 DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16491 putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) ); 16492 break; 16493 16494 /* Sum Across Partial */ 16495 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 16496 IRTemp aEE, aEO, aOE, aOO; 16497 aEE = aEO = aOE = aOO = IRTemp_INVALID; 16498 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16499 16500 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 16501 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 16502 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 16503 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 16504 16505 /* break V128 to 4xI32's, zero-extending to I64's */ 16506 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 16507 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 16508 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 16509 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 16510 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16511 16512 /* add lanes */ 16513 assign( z3, binop(Iop_Add64, mkexpr(b3), 16514 binop(Iop_Add64, 16515 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 16516 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 16517 assign( z2, binop(Iop_Add64, mkexpr(b2), 16518 binop(Iop_Add64, 16519 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16520 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16521 assign( z1, binop(Iop_Add64, mkexpr(b1), 16522 binop(Iop_Add64, 16523 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16524 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16525 assign( z0, binop(Iop_Add64, mkexpr(b0), 16526 binop(Iop_Add64, 16527 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16528 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16529 16530 /* saturate-narrow to 32bit, and combine to V128 */ 16531 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 16532 mkexpr(z1), mkexpr(z0)) ); 16533 break; 16534 } 16535 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 16536 IRTemp aEE, aEO, aOE, aOO; 16537 aEE = aEO = aOE = aOO = IRTemp_INVALID; 16538 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16539 16540 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 16541 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 16542 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 16543 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 16544 16545 /* break V128 to 4xI32's, sign-extending to I64's */ 16546 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 16547 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 16548 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 16549 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 16550 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16551 16552 /* add lanes */ 16553 assign( z3, binop(Iop_Add64, mkexpr(b3), 16554 binop(Iop_Add64, 16555 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 16556 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 16557 assign( z2, binop(Iop_Add64, mkexpr(b2), 16558 binop(Iop_Add64, 16559 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16560 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16561 assign( z1, binop(Iop_Add64, mkexpr(b1), 16562 binop(Iop_Add64, 16563 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16564 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16565 assign( z0, binop(Iop_Add64, mkexpr(b0), 16566 binop(Iop_Add64, 16567 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16568 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16569 16570 /* saturate-narrow to 32bit, and combine to V128 */ 16571 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16572 mkexpr(z1), mkexpr(z0)) ); 16573 break; 16574 } 16575 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 16576 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16577 16578 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 16579 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 16580 16581 /* break V128 to 4xI32's, sign-extending to I64's */ 16582 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 16583 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 16584 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16585 16586 /* add lanes */ 16587 assign( z3, binop(Iop_Add64, mkexpr(b3), 16588 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 16589 assign( z2, binop(Iop_Add64, mkexpr(b2), 16590 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 16591 assign( z1, binop(Iop_Add64, mkexpr(b1), 16592 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 16593 assign( z0, binop(Iop_Add64, mkexpr(b0), 16594 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 16595 16596 /* saturate-narrow to 32bit, and combine to V128 */ 16597 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16598 mkexpr(z1), mkexpr(z0)) ); 16599 break; 16600 } 16601 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 16602 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16603 16604 /* break V128 to 4xI32's, sign-extending to I64's */ 16605 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16606 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16607 16608 /* add lanes */ 16609 assign( z2, binop(Iop_Add64, mkexpr(b2), 16610 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 16611 assign( z0, binop(Iop_Add64, mkexpr(b0), 16612 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 16613 16614 /* saturate-narrow to 32bit, and combine to V128 */ 16615 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 16616 mkU64(0), mkexpr(z0)) ); 16617 break; 16618 } 16619 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 16620 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16621 16622 /* break V128 to 4xI32's, sign-extending to I64's */ 16623 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16624 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16625 16626 /* add lanes */ 16627 assign( z0, binop(Iop_Add64, mkexpr(b0), 16628 binop(Iop_Add64, 16629 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16630 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16631 16632 /* saturate-narrow to 32bit, and combine to V128 */ 16633 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 16634 mkU64(0), mkexpr(z0)) ); 16635 break; 16636 } 16637 default: 16638 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 16639 return False; 16640 } 16641 return True; 16642 } 16643 16644 /* 16645 AltiVec Logic Instructions 16646 */ 16647 static Bool dis_av_logic ( UInt theInstr ) 16648 { 16649 /* VX-Form */ 16650 UChar opc1 = ifieldOPC(theInstr); 16651 UChar vD_addr = ifieldRegDS(theInstr); 16652 UChar vA_addr = ifieldRegA(theInstr); 16653 UChar vB_addr = ifieldRegB(theInstr); 16654 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16655 16656 IRTemp vA = newTemp(Ity_V128); 16657 IRTemp vB = newTemp(Ity_V128); 16658 assign( vA, getVReg(vA_addr)); 16659 assign( vB, getVReg(vB_addr)); 16660 16661 if (opc1 != 0x4) { 16662 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 16663 return False; 16664 } 16665 16666 switch (opc2) { 16667 case 0x404: // vand (And, AV p147) 16668 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16669 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 16670 break; 16671 16672 case 0x444: // vandc (And, AV p148) 16673 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16674 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 16675 unop(Iop_NotV128, mkexpr(vB))) ); 16676 break; 16677 16678 case 0x484: // vor (Or, AV p217) 16679 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16680 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 16681 break; 16682 16683 case 0x4C4: // vxor (Xor, AV p282) 16684 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16685 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 16686 break; 16687 16688 case 0x504: // vnor (Nor, AV p216) 16689 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16690 putVReg( vD_addr, 16691 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 16692 break; 16693 16694 case 0x544: // vorc (vA Or'd with complement of vb) 16695 DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16696 putVReg( vD_addr, binop( Iop_OrV128, 16697 mkexpr( vA ), 16698 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 16699 break; 16700 16701 case 0x584: // vnand (Nand) 16702 DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16703 putVReg( vD_addr, unop( Iop_NotV128, 16704 binop(Iop_AndV128, mkexpr( vA ), 16705 mkexpr( vB ) ) ) ); 16706 break; 16707 16708 case 0x684: // veqv (complemented XOr) 16709 DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16710 putVReg( vD_addr, unop( Iop_NotV128, 16711 binop( Iop_XorV128, mkexpr( vA ), 16712 mkexpr( vB ) ) ) ); 16713 break; 16714 16715 default: 16716 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 16717 return False; 16718 } 16719 return True; 16720 } 16721 16722 /* 16723 AltiVec Compare Instructions 16724 */ 16725 static Bool dis_av_cmp ( UInt theInstr ) 16726 { 16727 /* VXR-Form */ 16728 UChar opc1 = ifieldOPC(theInstr); 16729 UChar vD_addr = ifieldRegDS(theInstr); 16730 UChar vA_addr = ifieldRegA(theInstr); 16731 UChar vB_addr = ifieldRegB(theInstr); 16732 UChar flag_rC = ifieldBIT10(theInstr); 16733 UInt opc2 = IFIELD( theInstr, 0, 10 ); 16734 16735 IRTemp vA = newTemp(Ity_V128); 16736 IRTemp vB = newTemp(Ity_V128); 16737 IRTemp vD = newTemp(Ity_V128); 16738 assign( vA, getVReg(vA_addr)); 16739 assign( vB, getVReg(vB_addr)); 16740 16741 if (opc1 != 0x4) { 16742 vex_printf("dis_av_cmp(ppc)(instr)\n"); 16743 return False; 16744 } 16745 16746 switch (opc2) { 16747 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 16748 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16749 vD_addr, vA_addr, vB_addr); 16750 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 16751 break; 16752 16753 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 16754 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16755 vD_addr, vA_addr, vB_addr); 16756 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 16757 break; 16758 16759 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 16760 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16761 vD_addr, vA_addr, vB_addr); 16762 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 16763 break; 16764 16765 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword) 16766 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16767 vD_addr, vA_addr, vB_addr); 16768 assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) ); 16769 break; 16770 16771 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 16772 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16773 vD_addr, vA_addr, vB_addr); 16774 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 16775 break; 16776 16777 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 16778 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16779 vD_addr, vA_addr, vB_addr); 16780 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 16781 break; 16782 16783 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 16784 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16785 vD_addr, vA_addr, vB_addr); 16786 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 16787 break; 16788 16789 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double) 16790 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16791 vD_addr, vA_addr, vB_addr); 16792 assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) ); 16793 break; 16794 16795 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 16796 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16797 vD_addr, vA_addr, vB_addr); 16798 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 16799 break; 16800 16801 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 16802 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16803 vD_addr, vA_addr, vB_addr); 16804 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 16805 break; 16806 16807 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 16808 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16809 vD_addr, vA_addr, vB_addr); 16810 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 16811 break; 16812 16813 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double) 16814 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16815 vD_addr, vA_addr, vB_addr); 16816 assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) ); 16817 break; 16818 16819 default: 16820 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 16821 return False; 16822 } 16823 16824 putVReg( vD_addr, mkexpr(vD) ); 16825 16826 if (flag_rC) { 16827 set_AV_CR6( mkexpr(vD), True ); 16828 } 16829 return True; 16830 } 16831 16832 /* 16833 AltiVec Multiply-Sum Instructions 16834 */ 16835 static Bool dis_av_multarith ( UInt theInstr ) 16836 { 16837 /* VA-Form */ 16838 UChar opc1 = ifieldOPC(theInstr); 16839 UChar vD_addr = ifieldRegDS(theInstr); 16840 UChar vA_addr = ifieldRegA(theInstr); 16841 UChar vB_addr = ifieldRegB(theInstr); 16842 UChar vC_addr = ifieldRegC(theInstr); 16843 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 16844 16845 IRTemp vA = newTemp(Ity_V128); 16846 IRTemp vB = newTemp(Ity_V128); 16847 IRTemp vC = newTemp(Ity_V128); 16848 IRTemp zeros = newTemp(Ity_V128); 16849 IRTemp aLo = newTemp(Ity_V128); 16850 IRTemp bLo = newTemp(Ity_V128); 16851 IRTemp cLo = newTemp(Ity_V128); 16852 IRTemp zLo = newTemp(Ity_V128); 16853 IRTemp aHi = newTemp(Ity_V128); 16854 IRTemp bHi = newTemp(Ity_V128); 16855 IRTemp cHi = newTemp(Ity_V128); 16856 IRTemp zHi = newTemp(Ity_V128); 16857 IRTemp abEvn = newTemp(Ity_V128); 16858 IRTemp abOdd = newTemp(Ity_V128); 16859 IRTemp z3 = newTemp(Ity_I64); 16860 IRTemp z2 = newTemp(Ity_I64); 16861 IRTemp z1 = newTemp(Ity_I64); 16862 IRTemp z0 = newTemp(Ity_I64); 16863 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 16864 IRTemp c3, c2, c1, c0; 16865 16866 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 16867 c3 = c2 = c1 = c0 = IRTemp_INVALID; 16868 16869 assign( vA, getVReg(vA_addr)); 16870 assign( vB, getVReg(vB_addr)); 16871 assign( vC, getVReg(vC_addr)); 16872 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 16873 16874 if (opc1 != 0x4) { 16875 vex_printf("dis_av_multarith(ppc)(instr)\n"); 16876 return False; 16877 } 16878 16879 switch (opc2) { 16880 /* Multiply-Add */ 16881 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 16882 IRTemp cSigns = newTemp(Ity_V128); 16883 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 16884 vD_addr, vA_addr, vB_addr, vC_addr); 16885 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 16886 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16887 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16888 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16889 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16890 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16891 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16892 16893 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16894 binop(Iop_SarN32x4, 16895 binop(Iop_MullEven16Sx8, 16896 mkexpr(aLo), mkexpr(bLo)), 16897 mkU8(15))) ); 16898 16899 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16900 binop(Iop_SarN32x4, 16901 binop(Iop_MullEven16Sx8, 16902 mkexpr(aHi), mkexpr(bHi)), 16903 mkU8(15))) ); 16904 16905 putVReg( vD_addr, 16906 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16907 break; 16908 } 16909 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 16910 IRTemp zKonst = newTemp(Ity_V128); 16911 IRTemp cSigns = newTemp(Ity_V128); 16912 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 16913 vD_addr, vA_addr, vB_addr, vC_addr); 16914 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 16915 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16916 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16917 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16918 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16919 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16920 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16921 16922 /* shifting our const avoids store/load version of Dup */ 16923 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 16924 mkU8(14)) ); 16925 16926 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16927 binop(Iop_SarN32x4, 16928 binop(Iop_Add32x4, mkexpr(zKonst), 16929 binop(Iop_MullEven16Sx8, 16930 mkexpr(aLo), mkexpr(bLo))), 16931 mkU8(15))) ); 16932 16933 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16934 binop(Iop_SarN32x4, 16935 binop(Iop_Add32x4, mkexpr(zKonst), 16936 binop(Iop_MullEven16Sx8, 16937 mkexpr(aHi), mkexpr(bHi))), 16938 mkU8(15))) ); 16939 16940 putVReg( vD_addr, 16941 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16942 break; 16943 } 16944 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 16945 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 16946 vD_addr, vA_addr, vB_addr, vC_addr); 16947 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16948 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16949 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 16950 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16951 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16952 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 16953 assign(zLo, binop(Iop_Add32x4, 16954 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 16955 mkexpr(cLo)) ); 16956 assign(zHi, binop(Iop_Add32x4, 16957 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 16958 mkexpr(cHi))); 16959 putVReg( vD_addr, 16960 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 16961 break; 16962 } 16963 16964 16965 /* Multiply-Sum */ 16966 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 16967 IRTemp abEE, abEO, abOE, abOO; 16968 abEE = abEO = abOE = abOO = IRTemp_INVALID; 16969 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 16970 vD_addr, vA_addr, vB_addr, vC_addr); 16971 16972 /* multiply vA,vB (unsigned, widening) */ 16973 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 16974 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 16975 16976 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 16977 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 16978 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 16979 16980 putVReg( vD_addr, 16981 binop(Iop_Add32x4, mkexpr(vC), 16982 binop(Iop_Add32x4, 16983 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 16984 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 16985 break; 16986 } 16987 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 16988 IRTemp aEvn, aOdd, bEvn, bOdd; 16989 IRTemp abEE = newTemp(Ity_V128); 16990 IRTemp abEO = newTemp(Ity_V128); 16991 IRTemp abOE = newTemp(Ity_V128); 16992 IRTemp abOO = newTemp(Ity_V128); 16993 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 16994 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 16995 vD_addr, vA_addr, vB_addr, vC_addr); 16996 16997 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 16998 (separating out adjacent lanes to different vectors) */ 16999 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 17000 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 17001 17002 /* multiply vA, vB, again separating adjacent lanes */ 17003 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 17004 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 17005 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 17006 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 17007 17008 /* add results together, + vC */ 17009 putVReg( vD_addr, 17010 binop(Iop_QAdd32Sx4, mkexpr(vC), 17011 binop(Iop_QAdd32Sx4, 17012 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 17013 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 17014 break; 17015 } 17016 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 17017 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 17018 vD_addr, vA_addr, vB_addr, vC_addr); 17019 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 17020 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 17021 putVReg( vD_addr, 17022 binop(Iop_Add32x4, mkexpr(vC), 17023 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 17024 break; 17025 } 17026 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 17027 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 17028 vD_addr, vA_addr, vB_addr, vC_addr); 17029 /* widening multiply, separating lanes */ 17030 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 17031 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 17032 17033 /* break V128 to 4xI32's, zero-extending to I64's */ 17034 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 17035 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 17036 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 17037 17038 /* add lanes */ 17039 assign( z3, binop(Iop_Add64, mkexpr(c3), 17040 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 17041 assign( z2, binop(Iop_Add64, mkexpr(c2), 17042 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 17043 assign( z1, binop(Iop_Add64, mkexpr(c1), 17044 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 17045 assign( z0, binop(Iop_Add64, mkexpr(c0), 17046 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 17047 17048 /* saturate-narrow to 32bit, and combine to V128 */ 17049 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 17050 mkexpr(z1), mkexpr(z0)) ); 17051 17052 break; 17053 } 17054 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 17055 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 17056 vD_addr, vA_addr, vB_addr, vC_addr); 17057 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 17058 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 17059 putVReg( vD_addr, 17060 binop(Iop_Add32x4, mkexpr(vC), 17061 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 17062 break; 17063 } 17064 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 17065 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 17066 vD_addr, vA_addr, vB_addr, vC_addr); 17067 /* widening multiply, separating lanes */ 17068 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 17069 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 17070 17071 /* break V128 to 4xI32's, sign-extending to I64's */ 17072 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 17073 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 17074 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 17075 17076 /* add lanes */ 17077 assign( z3, binop(Iop_Add64, mkexpr(c3), 17078 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 17079 assign( z2, binop(Iop_Add64, mkexpr(c2), 17080 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 17081 assign( z1, binop(Iop_Add64, mkexpr(c1), 17082 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 17083 assign( z0, binop(Iop_Add64, mkexpr(c0), 17084 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 17085 17086 /* saturate-narrow to 32bit, and combine to V128 */ 17087 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 17088 mkexpr(z1), mkexpr(z0)) ); 17089 break; 17090 } 17091 default: 17092 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 17093 return False; 17094 } 17095 return True; 17096 } 17097 17098 /* 17099 AltiVec Polynomial Multiply-Sum Instructions 17100 */ 17101 static Bool dis_av_polymultarith ( UInt theInstr ) 17102 { 17103 /* VA-Form */ 17104 UChar opc1 = ifieldOPC(theInstr); 17105 UChar vD_addr = ifieldRegDS(theInstr); 17106 UChar vA_addr = ifieldRegA(theInstr); 17107 UChar vB_addr = ifieldRegB(theInstr); 17108 UChar vC_addr = ifieldRegC(theInstr); 17109 UInt opc2 = IFIELD(theInstr, 0, 11); 17110 IRTemp vA = newTemp(Ity_V128); 17111 IRTemp vB = newTemp(Ity_V128); 17112 IRTemp vC = newTemp(Ity_V128); 17113 17114 assign( vA, getVReg(vA_addr)); 17115 assign( vB, getVReg(vB_addr)); 17116 assign( vC, getVReg(vC_addr)); 17117 17118 if (opc1 != 0x4) { 17119 vex_printf("dis_av_polymultarith(ppc)(instr)\n"); 17120 return False; 17121 } 17122 17123 switch (opc2) { 17124 /* Polynomial Multiply-Add */ 17125 case 0x408: // vpmsumb Vector Polynomial Multipy-sum Byte 17126 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17127 putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16, 17128 mkexpr(vA), mkexpr(vB)) ); 17129 break; 17130 case 0x448: // vpmsumd Vector Polynomial Multipy-sum Double Word 17131 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17132 putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2, 17133 mkexpr(vA), mkexpr(vB)) ); 17134 break; 17135 case 0x488: // vpmsumw Vector Polynomial Multipy-sum Word 17136 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17137 putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4, 17138 mkexpr(vA), mkexpr(vB)) ); 17139 break; 17140 case 0x4C8: // vpmsumh Vector Polynomial Multipy-sum Half Word 17141 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17142 putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8, 17143 mkexpr(vA), mkexpr(vB)) ); 17144 break; 17145 default: 17146 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2); 17147 return False; 17148 } 17149 return True; 17150 } 17151 17152 /* 17153 AltiVec Shift/Rotate Instructions 17154 */ 17155 static Bool dis_av_shift ( UInt theInstr ) 17156 { 17157 /* VX-Form */ 17158 UChar opc1 = ifieldOPC(theInstr); 17159 UChar vD_addr = ifieldRegDS(theInstr); 17160 UChar vA_addr = ifieldRegA(theInstr); 17161 UChar vB_addr = ifieldRegB(theInstr); 17162 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17163 17164 IRTemp vA = newTemp(Ity_V128); 17165 IRTemp vB = newTemp(Ity_V128); 17166 assign( vA, getVReg(vA_addr)); 17167 assign( vB, getVReg(vB_addr)); 17168 17169 if (opc1 != 0x4){ 17170 vex_printf("dis_av_shift(ppc)(instr)\n"); 17171 return False; 17172 } 17173 17174 switch (opc2) { 17175 /* Rotate */ 17176 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 17177 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17178 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 17179 break; 17180 17181 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 17182 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17183 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 17184 break; 17185 17186 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 17187 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17188 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 17189 break; 17190 17191 case 0x0C4: // vrld (Rotate Left Integer Double Word) 17192 DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17193 putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) ); 17194 break; 17195 17196 17197 /* Shift Left */ 17198 case 0x104: // vslb (Shift Left Integer B, AV p240) 17199 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17200 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 17201 break; 17202 17203 case 0x144: // vslh (Shift Left Integer HW, AV p242) 17204 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17205 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 17206 break; 17207 17208 case 0x184: // vslw (Shift Left Integer W, AV p244) 17209 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17210 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 17211 break; 17212 17213 case 0x5C4: // vsld (Shift Left Integer Double Word) 17214 DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17215 putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) ); 17216 break; 17217 17218 case 0x1C4: { // vsl (Shift Left, AV p239) 17219 IRTemp sh = newTemp(Ity_I8); 17220 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17221 assign( sh, binop(Iop_And8, mkU8(0x7), 17222 unop(Iop_32to8, 17223 unop(Iop_V128to32, mkexpr(vB)))) ); 17224 putVReg( vD_addr, 17225 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 17226 break; 17227 } 17228 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 17229 IRTemp sh = newTemp(Ity_I8); 17230 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17231 assign( sh, binop(Iop_And8, mkU8(0x78), 17232 unop(Iop_32to8, 17233 unop(Iop_V128to32, mkexpr(vB)))) ); 17234 putVReg( vD_addr, 17235 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 17236 break; 17237 } 17238 17239 17240 /* Shift Right */ 17241 case 0x204: // vsrb (Shift Right B, AV p256) 17242 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17243 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 17244 break; 17245 17246 case 0x244: // vsrh (Shift Right HW, AV p257) 17247 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17248 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 17249 break; 17250 17251 case 0x284: // vsrw (Shift Right W, AV p259) 17252 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17253 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 17254 break; 17255 17256 case 0x2C4: { // vsr (Shift Right, AV p251) 17257 IRTemp sh = newTemp(Ity_I8); 17258 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17259 assign( sh, binop(Iop_And8, mkU8(0x7), 17260 unop(Iop_32to8, 17261 unop(Iop_V128to32, mkexpr(vB)))) ); 17262 putVReg( vD_addr, 17263 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 17264 break; 17265 } 17266 case 0x304: // vsrab (Shift Right Alg B, AV p253) 17267 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17268 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 17269 break; 17270 17271 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 17272 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17273 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 17274 break; 17275 17276 case 0x384: // vsraw (Shift Right Alg W, AV p255) 17277 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17278 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 17279 break; 17280 17281 case 0x3C4: // vsrad (Shift Right Alg Double Word) 17282 DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17283 putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) ); 17284 break; 17285 17286 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 17287 IRTemp sh = newTemp(Ity_I8); 17288 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17289 assign( sh, binop(Iop_And8, mkU8(0x78), 17290 unop(Iop_32to8, 17291 unop(Iop_V128to32, mkexpr(vB)))) ); 17292 putVReg( vD_addr, 17293 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 17294 break; 17295 } 17296 17297 case 0x6C4: // vsrd (Shift Right Double Word) 17298 DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17299 putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) ); 17300 break; 17301 17302 17303 default: 17304 vex_printf("dis_av_shift(ppc)(opc2)\n"); 17305 return False; 17306 } 17307 return True; 17308 } 17309 17310 /* 17311 AltiVec Permute Instructions 17312 */ 17313 static Bool dis_av_permute ( UInt theInstr ) 17314 { 17315 /* VA-Form, VX-Form */ 17316 UChar opc1 = ifieldOPC(theInstr); 17317 UChar vD_addr = ifieldRegDS(theInstr); 17318 UChar vA_addr = ifieldRegA(theInstr); 17319 UChar UIMM_5 = vA_addr; 17320 UChar vB_addr = ifieldRegB(theInstr); 17321 UChar vC_addr = ifieldRegC(theInstr); 17322 UChar b10 = ifieldBIT10(theInstr); 17323 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 17324 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 17325 17326 UChar SIMM_8 = extend_s_5to8(UIMM_5); 17327 17328 IRTemp vA = newTemp(Ity_V128); 17329 IRTemp vB = newTemp(Ity_V128); 17330 IRTemp vC = newTemp(Ity_V128); 17331 assign( vA, getVReg(vA_addr)); 17332 assign( vB, getVReg(vB_addr)); 17333 assign( vC, getVReg(vC_addr)); 17334 17335 if (opc1 != 0x4) { 17336 vex_printf("dis_av_permute(ppc)(instr)\n"); 17337 return False; 17338 } 17339 17340 switch (opc2) { 17341 case 0x2A: // vsel (Conditional Select, AV p238) 17342 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 17343 /* vD = (vA & ~vC) | (vB & vC) */ 17344 putVReg( vD_addr, binop(Iop_OrV128, 17345 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 17346 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 17347 return True; 17348 17349 case 0x2B: { // vperm (Permute, AV p218) 17350 /* limited to two args for IR, so have to play games... */ 17351 IRTemp a_perm = newTemp(Ity_V128); 17352 IRTemp b_perm = newTemp(Ity_V128); 17353 IRTemp mask = newTemp(Ity_V128); 17354 IRTemp vC_andF = newTemp(Ity_V128); 17355 DIP("vperm v%d,v%d,v%d,v%d\n", 17356 vD_addr, vA_addr, vB_addr, vC_addr); 17357 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 17358 IR specifies, and also to hide irrelevant bits from 17359 memcheck */ 17360 assign( vC_andF, 17361 binop(Iop_AndV128, mkexpr(vC), 17362 unop(Iop_Dup8x16, mkU8(0xF))) ); 17363 assign( a_perm, 17364 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 17365 assign( b_perm, 17366 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 17367 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 17368 assign( mask, binop(Iop_SarN8x16, 17369 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 17370 mkU8(7)) ); 17371 // dst = (a & ~mask) | (b & mask) 17372 putVReg( vD_addr, binop(Iop_OrV128, 17373 binop(Iop_AndV128, mkexpr(a_perm), 17374 unop(Iop_NotV128, mkexpr(mask))), 17375 binop(Iop_AndV128, mkexpr(b_perm), 17376 mkexpr(mask))) ); 17377 return True; 17378 } 17379 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 17380 if (b10 != 0) { 17381 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 17382 return False; 17383 } 17384 DIP("vsldoi v%d,v%d,v%d,%d\n", 17385 vD_addr, vA_addr, vB_addr, SHB_uimm4); 17386 if (SHB_uimm4 == 0) 17387 putVReg( vD_addr, mkexpr(vA) ); 17388 else 17389 putVReg( vD_addr, 17390 binop(Iop_OrV128, 17391 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 17392 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 17393 return True; 17394 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR) 17395 IRTemp a_perm = newTemp(Ity_V128); 17396 IRTemp b_perm = newTemp(Ity_V128); 17397 IRTemp vrc_a = newTemp(Ity_V128); 17398 IRTemp vrc_b = newTemp(Ity_V128); 17399 17400 /* IBM index is 0:7, Change index value to index 7:0 */ 17401 assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ), 17402 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) ); 17403 assign( vrc_a, binop( Iop_ShrV128, 17404 binop( Iop_AndV128, mkexpr( vC ), 17405 unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ), 17406 mkU8 ( 4 ) ) ); 17407 assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) ); 17408 assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) ); 17409 putVReg( vD_addr, binop( Iop_XorV128, 17410 mkexpr( a_perm ), mkexpr( b_perm) ) ); 17411 return True; 17412 } 17413 default: 17414 break; // Fall through... 17415 } 17416 17417 opc2 = IFIELD( theInstr, 0, 11 ); 17418 switch (opc2) { 17419 17420 /* Merge */ 17421 case 0x00C: // vmrghb (Merge High B, AV p195) 17422 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17423 putVReg( vD_addr, 17424 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 17425 break; 17426 17427 case 0x04C: // vmrghh (Merge High HW, AV p196) 17428 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17429 putVReg( vD_addr, 17430 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 17431 break; 17432 17433 case 0x08C: // vmrghw (Merge High W, AV p197) 17434 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17435 putVReg( vD_addr, 17436 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 17437 break; 17438 17439 case 0x10C: // vmrglb (Merge Low B, AV p198) 17440 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17441 putVReg( vD_addr, 17442 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 17443 break; 17444 17445 case 0x14C: // vmrglh (Merge Low HW, AV p199) 17446 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17447 putVReg( vD_addr, 17448 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 17449 break; 17450 17451 case 0x18C: // vmrglw (Merge Low W, AV p200) 17452 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17453 putVReg( vD_addr, 17454 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 17455 break; 17456 17457 17458 /* Splat */ 17459 case 0x20C: { // vspltb (Splat Byte, AV p245) 17460 /* vD = Dup8x16( vB[UIMM_5] ) */ 17461 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 17462 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17463 putVReg( vD_addr, unop(Iop_Dup8x16, 17464 unop(Iop_32to8, unop(Iop_V128to32, 17465 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 17466 break; 17467 } 17468 case 0x24C: { // vsplth (Splat Half Word, AV p246) 17469 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 17470 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17471 putVReg( vD_addr, unop(Iop_Dup16x8, 17472 unop(Iop_32to16, unop(Iop_V128to32, 17473 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 17474 break; 17475 } 17476 case 0x28C: { // vspltw (Splat Word, AV p250) 17477 /* vD = Dup32x4( vB[UIMM_5] ) */ 17478 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 17479 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 17480 putVReg( vD_addr, unop(Iop_Dup32x4, 17481 unop(Iop_V128to32, 17482 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 17483 break; 17484 } 17485 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 17486 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 17487 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 17488 break; 17489 17490 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 17491 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 17492 putVReg( vD_addr, 17493 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 17494 break; 17495 17496 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 17497 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 17498 putVReg( vD_addr, 17499 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 17500 break; 17501 17502 case 0x68C: // vmrgow (Merge Odd Word) 17503 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17504 /* VD[0] <- VA[1] 17505 VD[1] <- VB[1] 17506 VD[2] <- VA[3] 17507 VD[3] <- VB[3] 17508 */ 17509 putVReg( vD_addr, 17510 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 17511 break; 17512 17513 case 0x78C: // vmrgew (Merge Even Word) 17514 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17515 /* VD[0] <- VA[0] 17516 VD[1] <- VB[0] 17517 VD[2] <- VA[2] 17518 VD[3] <- VB[2] 17519 */ 17520 putVReg( vD_addr, 17521 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 17522 break; 17523 17524 default: 17525 vex_printf("dis_av_permute(ppc)(opc2)\n"); 17526 return False; 17527 } 17528 return True; 17529 } 17530 17531 /* 17532 AltiVec Pack/Unpack Instructions 17533 */ 17534 static Bool dis_av_pack ( UInt theInstr ) 17535 { 17536 /* VX-Form */ 17537 UChar opc1 = ifieldOPC(theInstr); 17538 UChar vD_addr = ifieldRegDS(theInstr); 17539 UChar vA_addr = ifieldRegA(theInstr); 17540 UChar vB_addr = ifieldRegB(theInstr); 17541 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17542 17543 IRTemp signs = IRTemp_INVALID; 17544 IRTemp zeros = IRTemp_INVALID; 17545 IRTemp vA = newTemp(Ity_V128); 17546 IRTemp vB = newTemp(Ity_V128); 17547 assign( vA, getVReg(vA_addr)); 17548 assign( vB, getVReg(vB_addr)); 17549 17550 if (opc1 != 0x4) { 17551 vex_printf("dis_av_pack(ppc)(instr)\n"); 17552 return False; 17553 } 17554 switch (opc2) { 17555 /* Packing */ 17556 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 17557 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17558 putVReg( vD_addr, 17559 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 17560 return True; 17561 17562 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 17563 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17564 putVReg( vD_addr, 17565 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 17566 return True; 17567 17568 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 17569 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17570 putVReg( vD_addr, 17571 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 17572 // TODO: set VSCR[SAT] 17573 return True; 17574 17575 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 17576 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17577 putVReg( vD_addr, 17578 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 17579 // TODO: set VSCR[SAT] 17580 return True; 17581 17582 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 17583 // This insn does a signed->unsigned saturating conversion. 17584 // Conversion done here, then uses unsigned->unsigned vpk insn: 17585 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 17586 IRTemp vA_tmp = newTemp(Ity_V128); 17587 IRTemp vB_tmp = newTemp(Ity_V128); 17588 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17589 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17590 unop(Iop_NotV128, 17591 binop(Iop_SarN16x8, 17592 mkexpr(vA), mkU8(15)))) ); 17593 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17594 unop(Iop_NotV128, 17595 binop(Iop_SarN16x8, 17596 mkexpr(vB), mkU8(15)))) ); 17597 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 17598 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17599 // TODO: set VSCR[SAT] 17600 return True; 17601 } 17602 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 17603 // This insn does a signed->unsigned saturating conversion. 17604 // Conversion done here, then uses unsigned->unsigned vpk insn: 17605 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17606 IRTemp vA_tmp = newTemp(Ity_V128); 17607 IRTemp vB_tmp = newTemp(Ity_V128); 17608 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17609 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17610 unop(Iop_NotV128, 17611 binop(Iop_SarN32x4, 17612 mkexpr(vA), mkU8(31)))) ); 17613 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17614 unop(Iop_NotV128, 17615 binop(Iop_SarN32x4, 17616 mkexpr(vB), mkU8(31)))) ); 17617 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 17618 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17619 // TODO: set VSCR[SAT] 17620 return True; 17621 } 17622 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 17623 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17624 putVReg( vD_addr, 17625 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 17626 // TODO: set VSCR[SAT] 17627 return True; 17628 17629 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 17630 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17631 putVReg( vD_addr, 17632 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 17633 // TODO: set VSCR[SAT] 17634 return True; 17635 17636 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 17637 /* CAB: Worth a new primop? */ 17638 /* Using shifts to compact pixel elements, then packing them */ 17639 IRTemp a1 = newTemp(Ity_V128); 17640 IRTemp a2 = newTemp(Ity_V128); 17641 IRTemp a3 = newTemp(Ity_V128); 17642 IRTemp a_tmp = newTemp(Ity_V128); 17643 IRTemp b1 = newTemp(Ity_V128); 17644 IRTemp b2 = newTemp(Ity_V128); 17645 IRTemp b3 = newTemp(Ity_V128); 17646 IRTemp b_tmp = newTemp(Ity_V128); 17647 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17648 assign( a1, binop(Iop_ShlN16x8, 17649 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 17650 mkU8(10)) ); 17651 assign( a2, binop(Iop_ShlN16x8, 17652 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 17653 mkU8(5)) ); 17654 assign( a3, binop(Iop_ShrN16x8, 17655 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 17656 mkU8(11)) ); 17657 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 17658 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 17659 17660 assign( b1, binop(Iop_ShlN16x8, 17661 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 17662 mkU8(10)) ); 17663 assign( b2, binop(Iop_ShlN16x8, 17664 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 17665 mkU8(5)) ); 17666 assign( b3, binop(Iop_ShrN16x8, 17667 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 17668 mkU8(11)) ); 17669 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 17670 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 17671 17672 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 17673 mkexpr(a_tmp), mkexpr(b_tmp)) ); 17674 return True; 17675 } 17676 17677 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo) 17678 DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17679 putVReg( vD_addr, 17680 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) ); 17681 return True; 17682 17683 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate) 17684 DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17685 putVReg( vD_addr, 17686 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) ); 17687 // TODO: set VSCR[SAT] 17688 return True; 17689 17690 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate) 17691 // This insn does a doubled signed->double unsigned saturating conversion 17692 // Conversion done here, then uses unsigned->unsigned vpk insn: 17693 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17694 // This is similar to the technique used for vpkswus, except done 17695 // with double word integers versus word integers. 17696 IRTemp vA_tmp = newTemp(Ity_V128); 17697 IRTemp vB_tmp = newTemp(Ity_V128); 17698 DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17699 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17700 unop(Iop_NotV128, 17701 binop(Iop_SarN64x2, 17702 mkexpr(vA), mkU8(63)))) ); 17703 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17704 unop(Iop_NotV128, 17705 binop(Iop_SarN64x2, 17706 mkexpr(vB), mkU8(63)))) ); 17707 putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4, 17708 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17709 // TODO: set VSCR[SAT] 17710 return True; 17711 } 17712 17713 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate) 17714 DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17715 putVReg( vD_addr, 17716 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) ); 17717 // TODO: set VSCR[SAT] 17718 return True; 17719 default: 17720 break; // Fall through... 17721 } 17722 17723 17724 if (vA_addr != 0) { 17725 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 17726 return False; 17727 } 17728 17729 signs = newTemp(Ity_V128); 17730 zeros = newTemp(Ity_V128); 17731 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 17732 17733 switch (opc2) { 17734 /* Unpacking */ 17735 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 17736 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 17737 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17738 putVReg( vD_addr, 17739 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 17740 break; 17741 } 17742 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 17743 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 17744 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17745 putVReg( vD_addr, 17746 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 17747 break; 17748 } 17749 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 17750 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 17751 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17752 putVReg( vD_addr, 17753 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 17754 break; 17755 } 17756 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 17757 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 17758 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17759 putVReg( vD_addr, 17760 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 17761 break; 17762 } 17763 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 17764 /* CAB: Worth a new primop? */ 17765 /* Using shifts to isolate pixel elements, then expanding them */ 17766 IRTemp z0 = newTemp(Ity_V128); 17767 IRTemp z1 = newTemp(Ity_V128); 17768 IRTemp z01 = newTemp(Ity_V128); 17769 IRTemp z2 = newTemp(Ity_V128); 17770 IRTemp z3 = newTemp(Ity_V128); 17771 IRTemp z23 = newTemp(Ity_V128); 17772 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 17773 assign( z0, binop(Iop_ShlN16x8, 17774 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17775 mkU8(8)) ); 17776 assign( z1, binop(Iop_ShrN16x8, 17777 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17778 mkU8(11)) ); 17779 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17780 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17781 assign( z2, binop(Iop_ShrN16x8, 17782 binop(Iop_ShlN16x8, 17783 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17784 mkU8(11)), 17785 mkU8(3)) ); 17786 assign( z3, binop(Iop_ShrN16x8, 17787 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17788 mkU8(11)) ); 17789 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17790 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17791 putVReg( vD_addr, 17792 binop(Iop_OrV128, 17793 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17794 mkexpr(z23)) ); 17795 break; 17796 } 17797 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 17798 /* identical to vupkhpx, except interleaving LO */ 17799 IRTemp z0 = newTemp(Ity_V128); 17800 IRTemp z1 = newTemp(Ity_V128); 17801 IRTemp z01 = newTemp(Ity_V128); 17802 IRTemp z2 = newTemp(Ity_V128); 17803 IRTemp z3 = newTemp(Ity_V128); 17804 IRTemp z23 = newTemp(Ity_V128); 17805 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 17806 assign( z0, binop(Iop_ShlN16x8, 17807 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17808 mkU8(8)) ); 17809 assign( z1, binop(Iop_ShrN16x8, 17810 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17811 mkU8(11)) ); 17812 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17813 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17814 assign( z2, binop(Iop_ShrN16x8, 17815 binop(Iop_ShlN16x8, 17816 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17817 mkU8(11)), 17818 mkU8(3)) ); 17819 assign( z3, binop(Iop_ShrN16x8, 17820 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17821 mkU8(11)) ); 17822 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17823 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17824 putVReg( vD_addr, 17825 binop(Iop_OrV128, 17826 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17827 mkexpr(z23)) ); 17828 break; 17829 } 17830 case 0x64E: { // vupkhsw (Unpack High Signed Word) 17831 DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr); 17832 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17833 putVReg( vD_addr, 17834 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) ); 17835 break; 17836 } 17837 case 0x6CE: { // vupklsw (Unpack Low Signed Word) 17838 DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr); 17839 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17840 putVReg( vD_addr, 17841 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) ); 17842 break; 17843 } 17844 default: 17845 vex_printf("dis_av_pack(ppc)(opc2)\n"); 17846 return False; 17847 } 17848 return True; 17849 } 17850 17851 /* 17852 AltiVec Cipher Instructions 17853 */ 17854 static Bool dis_av_cipher ( UInt theInstr ) 17855 { 17856 /* VX-Form */ 17857 UChar opc1 = ifieldOPC(theInstr); 17858 UChar vD_addr = ifieldRegDS(theInstr); 17859 UChar vA_addr = ifieldRegA(theInstr); 17860 UChar vB_addr = ifieldRegB(theInstr); 17861 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17862 17863 IRTemp vA = newTemp(Ity_V128); 17864 IRTemp vB = newTemp(Ity_V128); 17865 assign( vA, getVReg(vA_addr)); 17866 assign( vB, getVReg(vB_addr)); 17867 17868 if (opc1 != 0x4) { 17869 vex_printf("dis_av_cipher(ppc)(instr)\n"); 17870 return False; 17871 } 17872 switch (opc2) { 17873 case 0x508: // vcipher (Vector Inverser Cipher) 17874 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17875 putVReg( vD_addr, 17876 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) ); 17877 return True; 17878 17879 case 0x509: // vcipherlast (Vector Inverser Cipher Last) 17880 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17881 putVReg( vD_addr, 17882 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) ); 17883 return True; 17884 17885 case 0x548: // vncipher (Vector Inverser Cipher) 17886 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17887 putVReg( vD_addr, 17888 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) ); 17889 return True; 17890 17891 case 0x549: // vncipherlast (Vector Inverser Cipher Last) 17892 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17893 putVReg( vD_addr, 17894 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) ); 17895 return True; 17896 17897 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher 17898 * subBytes transform) 17899 */ 17900 DIP("vsbox v%d,v%d\n", vD_addr, vA_addr); 17901 putVReg( vD_addr, 17902 unop(Iop_CipherSV128, mkexpr(vA) ) ); 17903 return True; 17904 17905 default: 17906 vex_printf("dis_av_cipher(ppc)(opc2)\n"); 17907 return False; 17908 } 17909 return True; 17910 } 17911 17912 /* 17913 AltiVec Secure Hash Instructions 17914 */ 17915 static Bool dis_av_hash ( UInt theInstr ) 17916 { 17917 /* VX-Form */ 17918 UChar opc1 = ifieldOPC(theInstr); 17919 UChar vRT_addr = ifieldRegDS(theInstr); 17920 UChar vRA_addr = ifieldRegA(theInstr); 17921 UChar s_field = IFIELD( theInstr, 11, 5 ); // st and six field 17922 UChar st = IFIELD( theInstr, 15, 1 ); // st 17923 UChar six = IFIELD( theInstr, 11, 4 ); // six field 17924 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17925 17926 IRTemp vA = newTemp(Ity_V128); 17927 IRTemp dst = newTemp(Ity_V128); 17928 assign( vA, getVReg(vRA_addr)); 17929 17930 if (opc1 != 0x4) { 17931 vex_printf("dis_av_hash(ppc)(instr)\n"); 17932 return False; 17933 } 17934 17935 switch (opc2) { 17936 case 0x682: // vshasigmaw 17937 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17938 assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) ); 17939 putVReg( vRT_addr, mkexpr(dst)); 17940 return True; 17941 17942 case 0x6C2: // vshasigmad, 17943 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17944 putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) ); 17945 return True; 17946 17947 default: 17948 vex_printf("dis_av_hash(ppc)(opc2)\n"); 17949 return False; 17950 } 17951 return True; 17952 } 17953 17954 /* 17955 * This function is used by the Vector add/subtract [extended] modulo/carry 17956 * instructions. 17957 * - For the non-extended add instructions, the cin arg is set to zero. 17958 * - For the extended add instructions, cin is the integer value of 17959 * src3.bit[127]. 17960 * - For the non-extended subtract instructions, src1 is added to the one's 17961 * complement of src2 + 1. We re-use the cin argument to hold the '1' 17962 * value for this operation. 17963 * - For the extended subtract instructions, cin is the integer value of src3.bit[127]. 17964 */ 17965 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB, 17966 IRExpr * cin, Bool modulo) 17967 { 17968 IRTemp _vecA_32 = IRTemp_INVALID; 17969 IRTemp _vecB_32 = IRTemp_INVALID; 17970 IRTemp res_32 = IRTemp_INVALID; 17971 IRTemp result = IRTemp_INVALID; 17972 IRTemp tmp_result = IRTemp_INVALID; 17973 IRTemp carry = IRTemp_INVALID; 17974 Int i; 17975 IRExpr * _vecA_low64 = unop( Iop_V128to64, vecA ); 17976 IRExpr * _vecB_low64 = unop( Iop_V128to64, vecB ); 17977 IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA ); 17978 IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB ); 17979 17980 for (i = 0; i < 4; i++) { 17981 _vecA_32 = newTemp(Ity_I32); 17982 _vecB_32 = newTemp(Ity_I32); 17983 res_32 = newTemp(Ity_I32); 17984 switch (i) { 17985 case 0: 17986 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) ); 17987 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) ); 17988 break; 17989 case 1: 17990 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) ); 17991 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) ); 17992 break; 17993 case 2: 17994 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) ); 17995 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) ); 17996 break; 17997 case 3: 17998 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) ); 17999 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) ); 18000 break; 18001 } 18002 18003 assign(res_32, binop( Iop_Add32, 18004 binop( Iop_Add32, 18005 binop ( Iop_Add32, 18006 mkexpr(_vecA_32), 18007 mkexpr(_vecB_32) ), 18008 (i == 0) ? mkU32(0) : mkexpr(carry) ), 18009 (i == 0) ? cin : mkU32(0) ) ); 18010 if (modulo) { 18011 result = newTemp(Ity_V128); 18012 assign(result, binop( Iop_OrV128, 18013 (i == 0) ? binop( Iop_64HLtoV128, 18014 mkU64(0), 18015 mkU64(0) ) : mkexpr(tmp_result), 18016 binop( Iop_ShlV128, 18017 binop( Iop_64HLtoV128, 18018 mkU64(0), 18019 binop( Iop_32HLto64, 18020 mkU32(0), 18021 mkexpr(res_32) ) ), 18022 mkU8(i * 32) ) ) ); 18023 tmp_result = newTemp(Ity_V128); 18024 assign(tmp_result, mkexpr(result)); 18025 } 18026 carry = newTemp(Ity_I32); 18027 assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U, 18028 mkexpr(res_32), 18029 mkexpr(_vecA_32 ) ) ) ); 18030 } 18031 if (modulo) 18032 return result; 18033 else 18034 return carry; 18035 } 18036 18037 18038 static Bool dis_av_quad ( UInt theInstr ) 18039 { 18040 /* VX-Form */ 18041 UChar opc1 = ifieldOPC(theInstr); 18042 UChar vRT_addr = ifieldRegDS(theInstr); 18043 UChar vRA_addr = ifieldRegA(theInstr); 18044 UChar vRB_addr = ifieldRegB(theInstr); 18045 UChar vRC_addr; 18046 UInt opc2 = IFIELD( theInstr, 0, 11 ); 18047 18048 IRTemp vA = newTemp(Ity_V128); 18049 IRTemp vB = newTemp(Ity_V128); 18050 IRTemp vC = IRTemp_INVALID; 18051 IRTemp cin = IRTemp_INVALID; 18052 assign( vA, getVReg(vRA_addr)); 18053 assign( vB, getVReg(vRB_addr)); 18054 18055 if (opc1 != 0x4) { 18056 vex_printf("dis_av_quad(ppc)(instr)\n"); 18057 return False; 18058 } 18059 18060 switch (opc2) { 18061 case 0x140: // vaddcuq 18062 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 18063 putVReg( vRT_addr, unop( Iop_32UtoV128, 18064 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18065 mkexpr(vB), 18066 mkU32(0), False) ) ) ); 18067 return True; 18068 case 0x100: // vadduqm 18069 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 18070 putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18071 mkexpr(vB), mkU32(0), True) ) ); 18072 return True; 18073 case 0x540: // vsubcuq 18074 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 18075 putVReg( vRT_addr, 18076 unop( Iop_32UtoV128, 18077 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18078 unop( Iop_NotV128, 18079 mkexpr(vB) ), 18080 mkU32(1), False) ) ) ); 18081 return True; 18082 case 0x500: // vsubuqm 18083 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 18084 putVReg( vRT_addr, 18085 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18086 unop( Iop_NotV128, mkexpr(vB) ), 18087 mkU32(1), True) ) ); 18088 return True; 18089 case 0x054C: // vbpermq 18090 { 18091 #define BPERMD_IDX_MASK 0x00000000000000FFULL 18092 #define BPERMD_BIT_MASK 0x8000000000000000ULL 18093 int i; 18094 IRExpr * vB_expr = mkexpr(vB); 18095 IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0)); 18096 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 18097 for (i = 0; i < 16; i++) { 18098 IRTemp idx_tmp = newTemp( Ity_V128 ); 18099 IRTemp perm_bit = newTemp( Ity_V128 ); 18100 IRTemp idx = newTemp( Ity_I8 ); 18101 IRTemp idx_LT127 = newTemp( Ity_I1 ); 18102 IRTemp idx_LT127_ity128 = newTemp( Ity_V128 ); 18103 18104 assign( idx_tmp, 18105 binop( Iop_AndV128, 18106 binop( Iop_64HLtoV128, 18107 mkU64(0), 18108 mkU64(BPERMD_IDX_MASK) ), 18109 vB_expr ) ); 18110 assign( idx_LT127, 18111 binop( Iop_CmpEQ32, 18112 unop ( Iop_64to32, 18113 unop( Iop_V128to64, binop( Iop_ShrV128, 18114 mkexpr(idx_tmp), 18115 mkU8(7) ) ) ), 18116 mkU32(0) ) ); 18117 18118 /* Below, we set idx to determine which bit of vA to use for the 18119 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'. 18120 */ 18121 assign( idx, 18122 binop( Iop_And8, 18123 unop( Iop_1Sto8, 18124 mkexpr(idx_LT127) ), 18125 unop( Iop_32to8, 18126 unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) ); 18127 18128 assign( idx_LT127_ity128, 18129 binop( Iop_64HLtoV128, 18130 mkU64(0), 18131 unop( Iop_32Uto64, 18132 unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) ); 18133 assign( perm_bit, 18134 binop( Iop_AndV128, 18135 mkexpr( idx_LT127_ity128 ), 18136 binop( Iop_ShrV128, 18137 binop( Iop_AndV128, 18138 binop (Iop_64HLtoV128, 18139 mkU64( BPERMD_BIT_MASK ), 18140 mkU64(0)), 18141 binop( Iop_ShlV128, 18142 mkexpr( vA ), 18143 mkexpr( idx ) ) ), 18144 mkU8( 127 ) ) ) ); 18145 res = binop( Iop_OrV128, 18146 res, 18147 binop( Iop_ShlV128, 18148 mkexpr( perm_bit ), 18149 mkU8( i + 64 ) ) ); 18150 vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) ); 18151 } 18152 putVReg( vRT_addr, res); 18153 return True; 18154 #undef BPERMD_IDX_MASK 18155 #undef BPERMD_BIT_MASK 18156 } 18157 18158 default: 18159 break; // fall through 18160 } 18161 18162 opc2 = IFIELD( theInstr, 0, 6 ); 18163 vRC_addr = ifieldRegC(theInstr); 18164 vC = newTemp(Ity_V128); 18165 cin = newTemp(Ity_I32); 18166 switch (opc2) { 18167 case 0x3D: // vaddecuq 18168 assign( vC, getVReg(vRC_addr)); 18169 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18170 vRC_addr); 18171 assign(cin, binop( Iop_And32, 18172 unop( Iop_64to32, 18173 unop( Iop_V128to64, mkexpr(vC) ) ), 18174 mkU32(1) ) ); 18175 putVReg( vRT_addr, 18176 unop( Iop_32UtoV128, 18177 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 18178 mkexpr(cin), 18179 False) ) ) ); 18180 return True; 18181 case 0x3C: // vaddeuqm 18182 assign( vC, getVReg(vRC_addr)); 18183 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18184 vRC_addr); 18185 assign(cin, binop( Iop_And32, 18186 unop( Iop_64to32, 18187 unop( Iop_V128to64, mkexpr(vC) ) ), 18188 mkU32(1) ) ); 18189 putVReg( vRT_addr, 18190 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 18191 mkexpr(cin), 18192 True) ) ); 18193 return True; 18194 case 0x3F: // vsubecuq 18195 assign( vC, getVReg(vRC_addr)); 18196 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18197 vRC_addr); 18198 assign(cin, binop( Iop_And32, 18199 unop( Iop_64to32, 18200 unop( Iop_V128to64, mkexpr(vC) ) ), 18201 mkU32(1) ) ); 18202 putVReg( vRT_addr, 18203 unop( Iop_32UtoV128, 18204 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18205 unop( Iop_NotV128, 18206 mkexpr(vB) ), 18207 mkexpr(cin), 18208 False) ) ) ); 18209 return True; 18210 case 0x3E: // vsubeuqm 18211 assign( vC, getVReg(vRC_addr)); 18212 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 18213 vRC_addr); 18214 assign(cin, binop( Iop_And32, 18215 unop( Iop_64to32, 18216 unop( Iop_V128to64, mkexpr(vC) ) ), 18217 mkU32(1) ) ); 18218 putVReg( vRT_addr, 18219 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 18220 unop( Iop_NotV128, mkexpr(vB) ), 18221 mkexpr(cin), 18222 True) ) ); 18223 return True; 18224 default: 18225 vex_printf("dis_av_quad(ppc)(opc2.2)\n"); 18226 return False; 18227 } 18228 18229 return True; 18230 } 18231 18232 18233 /* 18234 AltiVec BCD Arithmetic instructions. 18235 These instructions modify CR6 for various conditions in the result, 18236 including when an overflow occurs. We could easily detect all conditions 18237 except when an overflow occurs. But since we can't be 100% accurate 18238 in our emulation of CR6, it seems best to just not support it all. 18239 */ 18240 static Bool dis_av_bcd ( UInt theInstr ) 18241 { 18242 /* VX-Form */ 18243 UChar opc1 = ifieldOPC(theInstr); 18244 UChar vRT_addr = ifieldRegDS(theInstr); 18245 UChar vRA_addr = ifieldRegA(theInstr); 18246 UChar vRB_addr = ifieldRegB(theInstr); 18247 UChar ps = IFIELD( theInstr, 9, 1 ); 18248 UInt opc2 = IFIELD( theInstr, 0, 9 ); 18249 18250 IRTemp vA = newTemp(Ity_V128); 18251 IRTemp vB = newTemp(Ity_V128); 18252 IRTemp dst = newTemp(Ity_V128); 18253 assign( vA, getVReg(vRA_addr)); 18254 assign( vB, getVReg(vRB_addr)); 18255 18256 if (opc1 != 0x4) { 18257 vex_printf("dis_av_bcd(ppc)(instr)\n"); 18258 return False; 18259 } 18260 18261 switch (opc2) { 18262 case 0x1: // bcdadd 18263 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 18264 assign( dst, triop( Iop_BCDAdd, mkexpr( vA ), 18265 mkexpr( vB ), mkU8( ps ) ) ); 18266 putVReg( vRT_addr, mkexpr(dst)); 18267 return True; 18268 18269 case 0x41: // bcdsub 18270 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 18271 assign( dst, triop( Iop_BCDSub, mkexpr( vA ), 18272 mkexpr( vB ), mkU8( ps ) ) ); 18273 putVReg( vRT_addr, mkexpr(dst)); 18274 return True; 18275 18276 default: 18277 vex_printf("dis_av_bcd(ppc)(opc2)\n"); 18278 return False; 18279 } 18280 return True; 18281 } 18282 18283 /* 18284 AltiVec Floating Point Arithmetic Instructions 18285 */ 18286 static Bool dis_av_fp_arith ( UInt theInstr ) 18287 { 18288 /* VA-Form */ 18289 UChar opc1 = ifieldOPC(theInstr); 18290 UChar vD_addr = ifieldRegDS(theInstr); 18291 UChar vA_addr = ifieldRegA(theInstr); 18292 UChar vB_addr = ifieldRegB(theInstr); 18293 UChar vC_addr = ifieldRegC(theInstr); 18294 UInt opc2=0; 18295 18296 IRTemp vA = newTemp(Ity_V128); 18297 IRTemp vB = newTemp(Ity_V128); 18298 IRTemp vC = newTemp(Ity_V128); 18299 assign( vA, getVReg(vA_addr)); 18300 assign( vB, getVReg(vB_addr)); 18301 assign( vC, getVReg(vC_addr)); 18302 18303 if (opc1 != 0x4) { 18304 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 18305 return False; 18306 } 18307 18308 IRTemp rm = newTemp(Ity_I32); 18309 assign(rm, get_IR_roundingmode()); 18310 18311 opc2 = IFIELD( theInstr, 0, 6 ); 18312 switch (opc2) { 18313 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 18314 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 18315 vD_addr, vA_addr, vC_addr, vB_addr); 18316 putVReg( vD_addr, 18317 triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST), 18318 mkexpr(vB), 18319 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18320 mkexpr(vA), mkexpr(vC))) ); 18321 return True; 18322 18323 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 18324 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 18325 vD_addr, vA_addr, vC_addr, vB_addr); 18326 putVReg( vD_addr, 18327 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 18328 mkexpr(vB), 18329 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18330 mkexpr(vA), mkexpr(vC))) ); 18331 return True; 18332 } 18333 18334 default: 18335 break; // Fall through... 18336 } 18337 18338 opc2 = IFIELD( theInstr, 0, 11 ); 18339 switch (opc2) { 18340 case 0x00A: // vaddfp (Add FP, AV p137) 18341 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18342 putVReg( vD_addr, triop(Iop_Add32Fx4, 18343 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 18344 return True; 18345 18346 case 0x04A: // vsubfp (Subtract FP, AV p261) 18347 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18348 putVReg( vD_addr, triop(Iop_Sub32Fx4, 18349 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 18350 return True; 18351 18352 case 0x40A: // vmaxfp (Maximum FP, AV p178) 18353 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18354 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 18355 return True; 18356 18357 case 0x44A: // vminfp (Minimum FP, AV p187) 18358 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 18359 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 18360 return True; 18361 18362 default: 18363 break; // Fall through... 18364 } 18365 18366 18367 if (vA_addr != 0) { 18368 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 18369 return False; 18370 } 18371 18372 switch (opc2) { 18373 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 18374 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 18375 putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) ); 18376 return True; 18377 18378 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 18379 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 18380 putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) ); 18381 return True; 18382 18383 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 18384 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 18385 DIP(" => not implemented\n"); 18386 return False; 18387 18388 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 18389 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 18390 DIP(" => not implemented\n"); 18391 return False; 18392 18393 default: 18394 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 18395 return False; 18396 } 18397 return True; 18398 } 18399 18400 /* 18401 AltiVec Floating Point Compare Instructions 18402 */ 18403 static Bool dis_av_fp_cmp ( UInt theInstr ) 18404 { 18405 /* VXR-Form */ 18406 UChar opc1 = ifieldOPC(theInstr); 18407 UChar vD_addr = ifieldRegDS(theInstr); 18408 UChar vA_addr = ifieldRegA(theInstr); 18409 UChar vB_addr = ifieldRegB(theInstr); 18410 UChar flag_rC = ifieldBIT10(theInstr); 18411 UInt opc2 = IFIELD( theInstr, 0, 10 ); 18412 18413 Bool cmp_bounds = False; 18414 18415 IRTemp vA = newTemp(Ity_V128); 18416 IRTemp vB = newTemp(Ity_V128); 18417 IRTemp vD = newTemp(Ity_V128); 18418 assign( vA, getVReg(vA_addr)); 18419 assign( vB, getVReg(vB_addr)); 18420 18421 if (opc1 != 0x4) { 18422 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 18423 return False; 18424 } 18425 18426 switch (opc2) { 18427 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 18428 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18429 vD_addr, vA_addr, vB_addr); 18430 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 18431 break; 18432 18433 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 18434 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18435 vD_addr, vA_addr, vB_addr); 18436 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 18437 break; 18438 18439 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 18440 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18441 vD_addr, vA_addr, vB_addr); 18442 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 18443 break; 18444 18445 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 18446 IRTemp gt = newTemp(Ity_V128); 18447 IRTemp lt = newTemp(Ity_V128); 18448 IRTemp zeros = newTemp(Ity_V128); 18449 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 18450 vD_addr, vA_addr, vB_addr); 18451 cmp_bounds = True; 18452 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 18453 18454 /* Note: making use of fact that the ppc backend for compare insns 18455 return zero'd lanes if either of the corresponding arg lanes is 18456 a nan. 18457 18458 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 18459 need this for the other compares too (vcmpeqfp etc)... 18460 Better still, tighten down the spec for compare irops. 18461 */ 18462 assign( gt, unop(Iop_NotV128, 18463 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 18464 assign( lt, unop(Iop_NotV128, 18465 binop(Iop_CmpGE32Fx4, mkexpr(vA), 18466 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 18467 mkexpr(zeros), 18468 mkexpr(vB)))) ); 18469 18470 // finally, just shift gt,lt to correct position 18471 assign( vD, binop(Iop_ShlN32x4, 18472 binop(Iop_OrV128, 18473 binop(Iop_AndV128, mkexpr(gt), 18474 unop(Iop_Dup32x4, mkU32(0x2))), 18475 binop(Iop_AndV128, mkexpr(lt), 18476 unop(Iop_Dup32x4, mkU32(0x1)))), 18477 mkU8(30)) ); 18478 break; 18479 } 18480 18481 default: 18482 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 18483 return False; 18484 } 18485 18486 putVReg( vD_addr, mkexpr(vD) ); 18487 18488 if (flag_rC) { 18489 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 18490 } 18491 return True; 18492 } 18493 18494 /* 18495 AltiVec Floating Point Convert/Round Instructions 18496 */ 18497 static Bool dis_av_fp_convert ( UInt theInstr ) 18498 { 18499 /* VX-Form */ 18500 UChar opc1 = ifieldOPC(theInstr); 18501 UChar vD_addr = ifieldRegDS(theInstr); 18502 UChar UIMM_5 = ifieldRegA(theInstr); 18503 UChar vB_addr = ifieldRegB(theInstr); 18504 UInt opc2 = IFIELD( theInstr, 0, 11 ); 18505 18506 IRTemp vB = newTemp(Ity_V128); 18507 IRTemp vScale = newTemp(Ity_V128); 18508 IRTemp vInvScale = newTemp(Ity_V128); 18509 18510 float scale, inv_scale; 18511 18512 assign( vB, getVReg(vB_addr)); 18513 18514 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 18515 scale = (float)( (unsigned int) 1<<UIMM_5 ); 18516 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 18517 inv_scale = 1/scale; 18518 assign( vInvScale, 18519 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 18520 18521 if (opc1 != 0x4) { 18522 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 18523 return False; 18524 } 18525 18526 switch (opc2) { 18527 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 18528 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18529 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18530 unop(Iop_I32UtoFx4, mkexpr(vB)), 18531 mkexpr(vInvScale)) ); 18532 return True; 18533 18534 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 18535 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18536 18537 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18538 unop(Iop_I32StoFx4, mkexpr(vB)), 18539 mkexpr(vInvScale)) ); 18540 return True; 18541 18542 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 18543 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18544 putVReg( vD_addr, 18545 unop(Iop_QFtoI32Ux4_RZ, 18546 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18547 mkexpr(vB), mkexpr(vScale))) ); 18548 return True; 18549 18550 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 18551 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18552 putVReg( vD_addr, 18553 unop(Iop_QFtoI32Sx4_RZ, 18554 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18555 mkexpr(vB), mkexpr(vScale))) ); 18556 return True; 18557 18558 default: 18559 break; // Fall through... 18560 } 18561 18562 if (UIMM_5 != 0) { 18563 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 18564 return False; 18565 } 18566 18567 switch (opc2) { 18568 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 18569 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 18570 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 18571 break; 18572 18573 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 18574 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 18575 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 18576 break; 18577 18578 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 18579 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 18580 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 18581 break; 18582 18583 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 18584 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 18585 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 18586 break; 18587 18588 default: 18589 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 18590 return False; 18591 } 18592 return True; 18593 } 18594 18595 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr, 18596 const VexAbiInfo* vbi, 18597 /*OUT*/DisResult* dres, 18598 Bool (*resteerOkFn)(void*,Addr), 18599 void* callback_opaque ) 18600 { 18601 UInt opc2 = IFIELD( theInstr, 1, 10 ); 18602 18603 switch (opc2) { 18604 case 0x28E: { //tbegin. 18605 /* The current implementation is to just fail the tbegin and execute 18606 * the failure path. The failure path is assumed to be functionaly 18607 * equivalent to the transactional path with the needed data locking 18608 * to ensure correctness. The tend is just a noop and shouldn't 18609 * actually get executed. 18610 * 1) set cr0 to 0x2 18611 * 2) Initialize TFHAR to CIA+4 18612 * 3) Initialize TEXASR 18613 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.) 18614 * 5) Continue executing at the next instruction. 18615 */ 18616 UInt R = IFIELD( theInstr, 21, 1 ); 18617 18618 ULong tm_reason; 18619 UInt failure_code = 0; /* Forcing failure, will not be due to tabort 18620 * or treclaim. 18621 */ 18622 UInt persistant = 1; /* set persistant since we are always failing 18623 * the tbegin. 18624 */ 18625 UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this 18626 as the reason for failing the trasaction */ 18627 UInt tm_exact = 1; /* have exact address for failure */ 18628 18629 DIP("tbegin. %u\n", R); 18630 18631 /* Set the CR0 field to indicate the tbegin failed. Then let 18632 * the code do the branch to the failure path. 18633 * 18634 * 000 || 0 Transaction initiation successful, 18635 * unnested (Transaction state of 18636 * Non-transactional prior to tbegin.) 18637 * 010 || 0 Transaction initiation successful, nested 18638 * (Transaction state of Transactional 18639 * prior to tbegin.) 18640 * 001 || 0 Transaction initiation unsuccessful, 18641 * (Transaction state of Suspended prior 18642 * to tbegin.) 18643 */ 18644 putCR321( 0, mkU8( 0x2 ) ); 18645 18646 tm_reason = generate_TMreason( failure_code, persistant, 18647 nest_overflow, tm_exact ); 18648 18649 storeTMfailure( guest_CIA_curr_instr, tm_reason, 18650 guest_CIA_curr_instr+4 ); 18651 18652 return True; 18653 18654 break; 18655 } 18656 18657 case 0x2AE: { //tend. 18658 /* The tend. is just a noop. Do nothing */ 18659 UInt A = IFIELD( theInstr, 25, 1 ); 18660 18661 DIP("tend. %u\n", A); 18662 break; 18663 } 18664 18665 case 0x2EE: { //tsr. 18666 /* The tsr. is just a noop. Do nothing */ 18667 UInt L = IFIELD( theInstr, 21, 1 ); 18668 18669 DIP("tsr. %u\n", L); 18670 break; 18671 } 18672 18673 case 0x2CE: { //tcheck. 18674 /* The tcheck. is just a noop. Do nothing */ 18675 UInt BF = IFIELD( theInstr, 25, 1 ); 18676 18677 DIP("tcheck. %u\n", BF); 18678 break; 18679 } 18680 18681 case 0x30E: { //tbortwc. 18682 /* The tabortwc. is just a noop. Do nothing */ 18683 UInt TO = IFIELD( theInstr, 25, 1 ); 18684 UInt RA = IFIELD( theInstr, 16, 5 ); 18685 UInt RB = IFIELD( theInstr, 11, 5 ); 18686 18687 DIP("tabortwc. %u,%u,%u\n", TO, RA, RB); 18688 break; 18689 } 18690 18691 case 0x32E: { //tbortdc. 18692 /* The tabortdc. is just a noop. Do nothing */ 18693 UInt TO = IFIELD( theInstr, 25, 1 ); 18694 UInt RA = IFIELD( theInstr, 16, 5 ); 18695 UInt RB = IFIELD( theInstr, 11, 5 ); 18696 18697 DIP("tabortdc. %u,%u,%u\n", TO, RA, RB); 18698 break; 18699 } 18700 18701 case 0x34E: { //tbortwci. 18702 /* The tabortwci. is just a noop. Do nothing */ 18703 UInt TO = IFIELD( theInstr, 25, 1 ); 18704 UInt RA = IFIELD( theInstr, 16, 5 ); 18705 UInt SI = IFIELD( theInstr, 11, 5 ); 18706 18707 DIP("tabortwci. %u,%u,%u\n", TO, RA, SI); 18708 break; 18709 } 18710 18711 case 0x36E: { //tbortdci. 18712 /* The tabortdci. is just a noop. Do nothing */ 18713 UInt TO = IFIELD( theInstr, 25, 1 ); 18714 UInt RA = IFIELD( theInstr, 16, 5 ); 18715 UInt SI = IFIELD( theInstr, 11, 5 ); 18716 18717 DIP("tabortdci. %u,%u,%u\n", TO, RA, SI); 18718 break; 18719 } 18720 18721 case 0x38E: { //tbort. 18722 /* The tabort. is just a noop. Do nothing */ 18723 UInt RA = IFIELD( theInstr, 16, 5 ); 18724 18725 DIP("tabort. %u\n", RA); 18726 break; 18727 } 18728 18729 case 0x3AE: { //treclaim. 18730 /* The treclaim. is just a noop. Do nothing */ 18731 UInt RA = IFIELD( theInstr, 16, 5 ); 18732 18733 DIP("treclaim. %u\n", RA); 18734 break; 18735 } 18736 18737 case 0x3EE: { //trechkpt. 18738 /* The trechkpt. is just a noop. Do nothing */ 18739 DIP("trechkpt.\n"); 18740 break; 18741 } 18742 18743 default: 18744 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n"); 18745 return False; 18746 } 18747 18748 return True; 18749 } 18750 18751 18752 /* The 0x3C primary opcode (VSX category) uses several different forms of 18753 * extended opcodes: 18754 * o XX2-form: 18755 * - [10:2] (IBM notation [21:29]) 18756 * o XX3-form variants: 18757 * - variant 1: [10:3] (IBM notation [21:28]) 18758 * - variant 2: [9:3] (IBM notation [22:28]) 18759 * - variant 3: [7:3] (IBM notation [24:28]) 18760 * o XX-4 form: 18761 * - [10:6] (IBM notation [21:25]) 18762 * 18763 * The XX2-form needs bit 0 masked from the standard extended opcode 18764 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 18765 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 18766 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 18767 * front end since their encoding does not begin at bit 21 like the standard 18768 * format. 18769 * 18770 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 18771 * secondary opcode for such VSX instructions. 18772 * 18773 */ 18774 18775 18776 struct vsx_insn { 18777 UInt opcode; 18778 const HChar * name; 18779 }; 18780 18781 // ATTENTION: Keep this array sorted on the opcocde!!! 18782 static struct vsx_insn vsx_all[] = { 18783 { 0x0, "xsaddsp" }, 18784 { 0x4, "xsmaddasp" }, 18785 { 0x8, "xxsldwi" }, 18786 { 0x14, "xsrsqrtesp" }, 18787 { 0x16, "xssqrtsp" }, 18788 { 0x18, "xxsel" }, 18789 { 0x20, "xssubsp" }, 18790 { 0x24, "xsmaddmsp" }, 18791 { 0x28, "xxpermdi" }, 18792 { 0x34, "xsresp" }, 18793 { 0x40, "xsmulsp" }, 18794 { 0x44, "xsmsubasp" }, 18795 { 0x48, "xxmrghw" }, 18796 { 0x60, "xsdivsp" }, 18797 { 0x64, "xsmsubmsp" }, 18798 { 0x80, "xsadddp" }, 18799 { 0x84, "xsmaddadp" }, 18800 { 0x8c, "xscmpudp" }, 18801 { 0x90, "xscvdpuxws" }, 18802 { 0x92, "xsrdpi" }, 18803 { 0x94, "xsrsqrtedp" }, 18804 { 0x96, "xssqrtdp" }, 18805 { 0xa0, "xssubdp" }, 18806 { 0xa4, "xsmaddmdp" }, 18807 { 0xac, "xscmpodp" }, 18808 { 0xb0, "xscvdpsxws" }, 18809 { 0xb2, "xsrdpiz" }, 18810 { 0xb4, "xsredp" }, 18811 { 0xc0, "xsmuldp" }, 18812 { 0xc4, "xsmsubadp" }, 18813 { 0xc8, "xxmrglw" }, 18814 { 0xd2, "xsrdpip" }, 18815 { 0xd4, "xstsqrtdp" }, 18816 { 0xd6, "xsrdpic" }, 18817 { 0xe0, "xsdivdp" }, 18818 { 0xe4, "xsmsubmdp" }, 18819 { 0xf2, "xsrdpim" }, 18820 { 0xf4, "xstdivdp" }, 18821 { 0x100, "xvaddsp" }, 18822 { 0x104, "xvmaddasp" }, 18823 { 0x10c, "xvcmpeqsp" }, 18824 { 0x110, "xvcvspuxws" }, 18825 { 0x112, "xvrspi" }, 18826 { 0x114, "xvrsqrtesp" }, 18827 { 0x116, "xvsqrtsp" }, 18828 { 0x120, "xvsubsp" }, 18829 { 0x124, "xvmaddmsp" }, 18830 { 0x12c, "xvcmpgtsp" }, 18831 { 0x130, "xvcvspsxws" }, 18832 { 0x132, "xvrspiz" }, 18833 { 0x134, "xvresp" }, 18834 { 0x140, "xvmulsp" }, 18835 { 0x144, "xvmsubasp" }, 18836 { 0x148, "xxspltw" }, 18837 { 0x14c, "xvcmpgesp" }, 18838 { 0x150, "xvcvuxwsp" }, 18839 { 0x152, "xvrspip" }, 18840 { 0x154, "xvtsqrtsp" }, 18841 { 0x156, "xvrspic" }, 18842 { 0x160, "xvdivsp" }, 18843 { 0x164, "xvmsubmsp" }, 18844 { 0x170, "xvcvsxwsp" }, 18845 { 0x172, "xvrspim" }, 18846 { 0x174, "xvtdivsp" }, 18847 { 0x180, "xvadddp" }, 18848 { 0x184, "xvmaddadp" }, 18849 { 0x18c, "xvcmpeqdp" }, 18850 { 0x190, "xvcvdpuxws" }, 18851 { 0x192, "xvrdpi" }, 18852 { 0x194, "xvrsqrtedp" }, 18853 { 0x196, "xvsqrtdp" }, 18854 { 0x1a0, "xvsubdp" }, 18855 { 0x1a4, "xvmaddmdp" }, 18856 { 0x1ac, "xvcmpgtdp" }, 18857 { 0x1b0, "xvcvdpsxws" }, 18858 { 0x1b2, "xvrdpiz" }, 18859 { 0x1b4, "xvredp" }, 18860 { 0x1c0, "xvmuldp" }, 18861 { 0x1c4, "xvmsubadp" }, 18862 { 0x1cc, "xvcmpgedp" }, 18863 { 0x1d0, "xvcvuxwdp" }, 18864 { 0x1d2, "xvrdpip" }, 18865 { 0x1d4, "xvtsqrtdp" }, 18866 { 0x1d6, "xvrdpic" }, 18867 { 0x1e0, "xvdivdp" }, 18868 { 0x1e4, "xvmsubmdp" }, 18869 { 0x1f0, "xvcvsxwdp" }, 18870 { 0x1f2, "xvrdpim" }, 18871 { 0x1f4, "xvtdivdp" }, 18872 { 0x204, "xsnmaddasp" }, 18873 { 0x208, "xxland" }, 18874 { 0x212, "xscvdpsp" }, 18875 { 0x216, "xscvdpspn" }, 18876 { 0x224, "xsnmaddmsp" }, 18877 { 0x228, "xxlandc" }, 18878 { 0x232, "xxrsp" }, 18879 { 0x244, "xsnmsubasp" }, 18880 { 0x248, "xxlor" }, 18881 { 0x250, "xscvuxdsp" }, 18882 { 0x264, "xsnmsubmsp" }, 18883 { 0x268, "xxlxor" }, 18884 { 0x270, "xscvsxdsp" }, 18885 { 0x280, "xsmaxdp" }, 18886 { 0x284, "xsnmaddadp" }, 18887 { 0x288, "xxlnor" }, 18888 { 0x290, "xscvdpuxds" }, 18889 { 0x292, "xscvspdp" }, 18890 { 0x296, "xscvspdpn" }, 18891 { 0x2a0, "xsmindp" }, 18892 { 0x2a4, "xsnmaddmdp" }, 18893 { 0x2a8, "xxlorc" }, 18894 { 0x2b0, "xscvdpsxds" }, 18895 { 0x2b2, "xsabsdp" }, 18896 { 0x2c0, "xscpsgndp" }, 18897 { 0x2c4, "xsnmsubadp" }, 18898 { 0x2c8, "xxlnand" }, 18899 { 0x2d0, "xscvuxddp" }, 18900 { 0x2d2, "xsnabsdp" }, 18901 { 0x2e4, "xsnmsubmdp" }, 18902 { 0x2e8, "xxleqv" }, 18903 { 0x2f0, "xscvsxddp" }, 18904 { 0x2f2, "xsnegdp" }, 18905 { 0x300, "xvmaxsp" }, 18906 { 0x304, "xvnmaddasp" }, 18907 { 0x30c, "xvcmpeqsp." }, 18908 { 0x310, "xvcvspuxds" }, 18909 { 0x312, "xvcvdpsp" }, 18910 { 0x320, "xvminsp" }, 18911 { 0x324, "xvnmaddmsp" }, 18912 { 0x32c, "xvcmpgtsp." }, 18913 { 0x330, "xvcvspsxds" }, 18914 { 0x332, "xvabssp" }, 18915 { 0x340, "xvcpsgnsp" }, 18916 { 0x344, "xvnmsubasp" }, 18917 { 0x34c, "xvcmpgesp." }, 18918 { 0x350, "xvcvuxdsp" }, 18919 { 0x352, "xvnabssp" }, 18920 { 0x364, "xvnmsubmsp" }, 18921 { 0x370, "xvcvsxdsp" }, 18922 { 0x372, "xvnegsp" }, 18923 { 0x380, "xvmaxdp" }, 18924 { 0x384, "xvnmaddadp" }, 18925 { 0x38c, "xvcmpeqdp." }, 18926 { 0x390, "xvcvdpuxds" }, 18927 { 0x392, "xvcvspdp" }, 18928 { 0x3a0, "xvmindp" }, 18929 { 0x3a4, "xvnmaddmdp" }, 18930 { 0x3ac, "xvcmpgtdp." }, 18931 { 0x3b0, "xvcvdpsxds" }, 18932 { 0x3b2, "xvabsdp" }, 18933 { 0x3c0, "xvcpsgndp" }, 18934 { 0x3c4, "xvnmsubadp" }, 18935 { 0x3cc, "xvcmpgedp." }, 18936 { 0x3d0, "xvcvuxddp" }, 18937 { 0x3d2, "xvnabsdp" }, 18938 { 0x3e4, "xvnmsubmdp" }, 18939 { 0x3f0, "xvcvsxddp" }, 18940 { 0x3f2, "xvnegdp" } 18941 }; 18942 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all) 18943 18944 18945 // ATTENTION: This search function assumes vsx_all array is sorted. 18946 static Int findVSXextOpCode(UInt opcode) 18947 { 18948 Int low, mid, high; 18949 low = 0; 18950 high = VSX_ALL_LEN - 1; 18951 while (low <= high) { 18952 mid = (low + high)/2; 18953 if (opcode < vsx_all[mid].opcode) 18954 high = mid - 1; 18955 else if (opcode > vsx_all[mid].opcode) 18956 low = mid + 1; 18957 else 18958 return mid; 18959 } 18960 return -1; 18961 } 18962 18963 18964 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 18965 * passed, and we then try to match it up with one of the VSX forms 18966 * below. 18967 */ 18968 static UInt get_VSX60_opc2(UInt opc2_full) 18969 { 18970 #define XX2_MASK 0x000003FE 18971 #define XX3_1_MASK 0x000003FC 18972 #define XX3_2_MASK 0x000001FC 18973 #define XX3_3_MASK 0x0000007C 18974 #define XX4_MASK 0x00000018 18975 Int ret; 18976 UInt vsxExtOpcode = 0; 18977 18978 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0) 18979 vsxExtOpcode = vsx_all[ret].opcode; 18980 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0) 18981 vsxExtOpcode = vsx_all[ret].opcode; 18982 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0) 18983 vsxExtOpcode = vsx_all[ret].opcode; 18984 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0) 18985 vsxExtOpcode = vsx_all[ret].opcode; 18986 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0) 18987 vsxExtOpcode = vsx_all[ret].opcode; 18988 18989 return vsxExtOpcode; 18990 } 18991 18992 /*------------------------------------------------------------*/ 18993 /*--- Disassemble a single instruction ---*/ 18994 /*------------------------------------------------------------*/ 18995 18996 /* Disassemble a single instruction into IR. The instruction 18997 is located in host memory at &guest_code[delta]. */ 18998 18999 static 19000 DisResult disInstr_PPC_WRK ( 19001 Bool (*resteerOkFn) ( /*opaque*/void*, Addr ), 19002 Bool resteerCisOk, 19003 void* callback_opaque, 19004 Long delta64, 19005 const VexArchInfo* archinfo, 19006 const VexAbiInfo* abiinfo, 19007 Bool sigill_diag 19008 ) 19009 { 19010 UChar opc1; 19011 UInt opc2; 19012 DisResult dres; 19013 UInt theInstr; 19014 IRType ty = mode64 ? Ity_I64 : Ity_I32; 19015 Bool allow_F = False; 19016 Bool allow_V = False; 19017 Bool allow_FX = False; 19018 Bool allow_GX = False; 19019 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 19020 Bool allow_DFP = False; 19021 Bool allow_isa_2_07 = False; 19022 UInt hwcaps = archinfo->hwcaps; 19023 Long delta; 19024 19025 /* What insn variants are we supporting today? */ 19026 if (mode64) { 19027 allow_F = True; 19028 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 19029 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 19030 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 19031 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 19032 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); 19033 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07)); 19034 } else { 19035 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 19036 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 19037 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 19038 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 19039 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 19040 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); 19041 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07)); 19042 } 19043 19044 /* The running delta */ 19045 delta = (Long)mkSzAddr(ty, (ULong)delta64); 19046 19047 /* Set result defaults. */ 19048 dres.whatNext = Dis_Continue; 19049 dres.len = 0; 19050 dres.continueAt = 0; 19051 dres.jk_StopHere = Ijk_INVALID; 19052 19053 /* At least this is simple on PPC32: insns are all 4 bytes long, and 19054 4-aligned. So just fish the whole thing out of memory right now 19055 and have done. */ 19056 theInstr = getUIntPPCendianly( &guest_code[delta] ); 19057 19058 if (0) vex_printf("insn: 0x%x\n", theInstr); 19059 19060 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 19061 19062 /* Spot "Special" instructions (see comment at top of file). */ 19063 { 19064 const UChar* code = guest_code + delta; 19065 /* Spot the 16-byte preamble: 19066 32-bit mode: 19067 5400183E rlwinm 0,0,3,0,31 19068 5400683E rlwinm 0,0,13,0,31 19069 5400E83E rlwinm 0,0,29,0,31 19070 5400983E rlwinm 0,0,19,0,31 19071 64-bit mode: 19072 78001800 rotldi 0,0,3 19073 78006800 rotldi 0,0,13 19074 7800E802 rotldi 0,0,61 19075 78009802 rotldi 0,0,51 19076 */ 19077 UInt word1 = mode64 ? 0x78001800 : 0x5400183E; 19078 UInt word2 = mode64 ? 0x78006800 : 0x5400683E; 19079 UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; 19080 UInt word4 = mode64 ? 0x78009802 : 0x5400983E; 19081 Bool is_special_preamble = False; 19082 if (getUIntPPCendianly(code+ 0) == word1 && 19083 getUIntPPCendianly(code+ 4) == word2 && 19084 getUIntPPCendianly(code+ 8) == word3 && 19085 getUIntPPCendianly(code+12) == word4) { 19086 is_special_preamble = True; 19087 } else if (! mode64 && 19088 getUIntPPCendianly(code+ 0) == 0x54001800 && 19089 getUIntPPCendianly(code+ 4) == 0x54006800 && 19090 getUIntPPCendianly(code+ 8) == 0x5400E800 && 19091 getUIntPPCendianly(code+12) == 0x54009800) { 19092 static Bool reported = False; 19093 if (!reported) { 19094 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n"); 19095 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n"); 19096 reported = True; 19097 } 19098 is_special_preamble = True; 19099 } 19100 if (is_special_preamble) { 19101 /* Got a "Special" instruction preamble. Which one is it? */ 19102 if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 19103 /* %R3 = client_request ( %R4 ) */ 19104 DIP("r3 = client_request ( %%r4 )\n"); 19105 delta += 20; 19106 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 19107 dres.jk_StopHere = Ijk_ClientReq; 19108 dres.whatNext = Dis_StopHere; 19109 goto decode_success; 19110 } 19111 else 19112 if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 19113 /* %R3 = guest_NRADDR */ 19114 DIP("r3 = guest_NRADDR\n"); 19115 delta += 20; 19116 dres.len = 20; 19117 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 19118 goto decode_success; 19119 } 19120 else 19121 if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 19122 delta += 20; 19123 if (host_endness == VexEndnessLE) { 19124 /* branch-and-link-to-noredir %R12 */ 19125 DIP("branch-and-link-to-noredir r12\n"); 19126 putGST( PPC_GST_LR, 19127 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 19128 putGST( PPC_GST_CIA, getIReg(12)); 19129 } else { 19130 /* branch-and-link-to-noredir %R11 */ 19131 DIP("branch-and-link-to-noredir r11\n"); 19132 putGST( PPC_GST_LR, 19133 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 19134 putGST( PPC_GST_CIA, getIReg(11)); 19135 } 19136 dres.jk_StopHere = Ijk_NoRedir; 19137 dres.whatNext = Dis_StopHere; 19138 goto decode_success; 19139 } 19140 else 19141 if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 19142 /* %R3 = guest_NRADDR_GPR2 */ 19143 DIP("r3 = guest_NRADDR_GPR2\n"); 19144 delta += 20; 19145 dres.len = 20; 19146 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 19147 goto decode_success; 19148 } 19149 else 19150 if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { 19151 DIP("IR injection\n"); 19152 if (host_endness == VexEndnessBE) 19153 vex_inject_ir(irsb, Iend_BE); 19154 else 19155 vex_inject_ir(irsb, Iend_LE); 19156 19157 delta += 20; 19158 dres.len = 20; 19159 19160 // Invalidate the current insn. The reason is that the IRop we're 19161 // injecting here can change. In which case the translation has to 19162 // be redone. For ease of handling, we simply invalidate all the 19163 // time. 19164 19165 stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr))); 19166 stmt(IRStmt_Put(OFFB_CMLEN, mkSzImm(ty, 20))); 19167 19168 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 19169 dres.whatNext = Dis_StopHere; 19170 dres.jk_StopHere = Ijk_InvalICache; 19171 goto decode_success; 19172 } 19173 /* We don't know what it is. Set opc1/opc2 so decode_failure 19174 can print the insn following the Special-insn preamble. */ 19175 theInstr = getUIntPPCendianly(code+16); 19176 opc1 = ifieldOPC(theInstr); 19177 opc2 = ifieldOPClo10(theInstr); 19178 goto decode_failure; 19179 /*NOTREACHED*/ 19180 } 19181 } 19182 19183 opc1 = ifieldOPC(theInstr); 19184 opc2 = ifieldOPClo10(theInstr); 19185 19186 // Note: all 'reserved' bits must be cleared, else invalid 19187 switch (opc1) { 19188 19189 /* Integer Arithmetic Instructions */ 19190 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 19191 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 19192 if (dis_int_arith( theInstr )) goto decode_success; 19193 goto decode_failure; 19194 19195 /* Integer Compare Instructions */ 19196 case 0x0B: case 0x0A: // cmpi, cmpli 19197 if (dis_int_cmp( theInstr )) goto decode_success; 19198 goto decode_failure; 19199 19200 /* Integer Logical Instructions */ 19201 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 19202 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 19203 if (dis_int_logic( theInstr )) goto decode_success; 19204 goto decode_failure; 19205 19206 /* Integer Rotate Instructions */ 19207 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 19208 if (dis_int_rot( theInstr )) goto decode_success; 19209 goto decode_failure; 19210 19211 /* 64bit Integer Rotate Instructions */ 19212 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 19213 if (!mode64) goto decode_failure; 19214 if (dis_int_rot( theInstr )) goto decode_success; 19215 goto decode_failure; 19216 19217 /* Integer Load Instructions */ 19218 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 19219 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 19220 case 0x20: case 0x21: // lwz, lwzu 19221 if (dis_int_load( theInstr )) goto decode_success; 19222 goto decode_failure; 19223 19224 /* Integer Store Instructions */ 19225 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 19226 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 19227 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19228 goto decode_failure; 19229 19230 /* Integer Load and Store Multiple Instructions */ 19231 case 0x2E: case 0x2F: // lmw, stmw 19232 if (dis_int_ldst_mult( theInstr )) goto decode_success; 19233 goto decode_failure; 19234 19235 /* Branch Instructions */ 19236 case 0x12: case 0x10: // b, bc 19237 if (dis_branch(theInstr, abiinfo, &dres, 19238 resteerOkFn, callback_opaque)) 19239 goto decode_success; 19240 goto decode_failure; 19241 19242 /* System Linkage Instructions */ 19243 case 0x11: // sc 19244 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 19245 goto decode_failure; 19246 19247 /* Trap Instructions */ 19248 case 0x02: // tdi 19249 if (!mode64) goto decode_failure; 19250 if (dis_trapi(theInstr, &dres)) goto decode_success; 19251 goto decode_failure; 19252 19253 case 0x03: // twi 19254 if (dis_trapi(theInstr, &dres)) goto decode_success; 19255 goto decode_failure; 19256 19257 /* Floating Point Load Instructions */ 19258 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 19259 case 0x33: // lfdu 19260 if (!allow_F) goto decode_noF; 19261 if (dis_fp_load( theInstr )) goto decode_success; 19262 goto decode_failure; 19263 19264 /* Floating Point Store Instructions */ 19265 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 19266 case 0x37: // stfdux 19267 if (!allow_F) goto decode_noF; 19268 if (dis_fp_store( theInstr )) goto decode_success; 19269 goto decode_failure; 19270 19271 /* Floating Point Load Double Pair Instructions */ 19272 case 0x39: case 0x3D: 19273 if (!allow_F) goto decode_noF; 19274 if (dis_fp_pair( theInstr )) goto decode_success; 19275 goto decode_failure; 19276 19277 /* 128-bit Integer Load */ 19278 case 0x38: // lq 19279 if (dis_int_load( theInstr )) goto decode_success; 19280 goto decode_failure; 19281 19282 /* 64bit Integer Loads */ 19283 case 0x3A: // ld, ldu, lwa 19284 if (!mode64) goto decode_failure; 19285 if (dis_int_load( theInstr )) goto decode_success; 19286 goto decode_failure; 19287 19288 case 0x3B: 19289 if (!allow_F) goto decode_noF; 19290 opc2 = ifieldOPClo10(theInstr); 19291 19292 switch (opc2) { 19293 case 0x2: // dadd - DFP Add 19294 case 0x202: // dsub - DFP Subtract 19295 case 0x22: // dmul - DFP Mult 19296 case 0x222: // ddiv - DFP Divide 19297 if (!allow_DFP) goto decode_noDFP; 19298 if (dis_dfp_arith( theInstr )) 19299 goto decode_success; 19300 case 0x82: // dcmpo, DFP comparison ordered instruction 19301 case 0x282: // dcmpu, DFP comparison unordered instruction 19302 if (!allow_DFP) goto decode_noDFP; 19303 if (dis_dfp_compare( theInstr ) ) 19304 goto decode_success; 19305 goto decode_failure; 19306 case 0x102: // dctdp - DFP convert to DFP long 19307 case 0x302: // drsp - DFP round to dfp short 19308 case 0x122: // dctfix - DFP convert to fixed 19309 if (!allow_DFP) goto decode_noDFP; 19310 if (dis_dfp_fmt_conv( theInstr )) 19311 goto decode_success; 19312 goto decode_failure; 19313 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed 19314 if (!allow_VX) 19315 goto decode_failure; 19316 if (!allow_DFP) goto decode_noDFP; 19317 if (dis_dfp_fmt_conv( theInstr )) 19318 goto decode_success; 19319 goto decode_failure; 19320 case 0x2A2: // dtstsf - DFP number of significant digits 19321 if (!allow_DFP) goto decode_noDFP; 19322 if (dis_dfp_significant_digits(theInstr)) 19323 goto decode_success; 19324 goto decode_failure; 19325 case 0x142: // ddedpd DFP Decode DPD to BCD 19326 case 0x342: // denbcd DFP Encode BCD to DPD 19327 if (!allow_DFP) goto decode_noDFP; 19328 if (dis_dfp_bcd(theInstr)) 19329 goto decode_success; 19330 goto decode_failure; 19331 case 0x162: // dxex - Extract exponent 19332 case 0x362: // diex - Insert exponent 19333 if (!allow_DFP) goto decode_noDFP; 19334 if (dis_dfp_extract_insert( theInstr ) ) 19335 goto decode_success; 19336 goto decode_failure; 19337 case 0x3CE: // fcfidus (implemented as native insn) 19338 if (!allow_VX) 19339 goto decode_noVX; 19340 if (dis_fp_round( theInstr )) 19341 goto decode_success; 19342 goto decode_failure; 19343 case 0x34E: // fcfids 19344 if (dis_fp_round( theInstr )) 19345 goto decode_success; 19346 goto decode_failure; 19347 } 19348 19349 opc2 = ifieldOPClo9( theInstr ); 19350 switch (opc2) { 19351 case 0x42: // dscli, DFP shift left 19352 case 0x62: // dscri, DFP shift right 19353 if (!allow_DFP) goto decode_noDFP; 19354 if (dis_dfp_shift( theInstr )) 19355 goto decode_success; 19356 goto decode_failure; 19357 case 0xc2: // dtstdc, DFP test data class 19358 case 0xe2: // dtstdg, DFP test data group 19359 if (!allow_DFP) goto decode_noDFP; 19360 if (dis_dfp_class_test( theInstr )) 19361 goto decode_success; 19362 goto decode_failure; 19363 } 19364 19365 opc2 = ifieldOPClo8( theInstr ); 19366 switch (opc2) { 19367 case 0x3: // dqua - DFP Quantize 19368 case 0x23: // drrnd - DFP Reround 19369 case 0x43: // dquai - DFP Quantize immediate 19370 if (!allow_DFP) goto decode_noDFP; 19371 if (dis_dfp_quantize_sig_rrnd( theInstr ) ) 19372 goto decode_success; 19373 goto decode_failure; 19374 case 0xA2: // dtstex - DFP Test exponent 19375 if (!allow_DFP) goto decode_noDFP; 19376 if (dis_dfp_exponent_test( theInstr ) ) 19377 goto decode_success; 19378 goto decode_failure; 19379 case 0x63: // drintx - Round to an integer value 19380 case 0xE3: // drintn - Round to an integer value 19381 if (!allow_DFP) goto decode_noDFP; 19382 if (dis_dfp_round( theInstr ) ) { 19383 goto decode_success; 19384 } 19385 goto decode_failure; 19386 default: 19387 break; /* fall through to next opc2 check */ 19388 } 19389 19390 opc2 = IFIELD(theInstr, 1, 5); 19391 switch (opc2) { 19392 /* Floating Point Arith Instructions */ 19393 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 19394 case 0x19: // fmuls 19395 if (dis_fp_arith(theInstr)) goto decode_success; 19396 goto decode_failure; 19397 case 0x16: // fsqrts 19398 if (!allow_FX) goto decode_noFX; 19399 if (dis_fp_arith(theInstr)) goto decode_success; 19400 goto decode_failure; 19401 case 0x18: // fres 19402 if (!allow_GX) goto decode_noGX; 19403 if (dis_fp_arith(theInstr)) goto decode_success; 19404 goto decode_failure; 19405 19406 /* Floating Point Mult-Add Instructions */ 19407 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 19408 case 0x1F: // fnmadds 19409 if (dis_fp_multadd(theInstr)) goto decode_success; 19410 goto decode_failure; 19411 19412 case 0x1A: // frsqrtes 19413 if (!allow_GX) goto decode_noGX; 19414 if (dis_fp_arith(theInstr)) goto decode_success; 19415 goto decode_failure; 19416 19417 default: 19418 goto decode_failure; 19419 } 19420 break; 19421 19422 case 0x3C: // VSX instructions (except load/store) 19423 { 19424 // All of these VSX instructions use some VMX facilities, so 19425 // if allow_V is not set, we'll skip trying to decode. 19426 if (!allow_V) goto decode_noVX; 19427 19428 UInt vsxOpc2 = get_VSX60_opc2(opc2); 19429 /* The vsxOpc2 returned is the "normalized" value, representing the 19430 * instructions secondary opcode as taken from the standard secondary 19431 * opcode field [21:30] (IBM notatition), even if the actual field 19432 * is non-standard. These normalized values are given in the opcode 19433 * appendices of the ISA 2.06 document. 19434 */ 19435 19436 switch (vsxOpc2) { 19437 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 19438 case 0x018: case 0x148: // xxsel, xxspltw 19439 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 19440 goto decode_failure; 19441 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor, 19442 case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc 19443 case 0x2C8: case 0x2E8: // xxlnand, xxleqv 19444 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 19445 goto decode_failure; 19446 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 19447 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 19448 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 19449 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 19450 case 0x034: case 0x014: // xsresp, xsrsqrtesp 19451 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 19452 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 19453 case 0x092: case 0x232: // xsrdpi, xsrsp 19454 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success; 19455 goto decode_failure; 19456 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 19457 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 19458 goto decode_failure; 19459 case 0x0: case 0x020: // xsaddsp, xssubsp 19460 case 0x080: // xsadddp 19461 case 0x060: case 0x0E0: // xsdivsp, xsdivdp 19462 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp 19463 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 19464 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp 19465 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 19466 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp 19467 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 19468 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp 19469 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 19470 case 0x040: case 0x0C0: // xsmulsp, xsmuldp 19471 case 0x0A0: // xssubdp 19472 case 0x016: case 0x096: // xssqrtsp,xssqrtdp 19473 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp 19474 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 19475 goto decode_failure; 19476 case 0x180: // xvadddp 19477 case 0x1E0: // xvdivdp 19478 case 0x1C0: // xvmuldp 19479 case 0x1A0: // xvsubdp 19480 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 19481 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 19482 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 19483 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 19484 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 19485 case 0x196: // xvsqrtdp 19486 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 19487 goto decode_failure; 19488 case 0x100: // xvaddsp 19489 case 0x160: // xvdivsp 19490 case 0x140: // xvmulsp 19491 case 0x120: // xvsubsp 19492 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 19493 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 19494 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 19495 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 19496 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 19497 case 0x116: // xvsqrtsp 19498 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 19499 goto decode_failure; 19500 19501 case 0x250: // xscvuxdsp 19502 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp 19503 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp 19504 case 0x090: // xscvdpuxws 19505 // The above VSX conversion instructions employ some ISA 2.06 19506 // floating point conversion instructions under the covers, 19507 // so if allow_VX (which means "supports ISA 2.06") is not set, 19508 // we'll skip the decode. 19509 if (!allow_VX) goto decode_noVX; 19510 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 19511 goto decode_failure; 19512 19513 case 0x2B0: // xscvdpsxds 19514 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp 19515 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 19516 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 19517 case 0x212: case 0x216: // xscvdpsp, xscvdpspn 19518 case 0x292: case 0x296: // xscvspdp, xscvspdpn 19519 case 0x312: // xvcvdpsp 19520 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 19521 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 19522 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 19523 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 19524 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 19525 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 19526 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 19527 goto decode_failure; 19528 19529 case 0x18C: case 0x38C: // xvcmpeqdp[.] 19530 case 0x10C: case 0x30C: // xvcmpeqsp[.] 19531 case 0x14C: case 0x34C: // xvcmpgesp[.] 19532 case 0x12C: case 0x32C: // xvcmpgtsp[.] 19533 case 0x1CC: case 0x3CC: // xvcmpgedp[.] 19534 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] 19535 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 19536 goto decode_failure; 19537 19538 case 0x134: // xvresp 19539 case 0x1B4: // xvredp 19540 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 19541 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 19542 case 0x300: case 0x320: // xvmaxsp, xvminsp 19543 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 19544 case 0x3B2: case 0x332: // xvabsdp, xvabssp 19545 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 19546 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 19547 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 19548 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 19549 case 0x112: case 0x156: // xvrspi, xvrspic 19550 case 0x172: case 0x152: // xvrspim, xvrspip 19551 case 0x132: // xvrspiz 19552 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 19553 goto decode_failure; 19554 19555 default: 19556 goto decode_failure; 19557 } 19558 break; 19559 } 19560 19561 /* 64bit Integer Stores */ 19562 case 0x3E: // std, stdu, stq 19563 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19564 goto decode_failure; 19565 19566 case 0x3F: 19567 if (!allow_F) goto decode_noF; 19568 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 19569 so we can simply fall through the first switch statement */ 19570 19571 opc2 = IFIELD(theInstr, 1, 5); 19572 switch (opc2) { 19573 /* Floating Point Arith Instructions */ 19574 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 19575 case 0x19: // fmul 19576 if (dis_fp_arith(theInstr)) goto decode_success; 19577 goto decode_failure; 19578 case 0x16: // fsqrt 19579 if (!allow_FX) goto decode_noFX; 19580 if (dis_fp_arith(theInstr)) goto decode_success; 19581 goto decode_failure; 19582 case 0x17: case 0x1A: // fsel, frsqrte 19583 if (!allow_GX) goto decode_noGX; 19584 if (dis_fp_arith(theInstr)) goto decode_success; 19585 goto decode_failure; 19586 19587 /* Floating Point Mult-Add Instructions */ 19588 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 19589 case 0x1F: // fnmadd 19590 if (dis_fp_multadd(theInstr)) goto decode_success; 19591 goto decode_failure; 19592 19593 case 0x18: // fre 19594 if (!allow_GX) goto decode_noGX; 19595 if (dis_fp_arith(theInstr)) goto decode_success; 19596 goto decode_failure; 19597 19598 default: 19599 break; // Fall through 19600 } 19601 19602 opc2 = IFIELD(theInstr, 1, 10); 19603 switch (opc2) { 19604 /* 128-bit DFP instructions */ 19605 case 0x2: // daddq - DFP Add 19606 case 0x202: // dsubq - DFP Subtract 19607 case 0x22: // dmulq - DFP Mult 19608 case 0x222: // ddivq - DFP Divide 19609 if (!allow_DFP) goto decode_noDFP; 19610 if (dis_dfp_arithq( theInstr )) 19611 goto decode_success; 19612 goto decode_failure; 19613 case 0x162: // dxexq - DFP Extract exponent 19614 case 0x362: // diexq - DFP Insert exponent 19615 if (!allow_DFP) goto decode_noDFP; 19616 if (dis_dfp_extract_insertq( theInstr )) 19617 goto decode_success; 19618 goto decode_failure; 19619 19620 case 0x82: // dcmpoq, DFP comparison ordered instruction 19621 case 0x282: // dcmpuq, DFP comparison unordered instruction 19622 if (!allow_DFP) goto decode_noDFP; 19623 if (dis_dfp_compare( theInstr ) ) 19624 goto decode_success; 19625 goto decode_failure; 19626 19627 case 0x102: // dctqpq - DFP convert to DFP extended 19628 case 0x302: // drdpq - DFP round to dfp Long 19629 case 0x122: // dctfixq - DFP convert to fixed quad 19630 case 0x322: // dcffixq - DFP convert from fixed quad 19631 if (!allow_DFP) goto decode_noDFP; 19632 if (dis_dfp_fmt_convq( theInstr )) 19633 goto decode_success; 19634 goto decode_failure; 19635 19636 case 0x2A2: // dtstsfq - DFP number of significant digits 19637 if (!allow_DFP) goto decode_noDFP; 19638 if (dis_dfp_significant_digits(theInstr)) 19639 goto decode_success; 19640 goto decode_failure; 19641 19642 case 0x142: // ddedpdq DFP Decode DPD to BCD 19643 case 0x342: // denbcdq DFP Encode BCD to DPD 19644 if (!allow_DFP) goto decode_noDFP; 19645 if (dis_dfp_bcdq(theInstr)) 19646 goto decode_success; 19647 goto decode_failure; 19648 19649 /* Floating Point Compare Instructions */ 19650 case 0x000: // fcmpu 19651 case 0x020: // fcmpo 19652 if (dis_fp_cmp(theInstr)) goto decode_success; 19653 goto decode_failure; 19654 19655 case 0x080: // ftdiv 19656 case 0x0A0: // ftsqrt 19657 if (dis_fp_tests(theInstr)) goto decode_success; 19658 goto decode_failure; 19659 19660 /* Floating Point Rounding/Conversion Instructions */ 19661 case 0x00C: // frsp 19662 case 0x00E: // fctiw 19663 case 0x00F: // fctiwz 19664 case 0x32E: // fctid 19665 case 0x32F: // fctidz 19666 case 0x34E: // fcfid 19667 if (dis_fp_round(theInstr)) goto decode_success; 19668 goto decode_failure; 19669 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 19670 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 19671 if (!allow_VX) goto decode_noVX; 19672 if (dis_fp_round(theInstr)) goto decode_success; 19673 goto decode_failure; 19674 19675 /* Power6 rounding stuff */ 19676 case 0x1E8: // frim 19677 case 0x1C8: // frip 19678 case 0x188: // frin 19679 case 0x1A8: // friz 19680 /* A hack to check for P6 capability . . . */ 19681 if ((allow_F && allow_V && allow_FX && allow_GX) && 19682 (dis_fp_round(theInstr))) 19683 goto decode_success; 19684 goto decode_failure; 19685 19686 /* Floating Point Move Instructions */ 19687 case 0x008: // fcpsgn 19688 case 0x028: // fneg 19689 case 0x048: // fmr 19690 case 0x088: // fnabs 19691 case 0x108: // fabs 19692 if (dis_fp_move( theInstr )) goto decode_success; 19693 goto decode_failure; 19694 19695 case 0x3c6: case 0x346: // fmrgew, fmrgow 19696 if (dis_fp_merge( theInstr )) goto decode_success; 19697 goto decode_failure; 19698 19699 /* Floating Point Status/Control Register Instructions */ 19700 case 0x026: // mtfsb1 19701 case 0x040: // mcrfs 19702 case 0x046: // mtfsb0 19703 case 0x086: // mtfsfi 19704 case 0x247: // mffs 19705 case 0x2C7: // mtfsf 19706 // Some of the above instructions need to know more about the 19707 // ISA level supported by the host. 19708 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success; 19709 goto decode_failure; 19710 19711 default: 19712 break; // Fall through... 19713 } 19714 19715 opc2 = ifieldOPClo9( theInstr ); 19716 switch (opc2) { 19717 case 0x42: // dscli, DFP shift left 19718 case 0x62: // dscri, DFP shift right 19719 if (!allow_DFP) goto decode_noDFP; 19720 if (dis_dfp_shiftq( theInstr )) 19721 goto decode_success; 19722 goto decode_failure; 19723 case 0xc2: // dtstdc, DFP test data class 19724 case 0xe2: // dtstdg, DFP test data group 19725 if (!allow_DFP) goto decode_noDFP; 19726 if (dis_dfp_class_test( theInstr )) 19727 goto decode_success; 19728 goto decode_failure; 19729 default: 19730 break; 19731 } 19732 19733 opc2 = ifieldOPClo8( theInstr ); 19734 switch (opc2) { 19735 case 0x3: // dquaq - DFP Quantize Quad 19736 case 0x23: // drrndq - DFP Reround Quad 19737 case 0x43: // dquaiq - DFP Quantize immediate Quad 19738 if (!allow_DFP) goto decode_noDFP; 19739 if (dis_dfp_quantize_sig_rrndq( theInstr )) 19740 goto decode_success; 19741 goto decode_failure; 19742 case 0xA2: // dtstexq - DFP Test exponent Quad 19743 if (!allow_DFP) goto decode_noDFP; 19744 if (dis_dfp_exponent_test( theInstr ) ) 19745 goto decode_success; 19746 goto decode_failure; 19747 case 0x63: // drintxq - DFP Round to an integer value 19748 case 0xE3: // drintnq - DFP Round to an integer value 19749 if (!allow_DFP) goto decode_noDFP; 19750 if (dis_dfp_roundq( theInstr )) 19751 goto decode_success; 19752 goto decode_failure; 19753 19754 default: 19755 goto decode_failure; 19756 } 19757 break; 19758 19759 case 0x13: 19760 switch (opc2) { 19761 19762 /* Condition Register Logical Instructions */ 19763 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 19764 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 19765 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 19766 if (dis_cond_logic( theInstr )) goto decode_success; 19767 goto decode_failure; 19768 19769 /* Branch Instructions */ 19770 case 0x210: case 0x010: // bcctr, bclr 19771 if (dis_branch(theInstr, abiinfo, &dres, 19772 resteerOkFn, callback_opaque)) 19773 goto decode_success; 19774 goto decode_failure; 19775 19776 /* Memory Synchronization Instructions */ 19777 case 0x096: // isync 19778 if (dis_memsync( theInstr )) goto decode_success; 19779 goto decode_failure; 19780 19781 default: 19782 goto decode_failure; 19783 } 19784 break; 19785 19786 19787 case 0x1F: 19788 19789 /* For arith instns, bit10 is the OE flag (overflow enable) */ 19790 19791 opc2 = IFIELD(theInstr, 1, 9); 19792 switch (opc2) { 19793 /* Integer Arithmetic Instructions */ 19794 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 19795 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 19796 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 19797 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 19798 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 19799 case 0x0C8: // subfze 19800 if (dis_int_arith( theInstr )) goto decode_success; 19801 goto decode_failure; 19802 19803 case 0x18B: // divweu (implemented as native insn) 19804 case 0x1AB: // divwe (implemented as native insn) 19805 if (!allow_VX) goto decode_noVX; 19806 if (dis_int_arith( theInstr )) goto decode_success; 19807 goto decode_failure; 19808 19809 /* 64bit Integer Arithmetic */ 19810 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 19811 case 0x1C9: case 0x1E9: // divdu, divd 19812 if (!mode64) goto decode_failure; 19813 if (dis_int_arith( theInstr )) goto decode_success; 19814 goto decode_failure; 19815 19816 case 0x1A9: // divde (implemented as native insn) 19817 case 0x189: // divdeuo (implemented as native insn) 19818 if (!allow_VX) goto decode_noVX; 19819 if (!mode64) goto decode_failure; 19820 if (dis_int_arith( theInstr )) goto decode_success; 19821 goto decode_failure; 19822 19823 case 0x1FC: // cmpb 19824 if (dis_int_logic( theInstr )) goto decode_success; 19825 goto decode_failure; 19826 19827 default: 19828 break; // Fall through... 19829 } 19830 19831 /* All remaining opcodes use full 10 bits. */ 19832 19833 opc2 = IFIELD(theInstr, 1, 10); 19834 switch (opc2) { 19835 /* Integer Compare Instructions */ 19836 case 0x000: case 0x020: // cmp, cmpl 19837 if (dis_int_cmp( theInstr )) goto decode_success; 19838 goto decode_failure; 19839 19840 /* Integer Logical Instructions */ 19841 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 19842 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 19843 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 19844 case 0x19C: case 0x13C: // orc, xor 19845 case 0x2DF: case 0x25F: // mftgpr, mffgpr 19846 if (dis_int_logic( theInstr )) goto decode_success; 19847 goto decode_failure; 19848 19849 case 0x28E: case 0x2AE: // tbegin., tend. 19850 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc. 19851 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. 19852 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt. 19853 if (dis_transactional_memory( theInstr, 19854 getUIntPPCendianly( &guest_code[delta + 4]), 19855 abiinfo, &dres, 19856 resteerOkFn, callback_opaque)) 19857 goto decode_success; 19858 goto decode_failure; 19859 19860 /* 64bit Integer Logical Instructions */ 19861 case 0x3DA: case 0x03A: // extsw, cntlzd 19862 if (!mode64) goto decode_failure; 19863 if (dis_int_logic( theInstr )) goto decode_success; 19864 goto decode_failure; 19865 19866 /* 64bit Integer Parity Instructions */ 19867 case 0xba: // prtyd 19868 if (!mode64) goto decode_failure; 19869 if (dis_int_parity( theInstr )) goto decode_success; 19870 goto decode_failure; 19871 19872 case 0x9a: // prtyw 19873 if (dis_int_parity( theInstr )) goto decode_success; 19874 goto decode_failure; 19875 19876 /* Integer Shift Instructions */ 19877 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 19878 case 0x218: // srw 19879 if (dis_int_shift( theInstr )) goto decode_success; 19880 goto decode_failure; 19881 19882 /* 64bit Integer Shift Instructions */ 19883 case 0x01B: case 0x31A: // sld, srad 19884 case 0x33A: case 0x33B: // sradi 19885 case 0x21B: // srd 19886 if (!mode64) goto decode_failure; 19887 if (dis_int_shift( theInstr )) goto decode_success; 19888 goto decode_failure; 19889 19890 /* Integer Load Instructions */ 19891 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 19892 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 19893 case 0x017: case 0x037: // lwzx, lwzux 19894 if (dis_int_load( theInstr )) goto decode_success; 19895 goto decode_failure; 19896 19897 /* 64bit Integer Load Instructions */ 19898 case 0x035: case 0x015: // ldux, ldx 19899 case 0x175: case 0x155: // lwaux, lwax 19900 if (!mode64) goto decode_failure; 19901 if (dis_int_load( theInstr )) goto decode_success; 19902 goto decode_failure; 19903 19904 /* Integer Store Instructions */ 19905 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 19906 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 19907 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19908 goto decode_failure; 19909 19910 /* 64bit Integer Store Instructions */ 19911 case 0x0B5: case 0x095: // stdux, stdx 19912 if (!mode64) goto decode_failure; 19913 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19914 goto decode_failure; 19915 19916 /* Integer Load and Store with Byte Reverse Instructions */ 19917 case 0x214: case 0x294: // ldbrx, stdbrx 19918 if (!mode64) goto decode_failure; 19919 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19920 goto decode_failure; 19921 19922 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx 19923 case 0x396: // sthbrx 19924 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19925 goto decode_failure; 19926 19927 /* Integer Load and Store String Instructions */ 19928 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 19929 case 0x295: { // stswx 19930 Bool stopHere = False; 19931 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 19932 if (!ok) goto decode_failure; 19933 if (stopHere) { 19934 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) ); 19935 dres.jk_StopHere = Ijk_Boring; 19936 dres.whatNext = Dis_StopHere; 19937 } 19938 goto decode_success; 19939 } 19940 19941 /* Memory Synchronization Instructions */ 19942 case 0x034: case 0x074: // lbarx, lharx 19943 case 0x2B6: case 0x2D6: // stbcx, sthcx 19944 if (!allow_isa_2_07) goto decode_noP8; 19945 if (dis_memsync( theInstr )) goto decode_success; 19946 goto decode_failure; 19947 19948 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 19949 case 0x256: // sync 19950 if (dis_memsync( theInstr )) goto decode_success; 19951 goto decode_failure; 19952 19953 /* 64bit Memory Synchronization Instructions */ 19954 case 0x054: case 0x0D6: // ldarx, stdcx. 19955 if (!mode64) goto decode_failure; 19956 if (dis_memsync( theInstr )) goto decode_success; 19957 goto decode_failure; 19958 19959 case 0x114: case 0x0B6: // lqarx, stqcx. 19960 if (dis_memsync( theInstr )) goto decode_success; 19961 goto decode_failure; 19962 19963 /* Processor Control Instructions */ 19964 case 0x33: case 0x73: // mfvsrd, mfvsrwz 19965 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz 19966 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 19967 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 19968 case 0x220: // mcrxrt 19969 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 19970 goto decode_failure; 19971 19972 /* Cache Management Instructions */ 19973 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 19974 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 19975 case 0x3D6: // icbi 19976 if (dis_cache_manage( theInstr, &dres, archinfo )) 19977 goto decode_success; 19978 goto decode_failure; 19979 19980 //zz /* External Control Instructions */ 19981 //zz case 0x136: case 0x1B6: // eciwx, ecowx 19982 //zz DIP("external control op => not implemented\n"); 19983 //zz goto decode_failure; 19984 19985 /* Trap Instructions */ 19986 case 0x004: // tw 19987 if (dis_trap(theInstr, &dres)) goto decode_success; 19988 goto decode_failure; 19989 19990 case 0x044: // td 19991 if (!mode64) goto decode_failure; 19992 if (dis_trap(theInstr, &dres)) goto decode_success; 19993 goto decode_failure; 19994 19995 /* Floating Point Load Instructions */ 19996 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 19997 case 0x277: // lfdux 19998 if (!allow_F) goto decode_noF; 19999 if (dis_fp_load( theInstr )) goto decode_success; 20000 goto decode_failure; 20001 20002 /* Floating Point Store Instructions */ 20003 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 20004 case 0x2F7: // stfdu, stfiwx 20005 if (!allow_F) goto decode_noF; 20006 if (dis_fp_store( theInstr )) goto decode_success; 20007 goto decode_failure; 20008 case 0x3D7: // stfiwx 20009 if (!allow_F) goto decode_noF; 20010 if (!allow_GX) goto decode_noGX; 20011 if (dis_fp_store( theInstr )) goto decode_success; 20012 goto decode_failure; 20013 20014 /* Floating Point Double Pair Indexed Instructions */ 20015 case 0x317: // lfdpx (Power6) 20016 case 0x397: // stfdpx (Power6) 20017 if (!allow_F) goto decode_noF; 20018 if (dis_fp_pair(theInstr)) goto decode_success; 20019 goto decode_failure; 20020 20021 case 0x357: // lfiwax 20022 if (!allow_F) goto decode_noF; 20023 if (dis_fp_load( theInstr )) goto decode_success; 20024 goto decode_failure; 20025 20026 case 0x377: // lfiwzx 20027 if (!allow_F) goto decode_noF; 20028 if (dis_fp_load( theInstr )) goto decode_success; 20029 goto decode_failure; 20030 20031 /* AltiVec instructions */ 20032 20033 /* AV Cache Control - Data streams */ 20034 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 20035 if (!allow_V) goto decode_noV; 20036 if (dis_av_datastream( theInstr )) goto decode_success; 20037 goto decode_failure; 20038 20039 /* AV Load */ 20040 case 0x006: case 0x026: // lvsl, lvsr 20041 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 20042 case 0x067: case 0x167: // lvx, lvxl 20043 if (!allow_V) goto decode_noV; 20044 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 20045 goto decode_failure; 20046 20047 /* AV Store */ 20048 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 20049 case 0x0E7: case 0x1E7: // stvx, stvxl 20050 if (!allow_V) goto decode_noV; 20051 if (dis_av_store( theInstr )) goto decode_success; 20052 goto decode_failure; 20053 20054 /* VSX Load */ 20055 case 0x00C: // lxsiwzx 20056 case 0x04C: // lxsiwax 20057 case 0x20C: // lxsspx 20058 case 0x24C: // lxsdx 20059 case 0x34C: // lxvd2x 20060 case 0x14C: // lxvdsx 20061 case 0x30C: // lxvw4x 20062 // All of these VSX load instructions use some VMX facilities, so 20063 // if allow_V is not set, we'll skip trying to decode. 20064 if (!allow_V) goto decode_noV; 20065 20066 if (dis_vx_load( theInstr )) goto decode_success; 20067 goto decode_failure; 20068 20069 /* VSX Store */ 20070 case 0x08C: // stxsiwx 20071 case 0x28C: // stxsspx 20072 case 0x2CC: // stxsdx 20073 case 0x3CC: // stxvd2x 20074 case 0x38C: // stxvw4x 20075 // All of these VSX store instructions use some VMX facilities, so 20076 // if allow_V is not set, we'll skip trying to decode. 20077 if (!allow_V) goto decode_noV; 20078 20079 if (dis_vx_store( theInstr )) goto decode_success; 20080 goto decode_failure; 20081 20082 /* Miscellaneous ISA 2.06 instructions */ 20083 case 0x1FA: // popcntd 20084 case 0x17A: // popcntw 20085 case 0x7A: // popcntb 20086 if (dis_int_logic( theInstr )) goto decode_success; 20087 goto decode_failure; 20088 20089 case 0x0FC: // bpermd 20090 if (!mode64) goto decode_failure; 20091 if (dis_int_logic( theInstr )) goto decode_success; 20092 goto decode_failure; 20093 20094 default: 20095 /* Deal with some other cases that we would otherwise have 20096 punted on. */ 20097 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 20098 /* only decode this insn when reserved bit 0 (31 in IBM's 20099 notation) is zero */ 20100 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 20101 UInt rT = ifieldRegDS( theInstr ); 20102 UInt rA = ifieldRegA( theInstr ); 20103 UInt rB = ifieldRegB( theInstr ); 20104 UInt bi = ifieldRegC( theInstr ); 20105 putIReg( 20106 rT, 20107 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)), 20108 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 20109 : getIReg(rA), 20110 getIReg(rB)) 20111 20112 ); 20113 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 20114 goto decode_success; 20115 } 20116 goto decode_failure; 20117 } 20118 break; 20119 20120 20121 case 0x04: 20122 /* AltiVec instructions */ 20123 20124 opc2 = IFIELD(theInstr, 0, 6); 20125 switch (opc2) { 20126 /* AV Mult-Add, Mult-Sum */ 20127 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 20128 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 20129 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 20130 if (!allow_V) goto decode_noV; 20131 if (dis_av_multarith( theInstr )) goto decode_success; 20132 goto decode_failure; 20133 20134 /* AV Permutations */ 20135 case 0x2A: // vsel 20136 case 0x2B: // vperm 20137 case 0x2C: // vsldoi 20138 if (!allow_V) goto decode_noV; 20139 if (dis_av_permute( theInstr )) goto decode_success; 20140 goto decode_failure; 20141 20142 case 0x2D: // vpermxor 20143 if (!allow_isa_2_07) goto decode_noP8; 20144 if (dis_av_permute( theInstr )) goto decode_success; 20145 goto decode_failure; 20146 20147 /* AV Floating Point Mult-Add/Sub */ 20148 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 20149 if (!allow_V) goto decode_noV; 20150 if (dis_av_fp_arith( theInstr )) goto decode_success; 20151 goto decode_failure; 20152 20153 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm 20154 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm 20155 if (!allow_V) goto decode_noV; 20156 if (dis_av_quad( theInstr)) goto decode_success; 20157 goto decode_failure; 20158 20159 default: 20160 break; // Fall through... 20161 } 20162 20163 opc2 = IFIELD(theInstr, 0, 9); 20164 switch (opc2) { 20165 /* BCD arithmetic */ 20166 case 0x1: case 0x41: // bcdadd, bcdsub 20167 if (!allow_isa_2_07) goto decode_noP8; 20168 if (dis_av_bcd( theInstr )) goto decode_success; 20169 goto decode_failure; 20170 20171 default: 20172 break; // Fall through... 20173 } 20174 20175 opc2 = IFIELD(theInstr, 0, 11); 20176 switch (opc2) { 20177 /* AV Arithmetic */ 20178 case 0x180: // vaddcuw 20179 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 20180 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 20181 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 20182 case 0x580: // vsubcuw 20183 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 20184 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 20185 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 20186 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 20187 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 20188 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 20189 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 20190 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 20191 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 20192 case 0x008: case 0x048: // vmuloub, vmulouh 20193 case 0x108: case 0x148: // vmulosb, vmulosh 20194 case 0x208: case 0x248: // vmuleub, vmuleuh 20195 case 0x308: case 0x348: // vmulesb, vmulesh 20196 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 20197 case 0x688: case 0x788: // vsum2sws, vsumsws 20198 if (!allow_V) goto decode_noV; 20199 if (dis_av_arith( theInstr )) goto decode_success; 20200 goto decode_failure; 20201 20202 case 0x088: case 0x089: // vmulouw, vmuluwm 20203 case 0x0C0: case 0x0C2: // vaddudm, vmaxud 20204 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd 20205 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw 20206 case 0x4C0: // vsubudm 20207 if (!allow_isa_2_07) goto decode_noP8; 20208 if (dis_av_arith( theInstr )) goto decode_success; 20209 goto decode_failure; 20210 20211 /* AV Polynomial Vector Multiply Add */ 20212 case 0x408: case 0x448: // vpmsumb, vpmsumd 20213 case 0x488: case 0x4C8: // vpmsumw, vpmsumh 20214 if (!allow_isa_2_07) goto decode_noP8; 20215 if (dis_av_polymultarith( theInstr )) goto decode_success; 20216 goto decode_failure; 20217 20218 /* AV Rotate, Shift */ 20219 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 20220 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 20221 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 20222 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 20223 case 0x1C4: case 0x2C4: // vsl, vsr 20224 case 0x40C: case 0x44C: // vslo, vsro 20225 if (!allow_V) goto decode_noV; 20226 if (dis_av_shift( theInstr )) goto decode_success; 20227 goto decode_failure; 20228 20229 case 0x0C4: // vrld 20230 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd 20231 if (!allow_isa_2_07) goto decode_noP8; 20232 if (dis_av_shift( theInstr )) goto decode_success; 20233 goto decode_failure; 20234 20235 /* AV Logic */ 20236 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 20237 case 0x4C4: case 0x504: // vxor, vnor 20238 if (!allow_V) goto decode_noV; 20239 if (dis_av_logic( theInstr )) goto decode_success; 20240 goto decode_failure; 20241 20242 case 0x544: // vorc 20243 case 0x584: case 0x684: // vnand, veqv 20244 if (!allow_isa_2_07) goto decode_noP8; 20245 if (dis_av_logic( theInstr )) goto decode_success; 20246 goto decode_failure; 20247 20248 /* AV Processor Control */ 20249 case 0x604: case 0x644: // mfvscr, mtvscr 20250 if (!allow_V) goto decode_noV; 20251 if (dis_av_procctl( theInstr )) goto decode_success; 20252 goto decode_failure; 20253 20254 /* AV Floating Point Arithmetic */ 20255 case 0x00A: case 0x04A: // vaddfp, vsubfp 20256 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 20257 case 0x1CA: // vlogefp 20258 case 0x40A: case 0x44A: // vmaxfp, vminfp 20259 if (!allow_V) goto decode_noV; 20260 if (dis_av_fp_arith( theInstr )) goto decode_success; 20261 goto decode_failure; 20262 20263 /* AV Floating Point Round/Convert */ 20264 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 20265 case 0x2CA: // vrfim 20266 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 20267 case 0x3CA: // vctsxs 20268 if (!allow_V) goto decode_noV; 20269 if (dis_av_fp_convert( theInstr )) goto decode_success; 20270 goto decode_failure; 20271 20272 /* AV Merge, Splat */ 20273 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 20274 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 20275 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 20276 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 20277 if (!allow_V) goto decode_noV; 20278 if (dis_av_permute( theInstr )) goto decode_success; 20279 goto decode_failure; 20280 20281 case 0x68C: case 0x78C: // vmrgow, vmrgew 20282 if (!allow_isa_2_07) goto decode_noP8; 20283 if (dis_av_permute( theInstr )) goto decode_success; 20284 goto decode_failure; 20285 20286 /* AV Pack, Unpack */ 20287 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 20288 case 0x0CE: // vpkuwus 20289 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 20290 case 0x1CE: // vpkswss 20291 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 20292 case 0x2CE: // vupklsh 20293 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 20294 if (!allow_V) goto decode_noV; 20295 if (dis_av_pack( theInstr )) goto decode_success; 20296 goto decode_failure; 20297 20298 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus 20299 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw 20300 if (!allow_isa_2_07) goto decode_noP8; 20301 if (dis_av_pack( theInstr )) goto decode_success; 20302 goto decode_failure; 20303 20304 case 0x508: case 0x509: // vcipher, vcipherlast 20305 case 0x548: case 0x549: // vncipher, vncipherlast 20306 case 0x5C8: // vsbox 20307 if (!allow_isa_2_07) goto decode_noP8; 20308 if (dis_av_cipher( theInstr )) goto decode_success; 20309 goto decode_failure; 20310 20311 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad 20312 if (!allow_isa_2_07) goto decode_noP8; 20313 if (dis_av_hash( theInstr )) goto decode_success; 20314 goto decode_failure; 20315 20316 case 0x702: case 0x742: // vclzb, vclzh 20317 case 0x782: case 0x7c2: // vclzw, vclzd 20318 if (!allow_isa_2_07) goto decode_noP8; 20319 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20320 goto decode_failure; 20321 20322 case 0x703: case 0x743: // vpopcntb, vpopcnth 20323 case 0x783: case 0x7c3: // vpopcntw, vpopcntd 20324 if (!allow_isa_2_07) goto decode_noP8; 20325 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20326 goto decode_failure; 20327 20328 case 0x50c: // vgbbd 20329 if (!allow_isa_2_07) goto decode_noP8; 20330 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 20331 goto decode_failure; 20332 20333 case 0x140: case 0x100: // vaddcuq, vadduqm 20334 case 0x540: case 0x500: // vsubcuq, vsubuqm 20335 case 0x54C: // vbpermq 20336 if (!allow_V) goto decode_noV; 20337 if (dis_av_quad( theInstr)) goto decode_success; 20338 goto decode_failure; 20339 20340 default: 20341 break; // Fall through... 20342 } 20343 20344 opc2 = IFIELD(theInstr, 0, 10); 20345 switch (opc2) { 20346 20347 /* AV Compare */ 20348 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 20349 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 20350 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 20351 if (!allow_V) goto decode_noV; 20352 if (dis_av_cmp( theInstr )) goto decode_success; 20353 goto decode_failure; 20354 20355 case 0x0C7: // vcmpequd 20356 case 0x2C7: // vcmpgtud 20357 case 0x3C7: // vcmpgtsd 20358 if (!allow_isa_2_07) goto decode_noP8; 20359 if (dis_av_cmp( theInstr )) goto decode_success; 20360 goto decode_failure; 20361 20362 /* AV Floating Point Compare */ 20363 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 20364 case 0x3C6: // vcmpbfp 20365 if (!allow_V) goto decode_noV; 20366 if (dis_av_fp_cmp( theInstr )) goto decode_success; 20367 goto decode_failure; 20368 20369 default: 20370 goto decode_failure; 20371 } 20372 break; 20373 20374 default: 20375 goto decode_failure; 20376 20377 decode_noF: 20378 vassert(!allow_F); 20379 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n" 20380 "can't be handled by Valgrind on this host. This instruction\n" 20381 "requires a host that supports Floating Point instructions.\n", 20382 theInstr); 20383 goto not_supported; 20384 decode_noV: 20385 vassert(!allow_V); 20386 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n" 20387 "that can't be handled by Valgrind. If this instruction is an\n" 20388 "Altivec instruction, Valgrind must be run on a host that supports" 20389 "AltiVec instructions. If the application was compiled for e500, then\n" 20390 "unfortunately Valgrind does not yet support e500 instructions.\n", 20391 theInstr); 20392 goto not_supported; 20393 decode_noVX: 20394 vassert(!allow_VX); 20395 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n" 20396 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n" 20397 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n", 20398 theInstr); 20399 goto not_supported; 20400 decode_noFX: 20401 vassert(!allow_FX); 20402 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n" 20403 "that can't be handled by Valgrind on this host. This instruction\n" 20404 "requires a host that supports the General Purpose-Optional instructions.\n", 20405 theInstr); 20406 goto not_supported; 20407 decode_noGX: 20408 vassert(!allow_GX); 20409 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n" 20410 "that can't be handled by Valgrind on this host. This instruction\n" 20411 "requires a host that supports the Graphic-Optional instructions.\n", 20412 theInstr); 20413 goto not_supported; 20414 decode_noDFP: 20415 vassert(!allow_DFP); 20416 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n" 20417 "that can't be handled by Valgrind on this host. This instruction\n" 20418 "requires a host that supports DFP instructions.\n", 20419 theInstr); 20420 goto not_supported; 20421 decode_noP8: 20422 vassert(!allow_isa_2_07); 20423 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n" 20424 "by Valgrind on this host. This instruction requires a host that\n" 20425 "supports Power 8 instructions.\n", 20426 theInstr); 20427 goto not_supported; 20428 20429 20430 decode_failure: 20431 /* All decode failures end up here. */ 20432 opc2 = (theInstr) & 0x7FF; 20433 if (sigill_diag) { 20434 vex_printf("disInstr(ppc): unhandled instruction: " 20435 "0x%x\n", theInstr); 20436 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 20437 opc1, opc1, opc2, opc2); 20438 } 20439 20440 not_supported: 20441 /* Tell the dispatcher that this insn cannot be decoded, and so has 20442 not been executed, and (is currently) the next to be executed. 20443 CIA should be up-to-date since it made so at the start of each 20444 insn, but nevertheless be paranoid and update it again right 20445 now. */ 20446 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 20447 dres.len = 0; 20448 dres.whatNext = Dis_StopHere; 20449 dres.jk_StopHere = Ijk_NoDecode; 20450 dres.continueAt = 0; 20451 return dres; 20452 } /* switch (opc) for the main (primary) opcode switch. */ 20453 20454 decode_success: 20455 /* All decode successes end up here. */ 20456 switch (dres.whatNext) { 20457 case Dis_Continue: 20458 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4)); 20459 break; 20460 case Dis_ResteerU: 20461 case Dis_ResteerC: 20462 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt)); 20463 break; 20464 case Dis_StopHere: 20465 break; 20466 default: 20467 vassert(0); 20468 } 20469 DIP("\n"); 20470 20471 if (dres.len == 0) { 20472 dres.len = 4; 20473 } else { 20474 vassert(dres.len == 20); 20475 } 20476 return dres; 20477 } 20478 20479 #undef DIP 20480 #undef DIS 20481 20482 20483 /*------------------------------------------------------------*/ 20484 /*--- Top-level fn ---*/ 20485 /*------------------------------------------------------------*/ 20486 20487 /* Disassemble a single instruction into IR. The instruction 20488 is located in host memory at &guest_code[delta]. */ 20489 20490 DisResult disInstr_PPC ( IRSB* irsb_IN, 20491 Bool (*resteerOkFn) ( void*, Addr ), 20492 Bool resteerCisOk, 20493 void* callback_opaque, 20494 const UChar* guest_code_IN, 20495 Long delta, 20496 Addr guest_IP, 20497 VexArch guest_arch, 20498 const VexArchInfo* archinfo, 20499 const VexAbiInfo* abiinfo, 20500 VexEndness host_endness_IN, 20501 Bool sigill_diag_IN ) 20502 { 20503 IRType ty; 20504 DisResult dres; 20505 UInt mask32, mask64; 20506 UInt hwcaps_guest = archinfo->hwcaps; 20507 20508 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 20509 20510 /* global -- ick */ 20511 mode64 = guest_arch == VexArchPPC64; 20512 ty = mode64 ? Ity_I64 : Ity_I32; 20513 if (!mode64 && (host_endness_IN == VexEndnessLE)) { 20514 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n"); 20515 dres.len = 0; 20516 dres.whatNext = Dis_StopHere; 20517 dres.jk_StopHere = Ijk_NoDecode; 20518 dres.continueAt = 0; 20519 return dres; 20520 } 20521 20522 /* do some sanity checks */ 20523 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 20524 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX 20525 | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07; 20526 20527 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 20528 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP 20529 | VEX_HWCAPS_PPC64_ISA2_07; 20530 20531 if (mode64) { 20532 vassert((hwcaps_guest & mask32) == 0); 20533 } else { 20534 vassert((hwcaps_guest & mask64) == 0); 20535 } 20536 20537 /* Set globals (see top of this file) */ 20538 guest_code = guest_code_IN; 20539 irsb = irsb_IN; 20540 host_endness = host_endness_IN; 20541 20542 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 20543 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 20544 20545 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque, 20546 delta, archinfo, abiinfo, sigill_diag_IN); 20547 20548 return dres; 20549 } 20550 20551 20552 /*------------------------------------------------------------*/ 20553 /*--- Unused stuff ---*/ 20554 /*------------------------------------------------------------*/ 20555 20556 ///* A potentially more memcheck-friendly implementation of Clz32, with 20557 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 20558 // 20559 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 20560 //{ 20561 // /* Welcome ... to SSA R Us. */ 20562 // IRTemp n1 = newTemp(Ity_I32); 20563 // IRTemp n2 = newTemp(Ity_I32); 20564 // IRTemp n3 = newTemp(Ity_I32); 20565 // IRTemp n4 = newTemp(Ity_I32); 20566 // IRTemp n5 = newTemp(Ity_I32); 20567 // IRTemp n6 = newTemp(Ity_I32); 20568 // IRTemp n7 = newTemp(Ity_I32); 20569 // IRTemp n8 = newTemp(Ity_I32); 20570 // IRTemp n9 = newTemp(Ity_I32); 20571 // IRTemp n10 = newTemp(Ity_I32); 20572 // IRTemp n11 = newTemp(Ity_I32); 20573 // IRTemp n12 = newTemp(Ity_I32); 20574 // 20575 // /* First, propagate the most significant 1-bit into all lower 20576 // positions in the word. */ 20577 // /* unsigned int clz ( unsigned int n ) 20578 // { 20579 // n |= (n >> 1); 20580 // n |= (n >> 2); 20581 // n |= (n >> 4); 20582 // n |= (n >> 8); 20583 // n |= (n >> 16); 20584 // return bitcount(~n); 20585 // } 20586 // */ 20587 // assign(n1, mkexpr(arg)); 20588 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 20589 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 20590 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 20591 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 20592 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 20593 // /* This gives a word of the form 0---01---1. Now invert it, giving 20594 // a word of the form 1---10---0, then do a population-count idiom 20595 // (to count the 1s, which is the number of leading zeroes, or 32 20596 // if the original word was 0. */ 20597 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 20598 // 20599 // /* unsigned int bitcount ( unsigned int n ) 20600 // { 20601 // n = n - ((n >> 1) & 0x55555555); 20602 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 20603 // n = (n + (n >> 4)) & 0x0F0F0F0F; 20604 // n = n + (n >> 8); 20605 // n = (n + (n >> 16)) & 0x3F; 20606 // return n; 20607 // } 20608 // */ 20609 // assign(n8, 20610 // binop(Iop_Sub32, 20611 // mkexpr(n7), 20612 // binop(Iop_And32, 20613 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 20614 // mkU32(0x55555555)))); 20615 // assign(n9, 20616 // binop(Iop_Add32, 20617 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 20618 // binop(Iop_And32, 20619 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 20620 // mkU32(0x33333333)))); 20621 // assign(n10, 20622 // binop(Iop_And32, 20623 // binop(Iop_Add32, 20624 // mkexpr(n9), 20625 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 20626 // mkU32(0x0F0F0F0F))); 20627 // assign(n11, 20628 // binop(Iop_Add32, 20629 // mkexpr(n10), 20630 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 20631 // assign(n12, 20632 // binop(Iop_Add32, 20633 // mkexpr(n11), 20634 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 20635 // return 20636 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 20637 //} 20638 20639 /*--------------------------------------------------------------------*/ 20640 /*--- end guest_ppc_toIR.c ---*/ 20641 /*--------------------------------------------------------------------*/ 20642