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-2017 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 /* The OV32 and CA32 bits were added with ISA3.0 */ 243 static Bool OV32_CA32_supported = False; 244 245 #define SIGN_BIT 0x8000000000000000ULL 246 #define SIGN_MASK 0x7fffffffffffffffULL 247 #define SIGN_BIT32 0x80000000 248 #define SIGN_MASK32 0x7fffffff 249 250 251 /*------------------------------------------------------------*/ 252 /*--- Debugging output ---*/ 253 /*------------------------------------------------------------*/ 254 255 #define DIP(format, args...) \ 256 if (vex_traceflags & VEX_TRACE_FE) \ 257 vex_printf(format, ## args) 258 259 #define DIS(buf, format, args...) \ 260 if (vex_traceflags & VEX_TRACE_FE) \ 261 vex_sprintf(buf, format, ## args) 262 263 264 /*------------------------------------------------------------*/ 265 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 266 /*------------------------------------------------------------*/ 267 268 #define offsetofPPCGuestState(_x) \ 269 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 270 offsetof(VexGuestPPC32State, _x)) 271 272 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 273 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 274 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 275 #define OFFB_LR offsetofPPCGuestState(guest_LR) 276 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 277 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 278 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 279 #define OFFB_XER_OV32 offsetofPPCGuestState(guest_XER_OV32) 280 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 281 #define OFFB_XER_CA32 offsetofPPCGuestState(guest_XER_CA32) 282 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 283 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 284 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 285 #define OFFB_C_FPCC offsetofPPCGuestState(guest_C_FPCC) 286 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 287 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 288 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 289 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 290 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 291 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 292 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 293 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 294 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 295 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU) 296 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 297 #define OFFB_PPR offsetofPPCGuestState(guest_PPR) 298 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB) 299 300 301 /*------------------------------------------------------------*/ 302 /*--- Extract instruction fields --- */ 303 /*------------------------------------------------------------*/ 304 305 /* Extract field from insn, given idx (zero = lsb) and field length */ 306 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 307 308 /* Extract primary opcode, instr[31:26] */ 309 static UChar ifieldOPC( UInt instr ) { 310 return toUChar( IFIELD( instr, 26, 6 ) ); 311 } 312 313 /* Extract 10-bit secondary opcode, instr[10:1] */ 314 static UInt ifieldOPClo10 ( UInt instr) { 315 return IFIELD( instr, 1, 10 ); 316 } 317 318 /* Extract 9-bit secondary opcode, instr[9:1] */ 319 static UInt ifieldOPClo9 ( UInt instr) { 320 return IFIELD( instr, 1, 9 ); 321 } 322 323 /* Extract 8-bit secondary opcode, instr[8:1] */ 324 static UInt ifieldOPClo8 ( UInt instr) { 325 return IFIELD( instr, 1, 8 ); 326 } 327 328 /* Extract 5-bit secondary opcode, instr[5:1] */ 329 static UInt ifieldOPClo5 ( UInt instr) { 330 return IFIELD( instr, 1, 5 ); 331 } 332 333 /* Extract 2-bit secondary opcode, instr[1:0] */ 334 static UInt ifieldOPC0o2 ( UInt instr) { 335 return IFIELD( instr, 0, 2 ); 336 } 337 338 /* Extract RD (destination register) field, instr[25:21] */ 339 static UChar ifieldRegDS( UInt instr ) { 340 return toUChar( IFIELD( instr, 21, 5 ) ); 341 } 342 343 /* Extract XT (destination register) field, instr[0,25:21] */ 344 static UChar ifieldRegXT ( UInt instr ) 345 { 346 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 347 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 348 return (upper_bit << 5) | lower_bits; 349 } 350 351 /* Extract XS (store source register) field, instr[0,25:21] */ 352 static inline UChar ifieldRegXS ( UInt instr ) 353 { 354 return ifieldRegXT ( instr ); 355 } 356 357 /* Extract RA (1st source register) field, instr[20:16] */ 358 static UChar ifieldRegA ( UInt instr ) { 359 return toUChar( IFIELD( instr, 16, 5 ) ); 360 } 361 362 /* Extract XA (1st source register) field, instr[2,20:16] */ 363 static UChar ifieldRegXA ( UInt instr ) 364 { 365 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 366 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 367 return (upper_bit << 5) | lower_bits; 368 } 369 370 /* Extract RB (2nd source register) field, instr[15:11] */ 371 static UChar ifieldRegB ( UInt instr ) { 372 return toUChar( IFIELD( instr, 11, 5 ) ); 373 } 374 375 /* Extract XB (2nd source register) field, instr[1,15:11] */ 376 static UChar ifieldRegXB ( UInt instr ) 377 { 378 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 379 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 380 return (upper_bit << 5) | lower_bits; 381 } 382 383 /* Extract RC (3rd source register) field, instr[10:6] */ 384 static UChar ifieldRegC ( UInt instr ) { 385 return toUChar( IFIELD( instr, 6, 5 ) ); 386 } 387 388 /* Extract XC (3rd source register) field, instr[3,10:6] */ 389 static UChar ifieldRegXC ( UInt instr ) 390 { 391 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 392 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 393 return (upper_bit << 5) | lower_bits; 394 } 395 396 /* Extract bit 10, instr[10] */ 397 static UChar ifieldBIT10 ( UInt instr ) { 398 return toUChar( IFIELD( instr, 10, 1 ) ); 399 } 400 401 /* Extract 2nd lowest bit, instr[1] */ 402 static UChar ifieldBIT1 ( UInt instr ) { 403 return toUChar( IFIELD( instr, 1, 1 ) ); 404 } 405 406 /* Extract lowest bit, instr[0] */ 407 static UChar ifieldBIT0 ( UInt instr ) { 408 return toUChar( instr & 0x1 ); 409 } 410 411 /* Extract unsigned bottom half, instr[15:0] */ 412 static UInt ifieldUIMM16 ( UInt instr ) { 413 return instr & 0xFFFF; 414 } 415 416 /* Extract unsigned bottom 26 bits, instr[25:0] */ 417 static UInt ifieldUIMM26 ( UInt instr ) { 418 return instr & 0x3FFFFFF; 419 } 420 421 /* Extract DM field, instr[9:8] */ 422 static UChar ifieldDM ( UInt instr ) { 423 return toUChar( IFIELD( instr, 8, 2 ) ); 424 } 425 426 /* Extract SHW field, instr[9:8] */ 427 static inline UChar ifieldSHW ( UInt instr ) 428 { 429 return ifieldDM ( instr ); 430 } 431 432 /*------------------------------------------------------------*/ 433 /*--- Guest-state identifiers ---*/ 434 /*------------------------------------------------------------*/ 435 436 typedef enum { 437 PPC_GST_CIA, // Current Instruction Address 438 PPC_GST_LR, // Link Register 439 PPC_GST_CTR, // Count Register 440 PPC_GST_XER, // Overflow, carry flags, byte count 441 PPC_GST_CR, // Condition Register 442 PPC_GST_FPSCR, // Floating Point Status/Control Register 443 PPC_GST_VRSAVE, // Vector Save/Restore Register 444 PPC_GST_VSCR, // Vector Status and Control Register 445 PPC_GST_EMWARN, // Emulation warnings 446 PPC_GST_CMSTART,// For icbi: start of area to invalidate 447 PPC_GST_CMLEN, // For icbi: length of area to invalidate 448 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 449 PPC_GST_SPRG3_RO, // SPRG3 450 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 451 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 452 PPC_GST_TEXASR, // Transactional EXception And Summary Register 453 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 454 PPC_GST_PPR, // Program Priority register 455 PPC_GST_PPR32, // Upper 32-bits of Program Priority register 456 PPC_GST_PSPB, /* Problem State Priority Boost register, Note, the 457 * register is initialized to a non-zero value. Currently 458 * Valgrind is not supporting the register value to 459 * automatically decrement. Could be added later if 460 * needed. 461 */ 462 PPC_GST_MAX 463 } PPC_GST; 464 465 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 466 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 467 #define MASK_FPSCR_C_FPCC 0x1F000ULL // Floating-Point Condition code FPCC 468 469 #define MASK_VSCR_VALID 0x00010001 470 471 472 /*------------------------------------------------------------*/ 473 /*--- FP Helpers ---*/ 474 /*------------------------------------------------------------*/ 475 476 /* Produce the 32-bit pattern corresponding to the supplied 477 float. */ 478 static UInt float_to_bits ( Float f ) 479 { 480 union { UInt i; Float f; } u; 481 vassert(4 == sizeof(UInt)); 482 vassert(4 == sizeof(Float)); 483 vassert(4 == sizeof(u)); 484 u.f = f; 485 return u.i; 486 } 487 488 489 /*------------------------------------------------------------*/ 490 /*--- Misc Helpers ---*/ 491 /*------------------------------------------------------------*/ 492 493 /* Generate mask with 1's from 'begin' through 'end', 494 wrapping if begin > end. 495 begin->end works from right to left, 0=lsb 496 */ 497 static UInt MASK32( UInt begin, UInt end ) 498 { 499 UInt m1, m2, mask; 500 vassert(begin < 32); 501 vassert(end < 32); 502 m1 = ((UInt)(-1)) << begin; 503 m2 = ((UInt)(-1)) << end << 1; 504 mask = m1 ^ m2; 505 if (begin > end) mask = ~mask; // wrap mask 506 return mask; 507 } 508 509 static ULong MASK64( UInt begin, UInt end ) 510 { 511 ULong m1, m2, mask; 512 vassert(begin < 64); 513 vassert(end < 64); 514 m1 = ((ULong)(-1)) << begin; 515 m2 = ((ULong)(-1)) << end << 1; 516 mask = m1 ^ m2; 517 if (begin > end) mask = ~mask; // wrap mask 518 return mask; 519 } 520 521 static Addr64 nextInsnAddr( void ) 522 { 523 return guest_CIA_curr_instr + 4; 524 } 525 526 527 /*------------------------------------------------------------*/ 528 /*--- Helper bits and pieces for deconstructing the ---*/ 529 /*--- ppc32/64 insn stream. ---*/ 530 /*------------------------------------------------------------*/ 531 532 /* Add a statement to the list held by "irsb". */ 533 static void stmt ( IRStmt* st ) 534 { 535 addStmtToIRSB( irsb, st ); 536 } 537 538 /* Generate a new temporary of the given type. */ 539 static IRTemp newTemp ( IRType ty ) 540 { 541 vassert(isPlausibleIRType(ty)); 542 return newIRTemp( irsb->tyenv, ty ); 543 } 544 545 /* Various simple conversions */ 546 547 static UChar extend_s_5to8 ( UChar x ) 548 { 549 return toUChar((((Int)x) << 27) >> 27); 550 } 551 552 static UInt extend_s_8to32( UChar x ) 553 { 554 return (UInt)((((Int)x) << 24) >> 24); 555 } 556 557 static UInt extend_s_16to32 ( UInt x ) 558 { 559 return (UInt)((((Int)x) << 16) >> 16); 560 } 561 562 static ULong extend_s_16to64 ( UInt x ) 563 { 564 return (ULong)((((Long)x) << 48) >> 48); 565 } 566 567 static ULong extend_s_26to64 ( UInt x ) 568 { 569 return (ULong)((((Long)x) << 38) >> 38); 570 } 571 572 static ULong extend_s_32to64 ( UInt x ) 573 { 574 return (ULong)((((Long)x) << 32) >> 32); 575 } 576 577 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 578 of the underlying host. */ 579 static UInt getUIntPPCendianly ( const UChar* p ) 580 { 581 UInt w = 0; 582 if (host_endness == VexEndnessBE) { 583 w = (w << 8) | p[0]; 584 w = (w << 8) | p[1]; 585 w = (w << 8) | p[2]; 586 w = (w << 8) | p[3]; 587 } else { 588 w = (w << 8) | p[3]; 589 w = (w << 8) | p[2]; 590 w = (w << 8) | p[1]; 591 w = (w << 8) | p[0]; 592 } 593 return w; 594 } 595 596 597 /*------------------------------------------------------------*/ 598 /*--- Helpers for constructing IR. ---*/ 599 /*------------------------------------------------------------*/ 600 601 static void assign ( IRTemp dst, IRExpr* e ) 602 { 603 stmt( IRStmt_WrTmp(dst, e) ); 604 } 605 606 /* This generates a normal (non store-conditional) store. */ 607 static void store ( IRExpr* addr, IRExpr* data ) 608 { 609 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 610 vassert(tyA == Ity_I32 || tyA == Ity_I64); 611 612 if (host_endness == VexEndnessBE) 613 stmt( IRStmt_Store(Iend_BE, addr, data) ); 614 else 615 stmt( IRStmt_Store(Iend_LE, addr, data) ); 616 } 617 618 static IRExpr* unop ( IROp op, IRExpr* a ) 619 { 620 return IRExpr_Unop(op, a); 621 } 622 623 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 624 { 625 return IRExpr_Binop(op, a1, a2); 626 } 627 628 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 629 { 630 return IRExpr_Triop(op, a1, a2, a3); 631 } 632 633 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 634 IRExpr* a3, IRExpr* a4 ) 635 { 636 return IRExpr_Qop(op, a1, a2, a3, a4); 637 } 638 639 static IRExpr* mkexpr ( IRTemp tmp ) 640 { 641 return IRExpr_RdTmp(tmp); 642 } 643 644 #define mkU1(_n) IRExpr_Const(IRConst_U1(_n)) 645 646 static IRExpr* mkU8 ( UChar i ) 647 { 648 return IRExpr_Const(IRConst_U8(i)); 649 } 650 651 static IRExpr* mkU16 ( UInt i ) 652 { 653 return IRExpr_Const(IRConst_U16(i)); 654 } 655 656 static IRExpr* mkU32 ( UInt i ) 657 { 658 return IRExpr_Const(IRConst_U32(i)); 659 } 660 661 static IRExpr* mkU64 ( ULong i ) 662 { 663 return IRExpr_Const(IRConst_U64(i)); 664 } 665 666 static IRExpr* mkV128 ( UShort i ) 667 { 668 vassert(i == 0 || i == 0xffff); 669 return IRExpr_Const(IRConst_V128(i)); 670 } 671 672 /* This generates a normal (non load-linked) load. */ 673 static IRExpr* load ( IRType ty, IRExpr* addr ) 674 { 675 if (host_endness == VexEndnessBE) 676 return IRExpr_Load(Iend_BE, ty, addr); 677 else 678 return IRExpr_Load(Iend_LE, ty, addr); 679 } 680 681 static IRStmt* stmt_load ( IRTemp result, 682 IRExpr* addr, IRExpr* storedata ) 683 { 684 if (host_endness == VexEndnessBE) 685 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 686 else 687 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 688 } 689 690 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 691 { 692 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 693 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 694 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 695 unop(Iop_1Uto32, arg2))); 696 } 697 698 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 699 { 700 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 701 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 702 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 703 unop(Iop_1Uto32, arg2))); 704 } 705 706 static inline IRExpr* mkXOr4_32( IRTemp t0, IRTemp t1, IRTemp t2, 707 IRTemp t3 ) 708 { 709 return binop( Iop_Xor32, 710 binop( Iop_Xor32, mkexpr( t0 ), mkexpr( t1 ) ), 711 binop( Iop_Xor32, mkexpr( t2 ), mkexpr( t3 ) ) ); 712 } 713 714 static inline IRExpr* mkOr3_V128( IRTemp t0, IRTemp t1, IRTemp t2 ) 715 { 716 return binop( Iop_OrV128, 717 mkexpr( t0 ), 718 binop( Iop_OrV128, mkexpr( t1 ), mkexpr( t2 ) ) ); 719 } 720 721 static inline IRExpr* mkOr4_V128( IRTemp t0, IRTemp t1, IRTemp t2, 722 IRTemp t3 ) 723 { 724 return binop( Iop_OrV128, 725 binop( Iop_OrV128, mkexpr( t0 ), mkexpr( t1 ) ), 726 binop( Iop_OrV128, mkexpr( t2 ), mkexpr( t3 ) ) ); 727 } 728 729 static inline IRExpr* mkOr4_V128_expr( IRExpr* t0, IRExpr* t1, IRExpr* t2, 730 IRExpr* t3 ) 731 { 732 /* arguments are already expressions */ 733 return binop( Iop_OrV128, 734 binop( Iop_OrV128, ( t0 ), ( t1 ) ), 735 binop( Iop_OrV128, ( t2 ), ( t3 ) ) ); 736 } 737 738 static IRExpr* mkNOT1 ( IRExpr* arg1 ) 739 { 740 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 741 return unop(Iop_32to1, unop(Iop_Not32, unop(Iop_1Uto32, arg1) ) ); 742 } 743 744 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 745 static void expand8Ux16( IRExpr* vIn, 746 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 747 { 748 IRTemp ones8x16 = newTemp(Ity_V128); 749 750 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 751 vassert(vEvn && *vEvn == IRTemp_INVALID); 752 vassert(vOdd && *vOdd == IRTemp_INVALID); 753 *vEvn = newTemp(Ity_V128); 754 *vOdd = newTemp(Ity_V128); 755 756 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 757 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 758 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 759 binop(Iop_ShrV128, vIn, mkU8(8))) ); 760 } 761 762 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 763 static void expand8Sx16( IRExpr* vIn, 764 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 765 { 766 IRTemp ones8x16 = newTemp(Ity_V128); 767 768 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 769 vassert(vEvn && *vEvn == IRTemp_INVALID); 770 vassert(vOdd && *vOdd == IRTemp_INVALID); 771 *vEvn = newTemp(Ity_V128); 772 *vOdd = newTemp(Ity_V128); 773 774 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 775 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 776 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 777 binop(Iop_ShrV128, vIn, mkU8(8))) ); 778 } 779 780 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 781 static void expand16Ux8( IRExpr* vIn, 782 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 783 { 784 IRTemp ones16x8 = newTemp(Ity_V128); 785 786 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 787 vassert(vEvn && *vEvn == IRTemp_INVALID); 788 vassert(vOdd && *vOdd == IRTemp_INVALID); 789 *vEvn = newTemp(Ity_V128); 790 *vOdd = newTemp(Ity_V128); 791 792 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 793 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 794 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 795 binop(Iop_ShrV128, vIn, mkU8(16))) ); 796 } 797 798 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 799 static void expand16Sx8( IRExpr* vIn, 800 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 801 { 802 IRTemp ones16x8 = newTemp(Ity_V128); 803 804 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 805 vassert(vEvn && *vEvn == IRTemp_INVALID); 806 vassert(vOdd && *vOdd == IRTemp_INVALID); 807 *vEvn = newTemp(Ity_V128); 808 *vOdd = newTemp(Ity_V128); 809 810 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 811 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 812 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 813 binop(Iop_ShrV128, vIn, mkU8(16))) ); 814 } 815 816 /* break V128 to 4xF64's*/ 817 static void breakV128to4xF64( IRExpr* t128, 818 /*OUTs*/ 819 IRTemp* t3, IRTemp* t2, 820 IRTemp* t1, IRTemp* t0 ) 821 { 822 IRTemp hi64 = newTemp(Ity_I64); 823 IRTemp lo64 = newTemp(Ity_I64); 824 825 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 826 vassert(t0 && *t0 == IRTemp_INVALID); 827 vassert(t1 && *t1 == IRTemp_INVALID); 828 vassert(t2 && *t2 == IRTemp_INVALID); 829 vassert(t3 && *t3 == IRTemp_INVALID); 830 *t0 = newTemp(Ity_F64); 831 *t1 = newTemp(Ity_F64); 832 *t2 = newTemp(Ity_F64); 833 *t3 = newTemp(Ity_F64); 834 835 assign( hi64, unop(Iop_V128HIto64, t128) ); 836 assign( lo64, unop(Iop_V128to64, t128) ); 837 assign( *t3, 838 unop( Iop_F32toF64, 839 unop( Iop_ReinterpI32asF32, 840 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 841 assign( *t2, 842 unop( Iop_F32toF64, 843 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 844 assign( *t1, 845 unop( Iop_F32toF64, 846 unop( Iop_ReinterpI32asF32, 847 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 848 assign( *t0, 849 unop( Iop_F32toF64, 850 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 851 } 852 853 854 /* break V128 to 4xI32's, then sign-extend to I64's */ 855 static void breakV128to4x64S( 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_I64); 869 *t1 = newTemp(Ity_I64); 870 *t2 = newTemp(Ity_I64); 871 *t3 = newTemp(Ity_I64); 872 873 assign( hi64, unop(Iop_V128HIto64, t128) ); 874 assign( lo64, unop(Iop_V128to64, t128) ); 875 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 876 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 877 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 878 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 879 } 880 881 /* break V128 to 4xI32's, then zero-extend to I64's */ 882 static void breakV128to4x64U ( IRExpr* t128, 883 /*OUTs*/ 884 IRTemp* t3, IRTemp* t2, 885 IRTemp* t1, IRTemp* t0 ) 886 { 887 IRTemp hi64 = newTemp(Ity_I64); 888 IRTemp lo64 = newTemp(Ity_I64); 889 890 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 891 vassert(t0 && *t0 == IRTemp_INVALID); 892 vassert(t1 && *t1 == IRTemp_INVALID); 893 vassert(t2 && *t2 == IRTemp_INVALID); 894 vassert(t3 && *t3 == IRTemp_INVALID); 895 *t0 = newTemp(Ity_I64); 896 *t1 = newTemp(Ity_I64); 897 *t2 = newTemp(Ity_I64); 898 *t3 = newTemp(Ity_I64); 899 900 assign( hi64, unop(Iop_V128HIto64, t128) ); 901 assign( lo64, unop(Iop_V128to64, t128) ); 902 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 903 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 904 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 905 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 906 } 907 908 static void breakV128to4x32( IRExpr* t128, 909 /*OUTs*/ 910 IRTemp* t3, IRTemp* t2, 911 IRTemp* t1, IRTemp* t0 ) 912 { 913 IRTemp hi64 = newTemp(Ity_I64); 914 IRTemp lo64 = newTemp(Ity_I64); 915 916 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 917 vassert(t0 && *t0 == IRTemp_INVALID); 918 vassert(t1 && *t1 == IRTemp_INVALID); 919 vassert(t2 && *t2 == IRTemp_INVALID); 920 vassert(t3 && *t3 == IRTemp_INVALID); 921 *t0 = newTemp(Ity_I32); 922 *t1 = newTemp(Ity_I32); 923 *t2 = newTemp(Ity_I32); 924 *t3 = newTemp(Ity_I32); 925 926 assign( hi64, unop(Iop_V128HIto64, t128) ); 927 assign( lo64, unop(Iop_V128to64, t128) ); 928 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 929 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 930 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 931 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 932 } 933 934 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 935 IRTemp t1, IRTemp t0 ) 936 { 937 return 938 binop( Iop_64HLtoV128, 939 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 940 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 941 ); 942 } 943 944 static IRExpr* extract_field_from_vector( IRTemp vB, IRExpr* index, UInt mask) 945 { 946 /* vB is a vector, extract bits starting at index to size of mask */ 947 return unop( Iop_V128to64, 948 binop( Iop_AndV128, 949 binop( Iop_ShrV128, 950 mkexpr( vB ), 951 unop( Iop_64to8, 952 binop( Iop_Mul64, index, 953 mkU64( 8 ) ) ) ), 954 binop( Iop_64HLtoV128, 955 mkU64( 0x0 ), 956 mkU64( mask ) ) ) ); 957 } 958 959 /* Signed saturating narrow 64S to 32 */ 960 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 961 { 962 IRTemp hi32 = newTemp(Ity_I32); 963 IRTemp lo32 = newTemp(Ity_I32); 964 965 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 966 967 assign( hi32, unop(Iop_64HIto32, t64)); 968 assign( lo32, unop(Iop_64to32, t64)); 969 970 return IRExpr_ITE( 971 /* if (hi32 == (lo32 >>s 31)) */ 972 binop(Iop_CmpEQ32, mkexpr(hi32), 973 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 974 /* then: within signed-32 range: lo half good enough */ 975 mkexpr(lo32), 976 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 977 binop(Iop_Add32, mkU32(0x7FFFFFFF), 978 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 979 } 980 981 /* Unsigned saturating narrow 64S to 32 */ 982 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 983 { 984 IRTemp hi32 = newTemp(Ity_I32); 985 IRTemp lo32 = newTemp(Ity_I32); 986 987 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 988 989 assign( hi32, unop(Iop_64HIto32, t64)); 990 assign( lo32, unop(Iop_64to32, t64)); 991 992 return IRExpr_ITE( 993 /* if (top 32 bits of t64 are 0) */ 994 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 995 /* then: within unsigned-32 range: lo half good enough */ 996 mkexpr(lo32), 997 /* else: positive saturate -> 0xFFFFFFFF */ 998 mkU32(0xFFFFFFFF)); 999 } 1000 1001 /* Signed saturate narrow 64->32, combining to V128 */ 1002 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 1003 IRExpr* t1, IRExpr* t0 ) 1004 { 1005 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 1006 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 1007 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 1008 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 1009 return binop(Iop_64HLtoV128, 1010 binop(Iop_32HLto64, 1011 mkQNarrow64Sto32( t3 ), 1012 mkQNarrow64Sto32( t2 )), 1013 binop(Iop_32HLto64, 1014 mkQNarrow64Sto32( t1 ), 1015 mkQNarrow64Sto32( t0 ))); 1016 } 1017 1018 /* Unsigned saturate narrow 64->32, combining to V128 */ 1019 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 1020 IRExpr* t1, IRExpr* t0 ) 1021 { 1022 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 1023 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 1024 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 1025 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 1026 return binop(Iop_64HLtoV128, 1027 binop(Iop_32HLto64, 1028 mkQNarrow64Uto32( t3 ), 1029 mkQNarrow64Uto32( t2 )), 1030 binop(Iop_32HLto64, 1031 mkQNarrow64Uto32( t1 ), 1032 mkQNarrow64Uto32( t0 ))); 1033 } 1034 1035 /* Simulate irops Iop_MullOdd*, since we don't have them */ 1036 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 1037 binop(Iop_MullEven8Ux16, \ 1038 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 1039 binop(Iop_ShrV128, expr_vB, mkU8(8))) 1040 1041 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 1042 binop(Iop_MullEven8Sx16, \ 1043 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 1044 binop(Iop_ShrV128, expr_vB, mkU8(8))) 1045 1046 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 1047 binop(Iop_MullEven16Ux8, \ 1048 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 1049 binop(Iop_ShrV128, expr_vB, mkU8(16))) 1050 1051 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 1052 binop(Iop_MullEven32Ux4, \ 1053 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 1054 binop(Iop_ShrV128, expr_vB, mkU8(32))) 1055 1056 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 1057 binop(Iop_MullEven16Sx8, \ 1058 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 1059 binop(Iop_ShrV128, expr_vB, mkU8(16))) 1060 1061 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 1062 binop(Iop_MullEven32Sx4, \ 1063 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 1064 binop(Iop_ShrV128, expr_vB, mkU8(32))) 1065 1066 1067 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 1068 { 1069 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1070 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 1071 } 1072 1073 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 1074 { 1075 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1076 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1077 } 1078 1079 static IROp mkSzOp ( IRType ty, IROp op8 ) 1080 { 1081 Int adj; 1082 vassert(ty == Ity_I8 || ty == Ity_I16 || 1083 ty == Ity_I32 || ty == Ity_I64); 1084 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1085 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1086 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1087 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1088 op8 == Iop_Not8 ); 1089 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1090 return adj + op8; 1091 } 1092 1093 /* Make sure we get valid 32 and 64bit addresses */ 1094 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1095 { 1096 vassert(ty == Ity_I32 || ty == Ity_I64); 1097 return ( ty == Ity_I64 ? 1098 (Addr64)addr : 1099 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1100 } 1101 1102 /* sz, ULong -> IRExpr */ 1103 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1104 { 1105 vassert(ty == Ity_I32 || ty == Ity_I64); 1106 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1107 } 1108 1109 /* sz, ULong -> IRConst */ 1110 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1111 { 1112 vassert(ty == Ity_I32 || ty == Ity_I64); 1113 return ( ty == Ity_I64 ? 1114 IRConst_U64(imm64) : 1115 IRConst_U32((UInt)imm64) ); 1116 } 1117 1118 /* Sign extend imm16 -> IRExpr* */ 1119 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1120 { 1121 vassert(ty == Ity_I32 || ty == Ity_I64); 1122 return ( ty == Ity_I64 ? 1123 mkU64(extend_s_16to64(imm16)) : 1124 mkU32(extend_s_16to32(imm16)) ); 1125 } 1126 1127 /* Sign extend imm32 -> IRExpr* */ 1128 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1129 { 1130 vassert(ty == Ity_I32 || ty == Ity_I64); 1131 return ( ty == Ity_I64 ? 1132 mkU64(extend_s_32to64(imm32)) : 1133 mkU32(imm32) ); 1134 } 1135 1136 /* IR narrows I32/I64 -> I8/I16/I32 */ 1137 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1138 { 1139 vassert(ty == Ity_I32 || ty == Ity_I64); 1140 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1141 } 1142 1143 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1144 { 1145 vassert(ty == Ity_I32 || ty == Ity_I64); 1146 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1147 } 1148 1149 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1150 { 1151 vassert(ty == Ity_I32 || ty == Ity_I64); 1152 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1153 } 1154 1155 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1156 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1157 { 1158 IROp op; 1159 vassert(ty == Ity_I32 || ty == Ity_I64); 1160 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1161 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1162 return unop(op, src); 1163 } 1164 1165 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1166 { 1167 IROp op; 1168 vassert(ty == Ity_I32 || ty == Ity_I64); 1169 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1170 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1171 return unop(op, src); 1172 } 1173 1174 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1175 { 1176 vassert(ty == Ity_I32 || ty == Ity_I64); 1177 if (ty == Ity_I32) 1178 return src; 1179 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1180 } 1181 1182 1183 static Int integerGuestRegOffset ( UInt archreg ) 1184 { 1185 vassert(archreg < 32); 1186 1187 // jrs: probably not necessary; only matters if we reference sub-parts 1188 // of the ppc registers, but that isn't the case 1189 // later: this might affect Altivec though? 1190 1191 switch (archreg) { 1192 case 0: return offsetofPPCGuestState(guest_GPR0); 1193 case 1: return offsetofPPCGuestState(guest_GPR1); 1194 case 2: return offsetofPPCGuestState(guest_GPR2); 1195 case 3: return offsetofPPCGuestState(guest_GPR3); 1196 case 4: return offsetofPPCGuestState(guest_GPR4); 1197 case 5: return offsetofPPCGuestState(guest_GPR5); 1198 case 6: return offsetofPPCGuestState(guest_GPR6); 1199 case 7: return offsetofPPCGuestState(guest_GPR7); 1200 case 8: return offsetofPPCGuestState(guest_GPR8); 1201 case 9: return offsetofPPCGuestState(guest_GPR9); 1202 case 10: return offsetofPPCGuestState(guest_GPR10); 1203 case 11: return offsetofPPCGuestState(guest_GPR11); 1204 case 12: return offsetofPPCGuestState(guest_GPR12); 1205 case 13: return offsetofPPCGuestState(guest_GPR13); 1206 case 14: return offsetofPPCGuestState(guest_GPR14); 1207 case 15: return offsetofPPCGuestState(guest_GPR15); 1208 case 16: return offsetofPPCGuestState(guest_GPR16); 1209 case 17: return offsetofPPCGuestState(guest_GPR17); 1210 case 18: return offsetofPPCGuestState(guest_GPR18); 1211 case 19: return offsetofPPCGuestState(guest_GPR19); 1212 case 20: return offsetofPPCGuestState(guest_GPR20); 1213 case 21: return offsetofPPCGuestState(guest_GPR21); 1214 case 22: return offsetofPPCGuestState(guest_GPR22); 1215 case 23: return offsetofPPCGuestState(guest_GPR23); 1216 case 24: return offsetofPPCGuestState(guest_GPR24); 1217 case 25: return offsetofPPCGuestState(guest_GPR25); 1218 case 26: return offsetofPPCGuestState(guest_GPR26); 1219 case 27: return offsetofPPCGuestState(guest_GPR27); 1220 case 28: return offsetofPPCGuestState(guest_GPR28); 1221 case 29: return offsetofPPCGuestState(guest_GPR29); 1222 case 30: return offsetofPPCGuestState(guest_GPR30); 1223 case 31: return offsetofPPCGuestState(guest_GPR31); 1224 default: break; 1225 } 1226 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1227 } 1228 1229 static IRExpr* getIReg ( UInt archreg ) 1230 { 1231 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1232 vassert(archreg < 32); 1233 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1234 } 1235 1236 /* Ditto, but write to a reg instead. */ 1237 static void putIReg ( UInt archreg, IRExpr* e ) 1238 { 1239 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1240 vassert(archreg < 32); 1241 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1242 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1243 } 1244 1245 1246 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1247 static Int floatGuestRegOffset ( UInt archreg ) 1248 { 1249 vassert(archreg < 32); 1250 1251 if (host_endness == VexEndnessLE) { 1252 switch (archreg) { 1253 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1254 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1255 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1256 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1257 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1258 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1259 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1260 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1261 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1262 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1263 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1264 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1265 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1266 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1267 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1268 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1269 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1270 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1271 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1272 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1273 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1274 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1275 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1276 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1277 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1278 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1279 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1280 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1281 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1282 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1283 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1284 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1285 default: break; 1286 } 1287 } else { 1288 switch (archreg) { 1289 case 0: return offsetofPPCGuestState(guest_VSR0); 1290 case 1: return offsetofPPCGuestState(guest_VSR1); 1291 case 2: return offsetofPPCGuestState(guest_VSR2); 1292 case 3: return offsetofPPCGuestState(guest_VSR3); 1293 case 4: return offsetofPPCGuestState(guest_VSR4); 1294 case 5: return offsetofPPCGuestState(guest_VSR5); 1295 case 6: return offsetofPPCGuestState(guest_VSR6); 1296 case 7: return offsetofPPCGuestState(guest_VSR7); 1297 case 8: return offsetofPPCGuestState(guest_VSR8); 1298 case 9: return offsetofPPCGuestState(guest_VSR9); 1299 case 10: return offsetofPPCGuestState(guest_VSR10); 1300 case 11: return offsetofPPCGuestState(guest_VSR11); 1301 case 12: return offsetofPPCGuestState(guest_VSR12); 1302 case 13: return offsetofPPCGuestState(guest_VSR13); 1303 case 14: return offsetofPPCGuestState(guest_VSR14); 1304 case 15: return offsetofPPCGuestState(guest_VSR15); 1305 case 16: return offsetofPPCGuestState(guest_VSR16); 1306 case 17: return offsetofPPCGuestState(guest_VSR17); 1307 case 18: return offsetofPPCGuestState(guest_VSR18); 1308 case 19: return offsetofPPCGuestState(guest_VSR19); 1309 case 20: return offsetofPPCGuestState(guest_VSR20); 1310 case 21: return offsetofPPCGuestState(guest_VSR21); 1311 case 22: return offsetofPPCGuestState(guest_VSR22); 1312 case 23: return offsetofPPCGuestState(guest_VSR23); 1313 case 24: return offsetofPPCGuestState(guest_VSR24); 1314 case 25: return offsetofPPCGuestState(guest_VSR25); 1315 case 26: return offsetofPPCGuestState(guest_VSR26); 1316 case 27: return offsetofPPCGuestState(guest_VSR27); 1317 case 28: return offsetofPPCGuestState(guest_VSR28); 1318 case 29: return offsetofPPCGuestState(guest_VSR29); 1319 case 30: return offsetofPPCGuestState(guest_VSR30); 1320 case 31: return offsetofPPCGuestState(guest_VSR31); 1321 default: break; 1322 } 1323 } 1324 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1325 } 1326 1327 static IRExpr* getFReg ( UInt archreg ) 1328 { 1329 vassert(archreg < 32); 1330 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1331 } 1332 1333 /* Ditto, but write to a reg instead. */ 1334 static void putFReg ( UInt archreg, IRExpr* e ) 1335 { 1336 vassert(archreg < 32); 1337 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1338 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1339 } 1340 1341 /* get Decimal float value. Note, they share floating point register file. */ 1342 static IRExpr* getDReg(UInt archreg) { 1343 IRExpr *e; 1344 vassert( archreg < 32 ); 1345 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1346 return e; 1347 } 1348 static IRExpr* getDReg32(UInt archreg) { 1349 IRExpr *e; 1350 vassert( archreg < 32 ); 1351 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1352 return e; 1353 } 1354 1355 /* Read a floating point register pair and combine their contents into a 1356 128-bit value */ 1357 static IRExpr *getDReg_pair(UInt archreg) { 1358 IRExpr *high = getDReg( archreg ); 1359 IRExpr *low = getDReg( archreg + 1 ); 1360 1361 return binop( Iop_D64HLtoD128, high, low ); 1362 } 1363 1364 /* Ditto, but write to a reg instead. */ 1365 static void putDReg32(UInt archreg, IRExpr* e) { 1366 vassert( archreg < 32 ); 1367 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1368 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1369 } 1370 1371 static void putDReg(UInt archreg, IRExpr* e) { 1372 vassert( archreg < 32 ); 1373 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1374 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1375 } 1376 1377 /* Write a 128-bit floating point value into a register pair. */ 1378 static void putDReg_pair(UInt archreg, IRExpr *e) { 1379 IRTemp low = newTemp( Ity_D64 ); 1380 IRTemp high = newTemp( Ity_D64 ); 1381 1382 vassert( archreg < 32 ); 1383 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1384 1385 assign( low, unop( Iop_D128LOtoD64, e ) ); 1386 assign( high, unop( Iop_D128HItoD64, e ) ); 1387 1388 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1389 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1390 } 1391 1392 static Int vsxGuestRegOffset ( UInt archreg ) 1393 { 1394 vassert(archreg < 64); 1395 switch (archreg) { 1396 case 0: return offsetofPPCGuestState(guest_VSR0); 1397 case 1: return offsetofPPCGuestState(guest_VSR1); 1398 case 2: return offsetofPPCGuestState(guest_VSR2); 1399 case 3: return offsetofPPCGuestState(guest_VSR3); 1400 case 4: return offsetofPPCGuestState(guest_VSR4); 1401 case 5: return offsetofPPCGuestState(guest_VSR5); 1402 case 6: return offsetofPPCGuestState(guest_VSR6); 1403 case 7: return offsetofPPCGuestState(guest_VSR7); 1404 case 8: return offsetofPPCGuestState(guest_VSR8); 1405 case 9: return offsetofPPCGuestState(guest_VSR9); 1406 case 10: return offsetofPPCGuestState(guest_VSR10); 1407 case 11: return offsetofPPCGuestState(guest_VSR11); 1408 case 12: return offsetofPPCGuestState(guest_VSR12); 1409 case 13: return offsetofPPCGuestState(guest_VSR13); 1410 case 14: return offsetofPPCGuestState(guest_VSR14); 1411 case 15: return offsetofPPCGuestState(guest_VSR15); 1412 case 16: return offsetofPPCGuestState(guest_VSR16); 1413 case 17: return offsetofPPCGuestState(guest_VSR17); 1414 case 18: return offsetofPPCGuestState(guest_VSR18); 1415 case 19: return offsetofPPCGuestState(guest_VSR19); 1416 case 20: return offsetofPPCGuestState(guest_VSR20); 1417 case 21: return offsetofPPCGuestState(guest_VSR21); 1418 case 22: return offsetofPPCGuestState(guest_VSR22); 1419 case 23: return offsetofPPCGuestState(guest_VSR23); 1420 case 24: return offsetofPPCGuestState(guest_VSR24); 1421 case 25: return offsetofPPCGuestState(guest_VSR25); 1422 case 26: return offsetofPPCGuestState(guest_VSR26); 1423 case 27: return offsetofPPCGuestState(guest_VSR27); 1424 case 28: return offsetofPPCGuestState(guest_VSR28); 1425 case 29: return offsetofPPCGuestState(guest_VSR29); 1426 case 30: return offsetofPPCGuestState(guest_VSR30); 1427 case 31: return offsetofPPCGuestState(guest_VSR31); 1428 case 32: return offsetofPPCGuestState(guest_VSR32); 1429 case 33: return offsetofPPCGuestState(guest_VSR33); 1430 case 34: return offsetofPPCGuestState(guest_VSR34); 1431 case 35: return offsetofPPCGuestState(guest_VSR35); 1432 case 36: return offsetofPPCGuestState(guest_VSR36); 1433 case 37: return offsetofPPCGuestState(guest_VSR37); 1434 case 38: return offsetofPPCGuestState(guest_VSR38); 1435 case 39: return offsetofPPCGuestState(guest_VSR39); 1436 case 40: return offsetofPPCGuestState(guest_VSR40); 1437 case 41: return offsetofPPCGuestState(guest_VSR41); 1438 case 42: return offsetofPPCGuestState(guest_VSR42); 1439 case 43: return offsetofPPCGuestState(guest_VSR43); 1440 case 44: return offsetofPPCGuestState(guest_VSR44); 1441 case 45: return offsetofPPCGuestState(guest_VSR45); 1442 case 46: return offsetofPPCGuestState(guest_VSR46); 1443 case 47: return offsetofPPCGuestState(guest_VSR47); 1444 case 48: return offsetofPPCGuestState(guest_VSR48); 1445 case 49: return offsetofPPCGuestState(guest_VSR49); 1446 case 50: return offsetofPPCGuestState(guest_VSR50); 1447 case 51: return offsetofPPCGuestState(guest_VSR51); 1448 case 52: return offsetofPPCGuestState(guest_VSR52); 1449 case 53: return offsetofPPCGuestState(guest_VSR53); 1450 case 54: return offsetofPPCGuestState(guest_VSR54); 1451 case 55: return offsetofPPCGuestState(guest_VSR55); 1452 case 56: return offsetofPPCGuestState(guest_VSR56); 1453 case 57: return offsetofPPCGuestState(guest_VSR57); 1454 case 58: return offsetofPPCGuestState(guest_VSR58); 1455 case 59: return offsetofPPCGuestState(guest_VSR59); 1456 case 60: return offsetofPPCGuestState(guest_VSR60); 1457 case 61: return offsetofPPCGuestState(guest_VSR61); 1458 case 62: return offsetofPPCGuestState(guest_VSR62); 1459 case 63: return offsetofPPCGuestState(guest_VSR63); 1460 default: break; 1461 } 1462 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1463 } 1464 1465 /* Vector registers are mapped to VSX registers[32..63]. */ 1466 static Int vectorGuestRegOffset ( UInt archreg ) 1467 { 1468 vassert(archreg < 32); 1469 1470 switch (archreg) { 1471 case 0: return offsetofPPCGuestState(guest_VSR32); 1472 case 1: return offsetofPPCGuestState(guest_VSR33); 1473 case 2: return offsetofPPCGuestState(guest_VSR34); 1474 case 3: return offsetofPPCGuestState(guest_VSR35); 1475 case 4: return offsetofPPCGuestState(guest_VSR36); 1476 case 5: return offsetofPPCGuestState(guest_VSR37); 1477 case 6: return offsetofPPCGuestState(guest_VSR38); 1478 case 7: return offsetofPPCGuestState(guest_VSR39); 1479 case 8: return offsetofPPCGuestState(guest_VSR40); 1480 case 9: return offsetofPPCGuestState(guest_VSR41); 1481 case 10: return offsetofPPCGuestState(guest_VSR42); 1482 case 11: return offsetofPPCGuestState(guest_VSR43); 1483 case 12: return offsetofPPCGuestState(guest_VSR44); 1484 case 13: return offsetofPPCGuestState(guest_VSR45); 1485 case 14: return offsetofPPCGuestState(guest_VSR46); 1486 case 15: return offsetofPPCGuestState(guest_VSR47); 1487 case 16: return offsetofPPCGuestState(guest_VSR48); 1488 case 17: return offsetofPPCGuestState(guest_VSR49); 1489 case 18: return offsetofPPCGuestState(guest_VSR50); 1490 case 19: return offsetofPPCGuestState(guest_VSR51); 1491 case 20: return offsetofPPCGuestState(guest_VSR52); 1492 case 21: return offsetofPPCGuestState(guest_VSR53); 1493 case 22: return offsetofPPCGuestState(guest_VSR54); 1494 case 23: return offsetofPPCGuestState(guest_VSR55); 1495 case 24: return offsetofPPCGuestState(guest_VSR56); 1496 case 25: return offsetofPPCGuestState(guest_VSR57); 1497 case 26: return offsetofPPCGuestState(guest_VSR58); 1498 case 27: return offsetofPPCGuestState(guest_VSR59); 1499 case 28: return offsetofPPCGuestState(guest_VSR60); 1500 case 29: return offsetofPPCGuestState(guest_VSR61); 1501 case 30: return offsetofPPCGuestState(guest_VSR62); 1502 case 31: return offsetofPPCGuestState(guest_VSR63); 1503 default: break; 1504 } 1505 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1506 } 1507 1508 static IRExpr* getVReg ( UInt archreg ) 1509 { 1510 vassert(archreg < 32); 1511 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1512 } 1513 1514 /* Get contents of 128-bit reg guest register */ 1515 static IRExpr* getF128Reg ( UInt archreg ) 1516 { 1517 vassert(archreg < 64); 1518 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_F128 ); 1519 } 1520 1521 /* Ditto, but write to a reg instead. */ 1522 static void putF128Reg ( UInt archreg, IRExpr* e ) 1523 { 1524 vassert(archreg < 64); 1525 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F128); 1526 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1527 } 1528 1529 /* Ditto, but write to a reg instead. */ 1530 static void putVReg ( UInt archreg, IRExpr* e ) 1531 { 1532 vassert(archreg < 32); 1533 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1534 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1535 } 1536 1537 /* Get contents of VSX guest register */ 1538 static IRExpr* getVSReg ( UInt archreg ) 1539 { 1540 vassert(archreg < 64); 1541 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1542 } 1543 1544 /* Ditto, but write to a VSX reg instead. */ 1545 static void putVSReg ( UInt archreg, IRExpr* e ) 1546 { 1547 vassert(archreg < 64); 1548 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1549 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1550 } 1551 1552 1553 static Int guestCR321offset ( UInt cr ) 1554 { 1555 switch (cr) { 1556 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1557 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1558 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1559 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1560 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1561 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1562 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1563 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1564 default: vpanic("guestCR321offset(ppc)"); 1565 } 1566 } 1567 1568 static Int guestCR0offset ( UInt cr ) 1569 { 1570 switch (cr) { 1571 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1572 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1573 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1574 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1575 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1576 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1577 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1578 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1579 default: vpanic("guestCR3offset(ppc)"); 1580 } 1581 } 1582 1583 typedef enum { 1584 _placeholder0, 1585 _placeholder1, 1586 _placeholder2, 1587 BYTE, 1588 HWORD, 1589 WORD, 1590 DWORD 1591 } _popcount_data_type; 1592 1593 /* Generate an IR sequence to do a popcount operation on the supplied 1594 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1595 Ity_I32 or Ity_I64 only. */ 1596 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1597 { 1598 /* Do count across 2^data_type bits, 1599 byte: data_type = 3 1600 half word: data_type = 4 1601 word: data_type = 5 1602 double word: data_type = 6 (not supported for 32-bit type) 1603 */ 1604 Int shift[6]; 1605 _popcount_data_type idx, i; 1606 IRTemp mask[6]; 1607 IRTemp old = IRTemp_INVALID; 1608 IRTemp nyu = IRTemp_INVALID; 1609 1610 vassert(ty == Ity_I64 || ty == Ity_I32); 1611 1612 if (ty == Ity_I32) { 1613 1614 for (idx = 0; idx < WORD; idx++) { 1615 mask[idx] = newTemp(ty); 1616 shift[idx] = 1 << idx; 1617 } 1618 assign(mask[0], mkU32(0x55555555)); 1619 assign(mask[1], mkU32(0x33333333)); 1620 assign(mask[2], mkU32(0x0F0F0F0F)); 1621 assign(mask[3], mkU32(0x00FF00FF)); 1622 assign(mask[4], mkU32(0x0000FFFF)); 1623 old = src; 1624 for (i = 0; i < data_type; i++) { 1625 nyu = newTemp(ty); 1626 assign(nyu, 1627 binop(Iop_Add32, 1628 binop(Iop_And32, 1629 mkexpr(old), 1630 mkexpr(mask[i])), 1631 binop(Iop_And32, 1632 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1633 mkexpr(mask[i])))); 1634 old = nyu; 1635 } 1636 return nyu; 1637 } 1638 1639 // else, ty == Ity_I64 1640 vassert(mode64); 1641 1642 for (i = 0; i < DWORD; i++) { 1643 mask[i] = newTemp( Ity_I64 ); 1644 shift[i] = 1 << i; 1645 } 1646 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1647 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1648 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1649 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1650 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1651 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1652 old = src; 1653 for (i = 0; i < data_type; i++) { 1654 nyu = newTemp( Ity_I64 ); 1655 assign( nyu, 1656 binop( Iop_Add64, 1657 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1658 binop( Iop_And64, 1659 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1660 mkexpr( mask[i] ) ) ) ); 1661 old = nyu; 1662 } 1663 return nyu; 1664 } 1665 1666 /* Special purpose population count function for 1667 * vpopcntd in 32-bit mode. 1668 */ 1669 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1670 { 1671 Int i, shift[6]; 1672 IRTemp mask[6]; 1673 IRTemp old = IRTemp_INVALID; 1674 IRTemp nyu1 = IRTemp_INVALID; 1675 IRTemp nyu2 = IRTemp_INVALID; 1676 IRTemp retval = newTemp(Ity_I64); 1677 1678 vassert(!mode64); 1679 1680 for (i = 0; i < WORD; i++) { 1681 mask[i] = newTemp(Ity_I32); 1682 shift[i] = 1 << i; 1683 } 1684 assign(mask[0], mkU32(0x55555555)); 1685 assign(mask[1], mkU32(0x33333333)); 1686 assign(mask[2], mkU32(0x0F0F0F0F)); 1687 assign(mask[3], mkU32(0x00FF00FF)); 1688 assign(mask[4], mkU32(0x0000FFFF)); 1689 old = src1; 1690 for (i = 0; i < WORD; i++) { 1691 nyu1 = newTemp(Ity_I32); 1692 assign(nyu1, 1693 binop(Iop_Add32, 1694 binop(Iop_And32, 1695 mkexpr(old), 1696 mkexpr(mask[i])), 1697 binop(Iop_And32, 1698 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1699 mkexpr(mask[i])))); 1700 old = nyu1; 1701 } 1702 1703 old = src2; 1704 for (i = 0; i < WORD; i++) { 1705 nyu2 = newTemp(Ity_I32); 1706 assign(nyu2, 1707 binop(Iop_Add32, 1708 binop(Iop_And32, 1709 mkexpr(old), 1710 mkexpr(mask[i])), 1711 binop(Iop_And32, 1712 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1713 mkexpr(mask[i])))); 1714 old = nyu2; 1715 } 1716 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1717 return retval; 1718 } 1719 1720 1721 // ROTL(src32/64, rot_amt5/6) 1722 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1723 IRExpr* rot_amt ) 1724 { 1725 IRExpr *mask, *rot; 1726 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1727 1728 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1729 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1730 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1731 rot = binop(Iop_Or64, 1732 binop(Iop_Shl64, src, mask), 1733 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1734 } else { 1735 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1736 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1737 rot = binop(Iop_Or32, 1738 binop(Iop_Shl32, src, mask), 1739 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1740 } 1741 /* Note: the ITE not merely an optimisation; it's needed 1742 because otherwise the Shr is a shift by the word size when 1743 mask denotes zero. For rotates by immediates, a lot of 1744 this junk gets folded out. */ 1745 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1746 /* non-zero rotate */ rot, 1747 /* zero rotate */ src); 1748 } 1749 1750 /* Standard effective address calc: (rA + rB) */ 1751 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1752 { 1753 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1754 vassert(rA < 32); 1755 vassert(rB < 32); 1756 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1757 } 1758 1759 /* Standard effective address calc: (rA + simm) */ 1760 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1761 { 1762 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1763 vassert(rA < 32); 1764 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1765 mkSzExtendS16(ty, simm16)); 1766 } 1767 1768 /* Standard effective address calc: (rA|0) */ 1769 static IRExpr* ea_rAor0 ( UInt rA ) 1770 { 1771 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1772 vassert(rA < 32); 1773 if (rA == 0) { 1774 return mkSzImm(ty, 0); 1775 } else { 1776 return getIReg(rA); 1777 } 1778 } 1779 1780 /* Standard effective address calc: (rA|0) + rB */ 1781 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1782 { 1783 vassert(rA < 32); 1784 vassert(rB < 32); 1785 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1786 } 1787 1788 /* Standard effective address calc: (rA|0) + simm16 */ 1789 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1790 { 1791 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1792 vassert(rA < 32); 1793 if (rA == 0) { 1794 return mkSzExtendS16(ty, simm16); 1795 } else { 1796 return ea_rA_simm( rA, simm16 ); 1797 } 1798 } 1799 1800 1801 /* Align effective address */ 1802 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1803 { 1804 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1805 ULong mask; 1806 switch (align) { 1807 case 1: return addr; // byte aligned 1808 case 2: mask = ~0ULL << 1; break; // half-word aligned 1809 case 4: mask = ~0ULL << 2; break; // word aligned 1810 case 16: mask = ~0ULL << 4; break; // quad-word aligned 1811 default: 1812 vex_printf("addr_align: align = %u\n", align); 1813 vpanic("addr_align(ppc)"); 1814 } 1815 1816 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1817 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1818 } 1819 1820 1821 /* Exit the trace if ADDR (intended to be a guest memory address) is 1822 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1823 restart of the current insn. */ 1824 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1825 { 1826 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1827 if (mode64) { 1828 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1829 stmt( 1830 IRStmt_Exit( 1831 binop(Iop_CmpNE64, 1832 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1833 mkU64(0)), 1834 Ijk_SigBUS, 1835 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1836 ) 1837 ); 1838 } else { 1839 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1840 stmt( 1841 IRStmt_Exit( 1842 binop(Iop_CmpNE32, 1843 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1844 mkU32(0)), 1845 Ijk_SigBUS, 1846 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1847 ) 1848 ); 1849 } 1850 } 1851 1852 1853 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1854 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1855 N) becomes undefined. That is at function calls and returns. ELF 1856 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1857 the address of the next instruction to be executed. 1858 */ 1859 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1860 IRTemp nia, const HChar* who ) 1861 { 1862 Int szB = vbi->guest_stack_redzone_size; 1863 if (0) vex_printf("AbiHint: %s\n", who); 1864 vassert(szB >= 0); 1865 if (szB > 0) { 1866 if (mode64) { 1867 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1868 stmt( IRStmt_AbiHint( 1869 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1870 szB, 1871 mkexpr(nia) 1872 )); 1873 } else { 1874 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1875 stmt( IRStmt_AbiHint( 1876 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1877 szB, 1878 mkexpr(nia) 1879 )); 1880 } 1881 } 1882 } 1883 1884 1885 /*------------------------------------------------------------*/ 1886 /*--- Helpers for condition codes. ---*/ 1887 /*------------------------------------------------------------*/ 1888 1889 /* Condition register layout. 1890 1891 In the hardware, CR is laid out like this. The leftmost end is the 1892 most significant bit in the register; however the IBM documentation 1893 numbers the bits backwards for some reason. 1894 1895 CR0 CR1 .......... CR6 CR7 1896 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1897 31 28 3 0 (normal bit numbering) 1898 1899 Each CR field is 4 bits: [<,>,==,SO] 1900 1901 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1902 1903 Indexing from BI to guest state: 1904 1905 let n = BI / 4 1906 off = BI % 4 1907 this references CR n: 1908 1909 off==0 -> guest_CRn_321 >> 3 1910 off==1 -> guest_CRn_321 >> 2 1911 off==2 -> guest_CRn_321 >> 1 1912 off==3 -> guest_CRn_SO 1913 1914 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1915 (normal notation) and in guest_CRn_321 the significant bits are 1916 3, 2 and 1 (normal notation). 1917 */ 1918 1919 static void putCR321 ( UInt cr, IRExpr* e ) 1920 { 1921 vassert(cr < 8); 1922 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1923 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1924 } 1925 1926 static void putCR0 ( UInt cr, IRExpr* e ) 1927 { 1928 vassert(cr < 8); 1929 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1930 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1931 } 1932 1933 static void putC ( IRExpr* e ) 1934 { 1935 /* The assumption is that the value of the Floating-Point Result 1936 * Class Descriptor bit (C) is passed in the lower four bits of a 1937 * 32 bit value. 1938 * 1939 * Note, the C and FPCC bits which are fields in the FPSCR 1940 * register are stored in their own memory location of 1941 * memory. The FPCC bits are in the lower 4 bits. The C bit needs 1942 * to be shifted to bit 4 in the memory location that holds C and FPCC. 1943 * Note not all of the FPSCR register bits are supported. We are 1944 * only writing C bit. 1945 */ 1946 IRExpr* tmp; 1947 1948 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32); 1949 1950 /* Get the FPCC bit field */ 1951 tmp = binop( Iop_And32, 1952 mkU32( 0xF ), 1953 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) ); 1954 1955 stmt( IRStmt_Put( OFFB_C_FPCC, 1956 unop( Iop_32to8, 1957 binop( Iop_Or32, tmp, 1958 binop( Iop_Shl32, 1959 binop( Iop_And32, mkU32( 0x1 ), e ), 1960 mkU8( 4 ) ) ) ) ) ); 1961 } 1962 1963 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1964 { 1965 vassert(cr < 8); 1966 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1967 } 1968 1969 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1970 { 1971 vassert(cr < 8); 1972 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1973 } 1974 1975 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1976 return it at the bottom of an I32; the top 31 bits are guaranteed 1977 to be zero. */ 1978 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1979 { 1980 UInt n = bi / 4; 1981 UInt off = bi % 4; 1982 vassert(bi < 32); 1983 if (off == 3) { 1984 /* Fetch the SO bit for this CR field */ 1985 /* Note: And32 is redundant paranoia iff guest state only has 0 1986 or 1 in that slot. */ 1987 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1988 } else { 1989 /* Fetch the <, > or == bit for this CR field */ 1990 return binop( Iop_And32, 1991 binop( Iop_Shr32, 1992 unop(Iop_8Uto32, getCR321(n)), 1993 mkU8(toUChar(3-off)) ), 1994 mkU32(1) ); 1995 } 1996 } 1997 1998 /* Dually, write the least significant bit of BIT to the specified CR 1999 bit. Indexing as per getCRbit. */ 2000 static void putCRbit ( UInt bi, IRExpr* bit ) 2001 { 2002 UInt n, off; 2003 IRExpr* safe; 2004 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 2005 safe = binop(Iop_And32, bit, mkU32(1)); 2006 n = bi / 4; 2007 off = bi % 4; 2008 vassert(bi < 32); 2009 if (off == 3) { 2010 /* This is the SO bit for this CR field */ 2011 putCR0(n, unop(Iop_32to8, safe)); 2012 } else { 2013 off = 3 - off; 2014 vassert(off == 1 || off == 2 || off == 3); 2015 putCR321( 2016 n, 2017 unop( Iop_32to8, 2018 binop( Iop_Or32, 2019 /* old value with field masked out */ 2020 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 2021 mkU32(~(1 << off))), 2022 /* new value in the right place */ 2023 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 2024 ) 2025 ) 2026 ); 2027 } 2028 } 2029 2030 /* Fetch the specified CR bit (as per IBM/hardware notation) and 2031 return it somewhere in an I32; it does not matter where, but 2032 whichever bit it is, all other bits are guaranteed to be zero. In 2033 other words, the I32-typed expression will be zero if the bit is 2034 zero and nonzero if the bit is 1. Write into *where the index 2035 of where the bit will be. */ 2036 2037 static 2038 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 2039 { 2040 UInt n = bi / 4; 2041 UInt off = bi % 4; 2042 vassert(bi < 32); 2043 if (off == 3) { 2044 /* Fetch the SO bit for this CR field */ 2045 /* Note: And32 is redundant paranoia iff guest state only has 0 2046 or 1 in that slot. */ 2047 *where = 0; 2048 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 2049 } else { 2050 /* Fetch the <, > or == bit for this CR field */ 2051 *where = 3-off; 2052 return binop( Iop_And32, 2053 unop(Iop_8Uto32, getCR321(n)), 2054 mkU32(1 << (3-off)) ); 2055 } 2056 } 2057 2058 /* Set the CR0 flags following an arithmetic operation. 2059 (Condition Register CR0 Field Definition, PPC32 p60) 2060 */ 2061 static IRExpr* getXER_SO ( void ); 2062 static void set_CR0 ( IRExpr* result ) 2063 { 2064 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 2065 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 2066 if (mode64) { 2067 putCR321( 0, unop(Iop_64to8, 2068 binop(Iop_CmpORD64S, result, mkU64(0))) ); 2069 } else { 2070 putCR321( 0, unop(Iop_32to8, 2071 binop(Iop_CmpORD32S, result, mkU32(0))) ); 2072 } 2073 putCR0( 0, getXER_SO() ); 2074 } 2075 2076 2077 /* Set the CR6 flags following an AltiVec compare operation. 2078 * NOTE: This also works for VSX single-precision compares. 2079 * */ 2080 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 2081 { 2082 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 2083 all_ones = (v[0] && v[1] && v[2] && v[3]) 2084 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 2085 */ 2086 IRTemp v0 = newTemp(Ity_V128); 2087 IRTemp v1 = newTemp(Ity_V128); 2088 IRTemp v2 = newTemp(Ity_V128); 2089 IRTemp v3 = newTemp(Ity_V128); 2090 IRTemp rOnes = newTemp(Ity_I8); 2091 IRTemp rZeros = newTemp(Ity_I8); 2092 2093 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 2094 2095 assign( v0, result ); 2096 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 2097 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 2098 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 2099 2100 assign( rZeros, unop(Iop_1Uto8, 2101 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2102 unop(Iop_Not32, 2103 unop(Iop_V128to32, 2104 binop(Iop_OrV128, 2105 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 2106 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 2107 ))) ); 2108 2109 if (test_all_ones) { 2110 assign( rOnes, unop(Iop_1Uto8, 2111 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2112 unop(Iop_V128to32, 2113 binop(Iop_AndV128, 2114 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 2115 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 2116 ))) ); 2117 putCR321( 6, binop(Iop_Or8, 2118 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 2119 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 2120 } else { 2121 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2122 } 2123 putCR0( 6, mkU8(0) ); 2124 } 2125 2126 2127 static IRExpr * create_DCM ( IRType size, IRTemp NaN, IRTemp inf, IRTemp zero, 2128 IRTemp dnorm, IRTemp pos) 2129 { 2130 /* This is a general function for creating the DCM for a 32-bit or 2131 64-bit expression based on the passes size. 2132 */ 2133 IRTemp neg; 2134 IROp opAND, opOR, opSHL, opXto1, op1UtoX; 2135 2136 vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) ); 2137 2138 if ( size == Ity_I32 ) { 2139 opSHL = Iop_Shl32; 2140 opAND = Iop_And32; 2141 opOR = Iop_Or32; 2142 opXto1 = Iop_32to1; 2143 op1UtoX = Iop_1Uto32; 2144 neg = newTemp( Ity_I32 ); 2145 2146 } else { 2147 opSHL = Iop_Shl64; 2148 opAND = Iop_And64; 2149 opOR = Iop_Or64; 2150 opXto1 = Iop_64to1; 2151 op1UtoX = Iop_1Uto64; 2152 neg = newTemp( Ity_I64 ); 2153 } 2154 2155 assign( neg, unop( op1UtoX, mkNOT1( unop( opXto1, 2156 mkexpr ( pos ) ) ) ) ); 2157 2158 return binop( opOR, 2159 binop( opSHL, mkexpr( NaN ), mkU8( 6 ) ), 2160 binop( opOR, 2161 binop( opOR, 2162 binop( opOR, 2163 binop( opSHL, 2164 binop( opAND, 2165 mkexpr( pos ), 2166 mkexpr( inf ) ), 2167 mkU8( 5 ) ), 2168 binop( opSHL, 2169 binop( opAND, 2170 mkexpr( neg ), 2171 mkexpr( inf ) ), 2172 mkU8( 4 ) ) ), 2173 binop( opOR, 2174 binop( opSHL, 2175 binop( opAND, 2176 mkexpr( pos ), 2177 mkexpr( zero ) ), 2178 mkU8( 3 ) ), 2179 binop( opSHL, 2180 binop( opAND, 2181 mkexpr( neg ), 2182 mkexpr( zero ) ), 2183 mkU8( 2 ) ) ) ), 2184 binop( opOR, 2185 binop( opSHL, 2186 binop( opAND, 2187 mkexpr( pos ), 2188 mkexpr( dnorm ) ), 2189 mkU8( 1 ) ), 2190 binop( opAND, 2191 mkexpr( neg ), 2192 mkexpr( dnorm ) ) ) ) ); 2193 } 2194 2195 /*------------------------------------------------------------*/ 2196 /*--- Helpers for XER flags. ---*/ 2197 /*------------------------------------------------------------*/ 2198 2199 static void putXER_SO ( IRExpr* e ) 2200 { 2201 IRExpr* so; 2202 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2203 so = binop(Iop_And8, e, mkU8(1)); 2204 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2205 } 2206 2207 static void putXER_OV ( IRExpr* e ) 2208 { 2209 /* Interface to write XER[OV] */ 2210 IRExpr* ov; 2211 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2212 ov = binop(Iop_And8, e, mkU8(1)); 2213 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2214 } 2215 2216 static void putXER_OV32 ( IRExpr* e ) 2217 { 2218 /*Interface to write XER[OV32] */ 2219 IRExpr* ov; 2220 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2221 ov = binop(Iop_And8, e, mkU8(1)); 2222 2223 /* The OV32 bit was added to XER in ISA 3.0. Do not write unless we 2224 * ISA 3.0 or beyond is supported. */ 2225 if( OV32_CA32_supported ) 2226 stmt( IRStmt_Put( OFFB_XER_OV32, ov ) ); 2227 } 2228 2229 static void putXER_CA ( IRExpr* e ) 2230 { 2231 /* Interface to write XER[CA] */ 2232 IRExpr* ca; 2233 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2234 ca = binop(Iop_And8, e, mkU8(1)); 2235 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2236 } 2237 2238 static void putXER_CA32 ( IRExpr* e ) 2239 { 2240 /* Interface to write XER[CA32] */ 2241 IRExpr* ca; 2242 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2243 ca = binop(Iop_And8, e, mkU8(1)); 2244 2245 /* The CA32 bit was added to XER in ISA 3.0. Do not write unless we 2246 * ISA 3.0 or beyond is supported. */ 2247 if( OV32_CA32_supported ) 2248 stmt( IRStmt_Put( OFFB_XER_CA32, ca ) ); 2249 } 2250 2251 static void putXER_BC ( IRExpr* e ) 2252 { 2253 IRExpr* bc; 2254 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2255 bc = binop(Iop_And8, e, mkU8(0x7F)); 2256 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2257 } 2258 2259 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2260 { 2261 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2262 } 2263 2264 static IRExpr* /* :: Ity_I32 */ getXER_SO_32 ( void ) 2265 { 2266 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2267 } 2268 2269 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2270 { 2271 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2272 } 2273 2274 static IRExpr* /* :: Ity_I8 */ getXER_OV32 ( void ) 2275 { 2276 return IRExpr_Get( OFFB_XER_OV32, Ity_I8 ); 2277 } 2278 2279 static IRExpr* /* :: Ity_I32 */ getXER_OV_32 ( void ) 2280 { 2281 /* get XER[OV], 32-bit interface */ 2282 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2283 } 2284 2285 static IRExpr* /* :: Ity_I32 */ getXER_OV32_32 ( void ) 2286 { 2287 /* get XER[OV32], 32-bit interface */ 2288 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV32()), mkU32(1) ); 2289 } 2290 2291 static IRExpr* /* :: Ity_I32 */ getXER_CA_32 ( void ) 2292 { 2293 /* get XER[CA], 32-bit interface */ 2294 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2295 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2296 } 2297 2298 static IRExpr* /* :: Ity_I32 */ getXER_CA32_32 ( void ) 2299 { 2300 /* get XER[CA32], 32-bit interface */ 2301 IRExpr* ca = IRExpr_Get( OFFB_XER_CA32, Ity_I8 ); 2302 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2303 } 2304 2305 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2306 { 2307 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2308 } 2309 2310 static IRExpr* /* :: Ity_I32 */ getXER_BC_32 ( void ) 2311 { 2312 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2313 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2314 } 2315 2316 2317 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2318 %XER.SO accordingly. */ 2319 2320 static IRExpr* calculate_XER_OV_32( UInt op, IRExpr* res, 2321 IRExpr* argL, IRExpr* argR ) 2322 { 2323 IRTemp t64; 2324 IRExpr* xer_ov; 2325 2326 # define INT32_MIN 0x80000000 2327 2328 # define XOR2(_aa,_bb) \ 2329 binop(Iop_Xor32,(_aa),(_bb)) 2330 2331 # define XOR3(_cc,_dd,_ee) \ 2332 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2333 2334 # define AND3(_ff,_gg,_hh) \ 2335 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2336 2337 #define NOT(_jj) \ 2338 unop(Iop_Not32, (_jj)) 2339 2340 switch (op) { 2341 case /* 0 */ PPCG_FLAG_OP_ADD: 2342 case /* 1 */ PPCG_FLAG_OP_ADDE: 2343 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2344 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2345 xer_ov 2346 = AND3( XOR3(argL,argR,mkU32(-1)), 2347 XOR2(argL,res), 2348 mkU32(INT32_MIN) ); 2349 /* xer_ov can only be 0 or 1<<31 */ 2350 xer_ov 2351 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2352 break; 2353 2354 case /* 2 */ PPCG_FLAG_OP_DIVW: 2355 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2356 xer_ov 2357 = mkOR1( 2358 mkAND1( 2359 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2360 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2361 ), 2362 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2363 ); 2364 xer_ov 2365 = unop(Iop_1Uto32, xer_ov); 2366 break; 2367 2368 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2369 /* argR == 0 */ 2370 xer_ov 2371 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2372 break; 2373 2374 case /* 4 */ PPCG_FLAG_OP_MULLW: 2375 /* OV true if result can't be represented in 32 bits 2376 i.e sHi != sign extension of sLo */ 2377 t64 = newTemp(Ity_I64); 2378 assign( t64, binop(Iop_MullS32, argL, argR) ); 2379 xer_ov 2380 = binop( Iop_CmpNE32, 2381 unop(Iop_64HIto32, mkexpr(t64)), 2382 binop( Iop_Sar32, 2383 unop(Iop_64to32, mkexpr(t64)), 2384 mkU8(31)) 2385 ); 2386 xer_ov 2387 = unop(Iop_1Uto32, xer_ov); 2388 break; 2389 2390 case /* 5 */ PPCG_FLAG_OP_NEG: 2391 /* argL == INT32_MIN */ 2392 xer_ov 2393 = unop( Iop_1Uto32, 2394 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2395 break; 2396 2397 case /* 6 */ PPCG_FLAG_OP_SUBF: 2398 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2399 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2400 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2401 xer_ov 2402 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2403 XOR2(NOT(argL),res), 2404 mkU32(INT32_MIN) ); 2405 /* xer_ov can only be 0 or 1<<31 */ 2406 xer_ov 2407 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2408 break; 2409 2410 case PPCG_FLAG_OP_DIVWEU: 2411 xer_ov 2412 = binop( Iop_Or32, 2413 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2414 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2415 break; 2416 2417 case PPCG_FLAG_OP_DIVWE: 2418 2419 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2420 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2421 * an overflow is implied. 2422 */ 2423 xer_ov = binop( Iop_Or32, 2424 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2425 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2426 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2427 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2428 break; 2429 2430 2431 2432 default: 2433 vex_printf("calculate_XER_OV_32: op = %u\n", op); 2434 vpanic("calculate_XER_OV_32(ppc)"); 2435 } 2436 2437 return xer_ov; 2438 2439 # undef INT32_MIN 2440 # undef AND3 2441 # undef XOR3 2442 # undef XOR2 2443 # undef NOT 2444 } 2445 2446 static void set_XER_OV_OV32_32( UInt op, IRExpr* res, 2447 IRExpr* argL, IRExpr* argR ) 2448 { 2449 IRExpr* xer_ov; 2450 2451 vassert(op < PPCG_FLAG_OP_NUMBER); 2452 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2453 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2454 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2455 2456 xer_ov = calculate_XER_OV_32( op, res, argL, argR ); 2457 2458 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2459 putXER_OV( unop(Iop_32to8, xer_ov) ); 2460 putXER_OV32( unop(Iop_32to8, xer_ov) ); 2461 } 2462 2463 static IRExpr* calculate_XER_OV_64( UInt op, IRExpr* res, 2464 IRExpr* argL, IRExpr* argR ) 2465 { 2466 IRExpr* xer_ov; 2467 2468 # define INT64_MIN 0x8000000000000000ULL 2469 2470 # define XOR2(_aa,_bb) \ 2471 binop(Iop_Xor64,(_aa),(_bb)) 2472 2473 # define XOR3(_cc,_dd,_ee) \ 2474 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2475 2476 # define AND3(_ff,_gg,_hh) \ 2477 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2478 2479 #define NOT(_jj) \ 2480 unop(Iop_Not64, (_jj)) 2481 2482 switch (op) { 2483 case /* 0 */ PPCG_FLAG_OP_ADD: 2484 case /* 1 */ PPCG_FLAG_OP_ADDE: 2485 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2486 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2487 xer_ov 2488 = AND3( XOR3(argL,argR,mkU64(-1)), 2489 XOR2(argL,res), 2490 mkU64(INT64_MIN) ); 2491 /* xer_ov can only be 0 or 1<<63 */ 2492 xer_ov 2493 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2494 break; 2495 2496 case /* 2 */ PPCG_FLAG_OP_DIVW: 2497 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2498 xer_ov 2499 = mkOR1( 2500 mkAND1( 2501 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2502 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2503 ), 2504 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2505 ); 2506 break; 2507 2508 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2509 /* argR == 0 */ 2510 xer_ov 2511 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2512 break; 2513 2514 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2515 /* OV true if result can't be represented in 64 bits 2516 i.e sHi != sign extension of sLo */ 2517 xer_ov 2518 = binop( Iop_CmpNE32, 2519 unop(Iop_64HIto32, res), 2520 binop( Iop_Sar32, 2521 unop(Iop_64to32, res), 2522 mkU8(31)) 2523 ); 2524 break; 2525 } 2526 2527 case /* 5 */ PPCG_FLAG_OP_NEG: 2528 /* argL == INT64_MIN */ 2529 xer_ov 2530 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2531 break; 2532 2533 case /* 6 */ PPCG_FLAG_OP_SUBF: 2534 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2535 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2536 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2537 xer_ov 2538 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2539 XOR2(NOT(argL),res), 2540 mkU64(INT64_MIN) ); 2541 /* xer_ov can only be 0 or 1<<63 */ 2542 xer_ov 2543 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2544 break; 2545 2546 case /* 14 */ PPCG_FLAG_OP_DIVDE: 2547 2548 /* If argR == 0, we must set the OV bit. But there's another condition 2549 * where we can get overflow set for divde . . . when the 2550 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2551 * both dividend and divisor are non-zero, it implies an overflow. 2552 */ 2553 xer_ov 2554 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2555 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2556 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2557 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2558 break; 2559 2560 case /* 17 */ PPCG_FLAG_OP_DIVDEU: 2561 /* If argR == 0 or if argL >= argR, set OV. */ 2562 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2563 binop( Iop_CmpLE64U, argR, argL ) ); 2564 break; 2565 2566 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2567 IRTemp t128; 2568 /* OV true if result can't be represented in 64 bits 2569 i.e sHi != sign extension of sLo */ 2570 t128 = newTemp(Ity_I128); 2571 assign( t128, binop(Iop_MullS64, argL, argR) ); 2572 xer_ov 2573 = binop( Iop_CmpNE64, 2574 unop(Iop_128HIto64, mkexpr(t128)), 2575 binop( Iop_Sar64, 2576 unop(Iop_128to64, mkexpr(t128)), 2577 mkU8(63)) 2578 ); 2579 break; 2580 } 2581 2582 default: 2583 vex_printf("calculate_XER_OV_64: op = %u\n", op); 2584 vpanic("calculate_XER_OV_64(ppc64)"); 2585 } 2586 2587 return xer_ov; 2588 2589 # undef INT64_MIN 2590 # undef AND3 2591 # undef XOR3 2592 # undef XOR2 2593 # undef NOT 2594 } 2595 2596 static void set_XER_OV_64( UInt op, IRExpr* res, 2597 IRExpr* argL, IRExpr* argR ) 2598 { 2599 IRExpr* xer_ov; 2600 vassert(op < PPCG_FLAG_OP_NUMBER); 2601 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2602 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2603 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2604 2605 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2606 xer_ov = calculate_XER_OV_64( op, res, argL, argR); 2607 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2608 2609 /* Update the summary overflow */ 2610 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2611 } 2612 2613 static void update_SO( void ) { 2614 /* Update the summary overflow bit */ 2615 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2616 } 2617 2618 static void copy_OV_to_OV32( void ) { 2619 /* Update the OV32 to match OV */ 2620 putXER_OV32( getXER_OV() ); 2621 } 2622 2623 static void set_XER_OV_OV32 ( IRType ty, UInt op, IRExpr* res, 2624 IRExpr* argL, IRExpr* argR ) 2625 { 2626 if (ty == Ity_I32) { 2627 set_XER_OV_OV32_32( op, res, argL, argR ); 2628 } else { 2629 IRExpr* xer_ov_32; 2630 set_XER_OV_64( op, res, argL, argR ); 2631 xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res), 2632 unop(Iop_64to32, argL), 2633 unop(Iop_64to32, argR)); 2634 putXER_OV32( unop(Iop_32to8, xer_ov_32) ); 2635 } 2636 } 2637 2638 static void set_XER_OV_OV32_SO ( IRType ty, UInt op, IRExpr* res, 2639 IRExpr* argL, IRExpr* argR ) 2640 { 2641 if (ty == Ity_I32) { 2642 set_XER_OV_OV32_32( op, res, argL, argR ); 2643 } else { 2644 IRExpr* xer_ov_32; 2645 set_XER_OV_64( op, res, argL, argR ); 2646 xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res), 2647 unop(Iop_64to32, argL), 2648 unop(Iop_64to32, argR)); 2649 putXER_OV32( unop(Iop_32to8, xer_ov_32) ); 2650 } 2651 update_SO(); 2652 } 2653 2654 2655 2656 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2657 value being OLDCA. Set %XER.CA accordingly. */ 2658 2659 static IRExpr* calculate_XER_CA_32 ( UInt op, IRExpr* res, 2660 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2661 { 2662 IRExpr* xer_ca; 2663 2664 switch (op) { 2665 case /* 0 */ PPCG_FLAG_OP_ADD: 2666 /* res <u argL */ 2667 xer_ca 2668 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2669 break; 2670 2671 case /* 1 */ PPCG_FLAG_OP_ADDE: 2672 /* res <u argL || (old_ca==1 && res==argL) */ 2673 xer_ca 2674 = mkOR1( 2675 binop(Iop_CmpLT32U, res, argL), 2676 mkAND1( 2677 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2678 binop(Iop_CmpEQ32, res, argL) 2679 ) 2680 ); 2681 xer_ca 2682 = unop(Iop_1Uto32, xer_ca); 2683 break; 2684 2685 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2686 /* res <u argR || (old_ca==1 && res==argR) */ 2687 xer_ca 2688 = mkOR1( 2689 binop(Iop_CmpLT32U, res, argR), 2690 mkAND1( 2691 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2692 binop(Iop_CmpEQ32, res, argR) 2693 ) 2694 ); 2695 xer_ca 2696 = unop(Iop_1Uto32, xer_ca); 2697 break; 2698 2699 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2700 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2701 /* res <=u argR */ 2702 xer_ca 2703 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2704 break; 2705 2706 case /* 10 */ PPCG_FLAG_OP_SRAW: 2707 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2708 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2709 bit of argL. */ 2710 /* This term valid for shift amount < 32 only */ 2711 xer_ca 2712 = binop( 2713 Iop_And32, 2714 binop(Iop_Sar32, argL, mkU8(31)), 2715 binop( Iop_And32, 2716 argL, 2717 binop( Iop_Sub32, 2718 binop(Iop_Shl32, mkU32(1), 2719 unop(Iop_32to8,argR)), 2720 mkU32(1) ) 2721 ) 2722 ); 2723 xer_ca 2724 = IRExpr_ITE( 2725 /* shift amt > 31 ? */ 2726 binop(Iop_CmpLT32U, mkU32(31), argR), 2727 /* yes -- get sign bit of argL */ 2728 binop(Iop_Shr32, argL, mkU8(31)), 2729 /* no -- be like srawi */ 2730 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2731 ); 2732 break; 2733 2734 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2735 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2736 0. Since the shift amount is known to be in the range 2737 0 .. 31 inclusive the following seems viable: 2738 xer.ca == 1 iff the following is nonzero: 2739 (argL >>s 31) -- either all 0s or all 1s 2740 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2741 xer_ca 2742 = binop( 2743 Iop_And32, 2744 binop(Iop_Sar32, argL, mkU8(31)), 2745 binop( Iop_And32, 2746 argL, 2747 binop( Iop_Sub32, 2748 binop(Iop_Shl32, mkU32(1), 2749 unop(Iop_32to8,argR)), 2750 mkU32(1) ) 2751 ) 2752 ); 2753 xer_ca 2754 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2755 break; 2756 2757 default: 2758 vex_printf("set_XER_CA: op = %u\n", op); 2759 vpanic("set_XER_CA(ppc)"); 2760 } 2761 2762 return xer_ca; 2763 } 2764 2765 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2766 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2767 { 2768 IRExpr* xer_ca; 2769 vassert(op < PPCG_FLAG_OP_NUMBER); 2770 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2771 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2772 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2773 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2774 2775 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2776 seems reasonable given that it's always generated by 2777 getXER_CA_32(), which masks it accordingly. In any case it being 2778 0 or 1 is an invariant of the ppc guest state representation; 2779 if it has any other value, that invariant has been violated. */ 2780 2781 xer_ca = calculate_XER_CA_32( op, res, argL, argR, oldca); 2782 2783 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2784 putXER_CA( unop(Iop_32to8, xer_ca) ); 2785 } 2786 2787 static IRExpr* calculate_XER_CA_64 ( UInt op, IRExpr* res, 2788 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2789 { 2790 IRExpr* xer_ca; 2791 2792 switch (op) { 2793 case /* 0 */ PPCG_FLAG_OP_ADD: 2794 /* res <u argL */ 2795 xer_ca 2796 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2797 break; 2798 2799 case /* 1 */ PPCG_FLAG_OP_ADDE: 2800 /* res <u argL || (old_ca==1 && res==argL) */ 2801 xer_ca 2802 = mkOR1( 2803 binop(Iop_CmpLT64U, res, argL), 2804 mkAND1( 2805 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2806 binop(Iop_CmpEQ64, res, argL) 2807 ) 2808 ); 2809 xer_ca 2810 = unop(Iop_1Uto32, xer_ca); 2811 break; 2812 2813 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2814 /* res <u argR || (old_ca==1 && res==argR) */ 2815 xer_ca 2816 = mkOR1( 2817 binop(Iop_CmpLT64U, res, argR), 2818 mkAND1( 2819 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2820 binop(Iop_CmpEQ64, res, argR) 2821 ) 2822 ); 2823 xer_ca 2824 = unop(Iop_1Uto32, xer_ca); 2825 break; 2826 2827 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2828 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2829 /* res <=u argR */ 2830 xer_ca 2831 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2832 break; 2833 2834 2835 case /* 10 */ PPCG_FLAG_OP_SRAW: 2836 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2837 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2838 bit of argL. */ 2839 /* This term valid for shift amount < 31 only */ 2840 2841 xer_ca 2842 = binop( 2843 Iop_And64, 2844 binop(Iop_Sar64, argL, mkU8(31)), 2845 binop( Iop_And64, 2846 argL, 2847 binop( Iop_Sub64, 2848 binop(Iop_Shl64, mkU64(1), 2849 unop(Iop_64to8,argR)), 2850 mkU64(1) ) 2851 ) 2852 ); 2853 xer_ca 2854 = IRExpr_ITE( 2855 /* shift amt > 31 ? */ 2856 binop(Iop_CmpLT64U, mkU64(31), argR), 2857 /* yes -- get sign bit of argL */ 2858 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2859 /* no -- be like srawi */ 2860 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2861 ); 2862 break; 2863 2864 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2865 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2866 Since the shift amount is known to be in the range 0 .. 31 2867 inclusive the following seems viable: 2868 xer.ca == 1 iff the following is nonzero: 2869 (argL >>s 31) -- either all 0s or all 1s 2870 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2871 2872 xer_ca 2873 = binop( 2874 Iop_And64, 2875 binop(Iop_Sar64, argL, mkU8(31)), 2876 binop( Iop_And64, 2877 argL, 2878 binop( Iop_Sub64, 2879 binop(Iop_Shl64, mkU64(1), 2880 unop(Iop_64to8,argR)), 2881 mkU64(1) ) 2882 ) 2883 ); 2884 xer_ca 2885 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2886 break; 2887 2888 2889 case /* 12 */ PPCG_FLAG_OP_SRAD: 2890 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2891 If it is <= 63, behave like SRADI; else XER.CA is the sign 2892 bit of argL. */ 2893 /* This term valid for shift amount < 63 only */ 2894 2895 xer_ca 2896 = binop( 2897 Iop_And64, 2898 binop(Iop_Sar64, argL, mkU8(63)), 2899 binop( Iop_And64, 2900 argL, 2901 binop( Iop_Sub64, 2902 binop(Iop_Shl64, mkU64(1), 2903 unop(Iop_64to8,argR)), 2904 mkU64(1) ) 2905 ) 2906 ); 2907 xer_ca 2908 = IRExpr_ITE( 2909 /* shift amt > 63 ? */ 2910 binop(Iop_CmpLT64U, mkU64(63), argR), 2911 /* yes -- get sign bit of argL */ 2912 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2913 /* no -- be like sradi */ 2914 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2915 ); 2916 break; 2917 2918 2919 case /* 13 */ PPCG_FLAG_OP_SRADI: 2920 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2921 Since the shift amount is known to be in the range 0 .. 63 2922 inclusive, the following seems viable: 2923 xer.ca == 1 iff the following is nonzero: 2924 (argL >>s 63) -- either all 0s or all 1s 2925 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2926 2927 xer_ca 2928 = binop( 2929 Iop_And64, 2930 binop(Iop_Sar64, argL, mkU8(63)), 2931 binop( Iop_And64, 2932 argL, 2933 binop( Iop_Sub64, 2934 binop(Iop_Shl64, mkU64(1), 2935 unop(Iop_64to8,argR)), 2936 mkU64(1) ) 2937 ) 2938 ); 2939 xer_ca 2940 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2941 break; 2942 2943 default: 2944 vex_printf("set_XER_CA: op = %u\n", op); 2945 vpanic("set_XER_CA(ppc64)"); 2946 } 2947 2948 return xer_ca; 2949 } 2950 2951 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2952 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2953 { 2954 IRExpr* xer_ca; 2955 vassert(op < PPCG_FLAG_OP_NUMBER); 2956 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2957 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2958 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2959 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2960 2961 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2962 seems reasonable given that it's always generated by 2963 getXER_CA_32(), which masks it accordingly. In any case it being 2964 0 or 1 is an invariant of the ppc guest state representation; 2965 if it has any other value, that invariant has been violated. */ 2966 2967 xer_ca = calculate_XER_CA_64( op, res, argL, argR, oldca ); 2968 2969 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2970 putXER_CA( unop(Iop_32to8, xer_ca) ); 2971 } 2972 2973 static void set_XER_CA_CA32 ( IRType ty, UInt op, IRExpr* res, 2974 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2975 { 2976 if (ty == Ity_I32) { 2977 set_XER_CA_32( op, res, argL, argR, oldca ); 2978 } else { 2979 set_XER_CA_64( op, res, argL, argR, oldca ); 2980 } 2981 } 2982 2983 2984 2985 /*------------------------------------------------------------*/ 2986 /*--- Read/write to guest-state --- */ 2987 /*------------------------------------------------------------*/ 2988 2989 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2990 { 2991 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2992 switch (reg) { 2993 case PPC_GST_SPRG3_RO: 2994 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2995 2996 case PPC_GST_CIA: 2997 return IRExpr_Get( OFFB_CIA, ty ); 2998 2999 case PPC_GST_LR: 3000 return IRExpr_Get( OFFB_LR, ty ); 3001 3002 case PPC_GST_CTR: 3003 return IRExpr_Get( OFFB_CTR, ty ); 3004 3005 case PPC_GST_VRSAVE: 3006 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 3007 3008 case PPC_GST_VSCR: 3009 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 3010 mkU32(MASK_VSCR_VALID)); 3011 3012 case PPC_GST_CR: { 3013 /* Synthesise the entire CR into a single word. Expensive. */ 3014 # define FIELD(_n) \ 3015 binop(Iop_Shl32, \ 3016 unop(Iop_8Uto32, \ 3017 binop(Iop_Or8, \ 3018 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 3019 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 3020 ) \ 3021 ), \ 3022 mkU8(4 * (7-(_n))) \ 3023 ) 3024 return binop(Iop_Or32, 3025 binop(Iop_Or32, 3026 binop(Iop_Or32, FIELD(0), FIELD(1)), 3027 binop(Iop_Or32, FIELD(2), FIELD(3)) 3028 ), 3029 binop(Iop_Or32, 3030 binop(Iop_Or32, FIELD(4), FIELD(5)), 3031 binop(Iop_Or32, FIELD(6), FIELD(7)) 3032 ) 3033 ); 3034 # undef FIELD 3035 } 3036 3037 case PPC_GST_XER: 3038 return binop(Iop_Or32, 3039 binop(Iop_Or32, 3040 binop(Iop_Or32, 3041 binop( Iop_Shl32, getXER_SO_32(), mkU8(31)), 3042 binop( Iop_Shl32, getXER_OV_32(), mkU8(30))), 3043 binop(Iop_Or32, 3044 binop( Iop_Shl32, getXER_CA_32(), mkU8(29)), 3045 getXER_BC_32())), 3046 binop(Iop_Or32, 3047 binop( Iop_Shl32, getXER_OV32_32(), mkU8(19)), 3048 binop( Iop_Shl32, getXER_CA32_32(), mkU8(18)))); 3049 3050 case PPC_GST_TFHAR: 3051 return IRExpr_Get( OFFB_TFHAR, ty ); 3052 3053 case PPC_GST_TEXASR: 3054 return IRExpr_Get( OFFB_TEXASR, ty ); 3055 3056 case PPC_GST_TEXASRU: 3057 return IRExpr_Get( OFFB_TEXASRU, ty ); 3058 3059 case PPC_GST_TFIAR: 3060 return IRExpr_Get( OFFB_TFIAR, ty ); 3061 3062 case PPC_GST_PPR: 3063 return IRExpr_Get( OFFB_PPR, ty ); 3064 3065 case PPC_GST_PPR32: 3066 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) ); 3067 3068 case PPC_GST_PSPB: 3069 return IRExpr_Get( OFFB_PSPB, ty ); 3070 3071 default: 3072 vex_printf("getGST(ppc): reg = %u", reg); 3073 vpanic("getGST(ppc)"); 3074 } 3075 } 3076 3077 /* Get a masked word from the given reg */ 3078 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, ULong mask ) 3079 { 3080 IRTemp val = newTemp(Ity_I32); 3081 vassert( reg < PPC_GST_MAX ); 3082 3083 switch (reg) { 3084 3085 case PPC_GST_FPSCR: { 3086 /* Vex-generated code expects the FPSCR to be set as follows: 3087 all exceptions masked, round-to-nearest. 3088 This corresponds to a FPSCR value of 0x0. */ 3089 3090 /* In the lower 32 bits of FPSCR, we're keeping track of the binary 3091 * floating point rounding mode and Floating-point Condition code, so 3092 * if the mask isn't asking for either of these, just return 0x0. 3093 */ 3094 if ( mask & ( MASK_FPSCR_C_FPCC | MASK_FPSCR_RN ) ) { 3095 assign( val, binop( Iop_Or32, 3096 unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ), 3097 binop( Iop_Shl32, 3098 unop( Iop_8Uto32, 3099 IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3100 mkU8( 12 ) ) ) ); 3101 } else { 3102 assign( val, mkU32(0x0) ); 3103 } 3104 3105 break; 3106 } 3107 3108 default: 3109 vex_printf("getGST_masked(ppc): reg = %u", reg); 3110 vpanic("getGST_masked(ppc)"); 3111 } 3112 3113 if ( mask != 0xFFFFFFFF ) { 3114 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 3115 } else { 3116 return mkexpr(val); 3117 } 3118 } 3119 3120 /* Get a masked word from the given reg */ 3121 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 3122 IRExpr * val; 3123 vassert( reg < PPC_GST_MAX ); 3124 3125 switch (reg) { 3126 3127 case PPC_GST_FPSCR: { 3128 /* In the upper 32 bits of FPSCR, we're only keeping track 3129 * of the decimal floating point rounding mode, so if the mask 3130 * isn't asking for this, just return 0x0. 3131 */ 3132 if (mask & MASK_FPSCR_DRN) { 3133 val = binop( Iop_And32, 3134 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 3135 unop( Iop_64HIto32, mkU64( mask ) ) ); 3136 } else { 3137 val = mkU32( 0x0ULL ); 3138 } 3139 break; 3140 } 3141 3142 default: 3143 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 3144 vpanic( "getGST_masked_upper(ppc)" ); 3145 } 3146 return val; 3147 } 3148 3149 3150 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 3151 and return it at the bottom of an I32; the top 27 bits are 3152 guaranteed to be zero. */ 3153 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 3154 { 3155 UInt shft, mask; 3156 3157 vassert( fld < 8 ); 3158 vassert( reg < PPC_GST_MAX ); 3159 3160 shft = 4*(7-fld); 3161 mask = 0xF<<shft; 3162 3163 switch (reg) { 3164 case PPC_GST_XER: 3165 vassert(fld ==7); 3166 return binop(Iop_Or32, 3167 binop(Iop_Or32, 3168 binop(Iop_Shl32, getXER_SO_32(), mkU8(3)), 3169 binop(Iop_Shl32, getXER_OV_32(), mkU8(2))), 3170 binop( Iop_Shl32, getXER_CA_32(), mkU8(1))); 3171 break; 3172 3173 default: 3174 if (shft == 0) 3175 return getGST_masked( reg, mask ); 3176 else 3177 return binop(Iop_Shr32, 3178 getGST_masked( reg, mask ), 3179 mkU8(toUChar( shft ))); 3180 } 3181 } 3182 3183 static void putGST ( PPC_GST reg, IRExpr* src ) 3184 { 3185 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3186 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 3187 vassert( reg < PPC_GST_MAX ); 3188 switch (reg) { 3189 case PPC_GST_IP_AT_SYSCALL: 3190 vassert( ty_src == ty ); 3191 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 3192 break; 3193 case PPC_GST_CIA: 3194 vassert( ty_src == ty ); 3195 stmt( IRStmt_Put( OFFB_CIA, src ) ); 3196 break; 3197 case PPC_GST_LR: 3198 vassert( ty_src == ty ); 3199 stmt( IRStmt_Put( OFFB_LR, src ) ); 3200 break; 3201 case PPC_GST_CTR: 3202 vassert( ty_src == ty ); 3203 stmt( IRStmt_Put( OFFB_CTR, src ) ); 3204 break; 3205 case PPC_GST_VRSAVE: 3206 vassert( ty_src == Ity_I32 ); 3207 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 3208 break; 3209 case PPC_GST_VSCR: 3210 vassert( ty_src == Ity_I32 ); 3211 stmt( IRStmt_Put( OFFB_VSCR, 3212 binop(Iop_And32, src, 3213 mkU32(MASK_VSCR_VALID)) ) ); 3214 break; 3215 case PPC_GST_XER: 3216 vassert( ty_src == Ity_I32 ); 3217 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 3218 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 3219 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 3220 putXER_OV32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(19))) ); 3221 putXER_CA32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(18))) ); 3222 putXER_BC( unop(Iop_32to8, src) ); 3223 break; 3224 3225 case PPC_GST_EMWARN: 3226 vassert( ty_src == Ity_I32 ); 3227 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 3228 break; 3229 3230 case PPC_GST_CMSTART: 3231 vassert( ty_src == ty ); 3232 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 3233 break; 3234 3235 case PPC_GST_CMLEN: 3236 vassert( ty_src == ty ); 3237 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 3238 break; 3239 3240 case PPC_GST_TEXASR: 3241 vassert( ty_src == Ity_I64 ); 3242 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 3243 break; 3244 3245 case PPC_GST_TEXASRU: 3246 vassert( ty_src == Ity_I32 ); 3247 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 3248 break; 3249 3250 case PPC_GST_TFIAR: 3251 vassert( ty_src == Ity_I64 ); 3252 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 3253 break; 3254 case PPC_GST_TFHAR: 3255 vassert( ty_src == Ity_I64 ); 3256 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 3257 break; 3258 3259 case PPC_GST_PPR32: 3260 case PPC_GST_PPR: 3261 { 3262 /* The Program Priority Register (PPR) stores the priority in 3263 * bits [52:50]. The user setable priorities are: 3264 * 3265 * 001 very low 3266 * 010 low 3267 * 011 medium low 3268 * 100 medium 3269 * 101 medium high 3270 * 3271 * If the argument is not between 0b001 and 0b100 the priority is set 3272 * to 0b100. The priority can only be set to 0b101 if the the Problem 3273 * State Boost Register is non-zero. The value of the PPR is not 3274 * changed if the input is not valid. 3275 */ 3276 3277 IRTemp not_valid = newTemp(Ity_I64); 3278 IRTemp has_perm = newTemp(Ity_I64); 3279 IRTemp new_src = newTemp(Ity_I64); 3280 IRTemp PSPB_val = newTemp(Ity_I64); 3281 IRTemp value = newTemp(Ity_I64); 3282 3283 vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 )); 3284 assign( PSPB_val, binop( Iop_32HLto64, 3285 mkU32( 0 ), 3286 IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) ); 3287 if( reg == PPC_GST_PPR32 ) { 3288 vassert( ty_src == Ity_I32 ); 3289 assign( value, binop( Iop_32HLto64, 3290 mkU32(0), 3291 binop( Iop_And32, 3292 binop( Iop_Shr32, src, mkU8( 18 ) ), 3293 mkU32( 0x7 ) ) ) ); 3294 } else { 3295 vassert( ty_src == Ity_I64 ); 3296 assign( value, binop( Iop_And64, 3297 binop( Iop_Shr64, src, mkU8( 50 ) ), 3298 mkU64( 0x7 ) ) ); 3299 } 3300 assign( has_perm, 3301 binop( Iop_And64, 3302 unop( Iop_1Sto64, 3303 binop( Iop_CmpEQ64, 3304 mkexpr( PSPB_val ), 3305 mkU64( 0 ) ) ), 3306 unop( Iop_1Sto64, 3307 binop( Iop_CmpEQ64, 3308 mkU64( 0x5 ), 3309 mkexpr( value ) ) ) ) ); 3310 assign( not_valid, 3311 binop( Iop_Or64, 3312 unop( Iop_1Sto64, 3313 binop( Iop_CmpEQ64, 3314 mkexpr( value ), 3315 mkU64( 0 ) ) ), 3316 unop( Iop_1Sto64, 3317 binop( Iop_CmpLT64U, 3318 mkU64( 0x5 ), 3319 mkexpr( value ) ) ) ) ); 3320 assign( new_src, 3321 binop( Iop_Or64, 3322 binop( Iop_And64, 3323 unop( Iop_Not64, 3324 mkexpr( not_valid ) ), 3325 src ), 3326 binop( Iop_And64, 3327 mkexpr( not_valid ), 3328 binop( Iop_Or64, 3329 binop( Iop_And64, 3330 mkexpr( has_perm), 3331 binop( Iop_Shl64, 3332 mkexpr( value ), 3333 mkU8( 50 ) ) ), 3334 binop( Iop_And64, 3335 IRExpr_Get( OFFB_PPR, ty ), 3336 unop( Iop_Not64, 3337 mkexpr( has_perm ) 3338 ) ) ) ) ) ); 3339 3340 /* make sure we only set the valid bit field [52:50] */ 3341 stmt( IRStmt_Put( OFFB_PPR, 3342 binop( Iop_And64, 3343 mkexpr( new_src ), 3344 mkU64( 0x1C000000000000) ) ) ); 3345 break; 3346 } 3347 default: 3348 vex_printf("putGST(ppc): reg = %u", reg); 3349 vpanic("putGST(ppc)"); 3350 } 3351 } 3352 3353 /* Write masked src to the given reg */ 3354 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 3355 { 3356 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3357 vassert( reg < PPC_GST_MAX ); 3358 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 3359 3360 switch (reg) { 3361 case PPC_GST_FPSCR: { 3362 /* Allow writes to either binary or decimal floating point 3363 Rounding Mode. 3364 */ 3365 /* If any part of |mask| covers FPSCR.RN, update the bits of 3366 FPSCR.RN by copying in |src| for locations where the 3367 corresponding bit in |mask| is 1, and leaving it unchanged 3368 for corresponding |mask| zero bits. */ 3369 if (mask & MASK_FPSCR_RN) { 3370 stmt( 3371 IRStmt_Put( 3372 OFFB_FPROUND, 3373 unop( 3374 Iop_32to8, 3375 binop( 3376 Iop_Or32, 3377 binop( 3378 Iop_And32, 3379 unop(Iop_64to32, src), 3380 mkU32(MASK_FPSCR_RN & mask) 3381 ), 3382 binop( 3383 Iop_And32, 3384 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 3385 mkU32(MASK_FPSCR_RN & ~mask) 3386 ) 3387 ) 3388 ) 3389 ) 3390 ); 3391 } 3392 3393 if (mask & MASK_FPSCR_C_FPCC) { 3394 /* FPCC bits are in [47:51] */ 3395 stmt( 3396 IRStmt_Put( 3397 OFFB_C_FPCC, 3398 unop( 3399 Iop_32to8, 3400 binop(Iop_Shr32, 3401 binop( 3402 Iop_Or32, 3403 binop( 3404 Iop_And32, 3405 unop(Iop_64to32, src), 3406 mkU32(MASK_FPSCR_C_FPCC & mask) ), 3407 binop( 3408 Iop_And32, 3409 unop(Iop_8Uto32, 3410 IRExpr_Get(OFFB_C_FPCC,Ity_I8)), 3411 mkU32(MASK_FPSCR_C_FPCC & ~mask) 3412 ) ), 3413 mkU8( 12 ) ) 3414 ) ) ); 3415 } 3416 3417 /* Similarly, update FPSCR.DRN if any bits of |mask| 3418 corresponding to FPSCR.DRN are set. */ 3419 if (mask & MASK_FPSCR_DRN) { 3420 stmt( 3421 IRStmt_Put( 3422 OFFB_DFPROUND, 3423 unop( 3424 Iop_32to8, 3425 binop( 3426 Iop_Or32, 3427 binop( 3428 Iop_And32, 3429 unop(Iop_64HIto32, src), 3430 mkU32((MASK_FPSCR_DRN & mask) >> 32) 3431 ), 3432 binop( 3433 Iop_And32, 3434 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 3435 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 3436 ) 3437 ) 3438 ) 3439 ) 3440 ); 3441 } 3442 3443 /* Give EmNote for attempted writes to: 3444 - Exception Controls 3445 - Non-IEEE Mode 3446 */ 3447 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3448 VexEmNote ew = EmWarn_PPCexns; 3449 3450 /* If any of the src::exception_control bits are actually set, 3451 side-exit to the next insn, reporting the warning, 3452 so that Valgrind's dispatcher sees the warning. */ 3453 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3454 stmt( 3455 IRStmt_Exit( 3456 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3457 Ijk_EmWarn, 3458 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3459 } 3460 3461 /* Ignore all other writes */ 3462 break; 3463 } 3464 3465 default: 3466 vex_printf("putGST_masked(ppc): reg = %u", reg); 3467 vpanic("putGST_masked(ppc)"); 3468 } 3469 } 3470 3471 /* Write the least significant nibble of src to the specified 3472 REG[FLD] (as per IBM/hardware notation). */ 3473 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3474 { 3475 UInt shft; 3476 ULong mask; 3477 3478 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3479 vassert( fld < 16 ); 3480 vassert( reg < PPC_GST_MAX ); 3481 3482 if (fld < 8) 3483 shft = 4*(7-fld); 3484 else 3485 shft = 4*(15-fld); 3486 mask = 0xF; 3487 mask = mask << shft; 3488 3489 switch (reg) { 3490 case PPC_GST_CR: 3491 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3492 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3493 break; 3494 3495 default: 3496 { 3497 IRExpr * src64 = unop( Iop_32Uto64, src ); 3498 3499 if (shft == 0) { 3500 putGST_masked( reg, src64, mask ); 3501 } else { 3502 putGST_masked( reg, 3503 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3504 mask ); 3505 } 3506 } 3507 } 3508 } 3509 3510 static void putFPCC ( IRExpr* e ) 3511 { 3512 /* The assumption is that the value of the FPCC are passed in the lower 3513 * four bits of a 32 bit value. 3514 * 3515 * Note, the C and FPCC bits which are a field of the FPSCR 3516 * register are stored in their own "register" in 3517 * memory. The FPCC bits are in the lower 4 bits. We don't need to 3518 * shift it to the bits to their location in the FPSCR register. Note, 3519 * not all of the FPSCR register bits are supported. We are writing all 3520 * of the bits in the FPCC field but not the C field. 3521 */ 3522 IRExpr* tmp; 3523 3524 vassert( typeOfIRExpr( irsb->tyenv, e ) == Ity_I32 ); 3525 /* Get the C bit field */ 3526 tmp = binop( Iop_And32, 3527 mkU32( 0x10 ), 3528 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) ); 3529 3530 stmt( IRStmt_Put( OFFB_C_FPCC, 3531 unop( Iop_32to8, 3532 binop( Iop_Or32, tmp, 3533 binop( Iop_And32, mkU32( 0xF ), e ) ) ) ) ); 3534 3535 } 3536 3537 static IRExpr* /* ::Ity_I32 */ getC ( void ) 3538 { 3539 /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of 3540 * the FPSCR registered are stored in its own "register" in guest state 3541 * with the FPCC bit field. C | FPCC 3542 */ 3543 IRTemp val = newTemp(Ity_I32); 3544 3545 assign( val, binop( Iop_Shr32, 3546 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3547 mkU8( 4 ) ) ); 3548 return mkexpr(val); 3549 } 3550 3551 static IRExpr* /* ::Ity_I32 */ getFPCC ( void ) 3552 { 3553 /* Note, the FPCC bits are a field of the FPSCR 3554 * register are stored in their own "register" in 3555 * guest state with the C bit field. C | FPCC 3556 */ 3557 IRTemp val = newTemp( Ity_I32 ); 3558 3559 assign( val, binop( Iop_And32, unop( Iop_8Uto32, 3560 IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3561 mkU32( 0xF ) )); 3562 return mkexpr(val); 3563 } 3564 3565 /*------------------------------------------------------------*/ 3566 /* Helpers for VSX instructions that do floating point 3567 * operations and need to determine if a src contains a 3568 * special FP value. 3569 * 3570 *------------------------------------------------------------*/ 3571 3572 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3573 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3574 mkexpr( x ), \ 3575 mkU64( NONZERO_FRAC_MASK ) ) 3576 3577 #define NONZERO_FRAC_MASK32 0x007fffffULL 3578 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3579 mkexpr( x ), \ 3580 mkU32( NONZERO_FRAC_MASK32 ) ) 3581 3582 // Returns exponent part of floating point src as I32 3583 static IRExpr * fp_exp_part( IRType size, IRTemp src ) 3584 { 3585 IRExpr *shift_by, *mask, *tsrc; 3586 3587 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3588 || ( size == Ity_I64 ) ); 3589 3590 if( size == Ity_I16 ) { 3591 /* The 16-bit floating point value is in the lower 16-bits 3592 * of the 32-bit input value. 3593 */ 3594 tsrc = mkexpr( src ); 3595 mask = mkU32( 0x1F ); 3596 shift_by = mkU8( 10 ); 3597 3598 } else if( size == Ity_I32 ) { 3599 tsrc = mkexpr( src ); 3600 mask = mkU32( 0xFF ); 3601 shift_by = mkU8( 23 ); 3602 3603 } else if( size == Ity_I64 ) { 3604 tsrc = unop( Iop_64HIto32, mkexpr( src ) ); 3605 mask = mkU32( 0x7FF ); 3606 shift_by = mkU8( 52 - 32 ); 3607 3608 } else { 3609 /*NOTREACHED*/ 3610 vassert(0); // Stops gcc complaining at "-Og" 3611 } 3612 3613 return binop( Iop_And32, binop( Iop_Shr32, tsrc, shift_by ), mask ); 3614 } 3615 3616 /* The following functions check the floating point value to see if it 3617 is zero, infinity, NaN, Normalized, Denormalized. 3618 */ 3619 /* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */ 3620 #define I16_EXP_MASK 0x7C00 3621 #define I16_FRACTION_MASK 0x03FF 3622 #define I32_EXP_MASK 0x7F800000 3623 #define I32_FRACTION_MASK 0x007FFFFF 3624 #define I64_EXP_MASK 0x7FF0000000000000ULL 3625 #define I64_FRACTION_MASK 0x000FFFFFFFFFFFFFULL 3626 #define V128_EXP_MASK 0x7FFF000000000000ULL 3627 #define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL /* upper 64-bit fractional mask */ 3628 3629 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask, 3630 IRTemp *zero ); 3631 3632 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask, 3633 IRTemp *zero ) { 3634 3635 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3636 || ( size == Ity_I64 ) || ( size == Ity_V128 ) ); 3637 3638 if( size == Ity_I16 ) { 3639 /* The 16-bit floating point value is in the lower 16-bits of 3640 the 32-bit input value */ 3641 *frac_mask = newTemp( Ity_I32 ); 3642 *exp_mask = newTemp( Ity_I32 ); 3643 *zero = newTemp( Ity_I32 ); 3644 assign( *exp_mask, mkU32( I16_EXP_MASK ) ); 3645 assign( *frac_mask, mkU32( I16_FRACTION_MASK ) ); 3646 assign( *zero, mkU32( 0 ) ); 3647 3648 } else if( size == Ity_I32 ) { 3649 *frac_mask = newTemp( Ity_I32 ); 3650 *exp_mask = newTemp( Ity_I32 ); 3651 *zero = newTemp( Ity_I32 ); 3652 assign( *exp_mask, mkU32( I32_EXP_MASK ) ); 3653 assign( *frac_mask, mkU32( I32_FRACTION_MASK ) ); 3654 assign( *zero, mkU32( 0 ) ); 3655 3656 } else if( size == Ity_I64 ) { 3657 *frac_mask = newTemp( Ity_I64 ); 3658 *exp_mask = newTemp( Ity_I64 ); 3659 *zero = newTemp( Ity_I64 ); 3660 assign( *exp_mask, mkU64( I64_EXP_MASK ) ); 3661 assign( *frac_mask, mkU64( I64_FRACTION_MASK ) ); 3662 assign( *zero, mkU64( 0 ) ); 3663 3664 } else { 3665 /* V128 is converted to upper and lower 64 bit values, */ 3666 /* uses 64-bit operators and temps */ 3667 *frac_mask = newTemp( Ity_I64 ); 3668 *exp_mask = newTemp( Ity_I64 ); 3669 *zero = newTemp( Ity_I64 ); 3670 assign( *exp_mask, mkU64( V128_EXP_MASK ) ); 3671 /* upper 64-bit fractional mask */ 3672 assign( *frac_mask, mkU64( V128_FRACTION_MASK ) ); 3673 assign( *zero, mkU64( 0 ) ); 3674 } 3675 } 3676 3677 /* Helper function for the various function which check the value of 3678 the floating point value. 3679 */ 3680 static IRExpr * exponent_compare( IRType size, IRTemp src, 3681 IRTemp exp_mask, IRExpr *exp_val ) 3682 { 3683 IROp opAND, opCmpEQ; 3684 3685 if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3686 /* The 16-bit floating point value is in the lower 16-bits of 3687 the 32-bit input value */ 3688 opAND = Iop_And32; 3689 opCmpEQ = Iop_CmpEQ32; 3690 3691 } else { 3692 opAND = Iop_And64; 3693 opCmpEQ = Iop_CmpEQ64; 3694 } 3695 3696 if( size == Ity_V128 ) { 3697 return binop( opCmpEQ, 3698 binop ( opAND, 3699 unop( Iop_V128HIto64, mkexpr( src ) ), 3700 mkexpr( exp_mask ) ), 3701 exp_val ); 3702 3703 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3704 return binop( opCmpEQ, 3705 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ), 3706 exp_val ); 3707 } else { 3708 /* 64-bit operands */ 3709 3710 if (mode64) { 3711 return binop( opCmpEQ, 3712 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ), 3713 exp_val ); 3714 } else { 3715 /* No support for 64-bit compares in 32-bit mode, need to do upper 3716 * and lower parts using 32-bit compare operators. 3717 */ 3718 return 3719 mkAND1( binop( Iop_CmpEQ32, 3720 binop ( Iop_And32, 3721 unop(Iop_64HIto32, mkexpr( src ) ), 3722 unop(Iop_64HIto32, mkexpr( exp_mask ) ) ), 3723 unop(Iop_64HIto32, exp_val ) ), 3724 binop( Iop_CmpEQ32, 3725 binop ( Iop_And32, 3726 unop(Iop_64to32, mkexpr( src ) ), 3727 unop(Iop_64to32, mkexpr( exp_mask ) ) ), 3728 unop(Iop_64to32, exp_val ) ) ); 3729 } 3730 } 3731 } 3732 3733 static IRExpr *fractional_part_compare( IRType size, IRTemp src, 3734 IRTemp frac_mask, IRExpr *zero ) 3735 { 3736 IROp opAND, opCmpEQ; 3737 3738 if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3739 /*The 16-bit floating point value is in the lower 16-bits of 3740 the 32-bit input value */ 3741 opAND = Iop_And32; 3742 opCmpEQ = Iop_CmpEQ32; 3743 3744 } else { 3745 opAND = Iop_And64; 3746 opCmpEQ = Iop_CmpEQ64; 3747 } 3748 3749 if( size == Ity_V128 ) { 3750 /* 128-bit, note we only care if the fractional part is zero so take upper 3751 52-bits of fractional part and lower 64-bits and OR them together and test 3752 for zero. This keeps the temp variables and operators all 64-bit. 3753 */ 3754 return binop( opCmpEQ, 3755 binop( Iop_Or64, 3756 binop( opAND, 3757 unop( Iop_V128HIto64, mkexpr( src ) ), 3758 mkexpr( frac_mask ) ), 3759 unop( Iop_V128to64, mkexpr( src ) ) ), 3760 zero ); 3761 3762 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3763 return binop( opCmpEQ, 3764 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ), 3765 zero ); 3766 } else { 3767 if (mode64) { 3768 return binop( opCmpEQ, 3769 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ), 3770 zero ); 3771 } else { 3772 /* No support for 64-bit compares in 32-bit mode, need to do upper 3773 * and lower parts using 32-bit compare operators. 3774 */ 3775 return 3776 mkAND1( binop( Iop_CmpEQ32, 3777 binop ( Iop_And32, 3778 unop(Iop_64HIto32, mkexpr( src ) ), 3779 unop(Iop_64HIto32, mkexpr( frac_mask ) ) ), 3780 mkU32 ( 0 ) ), 3781 binop( Iop_CmpEQ32, 3782 binop ( Iop_And32, 3783 unop(Iop_64to32, mkexpr( src ) ), 3784 unop(Iop_64to32, mkexpr( frac_mask ) ) ), 3785 mkU32 ( 0 ) ) ); 3786 } 3787 } 3788 } 3789 3790 // Infinity: exp has all bits set, and fraction is zero; s = 0/1 3791 static IRExpr * is_Inf( IRType size, IRTemp src ) 3792 { 3793 IRExpr *max_exp, *zero_frac; 3794 IRTemp exp_mask, frac_mask, zero; 3795 3796 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3797 3798 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3799 max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) ); 3800 3801 /* check fractional part is all zeros */ 3802 zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) ); 3803 3804 return mkAND1( max_exp, zero_frac ); 3805 } 3806 3807 // Zero: exp is zero and fraction is zero; s = 0/1 3808 static IRExpr * is_Zero( IRType size, IRTemp src ) 3809 { 3810 IRExpr *zero_exp, *zero_frac; 3811 IRTemp exp_mask, frac_mask, zero; 3812 3813 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3814 3815 /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */ 3816 zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) ); 3817 3818 /* check fractional part is all zeros */ 3819 zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) ); 3820 3821 return mkAND1( zero_exp, zero_frac ); 3822 } 3823 3824 /* SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1' 3825 * QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0' 3826 */ 3827 static IRExpr * is_NaN( IRType size, IRTemp src ) 3828 { 3829 IRExpr *max_exp, *not_zero_frac; 3830 IRTemp exp_mask, frac_mask, zero; 3831 3832 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3833 3834 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3835 max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) ); 3836 3837 /* check fractional part is not zero */ 3838 not_zero_frac = unop( Iop_Not1, 3839 fractional_part_compare( size, src, frac_mask, 3840 mkexpr( zero ) ) ); 3841 3842 return mkAND1( max_exp, not_zero_frac ); 3843 } 3844 3845 /* Denormalized number has a zero exponent and non zero fraction. */ 3846 static IRExpr * is_Denorm( IRType size, IRTemp src ) 3847 { 3848 IRExpr *zero_exp, *not_zero_frac; 3849 IRTemp exp_mask, frac_mask, zero; 3850 3851 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3852 3853 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3854 zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) ); 3855 3856 /* check fractional part is not zero */ 3857 not_zero_frac = unop( Iop_Not1, 3858 fractional_part_compare( size, src, frac_mask, 3859 mkexpr( zero ) ) ); 3860 3861 return mkAND1( zero_exp, not_zero_frac ); 3862 } 3863 3864 /* Normalized number has exponent between 1 and max_exp -1, or in other words 3865 the exponent is not zero and not equal to the max exponent value. */ 3866 static IRExpr * is_Norm( IRType size, IRTemp src ) 3867 { 3868 IRExpr *not_zero_exp, *not_max_exp; 3869 IRTemp exp_mask, zero; 3870 3871 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3872 || ( size == Ity_I64 ) || ( size == Ity_V128 ) ); 3873 3874 if( size == Ity_I16 ) { 3875 /* The 16-bit floating point value is in the lower 16-bits of 3876 the 32-bit input value */ 3877 exp_mask = newTemp( Ity_I32 ); 3878 zero = newTemp( Ity_I32 ); 3879 assign( exp_mask, mkU32( I16_EXP_MASK ) ); 3880 assign( zero, mkU32( 0 ) ); 3881 3882 } else if( size == Ity_I32 ) { 3883 exp_mask = newTemp( Ity_I32 ); 3884 zero = newTemp( Ity_I32 ); 3885 assign( exp_mask, mkU32( I32_EXP_MASK ) ); 3886 assign( zero, mkU32( 0 ) ); 3887 3888 } else if( size == Ity_I64 ) { 3889 exp_mask = newTemp( Ity_I64 ); 3890 zero = newTemp( Ity_I64 ); 3891 assign( exp_mask, mkU64( I64_EXP_MASK ) ); 3892 assign( zero, mkU64( 0 ) ); 3893 3894 } else { 3895 /* V128 is converted to upper and lower 64 bit values, */ 3896 /* uses 64-bit operators and temps */ 3897 exp_mask = newTemp( Ity_I64 ); 3898 zero = newTemp( Ity_I64 ); 3899 assign( exp_mask, mkU64( V128_EXP_MASK ) ); 3900 assign( zero, mkU64( 0 ) ); 3901 } 3902 3903 not_zero_exp = unop( Iop_Not1, 3904 exponent_compare( size, src, 3905 exp_mask, mkexpr( zero ) ) ); 3906 not_max_exp = unop( Iop_Not1, 3907 exponent_compare( size, src, 3908 exp_mask, mkexpr( exp_mask ) ) ); 3909 3910 return mkAND1( not_zero_exp, not_max_exp ); 3911 } 3912 3913 3914 static IRExpr * create_FPCC( IRTemp NaN, IRTemp inf, 3915 IRTemp zero, IRTemp norm, 3916 IRTemp dnorm, IRTemp pos, 3917 IRTemp neg ) { 3918 IRExpr *bit0, *bit1, *bit2, *bit3; 3919 3920 /* If the result is NaN then must force bits 1, 2 and 3 to zero 3921 * to get correct result. 3922 */ 3923 bit0 = unop( Iop_1Uto32, mkOR1( mkexpr( NaN ), mkexpr( inf ) ) ); 3924 bit1 = unop( Iop_1Uto32, mkAND1( mkNOT1( mkexpr( NaN ) ), mkexpr( zero ) ) ); 3925 bit2 = unop( Iop_1Uto32, 3926 mkAND1( mkNOT1( mkexpr( NaN ) ), 3927 mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( pos ), 3928 mkexpr( dnorm ) ), 3929 mkAND1( mkexpr( pos ), 3930 mkexpr( norm ) ) ), 3931 mkAND1( mkexpr( pos ), 3932 mkexpr( inf ) ) ), 3933 mkAND1( mkNOT1 ( mkexpr( zero ) ), 3934 mkNOT1( mkexpr( NaN ) ) ) ) ) ); 3935 bit3 = unop( Iop_1Uto32, 3936 mkAND1( mkNOT1( mkexpr( NaN ) ), 3937 mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( neg ), 3938 mkexpr( dnorm ) ), 3939 mkAND1( mkexpr( neg ), 3940 mkexpr( norm ) ) ), 3941 mkAND1( mkexpr( neg ), 3942 mkexpr( inf ) ) ), 3943 mkAND1( mkNOT1 ( mkexpr( zero ) ), 3944 mkNOT1( mkexpr( NaN ) ) ) ) ) ); 3945 3946 return binop( Iop_Or32, 3947 binop( Iop_Or32, 3948 bit0, 3949 binop( Iop_Shl32, bit1, mkU8( 1 ) ) ), 3950 binop( Iop_Or32, 3951 binop( Iop_Shl32, bit2, mkU8( 2 ) ), 3952 binop( Iop_Shl32, bit3, mkU8( 3 ) ) ) ); 3953 } 3954 3955 static IRExpr * create_C( IRTemp NaN, IRTemp zero, 3956 IRTemp dnorm, IRTemp pos, 3957 IRTemp neg ) 3958 { 3959 3960 return unop( Iop_1Uto32, 3961 mkOR1( mkOR1( mkexpr( NaN ), 3962 mkAND1( mkexpr( neg ), mkexpr( dnorm ) ) ), 3963 mkOR1( mkAND1( mkexpr( neg ), mkexpr( zero ) ), 3964 mkAND1( mkexpr( pos ), mkexpr( dnorm ) ) ) ) ); 3965 } 3966 3967 static void generate_store_FPRF( IRType size, IRTemp src ) 3968 { 3969 IRExpr *FPCC, *C; 3970 IRTemp NaN = newTemp( Ity_I1 ), inf = newTemp( Ity_I1 ); 3971 IRTemp dnorm = newTemp( Ity_I1 ), norm = newTemp( Ity_I1 ); 3972 IRTemp pos = newTemp( Ity_I1 ), neg = newTemp( Ity_I1 ); 3973 IRTemp zero = newTemp( Ity_I1 ); 3974 3975 IRTemp sign_bit = newTemp( Ity_I1 ); 3976 IRTemp value; 3977 3978 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3979 || ( size == Ity_I64 ) || ( size == Ity_F128 ) ); 3980 3981 vassert( ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I32 ) 3982 || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I64 ) 3983 || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_F128 ) ); 3984 3985 if( size == Ity_I16 ) { 3986 /* The 16-bit floating point value is in the lower 16-bits of 3987 the 32-bit input value */ 3988 value = newTemp( Ity_I32 ); 3989 assign( value, mkexpr( src ) ); 3990 assign( sign_bit, 3991 unop ( Iop_32to1, 3992 binop( Iop_And32, 3993 binop( Iop_Shr32, mkexpr( value ), mkU8( 15 ) ), 3994 mkU32( 0x1 ) ) ) ); 3995 3996 } else if( size == Ity_I32 ) { 3997 value = newTemp( size ); 3998 assign( value, mkexpr( src ) ); 3999 assign( sign_bit, 4000 unop ( Iop_32to1, 4001 binop( Iop_And32, 4002 binop( Iop_Shr32, mkexpr( value ), mkU8( 31 ) ), 4003 mkU32( 0x1 ) ) ) ); 4004 4005 } else if( size == Ity_I64 ) { 4006 value = newTemp( size ); 4007 assign( value, mkexpr( src ) ); 4008 assign( sign_bit, 4009 unop ( Iop_64to1, 4010 binop( Iop_And64, 4011 binop( Iop_Shr64, mkexpr( value ), mkU8( 63 ) ), 4012 mkU64( 0x1 ) ) ) ); 4013 4014 } else { 4015 /* Move the F128 bit pattern to an integer V128 bit pattern */ 4016 value = newTemp( Ity_V128 ); 4017 assign( value, 4018 binop( Iop_64HLtoV128, 4019 unop( Iop_ReinterpF64asI64, 4020 unop( Iop_F128HItoF64, mkexpr( src ) ) ), 4021 unop( Iop_ReinterpF64asI64, 4022 unop( Iop_F128LOtoF64, mkexpr( src ) ) ) ) ); 4023 4024 size = Ity_V128; 4025 assign( sign_bit, 4026 unop ( Iop_64to1, 4027 binop( Iop_And64, 4028 binop( Iop_Shr64, 4029 unop( Iop_V128HIto64, mkexpr( value ) ), 4030 mkU8( 63 ) ), 4031 mkU64( 0x1 ) ) ) ); 4032 } 4033 4034 /* Calculate the floating point result field FPRF */ 4035 assign( NaN, is_NaN( size, value ) ); 4036 assign( inf, is_Inf( size, value ) ); 4037 assign( zero, is_Zero( size, value ) ); 4038 assign( norm, is_Norm( size, value ) ); 4039 assign( dnorm, is_Denorm( size, value ) ); 4040 assign( pos, mkAND1( mkNOT1( mkexpr( sign_bit ) ), mkU1( 1 ) ) ); 4041 assign( neg, mkAND1( mkexpr( sign_bit ), mkU1( 1 ) ) ); 4042 4043 /* create the FPRF bit field 4044 * 4045 * FPRF field[4:0] type of value 4046 * 10001 QNaN 4047 * 01001 - infininity 4048 * 01000 - Normalized 4049 * 11000 - Denormalized 4050 * 10010 - zero 4051 * 00010 + zero 4052 * 10100 + Denormalized 4053 * 00100 + Normalized 4054 * 00101 + infinity 4055 */ 4056 FPCC = create_FPCC( NaN, inf, zero, norm, dnorm, pos, neg ); 4057 C = create_C( NaN, zero, dnorm, pos, neg ); 4058 4059 /* Write the C and FPCC fields of the FPRF field */ 4060 putC( C ); 4061 putFPCC( FPCC ); 4062 } 4063 4064 /* This function takes an Ity_I32 input argument interpreted 4065 as a single-precision floating point value. If src is a 4066 SNaN, it is changed to a QNaN and returned; otherwise, 4067 the original value is returned. */ 4068 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 4069 { 4070 #define SNAN_MASK32 0x00400000 4071 IRTemp tmp = newTemp(Ity_I32); 4072 IRTemp mask = newTemp(Ity_I32); 4073 IRTemp is_SNAN = newTemp(Ity_I1); 4074 4075 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 4076 assign(tmp, src); 4077 4078 /* check if input is SNaN, if it is convert to QNaN */ 4079 assign( is_SNAN, 4080 mkAND1( is_NaN( Ity_I32, tmp ), 4081 binop( Iop_CmpEQ32, 4082 binop( Iop_And32, mkexpr( tmp ), 4083 mkU32( SNAN_MASK32 ) ), 4084 mkU32( 0 ) ) ) ); 4085 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 4086 assign ( mask, binop( Iop_And32, 4087 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 4088 mkU32( SNAN_MASK32 ) ) ); 4089 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 4090 } 4091 4092 4093 /* This helper function performs the negation part of operations of the form: 4094 * "Negate Multiply-<op>" 4095 * where "<op>" is either "Add" or "Sub". 4096 * 4097 * This function takes one argument -- the floating point intermediate result (converted to 4098 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 4099 * the operation described above. 4100 */ 4101 static IRTemp getNegatedResult(IRTemp intermediateResult) 4102 { 4103 ULong signbit_mask = 0x8000000000000000ULL; 4104 IRTemp signbit_32 = newTemp(Ity_I32); 4105 IRTemp resultantSignbit = newTemp(Ity_I1); 4106 IRTemp negatedResult = newTemp(Ity_I64); 4107 assign( signbit_32, binop( Iop_Shr32, 4108 unop( Iop_64HIto32, 4109 binop( Iop_And64, mkexpr( intermediateResult ), 4110 mkU64( signbit_mask ) ) ), 4111 mkU8( 31 ) ) ); 4112 /* We negate the signbit if and only if the intermediate result from the 4113 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 4114 */ 4115 assign( resultantSignbit, 4116 unop( Iop_Not1, 4117 binop( Iop_CmpEQ32, 4118 binop( Iop_Xor32, 4119 mkexpr( signbit_32 ), 4120 unop( Iop_1Uto32, is_NaN( Ity_I64, 4121 intermediateResult ) ) ), 4122 mkU32( 1 ) ) ) ); 4123 4124 assign( negatedResult, 4125 binop( Iop_Or64, 4126 binop( Iop_And64, 4127 mkexpr( intermediateResult ), 4128 mkU64( ~signbit_mask ) ), 4129 binop( Iop_32HLto64, 4130 binop( Iop_Shl32, 4131 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 4132 mkU8( 31 ) ), 4133 mkU32( 0 ) ) ) ); 4134 4135 return negatedResult; 4136 } 4137 4138 /* This helper function performs the negation part of operations of the form: 4139 * "Negate Multiply-<op>" 4140 * where "<op>" is either "Add" or "Sub". 4141 * 4142 * This function takes one argument -- the floating point intermediate result (converted to 4143 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 4144 * the operation described above. 4145 */ 4146 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 4147 { 4148 UInt signbit_mask = 0x80000000; 4149 IRTemp signbit_32 = newTemp(Ity_I32); 4150 IRTemp resultantSignbit = newTemp(Ity_I1); 4151 IRTemp negatedResult = newTemp(Ity_I32); 4152 assign( signbit_32, binop( Iop_Shr32, 4153 binop( Iop_And32, mkexpr( intermediateResult ), 4154 mkU32( signbit_mask ) ), 4155 mkU8( 31 ) ) ); 4156 /* We negate the signbit if and only if the intermediate result from the 4157 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 4158 */ 4159 assign( resultantSignbit, 4160 unop( Iop_Not1, 4161 binop( Iop_CmpEQ32, 4162 binop( Iop_Xor32, 4163 mkexpr( signbit_32 ), 4164 unop( Iop_1Uto32, is_NaN( Ity_I32, 4165 intermediateResult ) ) ), 4166 mkU32( 1 ) ) ) ); 4167 4168 assign( negatedResult, 4169 binop( Iop_Or32, 4170 binop( Iop_And32, 4171 mkexpr( intermediateResult ), 4172 mkU32( ~signbit_mask ) ), 4173 binop( Iop_Shl32, 4174 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 4175 mkU8( 31 ) ) ) ); 4176 4177 return negatedResult; 4178 } 4179 4180 /* This function takes two quad_precision floating point numbers of type 4181 V128 and return 1 if src_A > src_B, 0 otherwise. */ 4182 static IRExpr * Quad_precision_gt ( IRTemp src_A, IRTemp src_B ) 4183 { 4184 #define FRAC_MASK64Hi 0x0000ffffffffffffULL 4185 #define MASK 0x7FFFFFFFFFFFFFFFULL /* exclude sign bit in upper 64 bits */ 4186 #define EXP_MASK 0x7fff 4187 4188 IRType ty = Ity_I64; 4189 IRTemp sign_A = newTemp( ty ); 4190 IRTemp sign_B = newTemp( ty ); 4191 IRTemp exp_A = newTemp( ty ); 4192 IRTemp exp_B = newTemp( ty ); 4193 IRTemp frac_A_hi = newTemp( ty ); 4194 IRTemp frac_B_hi = newTemp( ty ); 4195 IRTemp frac_A_lo = newTemp( ty ); 4196 IRTemp frac_B_lo = newTemp( ty ); 4197 4198 4199 /* extract exponents, and fractional parts so they can be compared */ 4200 assign( sign_A, binop( Iop_Shr64, 4201 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4202 mkU8( 63 ) ) ); 4203 assign( sign_B, binop( Iop_Shr64, 4204 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4205 mkU8( 63 ) ) ); 4206 assign( exp_A, binop( Iop_And64, 4207 binop( Iop_Shr64, 4208 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4209 mkU8( 48 ) ), 4210 mkU64( EXP_MASK ) ) ); 4211 assign( exp_B, binop( Iop_And64, 4212 binop( Iop_Shr64, 4213 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4214 mkU8( 48 ) ), 4215 mkU64( EXP_MASK ) ) ); 4216 assign( frac_A_hi, binop( Iop_And64, 4217 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4218 mkU64( FRAC_MASK64Hi ) ) ); 4219 assign( frac_B_hi, binop( Iop_And64, 4220 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4221 mkU64( FRAC_MASK64Hi ) ) ); 4222 assign( frac_A_lo, unop( Iop_V128to64, mkexpr( src_A ) ) ); 4223 assign( frac_B_lo, unop( Iop_V128to64, mkexpr( src_B ) ) ); 4224 4225 IRExpr * A_zero = mkAND1( binop( Iop_CmpEQ64, 4226 binop( Iop_And64, 4227 unop( Iop_V128HIto64, 4228 mkexpr( src_A ) ), 4229 mkU64( MASK ) ), 4230 mkU64( 0 ) ), 4231 binop( Iop_CmpEQ64, 4232 unop( Iop_V128to64, mkexpr( src_A ) ), 4233 mkU64( 0 ) ) ); 4234 IRExpr * B_zero = mkAND1( binop( Iop_CmpEQ64, 4235 binop( Iop_And64, 4236 unop( Iop_V128HIto64, 4237 mkexpr( src_B ) ), 4238 mkU64( MASK ) ), 4239 mkU64( 0 ) ), 4240 binop( Iop_CmpEQ64, 4241 unop( Iop_V128to64, mkexpr( src_B ) ), 4242 mkU64( 0 ) ) ); 4243 IRExpr * A_B_zero = mkAND1( A_zero, B_zero ); 4244 4245 /* Compare numbers */ 4246 IRExpr * both_pos = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ), 4247 mkU64( 0 ) ), 4248 binop( Iop_CmpEQ64, mkexpr( sign_B ), 4249 mkU64( 0 ) ) ); 4250 IRExpr * both_neg = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ), 4251 mkU64( 1 ) ), 4252 binop( Iop_CmpEQ64, mkexpr( sign_B ), 4253 mkU64( 1 ) ) ); 4254 IRExpr * sign_eq = binop( Iop_CmpEQ64, mkexpr( sign_A ), mkexpr( sign_B ) ); 4255 IRExpr * sign_gt = binop( Iop_CmpLT64U, mkexpr( sign_A ), 4256 mkexpr( sign_B ) ); /* A pos, B neg */ 4257 4258 IRExpr * exp_eq = binop( Iop_CmpEQ64, mkexpr( exp_A ), mkexpr( exp_B ) ); 4259 IRExpr * exp_gt = binop( Iop_CmpLT64U, mkexpr( exp_B ), mkexpr( exp_A ) ); 4260 IRExpr * exp_lt = binop( Iop_CmpLT64U, mkexpr( exp_A ), mkexpr( exp_B ) ); 4261 4262 IRExpr * frac_hi_eq = binop( Iop_CmpEQ64, mkexpr( frac_A_hi), 4263 mkexpr( frac_B_hi ) ); 4264 IRExpr * frac_hi_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_hi ), 4265 mkexpr( frac_A_hi ) ); 4266 IRExpr * frac_hi_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_hi ), 4267 mkexpr( frac_B_hi ) ); 4268 4269 IRExpr * frac_lo_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_lo ), 4270 mkexpr( frac_A_lo ) ); 4271 IRExpr * frac_lo_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_lo ), 4272 mkexpr( frac_B_lo ) ); 4273 4274 /* src_A and src_B both positive */ 4275 IRExpr *pos_cmp = mkOR1( exp_gt, 4276 mkAND1( exp_eq, 4277 mkOR1( frac_hi_gt, 4278 mkAND1( frac_hi_eq, frac_lo_gt ) ) 4279 ) ); 4280 4281 /* src_A and src_B both negative */ 4282 IRExpr *neg_cmp = mkOR1( exp_lt, 4283 mkAND1( exp_eq, 4284 mkOR1( frac_hi_lt, 4285 mkAND1( frac_hi_eq, frac_lo_lt ) ) 4286 ) ); 4287 4288 /* Need to check the case where one value is a positive 4289 * zero and the other value is a negative zero 4290 */ 4291 return mkAND1( mkNOT1( A_B_zero ), 4292 mkOR1( sign_gt, 4293 mkAND1( sign_eq, 4294 mkOR1( mkAND1( both_pos, pos_cmp ), 4295 mkAND1( both_neg, neg_cmp ) ) ) ) ); 4296 } 4297 4298 /*----------------------------------------------------------- 4299 * Helpers for VX instructions that work on National decimal values, 4300 * Zoned decimal values and BCD values. 4301 * 4302 *------------------------------------------------------------*/ 4303 static IRExpr * is_National_decimal (IRTemp src) 4304 { 4305 /* The src is a 128-bit value containing a sign code in half word 7 4306 * and seven digits in halfwords 0 to 6 (IBM numbering). A valid 4307 * national decimal value has the following: 4308 * - the sign code must be 0x002B (positive) or 0x002D (negative) 4309 * - the digits must be in the range 0x0030 to 0x0039 4310 */ 4311 Int i; 4312 IRExpr * valid_pos_sign; 4313 IRExpr * valid_neg_sign; 4314 IRTemp valid_num[8]; 4315 IRTemp digit[7]; 4316 4317 valid_pos_sign = binop( Iop_CmpEQ64, 4318 binop( Iop_And64, 4319 mkU64( 0xFFFF ), 4320 unop( Iop_V128to64, mkexpr( src ) ) ), 4321 mkU64( 0x002B ) ); 4322 4323 valid_neg_sign = binop( Iop_CmpEQ64, 4324 binop( Iop_And64, 4325 mkU64( 0xFFFF ), 4326 unop( Iop_V128to64, mkexpr( src ) ) ), 4327 mkU64( 0x002D ) ); 4328 4329 valid_num[0] = newTemp( Ity_I1 ); 4330 digit[0] = newTemp( Ity_I64 ); 4331 assign( valid_num[0], mkU1( 1 ) ); // Assume true to start 4332 4333 for(i = 0; i < 7; i++) { 4334 valid_num[i+1] = newTemp( Ity_I1 ); 4335 digit[i] = newTemp( Ity_I64 ); 4336 assign( digit[i], binop( Iop_And64, 4337 unop( Iop_V128to64, 4338 binop( Iop_ShrV128, 4339 mkexpr( src ), 4340 mkU8( (7-i)*16 ) ) ), 4341 mkU64( 0xFFFF ) ) ); 4342 4343 assign( valid_num[i+1], 4344 mkAND1( mkexpr( valid_num[i] ), 4345 mkAND1( binop( Iop_CmpLE64U, 4346 mkexpr( digit[i] ), 4347 mkU64( 0x39 ) ), 4348 binop( Iop_CmpLE64U, 4349 mkU64( 0x30 ), 4350 mkexpr( digit[i] ) ) ) ) ); 4351 } 4352 4353 return mkAND1( mkOR1( valid_pos_sign, valid_neg_sign), 4354 mkexpr( valid_num[7] ) ); 4355 } 4356 4357 static IRExpr * is_Zoned_decimal (IRTemp src, UChar ps) 4358 { 4359 /* The src is a 128-bit value containing a sign code the least significant 4360 * two bytes. The upper pairs of bytes contain digits. A valid Zoned 4361 * decimal value has the following: 4362 * - the sign code must be between 0x0X to 0xFX inclusive (X - don't care) 4363 * - bits [0:3] of each digit must be equal to 0x3 4364 * - bits [4:7] of each digit must be between 0x0 and 0x9 4365 * 4366 * If ps = 0 4367 * Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB 4368 * (note 0bX0XX XXXX is positive) 4369 * 4370 * Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF 4371 * (note 0bX1XX XXXX is negative) 4372 * 4373 * If ps = 1, then the sign code must be in the range 0xA to 0xF 4374 * Positive sign codes are: 0xA, 0xC, 0xE, 0xF 4375 * 4376 * Negative sign codes are 0xB, 0xD 4377 */ 4378 Int i, mask_hi, mask_lo; 4379 IRExpr *valid_range; 4380 IRTemp valid_num[16]; 4381 IRTemp digit[15]; 4382 4383 /* check the range of the sign value based on the value of ps */ 4384 valid_range = mkOR1( 4385 mkAND1( binop( Iop_CmpEQ64, 4386 mkU64( 1 ), 4387 mkU64( ps ) ), 4388 mkAND1( binop( Iop_CmpLE64U, 4389 binop( Iop_And64, 4390 mkU64( 0xF0 ), 4391 unop( Iop_V128to64, 4392 mkexpr( src ) ) ), 4393 4394 mkU64( 0xF0 ) ), 4395 binop( Iop_CmpLE64U, 4396 mkU64( 0xA0 ), 4397 binop( Iop_And64, 4398 mkU64( 0xF0 ), 4399 unop( Iop_V128to64, 4400 mkexpr( src ) ))))), 4401 binop( Iop_CmpEQ64, 4402 mkU64( 0 ), 4403 mkU64( ps ) ) ); 4404 4405 valid_num[0] = newTemp( Ity_I1 ); 4406 assign( valid_num[0], mkU1( 1) ); // Assume true to start 4407 4408 if (ps == 0) { 4409 mask_hi = 0x39; 4410 mask_lo = 0x30; 4411 } else { 4412 mask_hi = 0xF9; 4413 mask_lo = 0xF0; 4414 } 4415 4416 for(i = 0; i < 15; i++) { 4417 valid_num[i+1] = newTemp( Ity_I1 ); 4418 digit[i] = newTemp( Ity_I64 ); 4419 assign( digit[i], binop( Iop_And64, 4420 unop( Iop_V128to64, 4421 binop( Iop_ShrV128, 4422 mkexpr( src ), 4423 mkU8( (15-i)*8 ) ) ), 4424 mkU64( 0xFF ) ) ); 4425 4426 assign( valid_num[i+1], 4427 mkAND1( mkexpr( valid_num[i] ), 4428 mkAND1( binop( Iop_CmpLE64U, 4429 mkexpr( digit[i] ), 4430 mkU64( mask_hi ) ), 4431 binop( Iop_CmpLE64U, 4432 mkU64( mask_lo ), 4433 mkexpr( digit[i] ) ) ) ) ); 4434 } 4435 4436 return mkAND1( valid_range, mkexpr( valid_num[15] ) ); 4437 } 4438 4439 static IRExpr * CmpGT128U ( IRExpr *src1, IRExpr *src2 ) 4440 { 4441 /* Unsigend compare of two 128-bit values */ 4442 IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt; 4443 4444 pos_upper_gt = binop( Iop_CmpLT64U, 4445 unop( Iop_V128HIto64, src2 ), 4446 unop( Iop_V128HIto64, src1 ) ); 4447 pos_upper_eq = binop( Iop_CmpEQ64, 4448 unop( Iop_V128HIto64, src1 ), 4449 unop( Iop_V128HIto64, src2 ) ); 4450 pos_lower_gt = binop( Iop_CmpLT64U, 4451 unop( Iop_V128to64, src2), 4452 unop( Iop_V128to64, src1) ); 4453 return mkOR1( pos_upper_gt, 4454 mkAND1( pos_upper_eq, 4455 pos_lower_gt ) ); 4456 } 4457 4458 4459 static IRExpr * is_BCDstring128 ( const VexAbiInfo* vbi, 4460 UInt Signed, IRExpr *src ) 4461 { 4462 4463 IRTemp valid = newTemp( Ity_I64 ); 4464 4465 /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and 4466 * a sign. The upper bytes are BCD values between 0x0 and 0x9. The sign 4467 * byte is the least significant byte. This function returns 64-bit 1 4468 * value if sign and digits are valid, 0 otherwise. 4469 * 4470 * This function was originally written using IR code. It has been 4471 * replaced with a clean helper due to the large amount of IR code 4472 * needed by this function. 4473 */ 4474 assign( valid, 4475 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4476 "is_BCDstring128_helper", 4477 fnptr_to_fnentry( vbi, &is_BCDstring128_helper ), 4478 mkIRExprVec_3( mkU64( Signed ), 4479 unop( Iop_V128HIto64, src ), 4480 unop( Iop_V128to64, src ) ) ) ); 4481 return mkexpr( valid ); 4482 } 4483 4484 static IRExpr * BCDstring_zero (IRExpr *src) 4485 { 4486 /* The src is a 128-bit value containing a BCD string. The function 4487 * returns a 1 if the BCD string values are all zero, 0 otherwise. 4488 */ 4489 IRTemp tsrc = newTemp( Ity_V128 ); 4490 assign( tsrc, src); 4491 4492 if ( mode64 ) { 4493 return mkAND1( binop( Iop_CmpEQ64, 4494 mkU64( 0 ), 4495 unop( Iop_V128HIto64, 4496 mkexpr( tsrc ) ) ), 4497 binop( Iop_CmpEQ64, 4498 mkU64( 0 ), 4499 unop( Iop_V128to64, 4500 mkexpr( tsrc ) ) ) ); 4501 } else { 4502 /* make this work in 32-bit mode */ 4503 return mkAND1( 4504 mkAND1( binop( Iop_CmpEQ32, 4505 mkU32( 0 ), 4506 unop( Iop_64HIto32, 4507 unop( Iop_V128HIto64, 4508 mkexpr( tsrc ) ) ) ), 4509 binop( Iop_CmpEQ32, 4510 mkU32( 0 ), 4511 unop( Iop_64to32, 4512 unop( Iop_V128HIto64, 4513 mkexpr( tsrc ) ) ) ) ), 4514 mkAND1( binop( Iop_CmpEQ32, 4515 mkU32( 0 ), 4516 unop( Iop_64HIto32, 4517 unop( Iop_V128to64, 4518 mkexpr( tsrc ) ) ) ), 4519 binop( Iop_CmpEQ32, 4520 mkU32( 0 ), 4521 unop( Iop_64to32, 4522 unop( Iop_V128to64, 4523 mkexpr( tsrc ) ) ) ) ) ); 4524 } 4525 } 4526 4527 static IRExpr * check_BCD_round (IRExpr *src, IRTemp shift) 4528 { 4529 /* The src is a 128-bit value containing 31 BCD digits with the sign in 4530 * the least significant byte. The bytes are BCD values between 0x0 and 0x9. 4531 * This routine checks the BCD digit in position shift (counting from 4532 * the least significant digit). If the digit is greater then five, 4533 * a 1 is returned indicating the string needs to be rounded up, 4534 * otherwise, 0 is returned. The value of shift (I64) is the index of 4535 * the BCD digit times four bits. 4536 */ 4537 return binop( Iop_CmpLE64U, 4538 mkU64( 6 ), 4539 binop( Iop_And64, 4540 unop( Iop_V128to64, 4541 binop( Iop_ShrV128, 4542 src, 4543 unop( Iop_64to8, mkexpr( shift ) ) ) ), 4544 mkU64( 0xF ) ) ); 4545 } 4546 4547 static IRTemp increment_BCDstring ( const VexAbiInfo* vbi, 4548 IRExpr *src, IRExpr *carry_in ) 4549 { 4550 /* The src is a 128-bit value containing 31 BCD digits with the sign in 4551 * the least significant byte. The bytes are BCD values between 0x0 and 0x9. 4552 * This function returns the BCD string incremented by 1. 4553 * 4554 * Call a clean helper to do the computation as it requires a lot of 4555 * IR code to do this. 4556 * 4557 * The helper function takes a 32-bit BCD string, in a 64-bit value, and 4558 * increments the string by the 32-bi carry in value. 4559 * 4560 * The incremented value is returned in the lower 32-bits of the result. 4561 * The carry out is returned in bits [35:32] of the result. The 4562 * helper function will be called for each of the four 32-bit strings 4563 * that make up the src string passing the returned carry out to the 4564 * next call. 4565 */ 4566 IRTemp bcd_result = newTemp( Ity_V128 ); 4567 IRTemp bcd_result0 = newTemp( Ity_I64 ); 4568 IRTemp bcd_result1 = newTemp( Ity_I64 ); 4569 IRTemp bcd_result2 = newTemp( Ity_I64 ); 4570 IRTemp bcd_result3 = newTemp( Ity_I64 ); 4571 IRExpr *bcd_string0, *bcd_string1, *bcd_string2, *bcd_string3; 4572 4573 bcd_string0 = binop( Iop_And64, 4574 mkU64( 0xFFFFFFFF ), unop( Iop_V128to64, src ) ); 4575 bcd_string1 = binop( Iop_Shr64, unop( Iop_V128to64, src ), mkU8( 32 ) ); 4576 bcd_string2 = binop( Iop_And64, 4577 mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64, src ) ); 4578 bcd_string3 = binop( Iop_Shr64, unop( Iop_V128HIto64, src ), mkU8( 32 ) ); 4579 4580 assign( bcd_result0, 4581 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4582 "increment_BCDstring32_helper", 4583 fnptr_to_fnentry( vbi, 4584 &increment_BCDstring32_helper ), 4585 mkIRExprVec_3( mkU64( True /*Signed*/ ), 4586 bcd_string0, 4587 binop( Iop_32HLto64, mkU32( 0 ), 4588 carry_in ) ) ) ); 4589 4590 assign( bcd_result1, 4591 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4592 "increment_BCDstring32_helper", 4593 fnptr_to_fnentry( vbi, 4594 &increment_BCDstring32_helper ), 4595 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4596 bcd_string1, 4597 binop( Iop_Shr64, 4598 mkexpr( bcd_result0 ), 4599 mkU8( 32 ) ) ) ) ); 4600 assign( bcd_result2, 4601 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4602 "increment_BCDstring32_helper", 4603 fnptr_to_fnentry( vbi, 4604 &increment_BCDstring32_helper ), 4605 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4606 bcd_string2, 4607 binop( Iop_Shr64, 4608 mkexpr( bcd_result1 ), 4609 mkU8( 32 ) ) ) ) ); 4610 assign( bcd_result3, 4611 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4612 "increment_BCDstring32_helper", 4613 fnptr_to_fnentry( vbi, 4614 &increment_BCDstring32_helper ), 4615 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4616 bcd_string3, 4617 binop( Iop_Shr64, 4618 mkexpr( bcd_result2 ), 4619 mkU8( 32 ) ) ) ) ); 4620 4621 /* Put the 128-bit result together from the intermediate results. Remember 4622 * to mask out the carry out from the upper 32 bits of the results. 4623 */ 4624 assign( bcd_result, 4625 binop( Iop_64HLtoV128, 4626 binop( Iop_Or64, 4627 binop( Iop_And64, 4628 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2 ) ), 4629 binop( Iop_Shl64, 4630 mkexpr (bcd_result3 ), mkU8( 32 ) ) ), 4631 binop( Iop_Or64, 4632 binop( Iop_And64, 4633 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0 ) ), 4634 binop( Iop_Shl64, 4635 mkexpr (bcd_result1 ), mkU8( 32 ) ) ) ) ); 4636 return bcd_result; 4637 } 4638 4639 static IRExpr * convert_to_zoned ( const VexAbiInfo* vbi, 4640 IRExpr *src, IRExpr *upper_byte ) 4641 { 4642 /* The function takes a V128 packed decimal value and returns 4643 * the value in zoned format. Note, the sign of the value is ignored. 4644 */ 4645 IRTemp result_low = newTemp( Ity_I64 ); 4646 IRTemp result_hi = newTemp( Ity_I64 ); 4647 IRTemp result = newTemp( Ity_V128 ); 4648 4649 /* Since we can only return 64-bits from a clean helper, we will 4650 * have to get the lower and upper 64-bits separately. 4651 */ 4652 4653 assign( result_low, 4654 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4655 "convert_to_zoned_helper", 4656 fnptr_to_fnentry( vbi, &convert_to_zoned_helper ), 4657 mkIRExprVec_4( unop( Iop_V128HIto64, src ), 4658 unop( Iop_V128to64, src ), 4659 upper_byte, 4660 mkU64( 0 ) ) ) ); 4661 4662 assign( result_hi, 4663 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4664 "convert_to_zoned_helper", 4665 fnptr_to_fnentry( vbi, &convert_to_zoned_helper ), 4666 mkIRExprVec_4( unop( Iop_V128HIto64, src ), 4667 unop( Iop_V128to64, src ), 4668 upper_byte, 4669 mkU64( 1 ) ) ) ); 4670 4671 4672 assign( result, 4673 binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) ); 4674 4675 return mkexpr( result ); 4676 } 4677 4678 static IRExpr * convert_to_national ( const VexAbiInfo* vbi, IRExpr *src ) { 4679 /* The function takes 128-bit value which has a 64-bit packed decimal 4680 * value in the lower 64-bits of the source. The packed decimal is 4681 * converted to the national format via a clean helper. The clean 4682 * helper is used to to the large amount of IR code needed to do the 4683 * conversion. The helper returns the upper 64-bits of the 128-bit 4684 * result if return_upper != 0. Otherwise, the lower 64-bits of the 4685 * result is returned. 4686 */ 4687 IRTemp result_low = newTemp( Ity_I64 ); 4688 IRTemp result_hi = newTemp( Ity_I64 ); 4689 IRTemp result = newTemp( Ity_V128 ); 4690 4691 /* Since we can only return 64-bits from a clean helper, we will 4692 * have to get the lower and upper 64-bits separately. 4693 */ 4694 4695 assign( result_low, 4696 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4697 "convert_to_national_helper", 4698 fnptr_to_fnentry( vbi, &convert_to_national_helper ), 4699 mkIRExprVec_2( unop( Iop_V128to64, src ), 4700 mkU64( 0 ) ) ) ); 4701 4702 assign( result_hi, 4703 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4704 "convert_to_national_helper", 4705 fnptr_to_fnentry( vbi, &convert_to_national_helper ), 4706 mkIRExprVec_2( unop( Iop_V128to64, src ), 4707 mkU64( 1 ) ) ) ); 4708 4709 assign( result, 4710 binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) ); 4711 4712 return mkexpr( result ); 4713 } 4714 4715 static IRExpr * convert_from_zoned ( const VexAbiInfo* vbi, IRExpr *src ) { 4716 /* The function takes 128-bit zoned value and returns a signless 64-bit 4717 * packed decimal value in the lower 64-bits of the 128-bit result. 4718 */ 4719 IRTemp result = newTemp( Ity_V128 ); 4720 4721 assign( result, 4722 binop( Iop_ShlV128, 4723 binop( Iop_64HLtoV128, 4724 mkU64( 0 ), 4725 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4726 "convert_from_zoned_helper", 4727 fnptr_to_fnentry( vbi, 4728 &convert_from_zoned_helper ), 4729 mkIRExprVec_2( unop( Iop_V128HIto64, 4730 src ), 4731 unop( Iop_V128to64, 4732 src ) ) ) ), 4733 mkU8( 4 ) ) ); 4734 4735 return mkexpr( result ); 4736 } 4737 4738 static IRExpr * convert_from_national ( const VexAbiInfo* vbi, IRExpr *src ) { 4739 /* The function takes 128-bit national value and returns a 64-bit 4740 * packed decimal value. 4741 */ 4742 IRTemp result = newTemp( Ity_I64); 4743 4744 assign( result, 4745 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4746 "convert_from_national_helper", 4747 fnptr_to_fnentry( vbi, 4748 &convert_from_national_helper ), 4749 mkIRExprVec_2( unop( Iop_V128HIto64, 4750 src ), 4751 unop( Iop_V128to64, 4752 src ) ) ) ); 4753 4754 return mkexpr( result ); 4755 } 4756 4757 static IRExpr * UNSIGNED_CMP_GT_V128 ( IRExpr *vA, IRExpr *vB ) { 4758 /* This function does an unsigned compare of two V128 values. The 4759 * function is for use in 32-bit mode only as it is expensive. The 4760 * issue is that compares (GT, LT, EQ) are not supported for operands 4761 * larger then 32-bits when running in 32-bit mode. The function returns 4762 * a 1-bit expression, 1 for TRUE and 0 for FALSE. 4763 */ 4764 IRTemp vA_word0 = newTemp( Ity_I32); 4765 IRTemp vA_word1 = newTemp( Ity_I32); 4766 IRTemp vA_word2 = newTemp( Ity_I32); 4767 IRTemp vA_word3 = newTemp( Ity_I32); 4768 IRTemp vB_word0 = newTemp( Ity_I32); 4769 IRTemp vB_word1 = newTemp( Ity_I32); 4770 IRTemp vB_word2 = newTemp( Ity_I32); 4771 IRTemp vB_word3 = newTemp( Ity_I32); 4772 4773 IRTemp eq_word1 = newTemp( Ity_I1); 4774 IRTemp eq_word2 = newTemp( Ity_I1); 4775 IRTemp eq_word3 = newTemp( Ity_I1); 4776 4777 4778 IRExpr *gt_word0, *gt_word1, *gt_word2, *gt_word3; 4779 IRExpr *eq_word3_2, *eq_word3_2_1; 4780 IRTemp result = newTemp( Ity_I1 ); 4781 4782 assign( vA_word0, unop( Iop_64to32, unop( Iop_V128to64, vA ) ) ); 4783 assign( vA_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vA ) ) ); 4784 assign( vA_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vA ) ) ); 4785 assign( vA_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vA ) ) ); 4786 4787 assign( vB_word0, unop( Iop_64to32, unop( Iop_V128to64, vB ) ) ); 4788 assign( vB_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vB ) ) ); 4789 assign( vB_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vB ) ) ); 4790 assign( vB_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vB ) ) ); 4791 4792 assign( eq_word3, binop( Iop_CmpEQ32, mkexpr( vA_word3 ), 4793 mkexpr( vB_word3 ) ) ); 4794 assign( eq_word2, binop( Iop_CmpEQ32, mkexpr( vA_word2 ), 4795 mkexpr( vB_word2 ) ) ); 4796 assign( eq_word1, binop( Iop_CmpEQ32, mkexpr( vA_word1 ), 4797 mkexpr( vB_word1 ) ) ); 4798 4799 gt_word3 = binop( Iop_CmpLT32U, mkexpr( vB_word3 ), mkexpr( vA_word3 ) ); 4800 gt_word2 = binop( Iop_CmpLT32U, mkexpr( vB_word2 ), mkexpr( vA_word2 ) ); 4801 gt_word1 = binop( Iop_CmpLT32U, mkexpr( vB_word1 ), mkexpr( vA_word1 ) ); 4802 gt_word0 = binop( Iop_CmpLT32U, mkexpr( vB_word0 ), mkexpr( vA_word0 ) ); 4803 4804 eq_word3_2 = mkAND1( mkexpr( eq_word3 ), mkexpr( eq_word2 ) ); 4805 eq_word3_2_1 = mkAND1( mkexpr( eq_word1 ), eq_word3_2 ); 4806 4807 assign( result, mkOR1( 4808 mkOR1( gt_word3, 4809 mkAND1( mkexpr( eq_word3 ), gt_word2 ) ), 4810 mkOR1( mkAND1( eq_word3_2, gt_word1 ), 4811 mkAND1( eq_word3_2_1, gt_word0 ) ) ) ); 4812 return mkexpr( result ); 4813 } 4814 4815 /*------------------------------------------------------------*/ 4816 /* Transactional memory helpers 4817 * 4818 *------------------------------------------------------------*/ 4819 4820 static ULong generate_TMreason( UInt failure_code, 4821 UInt persistant, 4822 UInt nest_overflow, 4823 UInt tm_exact ) 4824 { 4825 ULong tm_err_code = 4826 ( (ULong) 0) << (63-6) /* Failure code */ 4827 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 4828 | ( (ULong) 0) << (63-8) /* Disallowed */ 4829 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 4830 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 4831 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 4832 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 4833 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 4834 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 4835 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 4836 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 4837 | ( (ULong) 0) << (63-30) /* Reserved */ 4838 | ( (ULong) 0) << (63-31) /* Abort */ 4839 | ( (ULong) 0) << (63-32) /* Suspend */ 4840 | ( (ULong) 0) << (63-33) /* Reserved */ 4841 | ( (ULong) 0) << (63-35) /* Privilege */ 4842 | ( (ULong) 0) << (63-36) /* Failure Summary */ 4843 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 4844 | ( (ULong) 0) << (63-38) /* ROT */ 4845 | ( (ULong) 0) << (63-51) /* Reserved */ 4846 | ( (ULong) 0) << (63-63); /* Transaction Level */ 4847 4848 return tm_err_code; 4849 } 4850 4851 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 4852 Addr64 handler_address ) 4853 { 4854 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 4855 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 4856 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 4857 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 4858 } 4859 4860 /*------------------------------------------------------------*/ 4861 /*--- Integer Instruction Translation --- */ 4862 /*------------------------------------------------------------*/ 4863 4864 /* 4865 Integer Arithmetic Instructions 4866 */ 4867 static Bool dis_int_mult_add ( UInt theInstr ) 4868 { 4869 /* VA-Form */ 4870 UChar rD_addr = ifieldRegDS( theInstr ); 4871 UChar rA_addr = ifieldRegA( theInstr ); 4872 UChar rB_addr = ifieldRegB( theInstr ); 4873 UChar rC_addr = ifieldRegC( theInstr ); 4874 UInt opc2 = IFIELD( theInstr, 0, 6 ); 4875 IRType ty = Ity_I64; 4876 IRTemp rA = newTemp( ty ); 4877 IRTemp rB = newTemp( ty ); 4878 IRTemp rC = newTemp( ty ); 4879 IRTemp rD = newTemp( ty ); 4880 IRTemp tmpLo = newTemp( Ity_I64 ); 4881 IRTemp tmpHi = newTemp( Ity_I64 ); 4882 IRTemp tmp2Hi = newTemp( Ity_I64 ); 4883 IRTemp result = newTemp( Ity_I128 ); 4884 IRTemp resultLo = newTemp( Ity_I64 ); 4885 IRExpr* carryout; 4886 4887 assign( rA, getIReg( rA_addr ) ); 4888 assign( rB, getIReg( rB_addr ) ); 4889 assign( rC, getIReg( rC_addr ) ); 4890 4891 switch (opc2) { 4892 case 0x30: // maddhd multiply-add High doubleword signed 4893 DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4894 4895 assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) ); 4896 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4897 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4898 4899 /* Multiply rA and rB then add rC. If the lower 32-bits of the result 4900 * is less then rC and the result rA * rB, a carry out of the lower 32 4901 * bits occurred and the upper 32 bits must be incremented by 1. Sign 4902 * extend rC and do the add to the upper 64 bits to handle the 4903 * negative case for rC. 4904 */ 4905 assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4906 assign( tmp2Hi, binop( Iop_Add64, 4907 mkexpr( tmpHi ), 4908 unop( Iop_1Sto64, 4909 unop( Iop_64to1, 4910 binop( Iop_Shr64, 4911 mkexpr( rC ), 4912 mkU8( 63 ) ) ) ) ) ); 4913 4914 /* need to do calculation for the upper 32 bit result */ 4915 carryout = mkAND1( binop( Iop_CmpLT64U, 4916 mkexpr( resultLo ), mkexpr( rC ) ), 4917 binop( Iop_CmpLT64U, 4918 mkexpr( resultLo ), mkexpr( tmpLo ) ) ); 4919 assign( rD, binop( Iop_Add64, 4920 mkexpr( tmp2Hi ), 4921 unop( Iop_1Uto64, carryout ) ) ); 4922 break; 4923 4924 case 0x31: // maddhdu multiply-add High doubleword unsigned 4925 DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4926 4927 assign( result, binop( Iop_MullU64, mkexpr( rA ), mkexpr( rB ) ) ); 4928 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4929 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4930 4931 /* Add rC, if the lower 32-bits of the result is less then rC and 4932 * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits 4933 * must be incremented by 1. 4934 */ 4935 assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4936 4937 /* need to do calculation for the upper 32 bit result */ 4938 carryout = mkAND1( binop( Iop_CmpLT64U, 4939 mkexpr(resultLo), mkexpr( rC ) ), 4940 binop( Iop_CmpLT64U, 4941 mkexpr(resultLo), mkexpr( tmpLo ) ) ); 4942 assign( rD, binop( Iop_Add64, 4943 mkexpr( tmpHi ), 4944 unop( Iop_1Uto64, carryout ) ) ); 4945 break; 4946 4947 case 0x33: // maddld multiply-add Low doubleword 4948 DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4949 4950 assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) ); 4951 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4952 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4953 4954 assign( rD, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4955 break; 4956 4957 default: 4958 vex_printf("dis_int_mult(ppc): unrecognized instruction\n"); 4959 return False; 4960 } 4961 4962 putIReg( rD_addr, mkexpr(rD) ); 4963 4964 return True; 4965 } 4966 4967 static Bool dis_int_arith ( UInt theInstr ) 4968 { 4969 /* D-Form, XO-Form */ 4970 UChar opc1 = ifieldOPC(theInstr); 4971 UChar rD_addr = ifieldRegDS(theInstr); 4972 UChar rA_addr = ifieldRegA(theInstr); 4973 UInt uimm16 = ifieldUIMM16(theInstr); 4974 UChar rB_addr = ifieldRegB(theInstr); 4975 UChar flag_OE = ifieldBIT10(theInstr); 4976 UInt opc2 = ifieldOPClo9(theInstr); 4977 UChar flag_rC = ifieldBIT0(theInstr); 4978 4979 Long simm16 = extend_s_16to64(uimm16); 4980 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4981 IRTemp rA = newTemp(ty); 4982 IRTemp rB = newTemp(ty); 4983 IRTemp rD = newTemp(ty); 4984 4985 Bool do_rc = False; 4986 4987 assign( rA, getIReg(rA_addr) ); 4988 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 4989 4990 switch (opc1) { 4991 /* D-Form */ 4992 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 4993 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 4994 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 4995 mkSzExtendS16(ty, uimm16) ) ); 4996 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 4997 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 4998 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 4999 break; 5000 5001 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 5002 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5003 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5004 mkSzExtendS16(ty, uimm16) ) ); 5005 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 5006 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 5007 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5008 do_rc = True; // Always record to CR 5009 flag_rC = 1; 5010 break; 5011 5012 case 0x0E: // addi (Add Immediate, PPC32 p350) 5013 // li rD,val == addi rD,0,val 5014 // la disp(rA) == addi rD,rA,disp 5015 if ( rA_addr == 0 ) { 5016 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 5017 assign( rD, mkSzExtendS16(ty, uimm16) ); 5018 } else { 5019 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5020 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5021 mkSzExtendS16(ty, uimm16) ) ); 5022 } 5023 break; 5024 5025 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 5026 // lis rD,val == addis rD,0,val 5027 if ( rA_addr == 0 ) { 5028 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 5029 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 5030 } else { 5031 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16); 5032 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5033 mkSzExtendS32(ty, uimm16 << 16) ) ); 5034 } 5035 break; 5036 5037 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 5038 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5039 if (mode64) 5040 assign( rD, unop(Iop_128to64, 5041 binop(Iop_MullS64, mkexpr(rA), 5042 mkSzExtendS16(ty, uimm16))) ); 5043 else 5044 assign( rD, unop(Iop_64to32, 5045 binop(Iop_MullS32, mkexpr(rA), 5046 mkSzExtendS16(ty, uimm16))) ); 5047 break; 5048 5049 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 5050 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5051 // rD = simm16 - rA 5052 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5053 mkSzExtendS16(ty, uimm16), 5054 mkexpr(rA)) ); 5055 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFI, 5056 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 5057 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5058 break; 5059 5060 /* XO-Form */ 5061 case 0x1F: 5062 do_rc = True; // All below record to CR 5063 5064 switch (opc2) { 5065 case 0x10A: // add (Add, PPC32 p347) 5066 DIP("add%s%s r%u,r%u,r%u\n", 5067 flag_OE ? "o" : "", flag_rC ? ".":"", 5068 rD_addr, rA_addr, rB_addr); 5069 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5070 mkexpr(rA), mkexpr(rB) ) ); 5071 if (flag_OE) { 5072 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD, 5073 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5074 } 5075 break; 5076 5077 case 0x00A: // addc (Add Carrying, PPC32 p348) 5078 DIP("addc%s%s r%u,r%u,r%u\n", 5079 flag_OE ? "o" : "", flag_rC ? ".":"", 5080 rD_addr, rA_addr, rB_addr); 5081 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5082 mkexpr(rA), mkexpr(rB)) ); 5083 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 5084 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5085 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5086 if (flag_OE) { 5087 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD, 5088 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5089 } 5090 break; 5091 5092 case 0x08A: { // adde (Add Extended, PPC32 p349) 5093 IRTemp old_xer_ca = newTemp(ty); 5094 DIP("adde%s%s r%u,r%u,r%u\n", 5095 flag_OE ? "o" : "", flag_rC ? ".":"", 5096 rD_addr, rA_addr, rB_addr); 5097 // rD = rA + rB + XER[CA] 5098 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5099 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5100 binop( mkSzOp(ty, Iop_Add8), 5101 mkexpr(rB), mkexpr(old_xer_ca))) ); 5102 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5103 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5104 mkexpr(old_xer_ca) ); 5105 if (flag_OE) { 5106 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5107 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5108 } 5109 break; 5110 } 5111 5112 case 0xAA: {// addex (Add Extended alternate carry bit Z23-form) 5113 DIP("addex r%u,r%u,r%u,%d\n", rD_addr, rA_addr, rB_addr, (Int)flag_OE); 5114 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5115 binop( mkSzOp(ty, Iop_Add8), mkexpr(rB), 5116 mkWidenFrom8( ty, getXER_OV(), False ) ) ) ); 5117 5118 /* CY bit is same as OE bit */ 5119 if (flag_OE == 0) { 5120 /* Exception, do not set SO bit */ 5121 set_XER_OV_OV32( ty, PPCG_FLAG_OP_ADDE, 5122 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5123 } else { 5124 /* CY=1, 2 and 3 (AKA flag_OE) are reserved */ 5125 vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE); 5126 vpanic("addex instruction\n"); 5127 } 5128 break; 5129 } 5130 5131 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 5132 IRTemp old_xer_ca = newTemp(ty); 5133 IRExpr *min_one; 5134 if (rB_addr != 0) { 5135 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 5136 return False; 5137 } 5138 DIP("addme%s%s r%u,r%u,r%u\n", 5139 flag_OE ? "o" : "", flag_rC ? ".":"", 5140 rD_addr, rA_addr, rB_addr); 5141 // rD = rA + (-1) + XER[CA] 5142 // => Just another form of adde 5143 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5144 min_one = mkSzImm(ty, (Long)-1); 5145 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5146 binop( mkSzOp(ty, Iop_Add8), 5147 min_one, mkexpr(old_xer_ca)) )); 5148 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5149 mkexpr(rD), mkexpr(rA), min_one, 5150 mkexpr(old_xer_ca) ); 5151 if (flag_OE) { 5152 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5153 mkexpr(rD), mkexpr(rA), min_one ); 5154 } 5155 break; 5156 } 5157 5158 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 5159 IRTemp old_xer_ca = newTemp(ty); 5160 if (rB_addr != 0) { 5161 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 5162 return False; 5163 } 5164 DIP("addze%s%s r%u,r%u,r%u\n", 5165 flag_OE ? "o" : "", flag_rC ? ".":"", 5166 rD_addr, rA_addr, rB_addr); 5167 // rD = rA + (0) + XER[CA] 5168 // => Just another form of adde 5169 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5170 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5171 mkexpr(rA), mkexpr(old_xer_ca)) ); 5172 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5173 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 5174 mkexpr(old_xer_ca) ); 5175 if (flag_OE) { 5176 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5177 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 5178 } 5179 break; 5180 } 5181 5182 case 0x1EB: // divw (Divide Word, PPC32 p388) 5183 DIP("divw%s%s r%u,r%u,r%u\n", 5184 flag_OE ? "o" : "", flag_rC ? ".":"", 5185 rD_addr, rA_addr, rB_addr); 5186 if (mode64) { 5187 /* Note: 5188 XER settings are mode independent, and reflect the 5189 overflow of the low-order 32bit result 5190 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 5191 */ 5192 /* rD[hi32] are undefined: setting them to sign of lo32 5193 - makes set_CR0 happy */ 5194 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 5195 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 5196 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 5197 divisor) ) ); 5198 if (flag_OE) { 5199 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5200 mkexpr(rD), dividend, divisor ); 5201 } 5202 } else { 5203 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 5204 if (flag_OE) { 5205 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5206 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5207 } 5208 } 5209 /* Note: 5210 if (0x8000_0000 / -1) or (x / 0) 5211 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 5212 => But _no_ exception raised. */ 5213 break; 5214 5215 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 5216 DIP("divwu%s%s r%u,r%u,r%u\n", 5217 flag_OE ? "o" : "", flag_rC ? ".":"", 5218 rD_addr, rA_addr, rB_addr); 5219 if (mode64) { 5220 /* Note: 5221 XER settings are mode independent, and reflect the 5222 overflow of the low-order 32bit result 5223 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 5224 */ 5225 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 5226 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 5227 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 5228 divisor) ) ); 5229 if (flag_OE) { 5230 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5231 mkexpr(rD), dividend, divisor ); 5232 } 5233 } else { 5234 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 5235 if (flag_OE) { 5236 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5237 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5238 } 5239 } 5240 /* Note: ditto comment divw, for (x / 0) */ 5241 break; 5242 5243 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 5244 if (flag_OE != 0) { 5245 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 5246 return False; 5247 } 5248 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5249 rD_addr, rA_addr, rB_addr); 5250 if (mode64) { 5251 /* rD[hi32] are undefined: setting them to sign of lo32 5252 - makes set_CR0 happy */ 5253 assign( rD, binop(Iop_Sar64, 5254 binop(Iop_Mul64, 5255 mk64lo32Sto64( mkexpr(rA) ), 5256 mk64lo32Sto64( mkexpr(rB) )), 5257 mkU8(32)) ); 5258 } else { 5259 assign( rD, unop(Iop_64HIto32, 5260 binop(Iop_MullS32, 5261 mkexpr(rA), mkexpr(rB))) ); 5262 } 5263 break; 5264 5265 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 5266 if (flag_OE != 0) { 5267 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 5268 return False; 5269 } 5270 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5271 rD_addr, rA_addr, rB_addr); 5272 if (mode64) { 5273 /* rD[hi32] are undefined: setting them to sign of lo32 5274 - makes set_CR0 happy */ 5275 assign( rD, binop(Iop_Sar64, 5276 binop(Iop_Mul64, 5277 mk64lo32Uto64( mkexpr(rA) ), 5278 mk64lo32Uto64( mkexpr(rB) ) ), 5279 mkU8(32)) ); 5280 } else { 5281 assign( rD, unop(Iop_64HIto32, 5282 binop(Iop_MullU32, 5283 mkexpr(rA), mkexpr(rB))) ); 5284 } 5285 break; 5286 5287 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 5288 DIP("mullw%s%s r%u,r%u,r%u\n", 5289 flag_OE ? "o" : "", flag_rC ? ".":"", 5290 rD_addr, rA_addr, rB_addr); 5291 if (mode64) { 5292 /* rD[hi32] are undefined: setting them to sign of lo32 5293 - set_XER_OV() and set_CR0() depend on this */ 5294 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 5295 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 5296 assign( rD, binop(Iop_MullS32, a, b) ); 5297 if (flag_OE) { 5298 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW, 5299 mkexpr(rD), 5300 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 5301 } 5302 } else { 5303 assign( rD, unop(Iop_64to32, 5304 binop(Iop_MullU32, 5305 mkexpr(rA), mkexpr(rB))) ); 5306 if (flag_OE) { 5307 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW, 5308 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5309 } 5310 } 5311 break; 5312 5313 case 0x068: // neg (Negate, PPC32 p493) 5314 if (rB_addr != 0) { 5315 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 5316 return False; 5317 } 5318 DIP("neg%s%s r%u,r%u\n", 5319 flag_OE ? "o" : "", flag_rC ? ".":"", 5320 rD_addr, rA_addr); 5321 // rD = (~rA) + 1 5322 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5323 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 5324 mkSzImm(ty, 1)) ); 5325 if (flag_OE) { 5326 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_NEG, 5327 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5328 } 5329 break; 5330 5331 case 0x028: // subf (Subtract From, PPC32 p537) 5332 DIP("subf%s%s r%u,r%u,r%u\n", 5333 flag_OE ? "o" : "", flag_rC ? ".":"", 5334 rD_addr, rA_addr, rB_addr); 5335 // rD = rB - rA 5336 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5337 mkexpr(rB), mkexpr(rA)) ); 5338 if (flag_OE) { 5339 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBF, 5340 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5341 } 5342 break; 5343 5344 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 5345 DIP("subfc%s%s r%u,r%u,r%u\n", 5346 flag_OE ? "o" : "", flag_rC ? ".":"", 5347 rD_addr, rA_addr, rB_addr); 5348 // rD = rB - rA 5349 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5350 mkexpr(rB), mkexpr(rA)) ); 5351 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFC, 5352 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5353 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5354 if (flag_OE) { 5355 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFC, 5356 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5357 } 5358 break; 5359 5360 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 5361 IRTemp old_xer_ca = newTemp(ty); 5362 DIP("subfe%s%s r%u,r%u,r%u\n", 5363 flag_OE ? "o" : "", flag_rC ? ".":"", 5364 rD_addr, rA_addr, rB_addr); 5365 // rD = (log not)rA + rB + XER[CA] 5366 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5367 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5368 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 5369 binop( mkSzOp(ty, Iop_Add8), 5370 mkexpr(rB), mkexpr(old_xer_ca))) ); 5371 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5372 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5373 mkexpr(old_xer_ca) ); 5374 if (flag_OE) { 5375 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5376 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5377 } 5378 break; 5379 } 5380 5381 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 5382 IRTemp old_xer_ca = newTemp(ty); 5383 IRExpr *min_one; 5384 if (rB_addr != 0) { 5385 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 5386 return False; 5387 } 5388 DIP("subfme%s%s r%u,r%u\n", 5389 flag_OE ? "o" : "", flag_rC ? ".":"", 5390 rD_addr, rA_addr); 5391 // rD = (log not)rA + (-1) + XER[CA] 5392 // => Just another form of subfe 5393 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5394 min_one = mkSzImm(ty, (Long)-1); 5395 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5396 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 5397 binop( mkSzOp(ty, Iop_Add8), 5398 min_one, mkexpr(old_xer_ca))) ); 5399 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5400 mkexpr(rD), mkexpr(rA), min_one, 5401 mkexpr(old_xer_ca) ); 5402 if (flag_OE) { 5403 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5404 mkexpr(rD), mkexpr(rA), min_one ); 5405 } 5406 break; 5407 } 5408 5409 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 5410 IRTemp old_xer_ca = newTemp(ty); 5411 if (rB_addr != 0) { 5412 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 5413 return False; 5414 } 5415 DIP("subfze%s%s r%u,r%u\n", 5416 flag_OE ? "o" : "", flag_rC ? ".":"", 5417 rD_addr, rA_addr); 5418 // rD = (log not)rA + (0) + XER[CA] 5419 // => Just another form of subfe 5420 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5421 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5422 unop( mkSzOp(ty, Iop_Not8), 5423 mkexpr(rA)), mkexpr(old_xer_ca)) ); 5424 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5425 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 5426 mkexpr(old_xer_ca) ); 5427 if (flag_OE) { 5428 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5429 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 5430 } 5431 break; 5432 } 5433 5434 5435 /* 64bit Arithmetic */ 5436 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 5437 if (flag_OE != 0) { 5438 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 5439 return False; 5440 } 5441 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5442 rD_addr, rA_addr, rB_addr); 5443 assign( rD, unop(Iop_128HIto64, 5444 binop(Iop_MullS64, 5445 mkexpr(rA), mkexpr(rB))) ); 5446 5447 break; 5448 5449 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 5450 if (flag_OE != 0) { 5451 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 5452 return False; 5453 } 5454 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5455 rD_addr, rA_addr, rB_addr); 5456 assign( rD, unop(Iop_128HIto64, 5457 binop(Iop_MullU64, 5458 mkexpr(rA), mkexpr(rB))) ); 5459 break; 5460 5461 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 5462 DIP("mulld%s%s r%u,r%u,r%u\n", 5463 flag_OE ? "o" : "", flag_rC ? ".":"", 5464 rD_addr, rA_addr, rB_addr); 5465 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 5466 if (flag_OE) { 5467 set_XER_OV_64( PPCG_FLAG_OP_MULLD, 5468 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5469 /* OV is set to 1 if product isn't representable. 5470 * In this case also need to set OV32 and SO to 1, 5471 * i.e. copy OV to OV32 and SO. 5472 */ 5473 copy_OV_to_OV32(); 5474 update_SO(); 5475 } 5476 break; 5477 5478 case 0x1E9: // divd (Divide DWord, PPC64 p419) 5479 DIP("divd%s%s r%u,r%u,r%u\n", 5480 flag_OE ? "o" : "", flag_rC ? ".":"", 5481 rD_addr, rA_addr, rB_addr); 5482 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 5483 if (flag_OE) { 5484 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5485 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5486 } 5487 break; 5488 /* Note: 5489 if (0x8000_0000_0000_0000 / -1) or (x / 0) 5490 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 5491 => But _no_ exception raised. */ 5492 5493 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 5494 DIP("divdu%s%s r%u,r%u,r%u\n", 5495 flag_OE ? "o" : "", flag_rC ? ".":"", 5496 rD_addr, rA_addr, rB_addr); 5497 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 5498 if (flag_OE) { 5499 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5500 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5501 } 5502 break; 5503 /* Note: ditto comment divd, for (x / 0) */ 5504 5505 case 0x18B: // divweu (Divide Word Extended Unsigned) 5506 { 5507 /* 5508 * If (RA) >= (RB), or if an attempt is made to perform the division 5509 * <anything> / 0 5510 * then the contents of register RD are undefined as are (if Rc=1) the contents of 5511 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 5512 * to 1. 5513 */ 5514 IRTemp res = newTemp(Ity_I32); 5515 IRExpr * dividend, * divisor; 5516 DIP("divweu%s%s r%u,r%u,r%u\n", 5517 flag_OE ? "o" : "", flag_rC ? ".":"", 5518 rD_addr, rA_addr, rB_addr); 5519 if (mode64) { 5520 dividend = unop( Iop_64to32, mkexpr( rA ) ); 5521 divisor = unop( Iop_64to32, mkexpr( rB ) ); 5522 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 5523 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 5524 } else { 5525 dividend = mkexpr( rA ); 5526 divisor = mkexpr( rB ); 5527 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 5528 assign( rD, mkexpr( res) ); 5529 } 5530 5531 if (flag_OE) { 5532 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU, 5533 mkexpr(res), dividend, divisor ); 5534 update_SO( ); 5535 } 5536 break; 5537 } 5538 5539 case 0x1AB: // divwe (Divide Word Extended) 5540 { 5541 /* 5542 * If the quotient cannot be represented in 32 bits, or if an 5543 * attempt is made to perform the division 5544 * <anything> / 0 5545 * then the contents of register RD are undefined as are (if 5546 * Rc=1) the contents of the LT, GT, and EQ bits of CR 5547 * Field 0. In these cases, if OE=1 then OV is set to 1. 5548 */ 5549 5550 IRTemp res = newTemp(Ity_I32); 5551 IRExpr * dividend, * divisor; 5552 DIP("divwe%s%s r%u,r%u,r%u\n", 5553 flag_OE ? "o" : "", flag_rC ? ".":"", 5554 rD_addr, rA_addr, rB_addr); 5555 if (mode64) { 5556 dividend = unop( Iop_64to32, mkexpr( rA ) ); 5557 divisor = unop( Iop_64to32, mkexpr( rB ) ); 5558 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 5559 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 5560 } else { 5561 dividend = mkexpr( rA ); 5562 divisor = mkexpr( rB ); 5563 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 5564 assign( rD, mkexpr( res) ); 5565 } 5566 5567 if (flag_OE) { 5568 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE, 5569 mkexpr(res), dividend, divisor ); 5570 update_SO( ); 5571 } 5572 break; 5573 } 5574 5575 5576 case 0x1A9: // divde (Divide Doubleword Extended) 5577 /* 5578 * If the quotient cannot be represented in 64 bits, or if an 5579 * attempt is made to perform the division 5580 * <anything> / 0 5581 * then the contents of register RD are undefined as are (if 5582 * Rc=1) the contents of the LT, GT, and EQ bits of CR 5583 * Field 0. In these cases, if OE=1 then OV is set to 1. 5584 */ 5585 DIP("divde%s%s r%u,r%u,r%u\n", 5586 flag_OE ? "o" : "", flag_rC ? ".":"", 5587 rD_addr, rA_addr, rB_addr); 5588 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 5589 if (flag_OE) { 5590 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 5591 mkexpr( rA ), mkexpr( rB ) ); 5592 copy_OV_to_OV32(); 5593 update_SO(); 5594 } 5595 break; 5596 5597 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 5598 // Same CR and OV rules as given for divweu above 5599 DIP("divdeu%s%s r%u,r%u,r%u\n", 5600 flag_OE ? "o" : "", flag_rC ? ".":"", 5601 rD_addr, rA_addr, rB_addr); 5602 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 5603 if (flag_OE) { 5604 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 5605 mkexpr( rA ), mkexpr( rB ) ); 5606 copy_OV_to_OV32(); 5607 update_SO(); 5608 } 5609 break; 5610 5611 default: 5612 vex_printf("dis_int_arith(ppc)(opc2)\n"); 5613 return False; 5614 } 5615 break; 5616 5617 default: 5618 vex_printf("dis_int_arith(ppc)(opc1)\n"); 5619 return False; 5620 } 5621 5622 putIReg( rD_addr, mkexpr(rD) ); 5623 5624 if (do_rc && flag_rC) { 5625 set_CR0( mkexpr(rD) ); 5626 } 5627 return True; 5628 } 5629 5630 static Bool dis_modulo_int ( UInt theInstr ) 5631 { 5632 /* X-Form */ 5633 UChar opc1 = ifieldOPC( theInstr ); 5634 UInt opc2 = ifieldOPClo10( theInstr ); 5635 UChar rA_addr = ifieldRegA( theInstr ); 5636 UChar rB_addr = ifieldRegB( theInstr ); 5637 UChar rD_addr = ifieldRegDS( theInstr ); 5638 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5639 IRTemp rD = newTemp( ty ); 5640 5641 switch (opc1) { 5642 /* X-Form */ 5643 case 0x1F: 5644 switch (opc2) { 5645 case 0x109: // modud Modulo Unsigned Double Word 5646 { 5647 IRTemp rA = newTemp( Ity_I64 ); 5648 IRTemp rB = newTemp( Ity_I64 ); 5649 IRTemp quotient = newTemp( Ity_I64 ); 5650 IRTemp quotientTimesDivisor = newTemp( Ity_I64 ); 5651 IRTemp remainder = newTemp( Ity_I64 ); 5652 IRTemp rB_0 = newTemp( Ity_I64 ); /* all 1's if rB = 0 */ 5653 5654 DIP("modud r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5655 5656 assign( rA, getIReg( rA_addr ) ); 5657 assign( rB, getIReg( rB_addr ) ); 5658 5659 assign( quotient, 5660 binop( Iop_DivU64, mkexpr( rA ), mkexpr( rB ) ) ); 5661 5662 assign( quotientTimesDivisor, 5663 binop( Iop_Mul64, 5664 mkexpr( quotient ), 5665 mkexpr( rB ) ) ); 5666 5667 assign( remainder, 5668 binop( Iop_Sub64, 5669 mkexpr( rA ), 5670 mkexpr( quotientTimesDivisor ) ) ); 5671 5672 /* Need to match the HW for these special cases 5673 * rB = 0 result all zeros 5674 */ 5675 assign( rB_0, unop( Iop_1Sto64, 5676 binop( Iop_CmpEQ64, 5677 mkexpr( rB ), 5678 mkU64( 0x0 ) ) ) ); 5679 5680 assign (rD, binop( Iop_And64, 5681 unop( Iop_Not64, mkexpr( rB_0 ) ), 5682 mkexpr( remainder ) ) ); 5683 break; 5684 } 5685 5686 case 0x10B: // moduw Modulo Unsigned Word 5687 { 5688 IRTemp quotient = newTemp( Ity_I32 ); 5689 IRTemp quotientTimesDivisor = newTemp( Ity_I32 ); 5690 IRTemp remainder = newTemp( Ity_I32 ); 5691 5692 IRTemp rA = newTemp( Ity_I32 ); 5693 IRTemp rB = newTemp( Ity_I32 ); 5694 IRTemp rB_0 = newTemp( Ity_I32 ); /* all 1's if rB = 0 */ 5695 5696 DIP("moduw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5697 5698 if ( ty == Ity_I64 ) { 5699 /* rA and rB are 32 bit values in bits 32:63 of the 5700 * 64-bit register. 5701 */ 5702 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 5703 assign( rB, unop( Iop_64to32, getIReg( rB_addr ) ) ); 5704 5705 } else { 5706 assign( rA, getIReg( rA_addr ) ); 5707 assign( rB, getIReg( rB_addr ) ); 5708 } 5709 5710 assign( quotient, 5711 binop( Iop_DivU32, mkexpr( rA ), mkexpr( rB ) ) ); 5712 5713 assign( quotientTimesDivisor, 5714 unop( Iop_64to32, 5715 binop( Iop_MullU32, 5716 mkexpr( quotient ), 5717 mkexpr( rB ) ) ) ); 5718 5719 assign( remainder, 5720 binop( Iop_Sub32, 5721 mkexpr( rA ), 5722 mkexpr( quotientTimesDivisor ) ) ); 5723 5724 /* Need to match the HW for these special cases 5725 * rB = 0 result all zeros 5726 */ 5727 assign( rB_0, unop( Iop_1Sto32, 5728 binop( Iop_CmpEQ32, 5729 mkexpr( rB ), 5730 mkU32( 0x0 ) ) ) ); 5731 5732 assign (rD, binop( Iop_32HLto64, 5733 mkU32( 0 ), 5734 binop( Iop_And32, 5735 unop( Iop_Not32, mkexpr( rB_0 ) ), 5736 mkexpr( remainder ) ) ) ); 5737 break; 5738 } 5739 5740 case 0x21A: // cnttzw, cnttzw. Count Trailing Zero Word 5741 { 5742 /* Note cnttzw RA, RS - RA is dest, RS is source. But the 5743 * order of the operands in theInst is opc1 RS RA opc2 which has 5744 * the operand fields backwards to what the standard order. 5745 */ 5746 UChar rA_address = ifieldRegA(theInstr); 5747 UChar rS_address = ifieldRegDS(theInstr); 5748 IRTemp rA = newTemp(Ity_I64); 5749 IRTemp rS = newTemp(Ity_I64); 5750 UChar flag_rC = ifieldBIT0(theInstr); 5751 IRTemp result = newTemp(Ity_I32); 5752 5753 DIP("cnttzw%s r%u,r%u\n", flag_rC ? "." : "", 5754 rA_address, rS_address); 5755 5756 assign( rS, getIReg( rS_address ) ); 5757 assign( result, unop( Iop_Ctz32, 5758 unop( Iop_64to32, mkexpr( rS ) ) ) ); 5759 assign( rA, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( result ) ) ); 5760 5761 if ( flag_rC ) 5762 set_CR0( mkexpr( rA ) ); 5763 5764 putIReg( rA_address, mkexpr( rA ) ); 5765 5766 return True; /* Return here since this inst is not consistent 5767 * with the other instructions 5768 */ 5769 } 5770 break; 5771 5772 case 0x23A: // cnttzd, cnttzd. Count Trailing Zero Double word 5773 { 5774 /* Note cnttzd RA, RS - RA is dest, RS is source. But the 5775 * order of the operands in theInst is opc1 RS RA opc2 which has 5776 * the operand order listed backwards to what is standard. 5777 */ 5778 UChar rA_address = ifieldRegA(theInstr); 5779 UChar rS_address = ifieldRegDS(theInstr); 5780 IRTemp rA = newTemp(Ity_I64); 5781 IRTemp rS = newTemp(Ity_I64); 5782 UChar flag_rC = ifieldBIT0(theInstr); 5783 5784 DIP("cnttzd%s r%u,r%u\n", flag_rC ? "." : "", 5785 rA_address, rS_address); 5786 5787 assign( rS, getIReg( rS_address ) ); 5788 assign( rA, unop( Iop_Ctz64, mkexpr( rS ) ) ); 5789 5790 if ( flag_rC == 1 ) 5791 set_CR0( mkexpr( rA ) ); 5792 5793 putIReg( rA_address, mkexpr( rA ) ); 5794 5795 return True; /* Return here since this inst is not consistent 5796 * with the other instructions 5797 */ 5798 } 5799 break; 5800 5801 case 0x309: // modsd Modulo Signed Double Word 5802 { 5803 IRTemp rA = newTemp( Ity_I64 ); 5804 IRTemp rB = newTemp( Ity_I64 ); 5805 IRTemp rA2_63 = newTemp( Ity_I64 ); /* all 1's if rA != -2^63 */ 5806 IRTemp rB_0 = newTemp( Ity_I1 ); /* 1 if rB = 0 */ 5807 IRTemp rB_1 = newTemp( Ity_I1 ); /* 1 if rB = -1 */ 5808 IRTemp rA_1 = newTemp( Ity_I1 ); /* 1 if rA = -1 */ 5809 IRTemp resultis0 = newTemp( Ity_I64 ); 5810 IRTemp resultisF = newTemp( Ity_I64 ); 5811 IRTemp quotient = newTemp( Ity_I64 ); 5812 IRTemp quotientTimesDivisor = newTemp( Ity_I64 ); 5813 IRTemp remainder = newTemp( Ity_I64 ); 5814 IRTemp tmp = newTemp( Ity_I64 ); 5815 5816 DIP("modsd r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5817 5818 assign( rA, getIReg( rA_addr ) ); 5819 assign( rB, getIReg( rB_addr ) ); 5820 5821 assign( rA2_63, unop ( Iop_1Sto64, 5822 binop( Iop_CmpNE64, 5823 mkexpr( rA ), 5824 mkU64( 0x8000000000000000 ) ) ) ); 5825 assign( rB_0, binop( Iop_CmpEQ64, 5826 mkexpr( rB ), 5827 mkU64( 0x0 ) ) ); 5828 5829 assign( rB_1, binop( Iop_CmpEQ64, 5830 mkexpr( rB ), 5831 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ); 5832 5833 assign( rA_1, binop( Iop_CmpEQ64, 5834 mkexpr( rA ), 5835 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ); 5836 5837 /* Need to match the HW for these special cases 5838 * rA = -2^31 and rB = -1 result all zeros 5839 * rA = -1 and rB = -1 result all zeros 5840 * rA = -1 and (rB != -1 AND rB != 0) result all 1's 5841 */ 5842 assign( resultis0, 5843 binop( Iop_Or64, 5844 mkexpr( rA2_63 ), 5845 unop ( Iop_1Sto64, mkexpr( rB_1 ) ) ) ); 5846 assign( resultisF, 5847 binop( Iop_And64, 5848 unop( Iop_1Sto64, mkexpr( rA_1 ) ), 5849 binop( Iop_And64, 5850 unop( Iop_Not64, 5851 unop( Iop_1Sto64, mkexpr( rB_0 ) ) ), 5852 unop( Iop_Not64, 5853 unop( Iop_1Sto64, mkexpr( rB_1 ) ) ) 5854 ) ) ); 5855 5856 /* The following remainder computation works as long as 5857 * rA != -2^63 and rB != -1. 5858 */ 5859 assign( quotient, 5860 binop( Iop_DivS64, mkexpr( rA ), mkexpr( rB ) ) ); 5861 5862 assign( quotientTimesDivisor, 5863 binop( Iop_Mul64, 5864 mkexpr( quotient ), 5865 mkexpr( rB ) ) ); 5866 5867 assign( remainder, 5868 binop( Iop_Sub64, 5869 mkexpr( rA ), 5870 mkexpr( quotientTimesDivisor ) ) ); 5871 5872 assign( tmp, binop( Iop_And64, 5873 mkexpr( remainder ), 5874 unop( Iop_Not64, 5875 mkexpr( resultis0 ) ) ) ); 5876 5877 assign( rD, binop( Iop_Or64, 5878 binop( Iop_And64, 5879 unop (Iop_Not64, 5880 mkexpr( resultisF ) ), 5881 mkexpr( tmp ) ), 5882 mkexpr( resultisF ) ) ); 5883 break; 5884 } 5885 case 0x30B: // modsw Modulo Signed Word 5886 { 5887 IRTemp rA = newTemp( Ity_I32 ); 5888 IRTemp rB = newTemp( Ity_I32 ); 5889 IRTemp rA2_32 = newTemp( Ity_I32 ); /* all 1's if rA = -2^32 */ 5890 IRTemp rB_0 = newTemp( Ity_I1 ); /* 1 if rB = 0 */ 5891 IRTemp rB_1 = newTemp( Ity_I1 ); /* 1 if rB = -1 */ 5892 IRTemp rA_1 = newTemp( Ity_I1 ); /* 1 if rA = -1 */ 5893 IRTemp resultis0 = newTemp( Ity_I32 ); 5894 IRTemp resultisF = newTemp( Ity_I64 ); 5895 IRTemp quotient = newTemp( Ity_I32 ); 5896 IRTemp quotientTimesDivisor = newTemp( Ity_I32 ); 5897 IRTemp remainder = newTemp( Ity_I32 ); 5898 IRTemp tmp = newTemp( Ity_I64 ); 5899 5900 DIP("modsw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5901 5902 if ( ty == Ity_I64 ) { 5903 /* rA and rB are 32 bit values in bits 32:63 of the 5904 * 64-bit register. 5905 */ 5906 assign( rA, unop(Iop_64to32, getIReg(rA_addr) ) ); 5907 assign( rB, unop(Iop_64to32, getIReg(rB_addr) ) ); 5908 5909 } else { 5910 assign( rA, getIReg(rA_addr) ); 5911 assign( rB, getIReg(rB_addr) ); 5912 } 5913 5914 assign( rA2_32, unop( Iop_1Sto32, 5915 binop( Iop_CmpEQ32, 5916 mkexpr( rA ), 5917 mkU32( 0x80000000 ) ) ) ); 5918 /* If the divisor is zero, then the result is undefined. 5919 * However, we will make the result be zero to match what 5920 * the hardware does. 5921 */ 5922 assign( rB_0, binop( Iop_CmpEQ32, 5923 mkexpr( rB ), 5924 mkU32( 0x0 ) ) ); 5925 5926 assign( rB_1, binop( Iop_CmpEQ32, 5927 mkexpr( rB ), 5928 mkU32( 0xFFFFFFFF ) ) ); 5929 5930 assign( rA_1, binop( Iop_CmpEQ32, 5931 mkexpr( rA ), 5932 mkU32( 0xFFFFFFFF ) ) ); 5933 5934 /* Need to match the HW for these special cases 5935 * rA = -2^31 and rB = -1 result all zeros 5936 * rA = -1 and rB = -1 result all zeros 5937 * rA = -1 and (rB != -1 AND rB != 0) result all 1's 5938 */ 5939 assign( resultis0, 5940 binop( Iop_Or32, 5941 unop( Iop_Not32, 5942 binop( Iop_And32, 5943 mkexpr( rA2_32 ), 5944 unop( Iop_1Sto32, 5945 mkexpr( rB_1 ) ) ) ), 5946 binop( Iop_And32, 5947 unop( Iop_1Sto32, mkexpr( rA_1 ) ), 5948 unop( Iop_1Sto32, mkexpr( rB_1 ) ) ) ) ); 5949 assign( resultisF, 5950 binop( Iop_And64, 5951 unop( Iop_1Sto64, mkexpr( rA_1 ) ), 5952 binop( Iop_And64, 5953 unop( Iop_Not64, 5954 unop( Iop_1Sto64, mkexpr( rB_0 ) ) ), 5955 unop( Iop_Not64, 5956 unop( Iop_1Sto64, mkexpr( rB_1 ) ) ) 5957 ) ) ); 5958 5959 /* The following remainder computation works as long as 5960 * rA != -2^31 and rB != -1. 5961 */ 5962 assign( quotient, 5963 binop( Iop_DivS32, mkexpr( rA ), mkexpr( rB ) ) ); 5964 5965 assign( quotientTimesDivisor, 5966 unop( Iop_64to32, 5967 binop( Iop_MullS32, 5968 mkexpr( quotient ), 5969 mkexpr( rB ) ) ) ); 5970 5971 assign( remainder, 5972 binop( Iop_Sub32, 5973 mkexpr( rA ), 5974 mkexpr( quotientTimesDivisor ) ) ); 5975 5976 assign( tmp, binop( Iop_32HLto64, 5977 mkU32( 0 ), 5978 binop( Iop_And32, 5979 mkexpr( remainder ), 5980 unop( Iop_Not32, 5981 mkexpr( resultis0 ) ) ) ) ); 5982 5983 assign( rD, binop( Iop_Or64, 5984 binop( Iop_And64, 5985 unop ( Iop_Not64, 5986 mkexpr( resultisF ) ), 5987 mkexpr( tmp ) ), 5988 mkexpr( resultisF ) ) ); 5989 break; 5990 } 5991 5992 default: 5993 vex_printf("dis_modulo_int(ppc)(opc2)\n"); 5994 return False; 5995 } 5996 break; 5997 5998 default: 5999 vex_printf("dis_modulo_int(ppc)(opc1)\n"); 6000 return False; 6001 } 6002 6003 putIReg( rD_addr, mkexpr( rD ) ); 6004 6005 return True; 6006 } 6007 6008 6009 /* 6010 Byte Compare Instructions 6011 */ 6012 static Bool dis_byte_cmp ( UInt theInstr ) 6013 { 6014 /* X-Form */ 6015 UChar opc1 = ifieldOPC(theInstr); 6016 UInt opc2 = ifieldOPClo10(theInstr); 6017 UChar rA_addr = ifieldRegA(theInstr); 6018 UChar rB_addr = ifieldRegB(theInstr); 6019 IRTemp rA = newTemp(Ity_I64); 6020 IRTemp rB = newTemp(Ity_I64); 6021 UChar L = toUChar( IFIELD( theInstr, 21, 1 ) ); 6022 UChar BF = toUChar( IFIELD( theInstr, 23, 3 ) ); 6023 6024 assign( rA, getIReg(rA_addr) ); 6025 assign( rB, getIReg(rB_addr) ); 6026 6027 if (opc1 != 0x1F) { 6028 vex_printf("dis_byte_cmp(ppc)(opc1)\n"); 6029 return False; 6030 } 6031 6032 switch (opc2) { 6033 case 0xc0: // cmprb (Compare Ranged Byte) 6034 { 6035 IRExpr *value; 6036 IRExpr *hi_1, *lo_1, *hi_2, *lo_2; 6037 IRExpr *inrange_1, *inrange_2; 6038 6039 DIP("cmprb %u,%u,r%u,r%u\n", BF, L, rA_addr, rB_addr); 6040 6041 hi_1 = binop( Iop_Shr64, 6042 binop( Iop_And64, 6043 mkexpr( rB ), 6044 mkU64( 0xFF000000 ) ), 6045 mkU8( 24 ) ); 6046 lo_1 = binop( Iop_Shr64, 6047 binop( Iop_And64, 6048 mkexpr( rB ), 6049 mkU64( 0xFF0000 ) ) , 6050 mkU8( 16 ) ); 6051 hi_2 = binop( Iop_Shr64, 6052 binop( Iop_And64, 6053 mkexpr( rB ), 6054 mkU64( 0xFF00 ) ), 6055 mkU8( 8 ) ); 6056 lo_2 = binop( Iop_And64, 6057 mkexpr( rB ), 6058 mkU64( 0xFF ) ); 6059 value = binop( Iop_And64, 6060 mkexpr( rA ), 6061 mkU64( 0xFF ) ); 6062 6063 inrange_1 = mkAND1( binop( Iop_CmpLE64U, value, hi_1 ), 6064 mkNOT1( binop( Iop_CmpLT64U, value, lo_1 ) ) ); 6065 inrange_2 = mkAND1( binop( Iop_CmpLE64U, value, hi_2 ), 6066 mkNOT1( binop( Iop_CmpLT64U, value, lo_2 ) ) ); 6067 6068 putGST_field( PPC_GST_CR, 6069 binop( Iop_Shl32, 6070 binop( Iop_Or32, 6071 unop( Iop_1Uto32, inrange_2 ), 6072 binop( Iop_And32, 6073 mkU32 ( L ), 6074 unop( Iop_1Uto32, inrange_1 ) ) ), 6075 mkU8( 2 ) ), 6076 BF ); 6077 } 6078 break; 6079 6080 case 0xE0: // cmpeqb (Compare Equal Byte) 6081 { 6082 Int i; 6083 IRTemp tmp[9]; 6084 IRExpr *value; 6085 6086 DIP("cmpeqb %u,r%u,r%u\n", BF, rA_addr, rB_addr); 6087 6088 value = binop( Iop_And64, 6089 mkexpr( rA ), 6090 mkU64( 0xFF ) ); 6091 6092 tmp[0] = newTemp(Ity_I32); 6093 assign( tmp[0], mkU32( 0 ) ); 6094 6095 for(i = 0; i < 8; i++) { 6096 tmp[i+1] = newTemp(Ity_I32); 6097 assign( tmp[i+1], binop( Iop_Or32, 6098 unop( Iop_1Uto32, 6099 binop( Iop_CmpEQ64, 6100 value, 6101 binop( Iop_And64, 6102 binop( Iop_Shr64, 6103 mkexpr( rB ), 6104 mkU8( i*8 ) ), 6105 mkU64( 0xFF ) ) ) ), 6106 mkexpr( tmp[i] ) ) ); 6107 } 6108 6109 putGST_field( PPC_GST_CR, 6110 binop( Iop_Shl32, 6111 unop( Iop_1Uto32, 6112 mkNOT1( binop( Iop_CmpEQ32, 6113 mkexpr( tmp[8] ), 6114 mkU32( 0 ) ) ) ), 6115 mkU8( 2 ) ), 6116 BF ); 6117 } 6118 break; 6119 6120 default: 6121 vex_printf("dis_byte_cmp(ppc)(opc2)\n"); 6122 return False; 6123 } 6124 return True; 6125 } 6126 6127 /* 6128 * Integer Miscellaneous instructions 6129 */ 6130 static Bool dis_int_misc ( UInt theInstr ) 6131 { 6132 Int wc = IFIELD(theInstr, 21, 2); 6133 UChar opc1 = ifieldOPC(theInstr); 6134 UInt opc2 = ifieldOPClo10(theInstr); 6135 6136 if ( opc1 != 0x1F ) { 6137 vex_printf("dis_modulo_int(ppc)(opc1)\n"); 6138 return False; 6139 } 6140 6141 switch (opc2) { 6142 case 0x01E: // wait, (X-from) 6143 DIP("wait %u\n", wc); 6144 6145 /* The wait instruction causes instruction fetching and execution 6146 * to be suspended. Instruction fetching and execution are resumed 6147 * when the events specified by the WC field occur. 6148 * 6149 * 0b00 Resume instruction fetching and execution when an 6150 * exception or an event-based branch exception occurs, 6151 * or a resume signal from the platform is recieved. 6152 * 6153 * 0b01 Reserved. 6154 * 6155 * For our purposes, we will just assume the contition is always 6156 * immediately satisfied. 6157 */ 6158 break; 6159 default: 6160 vex_printf("dis_int_misc(ppc)(opc2)\n"); 6161 return False; 6162 } 6163 6164 return True; 6165 } 6166 6167 /* 6168 Integer Compare Instructions 6169 */ 6170 static Bool dis_int_cmp ( UInt theInstr ) 6171 { 6172 /* D-Form, X-Form */ 6173 UChar opc1 = ifieldOPC(theInstr); 6174 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6175 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 6176 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 6177 UChar rA_addr = ifieldRegA(theInstr); 6178 UInt uimm16 = ifieldUIMM16(theInstr); 6179 UChar rB_addr = ifieldRegB(theInstr); 6180 UInt opc2 = ifieldOPClo10(theInstr); 6181 UChar b0 = ifieldBIT0(theInstr); 6182 6183 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6184 IRExpr *a = getIReg(rA_addr); 6185 IRExpr *b; 6186 6187 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 6188 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 6189 return False; 6190 } 6191 6192 if (( b22 != 0 ) && ( opc2 != 0x080 ) ) { // setb case exception 6193 vex_printf("dis_int_cmp(ppc)(b22)\n"); 6194 return False; 6195 } 6196 6197 switch (opc1) { 6198 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 6199 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 6200 (Int)extend_s_16to32(uimm16)); 6201 b = mkSzExtendS16( ty, uimm16 ); 6202 if (flag_L == 1) { 6203 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 6204 } else { 6205 a = mkNarrowTo32( ty, a ); 6206 b = mkNarrowTo32( ty, b ); 6207 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 6208 } 6209 putCR0( crfD, getXER_SO() ); 6210 break; 6211 6212 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 6213 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 6214 b = mkSzImm( ty, uimm16 ); 6215 if (flag_L == 1) { 6216 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 6217 } else { 6218 a = mkNarrowTo32( ty, a ); 6219 b = mkNarrowTo32( ty, b ); 6220 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 6221 } 6222 putCR0( crfD, getXER_SO() ); 6223 break; 6224 6225 /* X Form */ 6226 case 0x1F: 6227 if (b0 != 0) { 6228 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 6229 return False; 6230 } 6231 b = getIReg(rB_addr); 6232 6233 switch (opc2) { 6234 case 0x000: // cmp (Compare, PPC32 p367) 6235 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 6236 /* Comparing a reg with itself produces a result which 6237 doesn't depend on the contents of the reg. Therefore 6238 remove the false dependency, which has been known to cause 6239 memcheck to produce false errors. */ 6240 if (rA_addr == rB_addr) 6241 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 6242 ? mkU64(0) : mkU32(0); 6243 if (flag_L == 1) { 6244 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 6245 } else { 6246 a = mkNarrowTo32( ty, a ); 6247 b = mkNarrowTo32( ty, b ); 6248 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 6249 } 6250 putCR0( crfD, getXER_SO() ); 6251 break; 6252 6253 case 0x020: // cmpl (Compare Logical, PPC32 p369) 6254 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 6255 /* Comparing a reg with itself produces a result which 6256 doesn't depend on the contents of the reg. Therefore 6257 remove the false dependency, which has been known to cause 6258 memcheck to produce false errors. */ 6259 if (rA_addr == rB_addr) 6260 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 6261 ? mkU64(0) : mkU32(0); 6262 if (flag_L == 1) { 6263 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 6264 } else { 6265 a = mkNarrowTo32( ty, a ); 6266 b = mkNarrowTo32( ty, b ); 6267 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 6268 } 6269 putCR0( crfD, getXER_SO() ); 6270 break; 6271 6272 case 0x080: // setb (Set Boolean) 6273 { 6274 UChar rT_addr = ifieldRegDS(theInstr); 6275 Int bfa = IFIELD(theInstr, 18, 3); 6276 IRTemp cr = newTemp(Ity_I32); 6277 IRTemp cr0 = newTemp(Ity_I32); 6278 IRTemp cr1 = newTemp(Ity_I32); 6279 IRTemp result = newTemp(Ity_I64); 6280 6281 DIP("setb r%u,%d\n", rT_addr, bfa); 6282 6283 /* Fetch the entire condition code value */ 6284 assign( cr, getGST( PPC_GST_CR ) ); 6285 6286 /* Get bit zero (IBM numbering) of the CR field specified 6287 * by bfa. 6288 */ 6289 assign( cr0, binop( Iop_And32, 6290 binop( Iop_Shr32, 6291 mkexpr( cr ), 6292 mkU8( (7-bfa)*4 ) ), 6293 mkU32( 0x8 ) ) ); 6294 assign( cr1, binop( Iop_And32, 6295 binop( Iop_Shr32, 6296 mkexpr( cr ), 6297 mkU8( (7-bfa)*4 ) ), 6298 mkU32( 0x4 ) ) ); 6299 assign( result, binop( Iop_Or64, 6300 unop( Iop_1Sto64, 6301 binop( Iop_CmpEQ32, 6302 mkexpr( cr0 ), 6303 mkU32( 0x8 ) ) ), 6304 binop( Iop_32HLto64, 6305 mkU32( 0 ), 6306 unop( Iop_1Uto32, 6307 binop( Iop_CmpEQ32, 6308 mkexpr( cr1 ), 6309 mkU32( 0x4 ) ) ) ) ) ); 6310 if ( ty == Ity_I64 ) 6311 putIReg( rT_addr, mkexpr( result ) ); 6312 else 6313 putIReg( rT_addr, unop( Iop_64to32, mkexpr(result ) ) ); 6314 } 6315 break; 6316 default: 6317 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 6318 return False; 6319 } 6320 break; 6321 6322 default: 6323 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 6324 return False; 6325 } 6326 6327 return True; 6328 } 6329 6330 6331 /* 6332 Integer Logical Instructions 6333 */ 6334 static Bool dis_int_logic ( UInt theInstr ) 6335 { 6336 /* D-Form, X-Form */ 6337 UChar opc1 = ifieldOPC(theInstr); 6338 UChar rS_addr = ifieldRegDS(theInstr); 6339 UChar rA_addr = ifieldRegA(theInstr); 6340 UInt uimm16 = ifieldUIMM16(theInstr); 6341 UChar rB_addr = ifieldRegB(theInstr); 6342 UInt opc2 = ifieldOPClo10(theInstr); 6343 UChar flag_rC = ifieldBIT0(theInstr); 6344 6345 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6346 IRTemp rS = newTemp(ty); 6347 IRTemp rA = newTemp(ty); 6348 IRTemp rB = newTemp(ty); 6349 IRExpr* irx; 6350 Bool do_rc = False; 6351 6352 assign( rS, getIReg(rS_addr) ); 6353 assign( rB, getIReg(rB_addr) ); 6354 6355 switch (opc1) { 6356 case 0x1C: // andi. (AND Immediate, PPC32 p358) 6357 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6358 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6359 mkSzImm(ty, uimm16)) ); 6360 do_rc = True; // Always record to CR 6361 flag_rC = 1; 6362 break; 6363 6364 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 6365 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6366 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6367 mkSzImm(ty, uimm16 << 16)) ); 6368 do_rc = True; // Always record to CR 6369 flag_rC = 1; 6370 break; 6371 6372 case 0x18: // ori (OR Immediate, PPC32 p497) 6373 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6374 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6375 mkSzImm(ty, uimm16)) ); 6376 break; 6377 6378 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 6379 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6380 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6381 mkSzImm(ty, uimm16 << 16)) ); 6382 break; 6383 6384 case 0x1A: // xori (XOR Immediate, PPC32 p550) 6385 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6386 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 6387 mkSzImm(ty, uimm16)) ); 6388 break; 6389 6390 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 6391 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6392 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 6393 mkSzImm(ty, uimm16 << 16)) ); 6394 break; 6395 6396 /* X Form */ 6397 case 0x1F: 6398 6399 opc2 = IFIELD( theInstr, 2, 9 ); 6400 6401 switch ( opc2 ) { 6402 case 0x1BD: // extswsli (Extend Sign Word shift left) 6403 { 6404 /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */ 6405 UChar sh = IFIELD( theInstr, 11, 5 ) | (IFIELD(theInstr, 1, 1) << 5); 6406 IRTemp temp = newTemp( ty ); 6407 6408 DIP("extswsli%s r%u,r%u,%u\n", flag_rC ? ".":"", 6409 rA_addr, rS_addr, sh); 6410 6411 assign( temp, unop( Iop_32Sto64, 6412 unop( Iop_64to32, mkexpr( rS ) ) ) ); 6413 assign( rA, binop( Iop_Shl64, mkexpr( temp ), mkU8( sh ) ) ); 6414 putIReg( rA_addr, mkexpr( rA ) ); 6415 6416 if ( flag_rC ) { 6417 set_CR0( mkexpr( rA ) ); 6418 } 6419 return True; 6420 } 6421 default: 6422 break; // drop to next opc2 check 6423 } 6424 6425 do_rc = True; // All below record to CR, except for where we return at case end. 6426 6427 opc2 = ifieldOPClo10( theInstr ); 6428 6429 switch (opc2) { 6430 case 0x01C: // and (AND, PPC32 p356) 6431 DIP("and%s r%u,r%u,r%u\n", 6432 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6433 assign(rA, binop( mkSzOp(ty, Iop_And8), 6434 mkexpr(rS), mkexpr(rB))); 6435 break; 6436 6437 case 0x03C: // andc (AND with Complement, PPC32 p357) 6438 DIP("andc%s r%u,r%u,r%u\n", 6439 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6440 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6441 unop( mkSzOp(ty, Iop_Not8), 6442 mkexpr(rB)))); 6443 break; 6444 6445 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 6446 IRExpr* lo32; 6447 if (rB_addr!=0) { 6448 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 6449 return False; 6450 } 6451 DIP("cntlzw%s r%u,r%u\n", 6452 flag_rC ? ".":"", rA_addr, rS_addr); 6453 6454 // mode64: count in low word only 6455 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 6456 6457 // Iop_Clz32 undefined for arg==0, so deal with that case: 6458 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 6459 assign(rA, mkWidenFrom32(ty, 6460 IRExpr_ITE( irx, 6461 unop(Iop_Clz32, lo32), 6462 mkU32(32)), 6463 False)); 6464 6465 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 6466 break; 6467 } 6468 6469 case 0x11C: // eqv (Equivalent, PPC32 p396) 6470 DIP("eqv%s r%u,r%u,r%u\n", 6471 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6472 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6473 binop( mkSzOp(ty, Iop_Xor8), 6474 mkexpr(rS), mkexpr(rB))) ); 6475 break; 6476 6477 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 6478 if (rB_addr!=0) { 6479 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 6480 return False; 6481 } 6482 DIP("extsb%s r%u,r%u\n", 6483 flag_rC ? ".":"", rA_addr, rS_addr); 6484 if (mode64) 6485 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 6486 else 6487 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 6488 break; 6489 6490 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 6491 if (rB_addr!=0) { 6492 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 6493 return False; 6494 } 6495 DIP("extsh%s r%u,r%u\n", 6496 flag_rC ? ".":"", rA_addr, rS_addr); 6497 if (mode64) 6498 assign( rA, unop(Iop_16Sto64, 6499 unop(Iop_64to16, mkexpr(rS))) ); 6500 else 6501 assign( rA, unop(Iop_16Sto32, 6502 unop(Iop_32to16, mkexpr(rS))) ); 6503 break; 6504 6505 case 0x1DC: // nand (NAND, PPC32 p492) 6506 DIP("nand%s r%u,r%u,r%u\n", 6507 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6508 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6509 binop( mkSzOp(ty, Iop_And8), 6510 mkexpr(rS), mkexpr(rB))) ); 6511 break; 6512 6513 case 0x07C: // nor (NOR, PPC32 p494) 6514 DIP("nor%s r%u,r%u,r%u\n", 6515 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6516 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6517 binop( mkSzOp(ty, Iop_Or8), 6518 mkexpr(rS), mkexpr(rB))) ); 6519 break; 6520 6521 case 0x1BC: // or (OR, PPC32 p495) 6522 if ((!flag_rC) && rS_addr == rB_addr) { 6523 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 6524 assign( rA, mkexpr(rS) ); 6525 } else { 6526 DIP("or%s r%u,r%u,r%u\n", 6527 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6528 assign( rA, binop( mkSzOp(ty, Iop_Or8), 6529 mkexpr(rS), mkexpr(rB)) ); 6530 } 6531 break; 6532 6533 case 0x19C: // orc (OR with Complement, PPC32 p496) 6534 DIP("orc%s r%u,r%u,r%u\n", 6535 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6536 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6537 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 6538 break; 6539 6540 case 0x13C: // xor (XOR, PPC32 p549) 6541 DIP("xor%s r%u,r%u,r%u\n", 6542 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6543 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 6544 mkexpr(rS), mkexpr(rB)) ); 6545 break; 6546 6547 6548 /* 64bit Integer Logical Instructions */ 6549 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 6550 if (rB_addr!=0) { 6551 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 6552 return False; 6553 } 6554 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 6555 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 6556 break; 6557 6558 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 6559 if (rB_addr!=0) { 6560 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 6561 return False; 6562 } 6563 DIP("cntlzd%s r%u,r%u\n", 6564 flag_rC ? ".":"", rA_addr, rS_addr); 6565 // Iop_Clz64 undefined for arg==0, so deal with that case: 6566 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 6567 assign(rA, IRExpr_ITE( irx, 6568 unop(Iop_Clz64, mkexpr(rS)), 6569 mkU64(64) )); 6570 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 6571 break; 6572 6573 case 0x1FC: // cmpb (Power6: compare bytes) 6574 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 6575 6576 if (mode64) 6577 assign( rA, unop( Iop_V128to64, 6578 binop( Iop_CmpEQ8x16, 6579 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 6580 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 6581 )) ); 6582 else 6583 assign( rA, unop( Iop_V128to32, 6584 binop( Iop_CmpEQ8x16, 6585 unop( Iop_32UtoV128, mkexpr(rS) ), 6586 unop( Iop_32UtoV128, mkexpr(rB) ) 6587 )) ); 6588 break; 6589 6590 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 6591 IRTemp frB = newTemp(Ity_F64); 6592 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 6593 6594 assign( frB, getFReg(rB_addr)); // always F64 6595 if (mode64) 6596 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 6597 else 6598 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 6599 6600 putIReg( rS_addr, mkexpr(rA)); 6601 return True; 6602 } 6603 6604 case 0x25F: { // mffgpr (move floating-point from general purpose register) 6605 IRTemp frA = newTemp(Ity_F64); 6606 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 6607 6608 if (mode64) 6609 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 6610 else 6611 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 6612 6613 putFReg( rS_addr, mkexpr(frA)); 6614 return True; 6615 } 6616 case 0x1FA: // popcntd (population count doubleword 6617 { 6618 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 6619 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 6620 putIReg( rA_addr, mkexpr(result) ); 6621 return True; 6622 } 6623 case 0x17A: // popcntw (Population Count Words) 6624 { 6625 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 6626 if (mode64) { 6627 IRTemp resultHi, resultLo; 6628 IRTemp argLo = newTemp(Ity_I32); 6629 IRTemp argHi = newTemp(Ity_I32); 6630 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 6631 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 6632 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 6633 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 6634 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 6635 } else { 6636 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 6637 putIReg( rA_addr, mkexpr(result) ); 6638 } 6639 return True; 6640 } 6641 case 0x7A: // popcntb (Population Count Byte) 6642 { 6643 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 6644 6645 if (mode64) { 6646 IRTemp resultHi, resultLo; 6647 IRTemp argLo = newTemp(Ity_I32); 6648 IRTemp argHi = newTemp(Ity_I32); 6649 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 6650 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 6651 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 6652 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 6653 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 6654 mkexpr(resultLo))); 6655 } else { 6656 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 6657 putIReg( rA_addr, mkexpr(result) ); 6658 } 6659 return True; 6660 } 6661 case 0x0FC: // bpermd (Bit Permute Doubleword) 6662 { 6663 /* This is a lot of rigmarole to emulate bpermd like this, as it 6664 * could be done much faster by implementing a call to the native 6665 * instruction. However, where possible I want to avoid using new 6666 * native instructions so that we can use valgrind to emulate those 6667 * instructions on older PPC64 hardware. 6668 */ 6669 #define BPERMD_IDX_MASK 0x00000000000000FFULL 6670 #define BPERMD_BIT_MASK 0x8000000000000000ULL 6671 int i; 6672 IRExpr * rS_expr = mkexpr(rS); 6673 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 6674 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 6675 for (i = 0; i < 8; i++) { 6676 IRTemp idx_tmp = newTemp( Ity_I64 ); 6677 IRTemp perm_bit = newTemp( Ity_I64 ); 6678 IRTemp idx = newTemp( Ity_I8 ); 6679 IRTemp idx_LT64 = newTemp( Ity_I1 ); 6680 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 6681 6682 assign( idx_tmp, 6683 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 6684 assign( idx_LT64, 6685 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 6686 assign( idx, 6687 binop( Iop_And8, 6688 unop( Iop_1Sto8, 6689 mkexpr(idx_LT64) ), 6690 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 6691 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 6692 * to determine which bit of rB to use for the perm bit, and then we shift 6693 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 6694 * to set the final perm bit. 6695 */ 6696 assign( idx_LT64_ity64, 6697 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 6698 assign( perm_bit, 6699 binop( Iop_And64, 6700 mkexpr( idx_LT64_ity64 ), 6701 binop( Iop_Shr64, 6702 binop( Iop_And64, 6703 mkU64( BPERMD_BIT_MASK ), 6704 binop( Iop_Shl64, 6705 mkexpr( rB ), 6706 mkexpr( idx ) ) ), 6707 mkU8( 63 ) ) ) ); 6708 res = binop( Iop_Or64, 6709 res, 6710 binop( Iop_Shl64, 6711 mkexpr( perm_bit ), 6712 mkU8( i ) ) ); 6713 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 6714 } 6715 putIReg(rA_addr, res); 6716 return True; 6717 } 6718 6719 default: 6720 vex_printf("dis_int_logic(ppc)(opc2)\n"); 6721 return False; 6722 } 6723 break; 6724 6725 default: 6726 vex_printf("dis_int_logic(ppc)(opc1)\n"); 6727 return False; 6728 } 6729 6730 putIReg( rA_addr, mkexpr(rA) ); 6731 6732 if (do_rc && flag_rC) { 6733 set_CR0( mkexpr(rA) ); 6734 } 6735 return True; 6736 } 6737 6738 /* 6739 Integer Parity Instructions 6740 */ 6741 static Bool dis_int_parity ( UInt theInstr ) 6742 { 6743 /* X-Form */ 6744 UChar opc1 = ifieldOPC(theInstr); 6745 UChar rS_addr = ifieldRegDS(theInstr); 6746 UChar rA_addr = ifieldRegA(theInstr); 6747 UChar rB_addr = ifieldRegB(theInstr); 6748 UInt opc2 = ifieldOPClo10(theInstr); 6749 UChar b0 = ifieldBIT0(theInstr); 6750 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6751 6752 IRTemp rS = newTemp(ty); 6753 IRTemp rA = newTemp(ty); 6754 IRTemp iTot1 = newTemp(Ity_I32); 6755 IRTemp iTot2 = newTemp(Ity_I32); 6756 IRTemp iTot3 = newTemp(Ity_I32); 6757 IRTemp iTot4 = newTemp(Ity_I32); 6758 IRTemp iTot5 = newTemp(Ity_I32); 6759 IRTemp iTot6 = newTemp(Ity_I32); 6760 IRTemp iTot7 = newTemp(Ity_I32); 6761 IRTemp iTot8 = newTemp(Ity_I32); 6762 IRTemp rS1 = newTemp(ty); 6763 IRTemp rS2 = newTemp(ty); 6764 IRTemp rS3 = newTemp(ty); 6765 IRTemp rS4 = newTemp(ty); 6766 IRTemp rS5 = newTemp(ty); 6767 IRTemp rS6 = newTemp(ty); 6768 IRTemp rS7 = newTemp(ty); 6769 IRTemp iHi = newTemp(Ity_I32); 6770 IRTemp iLo = newTemp(Ity_I32); 6771 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 6772 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 6773 6774 if (opc1 != 0x1f || rB_addr || b0) { 6775 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 6776 return False; 6777 } 6778 6779 assign( rS, getIReg(rS_addr) ); 6780 6781 switch (opc2) { 6782 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 6783 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 6784 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 6785 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 6786 assign( iTot2, binop(Iop_Add32, 6787 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 6788 mkexpr(iTot1)) ); 6789 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 6790 assign( iTot3, binop(Iop_Add32, 6791 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 6792 mkexpr(iTot2)) ); 6793 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 6794 assign( iTot4, binop(Iop_Add32, 6795 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 6796 mkexpr(iTot3)) ); 6797 if (mode64) { 6798 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 6799 assign( iTot5, binop(Iop_Add32, 6800 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 6801 mkexpr(iTot4)) ); 6802 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 6803 assign( iTot6, binop(Iop_Add32, 6804 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 6805 mkexpr(iTot5)) ); 6806 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 6807 assign( iTot7, binop(Iop_Add32, 6808 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 6809 mkexpr(iTot6)) ); 6810 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 6811 assign( iTot8, binop(Iop_Add32, 6812 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 6813 mkexpr(iTot7)) ); 6814 assign( rA, unop(Iop_32Uto64, 6815 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 6816 } else 6817 assign( rA, mkexpr(iTot4) ); 6818 6819 break; 6820 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 6821 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 6822 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 6823 assign( iTot2, binop(Iop_Add32, 6824 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 6825 mkexpr(iTot1)) ); 6826 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 6827 assign( iTot3, binop(Iop_Add32, 6828 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 6829 mkexpr(iTot2)) ); 6830 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 6831 assign( iTot4, binop(Iop_Add32, 6832 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 6833 mkexpr(iTot3)) ); 6834 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 6835 6836 if (mode64) { 6837 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 6838 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 6839 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 6840 assign( iTot6, binop(Iop_Add32, 6841 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 6842 mkexpr(iTot5)) ); 6843 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 6844 assign( iTot7, binop(Iop_Add32, 6845 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 6846 mkexpr(iTot6)) ); 6847 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 6848 assign( iTot8, binop(Iop_Add32, 6849 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 6850 mkexpr(iTot7)) ); 6851 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 6852 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 6853 } else 6854 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 6855 break; 6856 default: 6857 vex_printf("dis_int_parity(ppc)(opc2)\n"); 6858 return False; 6859 } 6860 6861 putIReg( rA_addr, mkexpr(rA) ); 6862 6863 return True; 6864 } 6865 6866 6867 /* 6868 Integer Rotate Instructions 6869 */ 6870 static Bool dis_int_rot ( UInt theInstr ) 6871 { 6872 /* M-Form, MDS-Form */ 6873 UChar opc1 = ifieldOPC(theInstr); 6874 UChar rS_addr = ifieldRegDS(theInstr); 6875 UChar rA_addr = ifieldRegA(theInstr); 6876 UChar rB_addr = ifieldRegB(theInstr); 6877 UChar sh_imm = rB_addr; 6878 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 6879 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 6880 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 6881 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 6882 UChar b1 = ifieldBIT1(theInstr); 6883 UChar flag_rC = ifieldBIT0(theInstr); 6884 6885 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6886 IRTemp rS = newTemp(ty); 6887 IRTemp rA = newTemp(ty); 6888 IRTemp rB = newTemp(ty); 6889 IRTemp rot = newTemp(ty); 6890 IRExpr *r; 6891 UInt mask32; 6892 ULong mask64; 6893 6894 assign( rS, getIReg(rS_addr) ); 6895 assign( rB, getIReg(rB_addr) ); 6896 6897 switch (opc1) { 6898 case 0x14: { 6899 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 6900 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6901 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6902 if (mode64) { 6903 // tmp32 = (ROTL(rS_Lo32, Imm) 6904 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 6905 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6906 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 6907 r = unop(Iop_32Uto64, r); 6908 assign( rot, binop(Iop_Or64, r, 6909 binop(Iop_Shl64, r, mkU8(32))) ); 6910 assign( rA, 6911 binop(Iop_Or64, 6912 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 6913 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 6914 } 6915 else { 6916 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 6917 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6918 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 6919 assign( rA, 6920 binop(Iop_Or32, 6921 binop(Iop_And32, mkU32(mask32), r), 6922 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 6923 } 6924 break; 6925 } 6926 6927 case 0x15: { 6928 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 6929 vassert(MaskBeg < 32); 6930 vassert(MaskEnd < 32); 6931 vassert(sh_imm < 32); 6932 6933 if (mode64) { 6934 IRTemp rTmp = newTemp(Ity_I64); 6935 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6936 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6937 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6938 // tmp32 = (ROTL(rS_Lo32, Imm) 6939 // rA = ((tmp32 || tmp32) & mask64) 6940 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 6941 r = unop(Iop_32Uto64, r); 6942 assign( rTmp, r ); 6943 r = NULL; 6944 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 6945 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 6946 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 6947 } 6948 else { 6949 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 6950 /* Special-case the ,n,0,31-n form as that is just n-bit 6951 shift left, PPC32 p501 */ 6952 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6953 rA_addr, rS_addr, sh_imm); 6954 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 6955 } 6956 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 6957 /* Special-case the ,32-n,n,31 form as that is just n-bit 6958 unsigned shift right, PPC32 p501 */ 6959 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6960 rA_addr, rS_addr, MaskBeg); 6961 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 6962 } 6963 else { 6964 /* General case. */ 6965 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6966 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6967 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6968 // rA = ROTL(rS, Imm) & mask 6969 assign( rA, binop(Iop_And32, 6970 ROTL(mkexpr(rS), mkU8(sh_imm)), 6971 mkU32(mask32)) ); 6972 } 6973 } 6974 break; 6975 } 6976 6977 case 0x17: { 6978 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 6979 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 6980 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 6981 if (mode64) { 6982 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6983 /* weird insn alert! 6984 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 6985 rA = ((tmp32 || tmp32) & mask64) 6986 */ 6987 // note, ROTL does the masking, so we don't do it here 6988 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 6989 unop(Iop_64to8, mkexpr(rB)) ); 6990 r = unop(Iop_32Uto64, r); 6991 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 6992 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 6993 } else { 6994 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6995 // rA = ROTL(rS, rB[0-4]) & mask 6996 // note, ROTL does the masking, so we don't do it here 6997 assign( rA, binop(Iop_And32, 6998 ROTL(mkexpr(rS), 6999 unop(Iop_32to8, mkexpr(rB))), 7000 mkU32(mask32)) ); 7001 } 7002 break; 7003 } 7004 7005 /* 64bit Integer Rotates */ 7006 case 0x1E: { 7007 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 7008 sh_imm |= b1 << 5; 7009 7010 vassert( msk_imm < 64 ); 7011 vassert( sh_imm < 64 ); 7012 7013 switch (opc2) { 7014 case 0x4: { 7015 /* r = ROTL64( rS, rB_lo6) */ 7016 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 7017 7018 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 7019 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 7020 rA_addr, rS_addr, rB_addr, msk_imm); 7021 // note, ROTL does the masking, so we don't do it here 7022 mask64 = MASK64(0, 63-msk_imm); 7023 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7024 break; 7025 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 7026 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 7027 rA_addr, rS_addr, rB_addr, msk_imm); 7028 mask64 = MASK64(63-msk_imm, 63); 7029 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7030 break; 7031 } 7032 break; 7033 } 7034 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 7035 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7036 rA_addr, rS_addr, sh_imm, msk_imm); 7037 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7038 mask64 = MASK64(sh_imm, 63-msk_imm); 7039 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7040 break; 7041 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 7042 /* 7043 Hmm... looks like this'll do the job more simply: 7044 r = SHL(rS, sh_imm) 7045 m = ~(1 << (63-msk_imm)) 7046 assign(rA, r & m); 7047 */ 7048 7049 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 7050 if (mode64 7051 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 7052 /* special-case the ,64-n,n form as that is just 7053 unsigned shift-right by n */ 7054 DIP("srdi%s r%u,r%u,%u\n", 7055 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 7056 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 7057 } else { 7058 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7059 rA_addr, rS_addr, sh_imm, msk_imm); 7060 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7061 mask64 = MASK64(0, 63-msk_imm); 7062 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7063 } 7064 break; 7065 7066 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 7067 if (mode64 7068 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 7069 /* special-case the ,n,63-n form as that is just 7070 shift-left by n */ 7071 DIP("sldi%s r%u,r%u,%u\n", 7072 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 7073 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 7074 } else { 7075 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7076 rA_addr, rS_addr, sh_imm, msk_imm); 7077 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7078 mask64 = MASK64(63-msk_imm, 63); 7079 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7080 } 7081 break; 7082 7083 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 7084 IRTemp rA_orig = newTemp(ty); 7085 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7086 rA_addr, rS_addr, sh_imm, msk_imm); 7087 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7088 mask64 = MASK64(sh_imm, 63-msk_imm); 7089 assign( rA_orig, getIReg(rA_addr) ); 7090 assign( rA, binop(Iop_Or64, 7091 binop(Iop_And64, mkU64(mask64), r), 7092 binop(Iop_And64, mkU64(~mask64), 7093 mkexpr(rA_orig))) ); 7094 break; 7095 } 7096 default: 7097 vex_printf("dis_int_rot(ppc)(opc2)\n"); 7098 return False; 7099 } 7100 break; 7101 } 7102 7103 default: 7104 vex_printf("dis_int_rot(ppc)(opc1)\n"); 7105 return False; 7106 } 7107 7108 putIReg( rA_addr, mkexpr(rA) ); 7109 7110 if (flag_rC) { 7111 set_CR0( mkexpr(rA) ); 7112 } 7113 return True; 7114 } 7115 7116 7117 /* 7118 Integer Load Instructions 7119 */ 7120 static Bool dis_int_load ( UInt theInstr ) 7121 { 7122 /* D-Form, X-Form, DS-Form */ 7123 UChar opc1 = ifieldOPC(theInstr); 7124 UChar rD_addr = ifieldRegDS(theInstr); 7125 UChar rA_addr = ifieldRegA(theInstr); 7126 UInt uimm16 = ifieldUIMM16(theInstr); 7127 UChar rB_addr = ifieldRegB(theInstr); 7128 UInt opc2 = ifieldOPClo10(theInstr); 7129 UChar b1 = ifieldBIT1(theInstr); 7130 UChar b0 = ifieldBIT0(theInstr); 7131 7132 Int simm16 = extend_s_16to32(uimm16); 7133 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7134 IRTemp EA = newTemp(ty); 7135 IRExpr* val; 7136 7137 switch (opc1) { 7138 case 0x1F: // register offset 7139 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7140 break; 7141 case 0x38: // immediate offset: 64bit: lq: maskoff 7142 // lowest 4 bits of immediate before forming EA 7143 simm16 = simm16 & 0xFFFFFFF0; 7144 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7145 break; 7146 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 7147 // lowest 2 bits of immediate before forming EA 7148 simm16 = simm16 & 0xFFFFFFFC; 7149 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7150 break; 7151 default: // immediate offset 7152 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7153 break; 7154 } 7155 7156 switch (opc1) { 7157 case 0x22: // lbz (Load B & Zero, PPC32 p433) 7158 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7159 val = load(Ity_I8, mkexpr(EA)); 7160 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7161 break; 7162 7163 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 7164 if (rA_addr == 0 || rA_addr == rD_addr) { 7165 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 7166 return False; 7167 } 7168 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7169 val = load(Ity_I8, mkexpr(EA)); 7170 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7171 putIReg( rA_addr, mkexpr(EA) ); 7172 break; 7173 7174 case 0x2A: // lha (Load HW Alg, PPC32 p445) 7175 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7176 val = load(Ity_I16, mkexpr(EA)); 7177 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7178 break; 7179 7180 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 7181 if (rA_addr == 0 || rA_addr == rD_addr) { 7182 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 7183 return False; 7184 } 7185 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7186 val = load(Ity_I16, mkexpr(EA)); 7187 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7188 putIReg( rA_addr, mkexpr(EA) ); 7189 break; 7190 7191 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 7192 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7193 val = load(Ity_I16, mkexpr(EA)); 7194 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7195 break; 7196 7197 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 7198 if (rA_addr == 0 || rA_addr == rD_addr) { 7199 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 7200 return False; 7201 } 7202 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7203 val = load(Ity_I16, mkexpr(EA)); 7204 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7205 putIReg( rA_addr, mkexpr(EA) ); 7206 break; 7207 7208 case 0x20: // lwz (Load W & Zero, PPC32 p460) 7209 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7210 val = load(Ity_I32, mkexpr(EA)); 7211 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7212 break; 7213 7214 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 7215 if (rA_addr == 0 || rA_addr == rD_addr) { 7216 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 7217 return False; 7218 } 7219 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7220 val = load(Ity_I32, mkexpr(EA)); 7221 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7222 putIReg( rA_addr, mkexpr(EA) ); 7223 break; 7224 7225 /* X Form */ 7226 case 0x1F: 7227 if (b0 != 0) { 7228 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 7229 return False; 7230 } 7231 7232 switch (opc2) { 7233 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 7234 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7235 if (rA_addr == 0 || rA_addr == rD_addr) { 7236 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 7237 return False; 7238 } 7239 val = load(Ity_I8, mkexpr(EA)); 7240 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7241 putIReg( rA_addr, mkexpr(EA) ); 7242 break; 7243 7244 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 7245 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7246 val = load(Ity_I8, mkexpr(EA)); 7247 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7248 break; 7249 7250 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 7251 if (rA_addr == 0 || rA_addr == rD_addr) { 7252 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 7253 return False; 7254 } 7255 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7256 val = load(Ity_I16, mkexpr(EA)); 7257 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7258 putIReg( rA_addr, mkexpr(EA) ); 7259 break; 7260 7261 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 7262 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7263 val = load(Ity_I16, mkexpr(EA)); 7264 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7265 break; 7266 7267 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 7268 if (rA_addr == 0 || rA_addr == rD_addr) { 7269 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 7270 return False; 7271 } 7272 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7273 val = load(Ity_I16, mkexpr(EA)); 7274 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7275 putIReg( rA_addr, mkexpr(EA) ); 7276 break; 7277 7278 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 7279 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7280 val = load(Ity_I16, mkexpr(EA)); 7281 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7282 break; 7283 7284 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 7285 if (rA_addr == 0 || rA_addr == rD_addr) { 7286 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 7287 return False; 7288 } 7289 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7290 val = load(Ity_I32, mkexpr(EA)); 7291 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7292 putIReg( rA_addr, mkexpr(EA) ); 7293 break; 7294 7295 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 7296 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7297 val = load(Ity_I32, mkexpr(EA)); 7298 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7299 break; 7300 7301 7302 /* 64bit Loads */ 7303 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 7304 if (rA_addr == 0 || rA_addr == rD_addr) { 7305 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 7306 return False; 7307 } 7308 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7309 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7310 putIReg( rA_addr, mkexpr(EA) ); 7311 break; 7312 7313 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 7314 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7315 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7316 break; 7317 7318 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 7319 if (rA_addr == 0 || rA_addr == rD_addr) { 7320 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 7321 return False; 7322 } 7323 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7324 putIReg( rD_addr, 7325 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7326 putIReg( rA_addr, mkexpr(EA) ); 7327 break; 7328 7329 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 7330 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7331 putIReg( rD_addr, 7332 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7333 break; 7334 7335 default: 7336 vex_printf("dis_int_load(ppc)(opc2)\n"); 7337 return False; 7338 } 7339 break; 7340 7341 /* DS Form - 64bit Loads. In each case EA will have been formed 7342 with the lowest 2 bits masked off the immediate offset. */ 7343 case 0x3A: 7344 switch ((b1<<1) | b0) { 7345 case 0x0: // ld (Load DWord, PPC64 p472) 7346 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7347 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7348 break; 7349 7350 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 7351 if (rA_addr == 0 || rA_addr == rD_addr) { 7352 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 7353 return False; 7354 } 7355 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7356 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7357 putIReg( rA_addr, mkexpr(EA) ); 7358 break; 7359 7360 case 0x2: // lwa (Load Word Alg, PPC64 p499) 7361 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7362 putIReg( rD_addr, 7363 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7364 break; 7365 7366 default: 7367 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 7368 return False; 7369 } 7370 break; 7371 7372 case 0x38: { 7373 IRTemp high = newTemp(ty); 7374 IRTemp low = newTemp(ty); 7375 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 7376 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7377 /* NOTE: there are some changes to XER[41:42] that have not been 7378 * implemented. 7379 */ 7380 // trap if EA misaligned on 16 byte address 7381 if (mode64) { 7382 if (host_endness == VexEndnessBE) { 7383 assign(high, load(ty, mkexpr( EA ) ) ); 7384 assign(low, load(ty, binop( Iop_Add64, 7385 mkexpr( EA ), 7386 mkU64( 8 ) ) ) ); 7387 } else { 7388 assign(low, load(ty, mkexpr( EA ) ) ); 7389 assign(high, load(ty, binop( Iop_Add64, 7390 mkexpr( EA ), 7391 mkU64( 8 ) ) ) ); 7392 } 7393 } else { 7394 assign(high, load(ty, binop( Iop_Add32, 7395 mkexpr( EA ), 7396 mkU32( 4 ) ) ) ); 7397 assign(low, load(ty, binop( Iop_Add32, 7398 mkexpr( EA ), 7399 mkU32( 12 ) ) ) ); 7400 } 7401 gen_SIGBUS_if_misaligned( EA, 16 ); 7402 putIReg( rD_addr, mkexpr( high) ); 7403 putIReg( rD_addr+1, mkexpr( low) ); 7404 break; 7405 } 7406 default: 7407 vex_printf("dis_int_load(ppc)(opc1)\n"); 7408 return False; 7409 } 7410 return True; 7411 } 7412 7413 7414 7415 /* 7416 Integer Store Instructions 7417 */ 7418 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 7419 { 7420 /* D-Form, X-Form, DS-Form */ 7421 UChar opc1 = ifieldOPC(theInstr); 7422 UInt rS_addr = ifieldRegDS(theInstr); 7423 UInt rA_addr = ifieldRegA(theInstr); 7424 UInt uimm16 = ifieldUIMM16(theInstr); 7425 UInt rB_addr = ifieldRegB(theInstr); 7426 UInt opc2 = ifieldOPClo10(theInstr); 7427 UChar b1 = ifieldBIT1(theInstr); 7428 UChar b0 = ifieldBIT0(theInstr); 7429 7430 Int simm16 = extend_s_16to32(uimm16); 7431 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7432 IRTemp rS = newTemp(ty); 7433 IRTemp rB = newTemp(ty); 7434 IRTemp EA = newTemp(ty); 7435 7436 assign( rB, getIReg(rB_addr) ); 7437 assign( rS, getIReg(rS_addr) ); 7438 7439 switch (opc1) { 7440 case 0x1F: // register offset 7441 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7442 break; 7443 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 7444 // lowest 2 bits of immediate before forming EA 7445 simm16 = simm16 & 0xFFFFFFFC; 7446 default: // immediate offset 7447 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7448 break; 7449 } 7450 7451 switch (opc1) { 7452 case 0x26: // stb (Store B, PPC32 p509) 7453 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7454 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7455 break; 7456 7457 case 0x27: // stbu (Store B, Update, PPC32 p510) 7458 if (rA_addr == 0 ) { 7459 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 7460 return False; 7461 } 7462 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7463 putIReg( rA_addr, mkexpr(EA) ); 7464 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7465 break; 7466 7467 case 0x2C: // sth (Store HW, PPC32 p522) 7468 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7469 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7470 break; 7471 7472 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 7473 if (rA_addr == 0) { 7474 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 7475 return False; 7476 } 7477 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7478 putIReg( rA_addr, mkexpr(EA) ); 7479 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7480 break; 7481 7482 case 0x24: // stw (Store W, PPC32 p530) 7483 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7484 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7485 break; 7486 7487 case 0x25: // stwu (Store W, Update, PPC32 p534) 7488 if (rA_addr == 0) { 7489 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 7490 return False; 7491 } 7492 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7493 putIReg( rA_addr, mkexpr(EA) ); 7494 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7495 break; 7496 7497 /* X Form : all these use EA_indexed */ 7498 case 0x1F: 7499 if (b0 != 0) { 7500 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 7501 return False; 7502 } 7503 7504 switch (opc2) { 7505 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 7506 if (rA_addr == 0) { 7507 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 7508 return False; 7509 } 7510 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7511 putIReg( rA_addr, mkexpr(EA) ); 7512 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7513 break; 7514 7515 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 7516 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7517 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7518 break; 7519 7520 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 7521 if (rA_addr == 0) { 7522 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 7523 return False; 7524 } 7525 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7526 putIReg( rA_addr, mkexpr(EA) ); 7527 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7528 break; 7529 7530 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 7531 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7532 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7533 break; 7534 7535 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 7536 if (rA_addr == 0) { 7537 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 7538 return False; 7539 } 7540 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7541 putIReg( rA_addr, mkexpr(EA) ); 7542 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7543 break; 7544 7545 case 0x097: // stwx (Store W Indexed, PPC32 p536) 7546 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7547 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7548 break; 7549 7550 7551 /* 64bit Stores */ 7552 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 7553 if (rA_addr == 0) { 7554 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 7555 return False; 7556 } 7557 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7558 putIReg( rA_addr, mkexpr(EA) ); 7559 store( mkexpr(EA), mkexpr(rS) ); 7560 break; 7561 7562 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 7563 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7564 store( mkexpr(EA), mkexpr(rS) ); 7565 break; 7566 7567 default: 7568 vex_printf("dis_int_store(ppc)(opc2)\n"); 7569 return False; 7570 } 7571 break; 7572 7573 /* DS Form - 64bit Stores. In each case EA will have been formed 7574 with the lowest 2 bits masked off the immediate offset. */ 7575 case 0x3E: 7576 switch ((b1<<1) | b0) { 7577 case 0x0: // std (Store DWord, PPC64 p580) 7578 if (!mode64) 7579 return False; 7580 7581 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7582 store( mkexpr(EA), mkexpr(rS) ); 7583 break; 7584 7585 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 7586 if (!mode64) 7587 return False; 7588 7589 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7590 putIReg( rA_addr, mkexpr(EA) ); 7591 store( mkexpr(EA), mkexpr(rS) ); 7592 break; 7593 7594 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 7595 IRTemp EA_hi = newTemp(ty); 7596 IRTemp EA_lo = newTemp(ty); 7597 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7598 7599 if (mode64) { 7600 if (host_endness == VexEndnessBE) { 7601 7602 /* upper 64-bits */ 7603 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 7604 7605 /* lower 64-bits */ 7606 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 7607 } else { 7608 /* upper 64-bits */ 7609 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 7610 7611 /* lower 64-bits */ 7612 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 7613 } 7614 } else { 7615 /* upper half of upper 64-bits */ 7616 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 7617 7618 /* lower half of upper 64-bits */ 7619 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 7620 } 7621 store( mkexpr(EA_hi), mkexpr(rS) ); 7622 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 7623 break; 7624 } 7625 default: 7626 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 7627 return False; 7628 } 7629 break; 7630 7631 default: 7632 vex_printf("dis_int_store(ppc)(opc1)\n"); 7633 return False; 7634 } 7635 return True; 7636 } 7637 7638 7639 7640 /* 7641 Integer Load/Store Multiple Instructions 7642 */ 7643 static Bool dis_int_ldst_mult ( UInt theInstr ) 7644 { 7645 /* D-Form */ 7646 UChar opc1 = ifieldOPC(theInstr); 7647 UChar rD_addr = ifieldRegDS(theInstr); 7648 UChar rS_addr = rD_addr; 7649 UChar rA_addr = ifieldRegA(theInstr); 7650 UInt uimm16 = ifieldUIMM16(theInstr); 7651 7652 Int simm16 = extend_s_16to32(uimm16); 7653 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7654 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 7655 IRTemp EA = newTemp(ty); 7656 UInt r = 0; 7657 UInt ea_off = 0; 7658 IRExpr* irx_addr; 7659 7660 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7661 7662 switch (opc1) { 7663 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 7664 if (rA_addr >= rD_addr) { 7665 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 7666 return False; 7667 } 7668 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7669 for (r = rD_addr; r <= 31; r++) { 7670 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 7671 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 7672 False) ); 7673 ea_off += 4; 7674 } 7675 break; 7676 7677 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 7678 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7679 for (r = rS_addr; r <= 31; r++) { 7680 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 7681 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 7682 ea_off += 4; 7683 } 7684 break; 7685 7686 default: 7687 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 7688 return False; 7689 } 7690 return True; 7691 } 7692 7693 7694 7695 /* 7696 Integer Load/Store String Instructions 7697 */ 7698 static 7699 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 7700 IRTemp EA, // EA 7701 Int rD, // first dst register 7702 Int maxBytes ) // 32 or 128 7703 { 7704 Int i, shift = 24; 7705 IRExpr* e_nbytes = mkexpr(tNBytes); 7706 IRExpr* e_EA = mkexpr(EA); 7707 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7708 7709 vassert(rD >= 0 && rD < 32); 7710 rD--; if (rD < 0) rD = 31; 7711 7712 for (i = 0; i < maxBytes; i++) { 7713 /* if (nBytes < (i+1)) goto NIA; */ 7714 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 7715 Ijk_Boring, 7716 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 7717 /* when crossing into a new dest register, set it to zero. */ 7718 if ((i % 4) == 0) { 7719 rD++; if (rD == 32) rD = 0; 7720 putIReg(rD, mkSzImm(ty, 0)); 7721 shift = 24; 7722 } 7723 /* rD |= (8Uto32(*(EA+i))) << shift */ 7724 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 7725 putIReg( 7726 rD, 7727 mkWidenFrom32( 7728 ty, 7729 binop( 7730 Iop_Or32, 7731 mkNarrowTo32(ty, getIReg(rD)), 7732 binop( 7733 Iop_Shl32, 7734 unop( 7735 Iop_8Uto32, 7736 load( Ity_I8, 7737 binop( mkSzOp(ty,Iop_Add8), 7738 e_EA, mkSzImm(ty,i))) 7739 ), 7740 mkU8(toUChar(shift)) 7741 ) 7742 ), 7743 /*Signed*/False 7744 ) 7745 ); 7746 shift -= 8; 7747 } 7748 } 7749 7750 static 7751 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 7752 IRTemp EA, // EA 7753 Int rS, // first src register 7754 Int maxBytes ) // 32 or 128 7755 { 7756 Int i, shift = 24; 7757 IRExpr* e_nbytes = mkexpr(tNBytes); 7758 IRExpr* e_EA = mkexpr(EA); 7759 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7760 7761 vassert(rS >= 0 && rS < 32); 7762 rS--; if (rS < 0) rS = 31; 7763 7764 for (i = 0; i < maxBytes; i++) { 7765 /* if (nBytes < (i+1)) goto NIA; */ 7766 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 7767 Ijk_Boring, 7768 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 7769 /* check for crossing into a new src register. */ 7770 if ((i % 4) == 0) { 7771 rS++; if (rS == 32) rS = 0; 7772 shift = 24; 7773 } 7774 /* *(EA+i) = 32to8(rS >> shift) */ 7775 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 7776 store( 7777 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 7778 unop( Iop_32to8, 7779 binop( Iop_Shr32, 7780 mkNarrowTo32( ty, getIReg(rS) ), 7781 mkU8( toUChar(shift) ))) 7782 ); 7783 shift -= 8; 7784 } 7785 } 7786 7787 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 7788 { 7789 /* X-Form */ 7790 UChar opc1 = ifieldOPC(theInstr); 7791 UChar rD_addr = ifieldRegDS(theInstr); 7792 UChar rS_addr = rD_addr; 7793 UChar rA_addr = ifieldRegA(theInstr); 7794 UChar rB_addr = ifieldRegB(theInstr); 7795 UChar NumBytes = rB_addr; 7796 UInt opc2 = ifieldOPClo10(theInstr); 7797 UChar b0 = ifieldBIT0(theInstr); 7798 7799 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7800 IRTemp t_EA = newTemp(ty); 7801 IRTemp t_nbytes = IRTemp_INVALID; 7802 7803 *stopHere = False; 7804 7805 if (opc1 != 0x1F || b0 != 0) { 7806 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 7807 return False; 7808 } 7809 7810 switch (opc2) { 7811 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 7812 /* NB: does not reject the case where RA is in the range of 7813 registers to be loaded. It should. */ 7814 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 7815 assign( t_EA, ea_rAor0(rA_addr) ); 7816 if (NumBytes == 8 && !mode64) { 7817 /* Special case hack */ 7818 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 7819 putIReg( rD_addr, 7820 load(Ity_I32, mkexpr(t_EA)) ); 7821 putIReg( (rD_addr+1) % 32, 7822 load(Ity_I32, 7823 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 7824 } else { 7825 t_nbytes = newTemp(Ity_I32); 7826 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 7827 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 7828 *stopHere = True; 7829 } 7830 return True; 7831 7832 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 7833 /* NB: does not reject the case where RA is in the range of 7834 registers to be loaded. It should. Although considering 7835 that that can only be detected at run time, it's not easy to 7836 do so. */ 7837 if (rD_addr == rA_addr || rD_addr == rB_addr) 7838 return False; 7839 if (rD_addr == 0 && rA_addr == 0) 7840 return False; 7841 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7842 t_nbytes = newTemp(Ity_I32); 7843 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 7844 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 7845 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 7846 *stopHere = True; 7847 return True; 7848 7849 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 7850 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 7851 assign( t_EA, ea_rAor0(rA_addr) ); 7852 if (NumBytes == 8 && !mode64) { 7853 /* Special case hack */ 7854 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 7855 store( mkexpr(t_EA), 7856 getIReg(rD_addr) ); 7857 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 7858 getIReg((rD_addr+1) % 32) ); 7859 } else { 7860 t_nbytes = newTemp(Ity_I32); 7861 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 7862 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 7863 *stopHere = True; 7864 } 7865 return True; 7866 7867 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 7868 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7869 t_nbytes = newTemp(Ity_I32); 7870 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 7871 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 7872 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 7873 *stopHere = True; 7874 return True; 7875 7876 default: 7877 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 7878 return False; 7879 } 7880 return True; 7881 } 7882 7883 7884 /* ------------------------------------------------------------------ 7885 Integer Branch Instructions 7886 ------------------------------------------------------------------ */ 7887 7888 /* 7889 Branch helper function 7890 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 7891 Returns an I32 which is 0x00000000 if the ctr condition failed 7892 and 0xFFFFFFFF otherwise. 7893 */ 7894 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 7895 { 7896 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7897 IRTemp ok = newTemp(Ity_I32); 7898 7899 if ((BO >> 2) & 1) { // independent of ctr 7900 assign( ok, mkU32(0xFFFFFFFF) ); 7901 } else { 7902 if ((BO >> 1) & 1) { // ctr == 0 ? 7903 assign( ok, unop( Iop_1Sto32, 7904 binop( mkSzOp(ty, Iop_CmpEQ8), 7905 getGST( PPC_GST_CTR ), 7906 mkSzImm(ty,0))) ); 7907 } else { // ctr != 0 ? 7908 assign( ok, unop( Iop_1Sto32, 7909 binop( mkSzOp(ty, Iop_CmpNE8), 7910 getGST( PPC_GST_CTR ), 7911 mkSzImm(ty,0))) ); 7912 } 7913 } 7914 return mkexpr(ok); 7915 } 7916 7917 7918 /* 7919 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 7920 Returns an I32 which is either 0 if the condition failed or 7921 some arbitrary nonzero value otherwise. */ 7922 7923 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 7924 { 7925 Int where; 7926 IRTemp res = newTemp(Ity_I32); 7927 IRTemp cr_bi = newTemp(Ity_I32); 7928 7929 if ((BO >> 4) & 1) { 7930 assign( res, mkU32(1) ); 7931 } else { 7932 // ok = (CR[BI] == BO[3]) Note, the following relies on 7933 // getCRbit_anywhere returning a value which 7934 // is either zero or has exactly 1 bit set. 7935 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 7936 7937 if ((BO >> 3) & 1) { 7938 /* We can use cr_bi as-is. */ 7939 assign( res, mkexpr(cr_bi) ); 7940 } else { 7941 /* We have to invert the sense of the information held in 7942 cr_bi. For that we need to know which bit 7943 getCRbit_anywhere regards as significant. */ 7944 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 7945 mkU32(1<<where)) ); 7946 } 7947 } 7948 return mkexpr(res); 7949 } 7950 7951 7952 /* 7953 Integer Branch Instructions 7954 */ 7955 static Bool dis_branch ( UInt theInstr, 7956 const VexAbiInfo* vbi, 7957 /*OUT*/DisResult* dres, 7958 Bool (*resteerOkFn)(void*,Addr), 7959 void* callback_opaque ) 7960 { 7961 UChar opc1 = ifieldOPC(theInstr); 7962 UChar BO = ifieldRegDS(theInstr); 7963 UChar BI = ifieldRegA(theInstr); 7964 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 7965 UChar b11to15 = ifieldRegB(theInstr); 7966 UInt opc2 = ifieldOPClo10(theInstr); 7967 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 7968 UChar flag_AA = ifieldBIT1(theInstr); 7969 UChar flag_LK = ifieldBIT0(theInstr); 7970 7971 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7972 Addr64 tgt = 0; 7973 UInt BD = extend_s_16to32(BD_u16); 7974 IRTemp do_branch = newTemp(Ity_I32); 7975 IRTemp ctr_ok = newTemp(Ity_I32); 7976 IRTemp cond_ok = newTemp(Ity_I32); 7977 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 7978 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 7979 IRTemp lr_old = newTemp(ty); 7980 7981 /* Hack to pass through code that just wants to read the PC */ 7982 if (theInstr == 0x429F0005) { 7983 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 7984 putGST( PPC_GST_LR, e_nia ); 7985 return True; 7986 } 7987 7988 /* The default what-next. Individual cases can override it. */ 7989 dres->whatNext = Dis_StopHere; 7990 vassert(dres->jk_StopHere == Ijk_INVALID); 7991 7992 switch (opc1) { 7993 case 0x12: // b (Branch, PPC32 p360) 7994 if (flag_AA) { 7995 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 7996 } else { 7997 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 7998 (Long)extend_s_26to64(LI_u26) ); 7999 } 8000 if (mode64) { 8001 DIP("b%s%s 0x%llx\n", 8002 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 8003 } else { 8004 DIP("b%s%s 0x%x\n", 8005 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 8006 } 8007 8008 if (flag_LK) { 8009 putGST( PPC_GST_LR, e_nia ); 8010 if (vbi->guest_ppc_zap_RZ_at_bl 8011 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 8012 IRTemp t_tgt = newTemp(ty); 8013 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 8014 make_redzone_AbiHint( vbi, t_tgt, 8015 "branch-and-link (unconditional call)" ); 8016 } 8017 } 8018 8019 if (resteerOkFn( callback_opaque, tgt )) { 8020 dres->whatNext = Dis_ResteerU; 8021 dres->continueAt = tgt; 8022 } else { 8023 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 8024 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 8025 } 8026 break; 8027 8028 case 0x10: // bc (Branch Conditional, PPC32 p361) 8029 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 8030 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 8031 8032 if (!(BO & 0x4)) { 8033 putGST( PPC_GST_CTR, 8034 binop(mkSzOp(ty, Iop_Sub8), 8035 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 8036 } 8037 8038 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 8039 cond_ok is either zero or nonzero, since that's the cheapest 8040 way to compute it. Anding them together gives a value which 8041 is either zero or non zero and so that's what we must test 8042 for in the IRStmt_Exit. */ 8043 assign( ctr_ok, branch_ctr_ok( BO ) ); 8044 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8045 assign( do_branch, 8046 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 8047 8048 if (flag_AA) { 8049 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 8050 } else { 8051 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 8052 (Long)extend_s_16to64(BD_u16)); 8053 } 8054 if (flag_LK) 8055 putGST( PPC_GST_LR, e_nia ); 8056 8057 stmt( IRStmt_Exit( 8058 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 8059 flag_LK ? Ijk_Call : Ijk_Boring, 8060 mkSzConst(ty, tgt), OFFB_CIA ) ); 8061 8062 dres->jk_StopHere = Ijk_Boring; 8063 putGST( PPC_GST_CIA, e_nia ); 8064 break; 8065 8066 case 0x13: 8067 /* For bclr and bcctr, it appears that the lowest two bits of 8068 b11to15 are a branch hint, and so we only need to ensure it's 8069 of the form 000XX. */ 8070 if ((b11to15 & ~3) != 0) { 8071 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15); 8072 return False; 8073 } 8074 8075 switch (opc2) { 8076 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 8077 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 8078 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 8079 return False; 8080 } 8081 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 8082 8083 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8084 8085 /* FIXME: this is confusing. lr_old holds the old value 8086 of ctr, not lr :-) */ 8087 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 8088 8089 if (flag_LK) 8090 putGST( PPC_GST_LR, e_nia ); 8091 8092 stmt( IRStmt_Exit( 8093 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 8094 Ijk_Boring, 8095 c_nia, OFFB_CIA )); 8096 8097 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 8098 make_redzone_AbiHint( vbi, lr_old, 8099 "b-ctr-l (indirect call)" ); 8100 } 8101 8102 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 8103 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 8104 break; 8105 8106 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 8107 Bool vanilla_return = False; 8108 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 8109 DIP("blr\n"); 8110 vanilla_return = True; 8111 } else { 8112 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 8113 } 8114 8115 if (!(BO & 0x4)) { 8116 putGST( PPC_GST_CTR, 8117 binop(mkSzOp(ty, Iop_Sub8), 8118 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 8119 } 8120 8121 /* See comments above for 'bc' about this */ 8122 assign( ctr_ok, branch_ctr_ok( BO ) ); 8123 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8124 assign( do_branch, 8125 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 8126 8127 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 8128 8129 if (flag_LK) 8130 putGST( PPC_GST_LR, e_nia ); 8131 8132 stmt( IRStmt_Exit( 8133 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 8134 Ijk_Boring, 8135 c_nia, OFFB_CIA )); 8136 8137 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 8138 make_redzone_AbiHint( vbi, lr_old, 8139 "branch-to-lr (unconditional return)" ); 8140 } 8141 8142 /* blrl is pretty strange; it's like a return that sets the 8143 return address of its caller to the insn following this 8144 one. Mark it as a return. */ 8145 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 8146 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 8147 break; 8148 } 8149 default: 8150 vex_printf("dis_int_branch(ppc)(opc2)\n"); 8151 return False; 8152 } 8153 break; 8154 8155 default: 8156 vex_printf("dis_int_branch(ppc)(opc1)\n"); 8157 return False; 8158 } 8159 8160 return True; 8161 } 8162 8163 /* 8164 * PC relative instruction 8165 */ 8166 static Bool dis_pc_relative ( UInt theInstr ) 8167 { 8168 /* DX-Form */ 8169 UChar opc1 = ifieldOPC(theInstr); 8170 unsigned long long D; 8171 UInt d0 = IFIELD(theInstr, 6, 10); 8172 UInt d1 = IFIELD(theInstr, 16, 5); 8173 UInt d2 = IFIELD(theInstr, 0, 1); 8174 UChar rT_addr = ifieldRegDS(theInstr); 8175 UInt opc2 = ifieldOPClo5(theInstr); 8176 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8177 8178 if ( opc1 != 0x13) { 8179 vex_printf("dis_pc_relative(ppc)(opc1)\n"); 8180 return False; 8181 } 8182 8183 switch (opc2) { 8184 case 0x002: // addpcis (Add PC immediate Shifted DX-form) 8185 { 8186 IRExpr* nia = mkSzImm(ty, nextInsnAddr()); 8187 IRExpr* result; 8188 8189 D = (d0 << 6) | (d1 << 1) | d2; 8190 DIP("addpcis %u,%llu\n", rT_addr, D); 8191 8192 if ( (D & 0x8000) == 0x8000 ) 8193 D = 0xFFFFFFFFFFFF0000UL | D; // sign extend 8194 8195 if ( ty == Ity_I32 ) { 8196 result = binop( Iop_Add32, nia, mkU32( D << 16 ) ); 8197 } else { 8198 vassert( ty == Ity_I64 ); 8199 result = binop( Iop_Add64, nia, mkU64( D << 16 ) ); 8200 } 8201 8202 putIReg( rT_addr, result); 8203 } 8204 break; 8205 8206 default: 8207 vex_printf("dis_pc_relative(ppc)(opc2)\n"); 8208 return False; 8209 } 8210 8211 return True; 8212 } 8213 8214 /* 8215 Condition Register Logical Instructions 8216 */ 8217 static Bool dis_cond_logic ( UInt theInstr ) 8218 { 8219 /* XL-Form */ 8220 UChar opc1 = ifieldOPC(theInstr); 8221 UChar crbD_addr = ifieldRegDS(theInstr); 8222 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 8223 UChar crbA_addr = ifieldRegA(theInstr); 8224 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 8225 UChar crbB_addr = ifieldRegB(theInstr); 8226 UInt opc2 = ifieldOPClo10(theInstr); 8227 UChar b0 = ifieldBIT0(theInstr); 8228 8229 IRTemp crbD = newTemp(Ity_I32); 8230 IRTemp crbA = newTemp(Ity_I32); 8231 IRTemp crbB = newTemp(Ity_I32); 8232 8233 if (opc1 != 19 || b0 != 0) { 8234 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 8235 return False; 8236 } 8237 8238 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 8239 if (((crbD_addr & 0x3) != 0) || 8240 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 8241 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 8242 return False; 8243 } 8244 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 8245 putCR0( crfD_addr, getCR0( crfS_addr) ); 8246 putCR321( crfD_addr, getCR321(crfS_addr) ); 8247 } else { 8248 assign( crbA, getCRbit(crbA_addr) ); 8249 if (crbA_addr == crbB_addr) 8250 crbB = crbA; 8251 else 8252 assign( crbB, getCRbit(crbB_addr) ); 8253 8254 switch (opc2) { 8255 case 0x101: // crand (Cond Reg AND, PPC32 p372) 8256 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8257 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 8258 break; 8259 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 8260 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8261 assign( crbD, binop(Iop_And32, 8262 mkexpr(crbA), 8263 unop(Iop_Not32, mkexpr(crbB))) ); 8264 break; 8265 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 8266 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8267 assign( crbD, unop(Iop_Not32, 8268 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 8269 break; 8270 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 8271 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8272 assign( crbD, unop(Iop_Not32, 8273 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 8274 break; 8275 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 8276 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8277 assign( crbD, unop(Iop_Not32, 8278 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 8279 break; 8280 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 8281 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8282 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 8283 break; 8284 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 8285 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8286 assign( crbD, binop(Iop_Or32, 8287 mkexpr(crbA), 8288 unop(Iop_Not32, mkexpr(crbB))) ); 8289 break; 8290 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 8291 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8292 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 8293 break; 8294 default: 8295 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 8296 return False; 8297 } 8298 8299 putCRbit( crbD_addr, mkexpr(crbD) ); 8300 } 8301 return True; 8302 } 8303 8304 8305 /* 8306 Trap instructions 8307 */ 8308 8309 /* Do the code generation for a trap. Returned Bool is true iff 8310 this is an unconditional trap. If the two arg IRExpr*s are 8311 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 8312 then they are 64-bit, and we must be disassembling 64-bit 8313 instructions. */ 8314 static Bool do_trap ( UChar TO, 8315 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 8316 { 8317 IRTemp argL, argR; 8318 IRExpr *argLe, *argRe, *cond, *tmp; 8319 8320 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 8321 8322 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 8323 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 8324 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 8325 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 8326 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 8327 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 8328 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 8329 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 8330 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 8331 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 8332 8333 const UChar b11100 = 0x1C; 8334 const UChar b00111 = 0x07; 8335 8336 if (is32bit) { 8337 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 8338 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 8339 } else { 8340 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 8341 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 8342 vassert( mode64 ); 8343 } 8344 8345 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 8346 /* Unconditional trap. Just do the exit without 8347 testing the arguments. */ 8348 stmt( IRStmt_Exit( 8349 binop(opCMPEQ, const0, const0), 8350 Ijk_SigTRAP, 8351 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 8352 OFFB_CIA 8353 )); 8354 return True; /* unconditional trap */ 8355 } 8356 8357 if (is32bit) { 8358 argL = newTemp(Ity_I32); 8359 argR = newTemp(Ity_I32); 8360 } else { 8361 argL = newTemp(Ity_I64); 8362 argR = newTemp(Ity_I64); 8363 } 8364 8365 assign( argL, argL0 ); 8366 assign( argR, argR0 ); 8367 8368 argLe = mkexpr(argL); 8369 argRe = mkexpr(argR); 8370 8371 cond = const0; 8372 if (TO & 16) { // L <s R 8373 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 8374 cond = binop(opOR, tmp, cond); 8375 } 8376 if (TO & 8) { // L >s R 8377 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 8378 cond = binop(opOR, tmp, cond); 8379 } 8380 if (TO & 4) { // L == R 8381 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 8382 cond = binop(opOR, tmp, cond); 8383 } 8384 if (TO & 2) { // L <u R 8385 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 8386 cond = binop(opOR, tmp, cond); 8387 } 8388 if (TO & 1) { // L >u R 8389 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 8390 cond = binop(opOR, tmp, cond); 8391 } 8392 stmt( IRStmt_Exit( 8393 binop(opCMPNE, cond, const0), 8394 Ijk_SigTRAP, 8395 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 8396 OFFB_CIA 8397 )); 8398 return False; /* not an unconditional trap */ 8399 } 8400 8401 static Bool dis_trapi ( UInt theInstr, 8402 /*OUT*/DisResult* dres ) 8403 { 8404 /* D-Form */ 8405 UChar opc1 = ifieldOPC(theInstr); 8406 UChar TO = ifieldRegDS(theInstr); 8407 UChar rA_addr = ifieldRegA(theInstr); 8408 UInt uimm16 = ifieldUIMM16(theInstr); 8409 ULong simm16 = extend_s_16to64(uimm16); 8410 Addr64 cia = guest_CIA_curr_instr; 8411 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8412 Bool uncond = False; 8413 8414 switch (opc1) { 8415 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 8416 uncond = do_trap( TO, 8417 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 8418 : getIReg(rA_addr), 8419 mkU32( (UInt)simm16 ), 8420 cia ); 8421 if (TO == 4) { 8422 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16); 8423 } else { 8424 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16); 8425 } 8426 break; 8427 case 0x02: // tdi 8428 if (!mode64) 8429 return False; 8430 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 8431 if (TO == 4) { 8432 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16); 8433 } else { 8434 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16); 8435 } 8436 break; 8437 default: 8438 return False; 8439 } 8440 8441 if (uncond) { 8442 /* If the trap shows signs of being unconditional, don't 8443 continue decoding past it. */ 8444 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8445 dres->jk_StopHere = Ijk_Boring; 8446 dres->whatNext = Dis_StopHere; 8447 } 8448 8449 return True; 8450 } 8451 8452 static Bool dis_trap ( UInt theInstr, 8453 /*OUT*/DisResult* dres ) 8454 { 8455 /* X-Form */ 8456 UInt opc2 = ifieldOPClo10(theInstr); 8457 UChar TO = ifieldRegDS(theInstr); 8458 UChar rA_addr = ifieldRegA(theInstr); 8459 UChar rB_addr = ifieldRegB(theInstr); 8460 Addr64 cia = guest_CIA_curr_instr; 8461 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8462 Bool uncond = False; 8463 8464 if (ifieldBIT0(theInstr) != 0) 8465 return False; 8466 8467 switch (opc2) { 8468 case 0x004: // tw (Trap Word, PPC64 p540) 8469 uncond = do_trap( TO, 8470 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 8471 : getIReg(rA_addr), 8472 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 8473 : getIReg(rB_addr), 8474 cia ); 8475 if (TO == 4) { 8476 DIP("tweq r%u,r%u\n", rA_addr, rB_addr); 8477 } else { 8478 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr); 8479 } 8480 break; 8481 case 0x044: // td (Trap Doubleword, PPC64 p534) 8482 if (!mode64) 8483 return False; 8484 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 8485 if (TO == 4) { 8486 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr); 8487 } else { 8488 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr); 8489 } 8490 break; 8491 default: 8492 return False; 8493 } 8494 8495 if (uncond) { 8496 /* If the trap shows signs of being unconditional, don't 8497 continue decoding past it. */ 8498 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8499 dres->jk_StopHere = Ijk_Boring; 8500 dres->whatNext = Dis_StopHere; 8501 } 8502 8503 return True; 8504 } 8505 8506 8507 /* 8508 System Linkage Instructions 8509 */ 8510 static Bool dis_syslink ( UInt theInstr, 8511 const VexAbiInfo* abiinfo, DisResult* dres ) 8512 { 8513 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8514 8515 if (theInstr != 0x44000002) { 8516 vex_printf("dis_syslink(ppc)(theInstr)\n"); 8517 return False; 8518 } 8519 8520 // sc (System Call, PPC32 p504) 8521 DIP("sc\n"); 8522 8523 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 8524 Valgrind can back the guest up to this instruction if it needs 8525 to restart the syscall. */ 8526 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 8527 8528 /* It's important that all ArchRegs carry their up-to-date value 8529 at this point. So we declare an end-of-block here, which 8530 forces any TempRegs caching ArchRegs to be flushed. */ 8531 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8532 8533 dres->whatNext = Dis_StopHere; 8534 dres->jk_StopHere = Ijk_Sys_syscall; 8535 return True; 8536 } 8537 8538 8539 /* 8540 Memory Synchronization Instructions 8541 8542 Note on Reservations: 8543 We rely on the assumption that V will in fact only allow one thread at 8544 once to run. In effect, a thread can make a reservation, but we don't 8545 check any stores it does. Instead, the reservation is cancelled when 8546 the scheduler switches to another thread (run_thread_for_a_while()). 8547 */ 8548 static Bool dis_memsync ( UInt theInstr ) 8549 { 8550 /* X-Form, XL-Form */ 8551 UChar opc1 = ifieldOPC(theInstr); 8552 UInt b11to25 = IFIELD(theInstr, 11, 15); 8553 UChar flag_L = ifieldRegDS(theInstr); 8554 UInt b11to20 = IFIELD(theInstr, 11, 10); 8555 UInt M0 = IFIELD(theInstr, 11, 5); 8556 UChar rD_addr = ifieldRegDS(theInstr); 8557 UChar rS_addr = rD_addr; 8558 UChar rA_addr = ifieldRegA(theInstr); 8559 UChar rB_addr = ifieldRegB(theInstr); 8560 UInt opc2 = ifieldOPClo10(theInstr); 8561 UChar b0 = ifieldBIT0(theInstr); 8562 8563 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8564 IRTemp EA = newTemp(ty); 8565 8566 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 8567 8568 switch (opc1) { 8569 /* XL-Form */ 8570 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 8571 if (opc2 != 0x096) { 8572 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 8573 return False; 8574 } 8575 if (b11to25 != 0 || b0 != 0) { 8576 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 8577 return False; 8578 } 8579 DIP("isync\n"); 8580 stmt( IRStmt_MBE(Imbe_Fence) ); 8581 break; 8582 8583 /* X-Form */ 8584 case 0x1F: 8585 switch (opc2) { 8586 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394) 8587 if (M0 == 0) { 8588 if (b11to20 != 0 || b0 != 0) { 8589 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n"); 8590 return False; 8591 } 8592 DIP("eieio\n"); 8593 } else { 8594 if (b11to20 != 0 || b0 != 0) { 8595 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n"); 8596 return False; 8597 } 8598 DIP("mbar %d\n", M0); 8599 } 8600 /* Insert a memory fence, just to be on the safe side. */ 8601 stmt( IRStmt_MBE(Imbe_Fence) ); 8602 break; 8603 8604 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 8605 IRTemp res; 8606 /* According to the PowerPC ISA version 2.05, b0 (called EH 8607 in the documentation) is merely a hint bit to the 8608 hardware, I think as to whether or not contention is 8609 likely. So we can just ignore it. */ 8610 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8611 8612 // trap if misaligned 8613 gen_SIGBUS_if_misaligned( EA, 4 ); 8614 8615 // and actually do the load 8616 res = newTemp(Ity_I32); 8617 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8618 8619 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 8620 break; 8621 } 8622 8623 case 0x034: { // lbarx (Load Word and Reserve Indexed) 8624 IRTemp res; 8625 /* According to the PowerPC ISA version 2.05, b0 (called EH 8626 in the documentation) is merely a hint bit to the 8627 hardware, I think as to whether or not contention is 8628 likely. So we can just ignore it. */ 8629 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8630 8631 // and actually do the load 8632 res = newTemp(Ity_I8); 8633 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8634 8635 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 8636 break; 8637 } 8638 8639 case 0x074: { // lharx (Load Word and Reserve Indexed) 8640 IRTemp res; 8641 /* According to the PowerPC ISA version 2.05, b0 (called EH 8642 in the documentation) is merely a hint bit to the 8643 hardware, I think as to whether or not contention is 8644 likely. So we can just ignore it. */ 8645 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8646 8647 // trap if misaligned 8648 gen_SIGBUS_if_misaligned( EA, 2 ); 8649 8650 // and actually do the load 8651 res = newTemp(Ity_I16); 8652 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8653 8654 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 8655 break; 8656 } 8657 8658 case 0x096: { 8659 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 8660 // Note this has to handle stwcx. in both 32- and 64-bit modes, 8661 // so isn't quite as straightforward as it might otherwise be. 8662 IRTemp rS = newTemp(Ity_I32); 8663 IRTemp resSC; 8664 if (b0 != 1) { 8665 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 8666 return False; 8667 } 8668 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8669 8670 // trap if misaligned 8671 gen_SIGBUS_if_misaligned( EA, 4 ); 8672 8673 // Get the data to be stored, and narrow to 32 bits if necessary 8674 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 8675 8676 // Do the store, and get success/failure bit into resSC 8677 resSC = newTemp(Ity_I1); 8678 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8679 8680 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8681 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8682 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8683 putCR0(0, getXER_SO()); 8684 8685 /* Note: 8686 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 8687 whether rS is stored is dependent on that value. */ 8688 /* So I guess we can just ignore this case? */ 8689 break; 8690 } 8691 8692 case 0x2B6: { 8693 // stbcx. (Store Byte Conditional Indexed) 8694 // Note this has to handle stbcx. in both 32- and 64-bit modes, 8695 // so isn't quite as straightforward as it might otherwise be. 8696 IRTemp rS = newTemp(Ity_I8); 8697 IRTemp resSC; 8698 if (b0 != 1) { 8699 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 8700 return False; 8701 } 8702 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8703 8704 // Get the data to be stored, and narrow to 32 bits if necessary 8705 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 8706 8707 // Do the store, and get success/failure bit into resSC 8708 resSC = newTemp(Ity_I1); 8709 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8710 8711 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8712 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8713 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8714 putCR0(0, getXER_SO()); 8715 8716 /* Note: 8717 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 8718 whether rS is stored is dependent on that value. */ 8719 /* So I guess we can just ignore this case? */ 8720 break; 8721 } 8722 8723 case 0x2D6: { 8724 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 8725 // Note this has to handle sthcx. in both 32- and 64-bit modes, 8726 // so isn't quite as straightforward as it might otherwise be. 8727 IRTemp rS = newTemp(Ity_I16); 8728 IRTemp resSC; 8729 if (b0 != 1) { 8730 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 8731 return False; 8732 } 8733 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8734 8735 // trap if misaligned 8736 gen_SIGBUS_if_misaligned( EA, 2 ); 8737 8738 // Get the data to be stored, and narrow to 16 bits if necessary 8739 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 8740 8741 // Do the store, and get success/failure bit into resSC 8742 resSC = newTemp(Ity_I1); 8743 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8744 8745 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8746 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8747 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8748 putCR0(0, getXER_SO()); 8749 8750 /* Note: 8751 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 8752 whether rS is stored is dependent on that value. */ 8753 /* So I guess we can just ignore this case? */ 8754 break; 8755 } 8756 8757 case 0x256: // sync (Synchronize, PPC32 p543), 8758 // also lwsync (L==1), ptesync (L==2) 8759 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 8760 8761 The PowerPC architecture used in IBM chips has expanded 8762 the sync instruction into two variants: lightweight sync 8763 and heavyweight sync. The original sync instruction is 8764 the new heavyweight sync and lightweight sync is a strict 8765 subset of the heavyweight sync functionality. This allows 8766 the programmer to specify a less expensive operation on 8767 high-end systems when the full sync functionality is not 8768 necessary. 8769 8770 The basic "sync" mnemonic now utilizes an operand. "sync" 8771 without an operand now becomes a extended mnemonic for 8772 heavyweight sync. Processors without the lwsync 8773 instruction will not decode the L field and will perform a 8774 heavyweight sync. Everything is backward compatible. 8775 8776 sync = sync 0 8777 lwsync = sync 1 8778 ptesync = sync 2 *** TODO - not implemented *** 8779 */ 8780 if (b11to20 != 0 || b0 != 0) { 8781 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 8782 return False; 8783 } 8784 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 8785 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 8786 return False; 8787 } 8788 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 8789 /* Insert a memory fence. It's sometimes important that these 8790 are carried through to the generated code. */ 8791 stmt( IRStmt_MBE(Imbe_Fence) ); 8792 break; 8793 8794 /* 64bit Memsync */ 8795 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 8796 IRTemp res; 8797 /* According to the PowerPC ISA version 2.05, b0 (called EH 8798 in the documentation) is merely a hint bit to the 8799 hardware, I think as to whether or not contention is 8800 likely. So we can just ignore it. */ 8801 if (!mode64) 8802 return False; 8803 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8804 8805 // trap if misaligned 8806 gen_SIGBUS_if_misaligned( EA, 8 ); 8807 8808 // and actually do the load 8809 res = newTemp(Ity_I64); 8810 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 8811 8812 putIReg( rD_addr, mkexpr(res) ); 8813 break; 8814 } 8815 8816 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 8817 // A marginally simplified version of the stwcx. case 8818 IRTemp rS = newTemp(Ity_I64); 8819 IRTemp resSC; 8820 if (b0 != 1) { 8821 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 8822 return False; 8823 } 8824 if (!mode64) 8825 return False; 8826 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8827 8828 // trap if misaligned 8829 gen_SIGBUS_if_misaligned( EA, 8 ); 8830 8831 // Get the data to be stored 8832 assign( rS, getIReg(rS_addr) ); 8833 8834 // Do the store, and get success/failure bit into resSC 8835 resSC = newTemp(Ity_I1); 8836 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8837 8838 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8839 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8840 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8841 putCR0(0, getXER_SO()); 8842 8843 /* Note: 8844 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 8845 whether rS is stored is dependent on that value. */ 8846 /* So I guess we can just ignore this case? */ 8847 break; 8848 } 8849 8850 /* 128bit Memsync */ 8851 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 8852 IRTemp res_hi = newTemp(ty); 8853 IRTemp res_lo = newTemp(ty); 8854 8855 /* According to the PowerPC ISA version 2.07, b0 (called EH 8856 in the documentation) is merely a hint bit to the 8857 hardware, I think as to whether or not contention is 8858 likely. So we can just ignore it. */ 8859 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8860 8861 // trap if misaligned 8862 gen_SIGBUS_if_misaligned( EA, 16 ); 8863 8864 // and actually do the load 8865 if (mode64) { 8866 if (host_endness == VexEndnessBE) { 8867 stmt( stmt_load( res_hi, 8868 mkexpr(EA), NULL/*this is a load*/) ); 8869 stmt( stmt_load( res_lo, 8870 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 8871 NULL/*this is a load*/) ); 8872 } else { 8873 stmt( stmt_load( res_lo, 8874 mkexpr(EA), NULL/*this is a load*/) ); 8875 stmt( stmt_load( res_hi, 8876 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 8877 NULL/*this is a load*/) ); 8878 } 8879 } else { 8880 stmt( stmt_load( res_hi, 8881 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 8882 NULL/*this is a load*/) ); 8883 stmt( stmt_load( res_lo, 8884 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 8885 NULL/*this is a load*/) ); 8886 } 8887 putIReg( rD_addr, mkexpr(res_hi) ); 8888 putIReg( rD_addr+1, mkexpr(res_lo) ); 8889 break; 8890 } 8891 8892 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 8893 // A marginally simplified version of the stwcx. case 8894 IRTemp rS_hi = newTemp(ty); 8895 IRTemp rS_lo = newTemp(ty); 8896 IRTemp resSC; 8897 if (b0 != 1) { 8898 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 8899 return False; 8900 } 8901 8902 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8903 8904 // trap if misaligned 8905 gen_SIGBUS_if_misaligned( EA, 16 ); 8906 // Get the data to be stored 8907 assign( rS_hi, getIReg(rS_addr) ); 8908 assign( rS_lo, getIReg(rS_addr+1) ); 8909 8910 // Do the store, and get success/failure bit into resSC 8911 resSC = newTemp(Ity_I1); 8912 8913 if (mode64) { 8914 if (host_endness == VexEndnessBE) { 8915 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 8916 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 8917 mkexpr(rS_lo) ); 8918 } else { 8919 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 8920 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 8921 mkexpr(rS_hi) ); 8922 } 8923 } else { 8924 stmt( stmt_load( resSC, binop( Iop_Add32, 8925 mkexpr(EA), 8926 mkU32(4) ), 8927 mkexpr(rS_hi) ) ); 8928 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 8929 } 8930 8931 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8932 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8933 putCR321(0, binop( Iop_Shl8, 8934 unop(Iop_1Uto8, mkexpr(resSC) ), 8935 mkU8(1))); 8936 putCR0(0, getXER_SO()); 8937 break; 8938 } 8939 8940 default: 8941 vex_printf("dis_memsync(ppc)(opc2)\n"); 8942 return False; 8943 } 8944 break; 8945 8946 default: 8947 vex_printf("dis_memsync(ppc)(opc1)\n"); 8948 return False; 8949 } 8950 return True; 8951 } 8952 8953 8954 8955 /* 8956 Integer Shift Instructions 8957 */ 8958 static Bool dis_int_shift ( UInt theInstr ) 8959 { 8960 /* X-Form, XS-Form */ 8961 UChar opc1 = ifieldOPC(theInstr); 8962 UChar rS_addr = ifieldRegDS(theInstr); 8963 UChar rA_addr = ifieldRegA(theInstr); 8964 UChar rB_addr = ifieldRegB(theInstr); 8965 UChar sh_imm = rB_addr; 8966 UInt opc2 = ifieldOPClo10(theInstr); 8967 UChar b1 = ifieldBIT1(theInstr); 8968 UChar flag_rC = ifieldBIT0(theInstr); 8969 8970 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8971 IRTemp rA = newTemp(ty); 8972 IRTemp rS = newTemp(ty); 8973 IRTemp rB = newTemp(ty); 8974 IRTemp outofrange = newTemp(Ity_I1); 8975 IRTemp rS_lo32 = newTemp(Ity_I32); 8976 IRTemp rB_lo32 = newTemp(Ity_I32); 8977 IRExpr* e_tmp; 8978 8979 assign( rS, getIReg(rS_addr) ); 8980 assign( rB, getIReg(rB_addr) ); 8981 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 8982 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 8983 8984 if (opc1 == 0x1F) { 8985 switch (opc2) { 8986 case 0x018: { // slw (Shift Left Word, PPC32 p505) 8987 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 8988 rA_addr, rS_addr, rB_addr); 8989 /* rA = rS << rB */ 8990 /* ppc32 semantics are: 8991 slw(x,y) = (x << (y & 31)) -- primary result 8992 & ~((y << 26) >>s 31) -- make result 0 8993 for y in 32 .. 63 8994 */ 8995 e_tmp = 8996 binop( Iop_And32, 8997 binop( Iop_Shl32, 8998 mkexpr(rS_lo32), 8999 unop( Iop_32to8, 9000 binop(Iop_And32, 9001 mkexpr(rB_lo32), mkU32(31)))), 9002 unop( Iop_Not32, 9003 binop( Iop_Sar32, 9004 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 9005 mkU8(31))) ); 9006 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 9007 break; 9008 } 9009 9010 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 9011 IRTemp sh_amt = newTemp(Ity_I32); 9012 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 9013 rA_addr, rS_addr, rB_addr); 9014 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 9015 amt = rB & 63 9016 rA = Sar32( rS, amt > 31 ? 31 : amt ) 9017 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 9018 */ 9019 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 9020 mkexpr(rB_lo32)) ); 9021 assign( outofrange, 9022 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 9023 e_tmp = binop( Iop_Sar32, 9024 mkexpr(rS_lo32), 9025 unop( Iop_32to8, 9026 IRExpr_ITE( mkexpr(outofrange), 9027 mkU32(31), 9028 mkexpr(sh_amt)) ) ); 9029 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 9030 9031 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAW, 9032 mkexpr(rA), 9033 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 9034 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 9035 mkWidenFrom32(ty, getXER_CA_32(), True) ); 9036 break; 9037 } 9038 9039 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 9040 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 9041 rA_addr, rS_addr, sh_imm); 9042 vassert(sh_imm < 32); 9043 if (mode64) { 9044 assign( rA, binop(Iop_Sar64, 9045 binop(Iop_Shl64, getIReg(rS_addr), 9046 mkU8(32)), 9047 mkU8(32 + sh_imm)) ); 9048 } else { 9049 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 9050 mkU8(sh_imm)) ); 9051 } 9052 9053 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAWI, 9054 mkexpr(rA), 9055 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 9056 mkSzImm(ty, sh_imm), 9057 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9058 break; 9059 9060 case 0x218: // srw (Shift Right Word, PPC32 p508) 9061 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 9062 rA_addr, rS_addr, rB_addr); 9063 /* rA = rS >>u rB */ 9064 /* ppc32 semantics are: 9065 srw(x,y) = (x >>u (y & 31)) -- primary result 9066 & ~((y << 26) >>s 31) -- make result 0 9067 for y in 32 .. 63 9068 */ 9069 e_tmp = 9070 binop( 9071 Iop_And32, 9072 binop( Iop_Shr32, 9073 mkexpr(rS_lo32), 9074 unop( Iop_32to8, 9075 binop(Iop_And32, mkexpr(rB_lo32), 9076 mkU32(31)))), 9077 unop( Iop_Not32, 9078 binop( Iop_Sar32, 9079 binop(Iop_Shl32, mkexpr(rB_lo32), 9080 mkU8(26)), 9081 mkU8(31)))); 9082 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 9083 break; 9084 9085 9086 /* 64bit Shifts */ 9087 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 9088 DIP("sld%s r%u,r%u,r%u\n", 9089 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9090 /* rA = rS << rB */ 9091 /* ppc64 semantics are: 9092 slw(x,y) = (x << (y & 63)) -- primary result 9093 & ~((y << 57) >>s 63) -- make result 0 9094 for y in 64 .. 9095 */ 9096 assign( rA, 9097 binop( 9098 Iop_And64, 9099 binop( Iop_Shl64, 9100 mkexpr(rS), 9101 unop( Iop_64to8, 9102 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 9103 unop( Iop_Not64, 9104 binop( Iop_Sar64, 9105 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 9106 mkU8(63)))) ); 9107 break; 9108 9109 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 9110 IRTemp sh_amt = newTemp(Ity_I64); 9111 DIP("srad%s r%u,r%u,r%u\n", 9112 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9113 /* amt = rB & 127 9114 rA = Sar64( rS, amt > 63 ? 63 : amt ) 9115 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 9116 */ 9117 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 9118 assign( outofrange, 9119 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 9120 assign( rA, 9121 binop( Iop_Sar64, 9122 mkexpr(rS), 9123 unop( Iop_64to8, 9124 IRExpr_ITE( mkexpr(outofrange), 9125 mkU64(63), 9126 mkexpr(sh_amt)) )) 9127 ); 9128 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAD, 9129 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 9130 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9131 break; 9132 } 9133 9134 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 9135 sh_imm |= b1<<5; 9136 vassert(sh_imm < 64); 9137 DIP("sradi%s r%u,r%u,%u\n", 9138 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 9139 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 9140 9141 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRADI, 9142 mkexpr(rA), 9143 getIReg(rS_addr), 9144 mkU64(sh_imm), 9145 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9146 break; 9147 9148 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 9149 DIP("srd%s r%u,r%u,r%u\n", 9150 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9151 /* rA = rS >>u rB */ 9152 /* ppc semantics are: 9153 srw(x,y) = (x >>u (y & 63)) -- primary result 9154 & ~((y << 57) >>s 63) -- make result 0 9155 for y in 64 .. 127 9156 */ 9157 assign( rA, 9158 binop( 9159 Iop_And64, 9160 binop( Iop_Shr64, 9161 mkexpr(rS), 9162 unop( Iop_64to8, 9163 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 9164 unop( Iop_Not64, 9165 binop( Iop_Sar64, 9166 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 9167 mkU8(63)))) ); 9168 break; 9169 9170 default: 9171 vex_printf("dis_int_shift(ppc)(opc2)\n"); 9172 return False; 9173 } 9174 } else { 9175 vex_printf("dis_int_shift(ppc)(opc1)\n"); 9176 return False; 9177 } 9178 9179 putIReg( rA_addr, mkexpr(rA) ); 9180 9181 if (flag_rC) { 9182 set_CR0( mkexpr(rA) ); 9183 } 9184 return True; 9185 } 9186 9187 9188 9189 /* 9190 Integer Load/Store Reverse Instructions 9191 */ 9192 /* Generates code to swap the byte order in an Ity_I32. */ 9193 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 9194 { 9195 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 9196 return 9197 binop(Iop_Or32, 9198 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 9199 binop(Iop_Or32, 9200 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 9201 mkU32(0x00FF0000)), 9202 binop(Iop_Or32, 9203 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 9204 mkU32(0x0000FF00)), 9205 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 9206 mkU32(0x000000FF) ) 9207 ))); 9208 } 9209 9210 /* Generates code to swap the byte order in the lower half of an Ity_I32, 9211 and zeroes the upper half. */ 9212 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 9213 { 9214 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 9215 return 9216 binop(Iop_Or32, 9217 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 9218 mkU32(0x0000FF00)), 9219 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 9220 mkU32(0x000000FF)) 9221 ); 9222 } 9223 9224 static Bool dis_int_ldst_rev ( UInt theInstr ) 9225 { 9226 /* X-Form */ 9227 UChar opc1 = ifieldOPC(theInstr); 9228 UChar rD_addr = ifieldRegDS(theInstr); 9229 UChar rS_addr = rD_addr; 9230 UChar rA_addr = ifieldRegA(theInstr); 9231 UChar rB_addr = ifieldRegB(theInstr); 9232 UInt opc2 = ifieldOPClo10(theInstr); 9233 UChar b0 = ifieldBIT0(theInstr); 9234 9235 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9236 IRTemp EA = newTemp(ty); 9237 IRTemp w1 = newTemp(Ity_I32); 9238 IRTemp w2 = newTemp(Ity_I32); 9239 9240 if (opc1 != 0x1F || b0 != 0) { 9241 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 9242 return False; 9243 } 9244 9245 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 9246 9247 switch (opc2) { 9248 9249 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 9250 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9251 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 9252 assign( w2, gen_byterev16(w1) ); 9253 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 9254 /* Signed */False) ); 9255 break; 9256 9257 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 9258 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9259 assign( w1, load(Ity_I32, mkexpr(EA)) ); 9260 assign( w2, gen_byterev32(w1) ); 9261 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 9262 /* Signed */False) ); 9263 break; 9264 9265 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 9266 { 9267 IRExpr * nextAddr; 9268 IRTemp w3 = newTemp( Ity_I32 ); 9269 IRTemp w4 = newTemp( Ity_I32 ); 9270 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9271 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 9272 assign( w2, gen_byterev32( w1 ) ); 9273 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 9274 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 9275 assign( w3, load( Ity_I32, nextAddr ) ); 9276 assign( w4, gen_byterev32( w3 ) ); 9277 if (host_endness == VexEndnessLE) 9278 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 9279 else 9280 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 9281 break; 9282 } 9283 9284 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 9285 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9286 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 9287 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 9288 break; 9289 9290 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 9291 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9292 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 9293 store( mkexpr(EA), gen_byterev32(w1) ); 9294 break; 9295 9296 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 9297 { 9298 IRTemp lo = newTemp(Ity_I32); 9299 IRTemp hi = newTemp(Ity_I32); 9300 IRTemp rS = newTemp(Ity_I64); 9301 assign( rS, getIReg( rS_addr ) ); 9302 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9303 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 9304 assign(hi, unop(Iop_64to32, mkexpr(rS))); 9305 store( mkexpr( EA ), 9306 binop( Iop_32HLto64, gen_byterev32( hi ), 9307 gen_byterev32( lo ) ) ); 9308 break; 9309 } 9310 9311 default: 9312 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 9313 return False; 9314 } 9315 return True; 9316 } 9317 9318 9319 9320 /* 9321 Processor Control Instructions 9322 */ 9323 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 9324 { 9325 UChar opc1 = ifieldOPC(theInstr); 9326 9327 /* X-Form */ 9328 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9329 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9330 UChar rD_addr = ifieldRegDS(theInstr); 9331 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 9332 9333 /* XFX-Form */ 9334 UChar rS_addr = rD_addr; 9335 UInt SPR = b11to20; 9336 UInt TBR = b11to20; 9337 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 9338 UInt CRM = IFIELD( theInstr, 12, 8 ); 9339 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9340 9341 UInt opc2 = ifieldOPClo10(theInstr); 9342 UChar b0 = ifieldBIT0(theInstr); 9343 9344 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9345 IRTemp rS = newTemp(ty); 9346 assign( rS, getIReg(rS_addr) ); 9347 9348 /* Reorder SPR field as per PPC32 p470 */ 9349 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 9350 /* Reorder TBR field as per PPC32 p475 */ 9351 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 9352 9353 /* b0 = 0, inst is treated as floating point inst for reservation purposes 9354 * b0 = 1, inst is treated as vector inst for reservation purposes 9355 */ 9356 if (opc1 != 0x1F) { 9357 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 9358 return False; 9359 } 9360 9361 switch (opc2) { 9362 /* X-Form */ 9363 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 9364 if (b21to22 != 0 || b11to20 != 0) { 9365 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 9366 return False; 9367 } 9368 DIP("mcrxr crf%d\n", crfD); 9369 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 9370 putGST_field( PPC_GST_CR, 9371 getGST_field( PPC_GST_XER, 7 ), 9372 crfD ); 9373 9374 // Clear XER[0-3] 9375 putXER_SO( mkU8(0) ); 9376 putXER_OV( mkU8(0) ); 9377 putXER_CA( mkU8(0) ); 9378 break; 9379 } 9380 9381 case 0x013: 9382 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 9383 // b20==1 & b11==0: mfocrf (Move from One CR Field) 9384 // However it seems that the 'mfcr' behaviour is an acceptable 9385 // implementation of mfocr (from the 2.02 arch spec) 9386 if (b11to20 == 0) { 9387 DIP("mfcr r%u\n", rD_addr); 9388 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 9389 /* Signed */False) ); 9390 break; 9391 } 9392 if (b20 == 1 && b11 == 0) { 9393 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 9394 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 9395 /* Signed */False) ); 9396 break; 9397 } 9398 /* not decodable */ 9399 return False; 9400 9401 /* XFX-Form */ 9402 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 9403 9404 switch (SPR) { // Choose a register... 9405 case 0x1: 9406 DIP("mfxer r%u\n", rD_addr); 9407 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 9408 /* Signed */False) ); 9409 break; 9410 case 0x8: 9411 DIP("mflr r%u\n", rD_addr); 9412 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 9413 break; 9414 case 0x9: 9415 DIP("mfctr r%u\n", rD_addr); 9416 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 9417 break; 9418 case 0x80: // 128 9419 DIP("mfspr r%u (TFHAR)\n", rD_addr); 9420 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 9421 break; 9422 case 0x81: // 129 9423 DIP("mfspr r%u (TFIAR)\n", rD_addr); 9424 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 9425 break; 9426 case 0x82: // 130 9427 DIP("mfspr r%u (TEXASR)\n", rD_addr); 9428 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 9429 break; 9430 case 0x83: // 131 9431 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 9432 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 9433 break; 9434 case 0x9F: // 159 9435 DIP("mfspr r%u (PSPB)\n", rD_addr); 9436 putIReg( rD_addr, getGST( PPC_GST_PSPB) ); 9437 break; 9438 case 0x380: // 896 9439 DIP("mfspr r%u (PPR)\n", rD_addr); 9440 putIReg( rD_addr, getGST( PPC_GST_PPR) ); 9441 break; 9442 case 0x382: // 898 9443 DIP("mfspr r%u (PPR)32\n", rD_addr); 9444 putIReg( rD_addr, getGST( PPC_GST_PPR32) ); 9445 break; 9446 case 0x100: 9447 DIP("mfvrsave r%u\n", rD_addr); 9448 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 9449 /* Signed */False) ); 9450 break; 9451 9452 case 0x103: 9453 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 9454 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 9455 break; 9456 9457 /* Even a lowly PPC7400 can run the associated helper, so no 9458 obvious need for feature testing at this point. */ 9459 case 268 /* 0x10C */: 9460 case 269 /* 0x10D */: { 9461 UInt arg = SPR==268 ? 0 : 1; 9462 IRTemp val = newTemp(Ity_I32); 9463 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 9464 IRDirty* d = unsafeIRDirty_1_N( 9465 val, 9466 0/*regparms*/, 9467 "ppc32g_dirtyhelper_MFSPR_268_269", 9468 fnptr_to_fnentry 9469 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 9470 args 9471 ); 9472 /* execute the dirty call, dumping the result in val. */ 9473 stmt( IRStmt_Dirty(d) ); 9474 putIReg( rD_addr, 9475 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 9476 DIP("mfspr r%u,%u", rD_addr, SPR); 9477 break; 9478 } 9479 9480 /* Again, runs natively on PPC7400 (7447, really). Not 9481 bothering with a feature test. */ 9482 case 287: /* 0x11F */ { 9483 IRTemp val = newTemp(Ity_I32); 9484 IRExpr** args = mkIRExprVec_0(); 9485 IRDirty* d = unsafeIRDirty_1_N( 9486 val, 9487 0/*regparms*/, 9488 "ppc32g_dirtyhelper_MFSPR_287", 9489 fnptr_to_fnentry 9490 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 9491 args 9492 ); 9493 /* execute the dirty call, dumping the result in val. */ 9494 stmt( IRStmt_Dirty(d) ); 9495 putIReg( rD_addr, 9496 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 9497 DIP("mfspr r%u,%u", rD_addr, SPR); 9498 break; 9499 } 9500 9501 default: 9502 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 9503 return False; 9504 } 9505 break; 9506 9507 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 9508 IRTemp val = newTemp(Ity_I64); 9509 IRExpr** args = mkIRExprVec_0(); 9510 IRDirty* d = unsafeIRDirty_1_N( 9511 val, 9512 0/*regparms*/, 9513 "ppcg_dirtyhelper_MFTB", 9514 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 9515 args ); 9516 /* execute the dirty call, dumping the result in val. */ 9517 stmt( IRStmt_Dirty(d) ); 9518 9519 switch (TBR) { 9520 case 269: 9521 DIP("mftbu r%u", rD_addr); 9522 putIReg( rD_addr, 9523 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 9524 /* Signed */False) ); 9525 break; 9526 case 268: 9527 DIP("mftb r%u", rD_addr); 9528 putIReg( rD_addr, (mode64) ? mkexpr(val) : 9529 unop(Iop_64to32, mkexpr(val)) ); 9530 break; 9531 default: 9532 return False; /* illegal instruction */ 9533 } 9534 break; 9535 } 9536 9537 case 0x090: { 9538 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 9539 // b20==1: mtocrf (Move to One Cond Reg Field) 9540 Int cr; 9541 UChar shft; 9542 if (b11 != 0) 9543 return False; 9544 if (b20 == 1) { 9545 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 9546 1 field is written. It seems more robust to decline to 9547 decode the insn if so. */ 9548 switch (CRM) { 9549 case 0x01: case 0x02: case 0x04: case 0x08: 9550 case 0x10: case 0x20: case 0x40: case 0x80: 9551 break; 9552 default: 9553 return False; 9554 } 9555 } 9556 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 9557 CRM, rS_addr); 9558 /* Write to each field specified by CRM */ 9559 for (cr = 0; cr < 8; cr++) { 9560 if ((CRM & (1 << (7-cr))) == 0) 9561 continue; 9562 shft = 4*(7-cr); 9563 putGST_field( PPC_GST_CR, 9564 binop(Iop_Shr32, 9565 mkNarrowTo32(ty, mkexpr(rS)), 9566 mkU8(shft)), cr ); 9567 } 9568 break; 9569 } 9570 9571 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 9572 9573 switch (SPR) { // Choose a register... 9574 case 0x1: 9575 DIP("mtxer r%u\n", rS_addr); 9576 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 9577 break; 9578 case 0x8: 9579 DIP("mtlr r%u\n", rS_addr); 9580 putGST( PPC_GST_LR, mkexpr(rS) ); 9581 break; 9582 case 0x9: 9583 DIP("mtctr r%u\n", rS_addr); 9584 putGST( PPC_GST_CTR, mkexpr(rS) ); 9585 break; 9586 case 0x100: 9587 DIP("mtvrsave r%u\n", rS_addr); 9588 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 9589 break; 9590 case 0x80: // 128 9591 DIP("mtspr r%u (TFHAR)\n", rS_addr); 9592 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 9593 break; 9594 case 0x81: // 129 9595 DIP("mtspr r%u (TFIAR)\n", rS_addr); 9596 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 9597 break; 9598 case 0x82: // 130 9599 DIP("mtspr r%u (TEXASR)\n", rS_addr); 9600 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 9601 break; 9602 case 0x9F: // 159 9603 DIP("mtspr r%u (PSPB)\n", rS_addr); 9604 putGST( PPC_GST_PSPB, mkexpr(rS) ); 9605 break; 9606 case 0x380: // 896 9607 DIP("mtspr r%u (PPR)\n", rS_addr); 9608 putGST( PPC_GST_PPR, mkexpr(rS) ); 9609 break; 9610 case 0x382: // 898 9611 DIP("mtspr r%u (PPR32)\n", rS_addr); 9612 putGST( PPC_GST_PPR32, mkexpr(rS) ); 9613 break; 9614 default: 9615 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 9616 return False; 9617 } 9618 break; 9619 9620 case 0x33: // mfvsrd 9621 { 9622 UChar XS = ifieldRegXS( theInstr ); 9623 UChar rA_addr = ifieldRegA(theInstr); 9624 IRExpr * high64; 9625 IRTemp vS = newTemp( Ity_V128 ); 9626 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS); 9627 9628 /* XS = SX || S 9629 * For SX=0, mfvsrd is treated as a Floating-Point 9630 * instruction in terms of resource availability. 9631 * For SX=1, mfvsrd is treated as a Vector instruction in 9632 * terms of resource availability. 9633 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9634 */ 9635 assign( vS, getVSReg( XS ) ); 9636 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 9637 putIReg( rA_addr, (mode64) ? high64 : 9638 unop( Iop_64to32, high64 ) ); 9639 break; 9640 } 9641 9642 case 0x73: // mfvsrwz 9643 { 9644 UChar XS = ifieldRegXS( theInstr ); 9645 UChar rA_addr = ifieldRegA(theInstr); 9646 IRExpr * high64; 9647 IRTemp vS = newTemp( Ity_V128 ); 9648 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS); 9649 /* XS = SX || S 9650 * For SX=0, mfvsrwz is treated as a Floating-Point 9651 * instruction in terms of resource availability. 9652 * For SX=1, mfvsrwz is treated as a Vector instruction in 9653 * terms of resource availability. 9654 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9655 */ 9656 9657 assign( vS, getVSReg( XS ) ); 9658 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 9659 /* move value to the destination setting the upper 32-bits to zero */ 9660 putIReg( rA_addr, (mode64) ? 9661 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 9662 unop( Iop_64to32, 9663 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 9664 break; 9665 } 9666 9667 case 0xB3: // mtvsrd 9668 { 9669 UChar XT = ifieldRegXT( theInstr ); 9670 UChar rA_addr = ifieldRegA(theInstr); 9671 IRTemp rA = newTemp(ty); 9672 DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr); 9673 /* XS = SX || S 9674 * For SX=0, mfvsrd is treated as a Floating-Point 9675 * instruction in terms of resource availability. 9676 * For SX=1, mfvsrd is treated as a Vector instruction in 9677 * terms of resource availability. 9678 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9679 */ 9680 assign( rA, getIReg(rA_addr) ); 9681 9682 if (mode64) 9683 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 9684 else 9685 putVSReg( XT, binop( Iop_64HLtoV128, 9686 binop( Iop_32HLto64, 9687 mkU32( 0 ), 9688 mkexpr( rA ) ), 9689 mkU64( 0 ) ) ); 9690 break; 9691 } 9692 9693 case 0xD3: // mtvsrwa 9694 { 9695 UChar XT = ifieldRegXT( theInstr ); 9696 UChar rA_addr = ifieldRegA(theInstr); 9697 IRTemp rA = newTemp( Ity_I32 ); 9698 DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr); 9699 /* XS = SX || S 9700 * For SX=0, mtvsrwa is treated as a Floating-Point 9701 * instruction in terms of resource availability. 9702 * For SX=1, mtvsrwa is treated as a Vector instruction in 9703 * terms of resource availability. 9704 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9705 */ 9706 if (mode64) 9707 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 9708 else 9709 assign( rA, getIReg(rA_addr) ); 9710 9711 putVSReg( XT, binop( Iop_64HLtoV128, 9712 unop( Iop_32Sto64, mkexpr( rA ) ), 9713 mkU64( 0 ) ) ); 9714 break; 9715 } 9716 9717 case 0xF3: // mtvsrwz 9718 { 9719 UChar XT = ifieldRegXT( theInstr ); 9720 UChar rA_addr = ifieldRegA(theInstr); 9721 IRTemp rA = newTemp( Ity_I32 ); 9722 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT); 9723 /* XS = SX || S 9724 * For SX=0, mtvsrwz is treated as a Floating-Point 9725 * instruction in terms of resource availability. 9726 * For SX=1, mtvsrwz is treated as a Vector instruction in 9727 * terms of resource availability. 9728 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9729 */ 9730 if (mode64) 9731 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 9732 else 9733 assign( rA, getIReg(rA_addr) ); 9734 9735 putVSReg( XT, binop( Iop_64HLtoV128, 9736 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 9737 mkU64( 0 ) ) ); 9738 break; 9739 } 9740 9741 default: 9742 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 9743 return False; 9744 } 9745 return True; 9746 } 9747 9748 9749 /* 9750 Cache Management Instructions 9751 */ 9752 static Bool dis_cache_manage ( UInt theInstr, 9753 DisResult* dres, 9754 const VexArchInfo* guest_archinfo ) 9755 { 9756 /* X-Form */ 9757 UChar opc1 = ifieldOPC(theInstr); 9758 UChar b21to25 = ifieldRegDS(theInstr); 9759 UChar rA_addr = ifieldRegA(theInstr); 9760 UChar rB_addr = ifieldRegB(theInstr); 9761 UInt opc2 = ifieldOPClo10(theInstr); 9762 UChar b0 = ifieldBIT0(theInstr); 9763 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 9764 Bool is_dcbzl = False; 9765 9766 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9767 9768 // Check for valid hint values for dcbt and dcbtst as currently described in 9769 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 9770 // means of modeling the hint anyway. 9771 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 9772 if (b21to25 == 0x10 || b21to25 < 0x10) 9773 b21to25 = 0; 9774 } 9775 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 9776 b21to25 = 0; 9777 9778 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 9779 if (b21to25 == 1) { 9780 is_dcbzl = True; 9781 b21to25 = 0; 9782 if (!(guest_archinfo->ppc_dcbzl_szB)) { 9783 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 9784 return False; 9785 } 9786 } 9787 } 9788 9789 if (opc1 != 0x1F || b0 != 0) { 9790 if (0) vex_printf("dis_cache_manage %d %d\n", 9791 opc1, b0); 9792 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n"); 9793 return False; 9794 } 9795 9796 /* stay sane .. */ 9797 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 9798 9799 switch (opc2) { 9800 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 9801 //zz vassert(0); /* AWAITING TEST CASE */ 9802 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 9803 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 9804 //zz break; 9805 9806 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 9807 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 9808 /* nop as far as vex is concerned */ 9809 break; 9810 9811 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 9812 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 9813 /* nop as far as vex is concerned */ 9814 break; 9815 9816 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 9817 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 9818 /* nop as far as vex is concerned */ 9819 break; 9820 9821 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 9822 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 9823 /* nop as far as vex is concerned */ 9824 break; 9825 9826 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 9827 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 9828 /* Clear all bytes in cache block at (rA|0) + rB. */ 9829 IRTemp EA = newTemp(ty); 9830 IRTemp addr = newTemp(ty); 9831 IRExpr* irx_addr; 9832 UInt i; 9833 UInt clearszB; 9834 if (is_dcbzl) { 9835 clearszB = guest_archinfo->ppc_dcbzl_szB; 9836 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 9837 } 9838 else { 9839 clearszB = guest_archinfo->ppc_dcbz_szB; 9840 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 9841 } 9842 9843 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 9844 9845 if (mode64) { 9846 /* Round EA down to the start of the containing block. */ 9847 assign( addr, binop( Iop_And64, 9848 mkexpr(EA), 9849 mkU64( ~((ULong)clearszB-1) )) ); 9850 9851 for (i = 0; i < clearszB / 8; i++) { 9852 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 9853 store( irx_addr, mkU64(0) ); 9854 } 9855 } else { 9856 /* Round EA down to the start of the containing block. */ 9857 assign( addr, binop( Iop_And32, 9858 mkexpr(EA), 9859 mkU32( ~(clearszB-1) )) ); 9860 9861 for (i = 0; i < clearszB / 4; i++) { 9862 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 9863 store( irx_addr, mkU32(0) ); 9864 } 9865 } 9866 break; 9867 } 9868 9869 case 0x3D6: { 9870 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 9871 /* Invalidate all translations containing code from the cache 9872 block at (rA|0) + rB. */ 9873 IRTemp EA = newTemp(ty); 9874 IRTemp addr = newTemp(ty); 9875 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 9876 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 9877 9878 /* Round EA down to the start of the containing block. */ 9879 assign( addr, binop( mkSzOp(ty, Iop_And8), 9880 mkexpr(EA), 9881 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 9882 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 9883 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 9884 9885 /* be paranoid ... */ 9886 stmt( IRStmt_MBE(Imbe_Fence) ); 9887 9888 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 9889 dres->jk_StopHere = Ijk_InvalICache; 9890 dres->whatNext = Dis_StopHere; 9891 break; 9892 } 9893 9894 default: 9895 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 9896 return False; 9897 } 9898 return True; 9899 } 9900 9901 9902 /*------------------------------------------------------------*/ 9903 /*--- Floating Point Helpers ---*/ 9904 /*------------------------------------------------------------*/ 9905 9906 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 9907 /* Produces a value in 0 .. 3, which is encoded as per the type 9908 IRRoundingMode. PPCRoundingMode encoding is different to 9909 IRRoundingMode, so need to map it. 9910 */ 9911 9912 static IRExpr* /* :: Ity_I32 */ set_round_to_Oddmode ( void ) 9913 { 9914 /* PPC/ valgrind have two-bits to designate the rounding mode. 9915 ISA 3.0 adds instructions than can use a round to odd mode 9916 but did not change the number of bits for the rm. Basically, 9917 they added two instructions that only differ by the rounding 9918 mode the operation uses. In essesce, they encoded the rm 9919 in the name. In order to avoid having to create Iops, that 9920 encode the rm in th name, we will "expand" the definition of 9921 the rounding mode bits. We will just pass the rm and then 9922 map the to odd mode to the appropriate PPCFpOp name that 9923 will tell us which instruction to map to. 9924 9925 rounding mode | PPC | IR 9926 ------------------------ 9927 to nearest | 000 | 00 9928 to zero | 001 | 11 9929 to +infinity | 010 | 10 9930 to -infinity | 011 | 01 9931 to odd | 1xx | xx 9932 */ 9933 return mkU32(8); 9934 } 9935 9936 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 9937 { 9938 /* 9939 rounding mode | PPC | IR 9940 ------------------------ 9941 to nearest | 00 | 00 9942 to zero | 01 | 11 9943 to +infinity | 10 | 10 9944 to -infinity | 11 | 01 9945 */ 9946 IRTemp rm_PPC32 = newTemp(Ity_I32); 9947 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 9948 9949 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 9950 return binop( Iop_Xor32, 9951 mkexpr(rm_PPC32), 9952 binop( Iop_And32, 9953 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 9954 mkU32(2) )); 9955 } 9956 9957 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 9958 * mapping would still work with the extended three bit DFP rounding 9959 * mode designator. 9960 9961 * rounding mode | PPC | IR 9962 * ----------------------------------------------- 9963 * to nearest, ties to even | 000 | 000 9964 * to zero | 001 | 011 9965 * to +infinity | 010 | 010 9966 * to -infinity | 011 | 001 9967 * to nearest, ties away from 0 | 100 | 100 9968 * to nearest, ties toward 0 | 101 | 111 9969 * to away from 0 | 110 | 110 9970 * to prepare for shorter precision | 111 | 101 9971 */ 9972 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 9973 { 9974 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 9975 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 9976 9977 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 9978 return binop( Iop_Xor32, 9979 mkexpr( rm_PPC32 ), 9980 binop( Iop_And32, 9981 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 9982 mkU32( 2 ) ) ); 9983 } 9984 9985 #define NANmaskSingle 0x7F800000 9986 #define NANmaskDouble 0x7FF00000 9987 9988 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 9989 { 9990 IRTemp exp_zero = newTemp(Ity_I8); 9991 IRTemp frac_mask = newTemp(Ity_I32); 9992 IRTemp frac_not_zero = newTemp(Ity_I8); 9993 9994 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 9995 * The input value is always 64-bits, for single precision values, the 9996 * lower 32 bits must be zero. 9997 * 9998 * Single Pricision 9999 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 10000 * [53:32] fraction field is zero for Infinity and non-zero for NAN 10001 * [31:0] unused for single precision representation 10002 * 10003 * Double Pricision 10004 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 10005 * [50:0] fraction field is zero for Infinity and non-zero for NAN 10006 * 10007 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 10008 */ 10009 assign( frac_mask, unop( Iop_Not32, 10010 binop( Iop_Or32, 10011 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 10012 10013 assign( exp_zero, 10014 unop( Iop_1Sto8, 10015 binop( Iop_CmpEQ32, 10016 binop( Iop_And32, 10017 unop( Iop_64HIto32, 10018 unop( Iop_ReinterpF64asI64, 10019 value ) ), 10020 Hi32Mask ), 10021 Hi32Mask ) ) ); 10022 assign( frac_not_zero, 10023 binop( Iop_Or8, 10024 unop( Iop_1Sto8, 10025 binop( Iop_CmpNE32, 10026 binop( Iop_And32, 10027 unop( Iop_64HIto32, 10028 unop( Iop_ReinterpF64asI64, 10029 value ) ), 10030 mkexpr( frac_mask ) ), 10031 mkU32( 0x0 ) ) ), 10032 unop( Iop_1Sto8, 10033 binop( Iop_CmpNE32, 10034 binop( Iop_And32, 10035 unop( Iop_64to32, 10036 unop( Iop_ReinterpF64asI64, 10037 value ) ), 10038 mkU32( 0xFFFFFFFF ) ), 10039 mkU32( 0x0 ) ) ) ) ); 10040 return unop( Iop_8Sto32, 10041 binop( Iop_And8, 10042 mkexpr( exp_zero ), 10043 mkexpr( frac_not_zero ) ) ); 10044 } 10045 10046 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 10047 { 10048 /* This function will only complement the 64-bit floating point value if it 10049 * is not Nan. NaN is not a signed value. Need to do computations using 10050 * 32-bit operands to ensure it will run in 32-bit mode. 10051 */ 10052 return binop( Iop_32HLto64, 10053 binop( Iop_Or32, 10054 binop( Iop_And32, 10055 nan_mask, 10056 unop( Iop_64HIto32, 10057 unop( Iop_ReinterpF64asI64, 10058 value ) ) ), 10059 binop( Iop_And32, 10060 unop( Iop_Not32, 10061 nan_mask ), 10062 unop( Iop_64HIto32, 10063 unop( Iop_ReinterpF64asI64, 10064 unop( Iop_NegF64, 10065 value ) ) ) ) ), 10066 unop( Iop_64to32, 10067 unop( Iop_ReinterpF64asI64, value ) ) ); 10068 } 10069 10070 /*------------------------------------------------------------*/ 10071 /*--- Floating Point Instruction Translation ---*/ 10072 /*------------------------------------------------------------*/ 10073 10074 /* 10075 Floating Point Load Instructions 10076 */ 10077 static Bool dis_fp_load ( UInt theInstr ) 10078 { 10079 /* X-Form, D-Form */ 10080 UChar opc1 = ifieldOPC(theInstr); 10081 UChar frD_addr = ifieldRegDS(theInstr); 10082 UChar rA_addr = ifieldRegA(theInstr); 10083 UChar rB_addr = ifieldRegB(theInstr); 10084 UInt opc2 = ifieldOPClo10(theInstr); 10085 UChar b0 = ifieldBIT0(theInstr); 10086 UInt uimm16 = ifieldUIMM16(theInstr); 10087 10088 Int simm16 = extend_s_16to32(uimm16); 10089 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10090 IRTemp EA = newTemp(ty); 10091 IRTemp rA = newTemp(ty); 10092 IRTemp rB = newTemp(ty); 10093 IRTemp iHi = newTemp(Ity_I32); 10094 IRTemp iLo = newTemp(Ity_I32); 10095 10096 assign( rA, getIReg(rA_addr) ); 10097 assign( rB, getIReg(rB_addr) ); 10098 10099 /* These are completely straightforward from a rounding and status 10100 bits perspective: no rounding involved and no funny status or CR 10101 bits affected. */ 10102 10103 switch (opc1) { 10104 case 0x30: // lfs (Load Float Single, PPC32 p441) 10105 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10106 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10107 putFReg( frD_addr, 10108 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10109 break; 10110 10111 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 10112 if (rA_addr == 0) 10113 return False; 10114 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10115 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10116 putFReg( frD_addr, 10117 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10118 putIReg( rA_addr, mkexpr(EA) ); 10119 break; 10120 10121 case 0x32: // lfd (Load Float Double, PPC32 p437) 10122 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10123 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10124 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10125 break; 10126 10127 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 10128 if (rA_addr == 0) 10129 return False; 10130 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10131 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10132 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10133 putIReg( rA_addr, mkexpr(EA) ); 10134 break; 10135 10136 case 0x1F: 10137 if (b0 != 0) { 10138 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 10139 return False; 10140 } 10141 10142 switch(opc2) { 10143 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 10144 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10145 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10146 putFReg( frD_addr, unop( Iop_F32toF64, 10147 load(Ity_F32, mkexpr(EA))) ); 10148 break; 10149 10150 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 10151 if (rA_addr == 0) 10152 return False; 10153 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10154 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10155 putFReg( frD_addr, 10156 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10157 putIReg( rA_addr, mkexpr(EA) ); 10158 break; 10159 10160 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 10161 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10162 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10163 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10164 break; 10165 10166 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 10167 if (rA_addr == 0) 10168 return False; 10169 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10170 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10171 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10172 putIReg( rA_addr, mkexpr(EA) ); 10173 break; 10174 10175 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 10176 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10177 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10178 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 10179 assign( iHi, binop(Iop_Sub32, 10180 mkU32(0), 10181 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 10182 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 10183 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 10184 break; 10185 10186 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 10187 { 10188 IRTemp dw = newTemp( Ity_I64 ); 10189 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10190 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10191 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 10192 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 10193 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 10194 break; 10195 } 10196 10197 default: 10198 vex_printf("dis_fp_load(ppc)(opc2)\n"); 10199 return False; 10200 } 10201 break; 10202 10203 default: 10204 vex_printf("dis_fp_load(ppc)(opc1)\n"); 10205 return False; 10206 } 10207 return True; 10208 } 10209 10210 10211 10212 /* 10213 Floating Point Store Instructions 10214 */ 10215 static Bool dis_fp_store ( UInt theInstr ) 10216 { 10217 /* X-Form, D-Form */ 10218 UChar opc1 = ifieldOPC(theInstr); 10219 UChar frS_addr = ifieldRegDS(theInstr); 10220 UChar rA_addr = ifieldRegA(theInstr); 10221 UChar rB_addr = ifieldRegB(theInstr); 10222 UInt opc2 = ifieldOPClo10(theInstr); 10223 UChar b0 = ifieldBIT0(theInstr); 10224 Int uimm16 = ifieldUIMM16(theInstr); 10225 10226 Int simm16 = extend_s_16to32(uimm16); 10227 IRTemp frS = newTemp(Ity_F64); 10228 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10229 IRTemp EA = newTemp(ty); 10230 IRTemp rA = newTemp(ty); 10231 IRTemp rB = newTemp(ty); 10232 10233 assign( frS, getFReg(frS_addr) ); 10234 assign( rA, getIReg(rA_addr) ); 10235 assign( rB, getIReg(rB_addr) ); 10236 10237 /* These are straightforward from a status bits perspective: no 10238 funny status or CR bits affected. For single precision stores, 10239 the values are truncated and denormalised (not rounded) to turn 10240 them into single precision values. */ 10241 10242 switch (opc1) { 10243 10244 case 0x34: // stfs (Store Float Single, PPC32 p518) 10245 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10246 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10247 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 10248 the value to be stored in the correct way, without any 10249 rounding. */ 10250 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10251 break; 10252 10253 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 10254 if (rA_addr == 0) 10255 return False; 10256 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10257 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10258 /* See comment for stfs */ 10259 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10260 putIReg( rA_addr, mkexpr(EA) ); 10261 break; 10262 10263 case 0x36: // stfd (Store Float Double, PPC32 p513) 10264 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10265 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10266 store( mkexpr(EA), mkexpr(frS) ); 10267 break; 10268 10269 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 10270 if (rA_addr == 0) 10271 return False; 10272 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10273 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10274 store( mkexpr(EA), mkexpr(frS) ); 10275 putIReg( rA_addr, mkexpr(EA) ); 10276 break; 10277 10278 case 0x1F: 10279 if (b0 != 0) { 10280 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 10281 return False; 10282 } 10283 switch(opc2) { 10284 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 10285 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10286 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10287 /* See note for stfs */ 10288 store( mkexpr(EA), 10289 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10290 break; 10291 10292 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 10293 if (rA_addr == 0) 10294 return False; 10295 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10296 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10297 /* See note for stfs */ 10298 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10299 putIReg( rA_addr, mkexpr(EA) ); 10300 break; 10301 10302 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 10303 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10304 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10305 store( mkexpr(EA), mkexpr(frS) ); 10306 break; 10307 10308 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 10309 if (rA_addr == 0) 10310 return False; 10311 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10312 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10313 store( mkexpr(EA), mkexpr(frS) ); 10314 putIReg( rA_addr, mkexpr(EA) ); 10315 break; 10316 10317 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 10318 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10319 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10320 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10321 store( mkexpr(EA), 10322 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 10323 break; 10324 10325 default: 10326 vex_printf("dis_fp_store(ppc)(opc2)\n"); 10327 return False; 10328 } 10329 break; 10330 10331 default: 10332 vex_printf("dis_fp_store(ppc)(opc1)\n"); 10333 return False; 10334 } 10335 return True; 10336 } 10337 10338 10339 10340 /* 10341 Floating Point Arith Instructions 10342 */ 10343 static Bool dis_fp_arith ( UInt theInstr ) 10344 { 10345 /* A-Form */ 10346 UChar opc1 = ifieldOPC(theInstr); 10347 UChar frD_addr = ifieldRegDS(theInstr); 10348 UChar frA_addr = ifieldRegA(theInstr); 10349 UChar frB_addr = ifieldRegB(theInstr); 10350 UChar frC_addr = ifieldRegC(theInstr); 10351 UChar opc2 = ifieldOPClo5(theInstr); 10352 UChar flag_rC = ifieldBIT0(theInstr); 10353 10354 IRTemp frD = newTemp(Ity_F64); 10355 IRTemp frA = newTemp(Ity_F64); 10356 IRTemp frB = newTemp(Ity_F64); 10357 IRTemp frC = newTemp(Ity_F64); 10358 IRExpr* rm = get_IR_roundingmode(); 10359 10360 /* By default, we will examine the results of the operation and set 10361 fpscr[FPRF] accordingly. */ 10362 Bool set_FPRF = True; 10363 10364 /* By default, if flag_RC is set, we will clear cr1 after the 10365 operation. In reality we should set cr1 to indicate the 10366 exception status of the operation, but since we're not 10367 simulating exceptions, the exception status will appear to be 10368 zero. Hence cr1 should be cleared if this is a . form insn. */ 10369 Bool clear_CR1 = True; 10370 10371 assign( frA, getFReg(frA_addr)); 10372 assign( frB, getFReg(frB_addr)); 10373 assign( frC, getFReg(frC_addr)); 10374 10375 switch (opc1) { 10376 case 0x3B: 10377 switch (opc2) { 10378 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 10379 if (frC_addr != 0) 10380 return False; 10381 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10382 frD_addr, frA_addr, frB_addr); 10383 assign( frD, triop( Iop_DivF64r32, 10384 rm, mkexpr(frA), mkexpr(frB) )); 10385 break; 10386 10387 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 10388 if (frC_addr != 0) 10389 return False; 10390 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10391 frD_addr, frA_addr, frB_addr); 10392 assign( frD, triop( Iop_SubF64r32, 10393 rm, mkexpr(frA), mkexpr(frB) )); 10394 break; 10395 10396 case 0x15: // fadds (Floating Add Single, PPC32 p401) 10397 if (frC_addr != 0) 10398 return False; 10399 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10400 frD_addr, frA_addr, frB_addr); 10401 assign( frD, triop( Iop_AddF64r32, 10402 rm, mkexpr(frA), mkexpr(frB) )); 10403 break; 10404 10405 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 10406 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 10407 if (frA_addr != 0 || frC_addr != 0) 10408 return False; 10409 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 10410 frD_addr, frB_addr); 10411 // however illogically, on ppc970 this insn behaves identically 10412 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 10413 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 10414 break; 10415 10416 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 10417 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10418 if (frA_addr != 0 || frC_addr != 0) 10419 return False; 10420 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 10421 frD_addr, frB_addr); 10422 { IRExpr* ieee_one 10423 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 10424 assign( frD, triop( Iop_DivF64r32, 10425 rm, 10426 ieee_one, mkexpr(frB) )); 10427 } 10428 break; 10429 10430 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 10431 if (frB_addr != 0) 10432 return False; 10433 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10434 frD_addr, frA_addr, frC_addr); 10435 assign( frD, triop( Iop_MulF64r32, 10436 rm, mkexpr(frA), mkexpr(frC) )); 10437 break; 10438 10439 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 10440 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10441 // Undocumented instruction? 10442 if (frA_addr != 0 || frC_addr != 0) 10443 return False; 10444 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 10445 frD_addr, frB_addr); 10446 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 10447 break; 10448 10449 default: 10450 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 10451 return False; 10452 } 10453 break; 10454 10455 case 0x3F: 10456 switch (opc2) { 10457 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 10458 if (frC_addr != 0) 10459 return False; 10460 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10461 frD_addr, frA_addr, frB_addr); 10462 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 10463 break; 10464 10465 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 10466 if (frC_addr != 0) 10467 return False; 10468 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10469 frD_addr, frA_addr, frB_addr); 10470 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 10471 break; 10472 10473 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 10474 if (frC_addr != 0) 10475 return False; 10476 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10477 frD_addr, frA_addr, frB_addr); 10478 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 10479 break; 10480 10481 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 10482 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 10483 if (frA_addr != 0 || frC_addr != 0) 10484 return False; 10485 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 10486 frD_addr, frB_addr); 10487 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 10488 break; 10489 10490 case 0x17: { // fsel (Floating Select, PPC32 p426) 10491 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10492 IRTemp cc = newTemp(Ity_I32); 10493 IRTemp cc_b0 = newTemp(Ity_I32); 10494 10495 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10496 frD_addr, frA_addr, frC_addr, frB_addr); 10497 10498 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 10499 // => GT|EQ == (cc & 0x1 == 0) 10500 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 10501 IRExpr_Const(IRConst_F64(0))) ); 10502 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 10503 10504 // frD = (frA >= 0.0) ? frC : frB 10505 // = (cc_b0 == 0) ? frC : frB 10506 assign( frD, 10507 IRExpr_ITE( 10508 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 10509 mkexpr(frC), 10510 mkexpr(frB) )); 10511 10512 /* One of the rare ones which don't mess with FPRF */ 10513 set_FPRF = False; 10514 break; 10515 } 10516 10517 case 0x18: // fre (Floating Reciprocal Estimate) 10518 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10519 // Note: unclear whether this insn really exists or not 10520 // ppc970 doesn't have it, but POWER5 does 10521 if (frA_addr != 0 || frC_addr != 0) 10522 return False; 10523 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 10524 frD_addr, frB_addr); 10525 { IRExpr* ieee_one 10526 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 10527 assign( frD, triop( Iop_DivF64, 10528 rm, 10529 ieee_one, mkexpr(frB) )); 10530 } 10531 break; 10532 10533 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 10534 if (frB_addr != 0) 10535 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 10536 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10537 frD_addr, frA_addr, frC_addr); 10538 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 10539 break; 10540 10541 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 10542 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10543 if (frA_addr != 0 || frC_addr != 0) 10544 return False; 10545 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 10546 frD_addr, frB_addr); 10547 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 10548 break; 10549 10550 default: 10551 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 10552 return False; 10553 } 10554 break; 10555 10556 default: 10557 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 10558 return False; 10559 } 10560 10561 putFReg( frD_addr, mkexpr(frD) ); 10562 10563 if (set_FPRF) { 10564 // XXX XXX XXX FIXME 10565 // set FPRF from frD 10566 } 10567 10568 if (flag_rC && clear_CR1) { 10569 putCR321( 1, mkU8(0) ); 10570 putCR0( 1, mkU8(0) ); 10571 } 10572 10573 return True; 10574 } 10575 10576 10577 10578 /* 10579 Floating Point Mult-Add Instructions 10580 */ 10581 static Bool dis_fp_multadd ( UInt theInstr ) 10582 { 10583 /* A-Form */ 10584 UChar opc1 = ifieldOPC(theInstr); 10585 UChar frD_addr = ifieldRegDS(theInstr); 10586 UChar frA_addr = ifieldRegA(theInstr); 10587 UChar frB_addr = ifieldRegB(theInstr); 10588 UChar frC_addr = ifieldRegC(theInstr); 10589 UChar opc2 = ifieldOPClo5(theInstr); 10590 UChar flag_rC = ifieldBIT0(theInstr); 10591 10592 IRTemp frD = newTemp(Ity_F64); 10593 IRTemp frA = newTemp(Ity_F64); 10594 IRTemp frB = newTemp(Ity_F64); 10595 IRTemp frC = newTemp(Ity_F64); 10596 IRTemp rmt = newTemp(Ity_I32); 10597 IRTemp tmp = newTemp(Ity_F64); 10598 IRTemp sign_tmp = newTemp(Ity_I64); 10599 IRTemp nan_mask = newTemp(Ity_I32); 10600 IRExpr* rm; 10601 10602 /* By default, we will examine the results of the operation and set 10603 fpscr[FPRF] accordingly. */ 10604 Bool set_FPRF = True; 10605 10606 /* By default, if flag_RC is set, we will clear cr1 after the 10607 operation. In reality we should set cr1 to indicate the 10608 exception status of the operation, but since we're not 10609 simulating exceptions, the exception status will appear to be 10610 zero. Hence cr1 should be cleared if this is a . form insn. */ 10611 Bool clear_CR1 = True; 10612 10613 /* Bind the rounding mode expression to a temp; there's no 10614 point in creating gratuitous CSEs, as we know we'll need 10615 to use it twice. */ 10616 assign( rmt, get_IR_roundingmode() ); 10617 rm = mkexpr(rmt); 10618 10619 assign( frA, getFReg(frA_addr)); 10620 assign( frB, getFReg(frB_addr)); 10621 assign( frC, getFReg(frC_addr)); 10622 10623 /* The rounding in this is all a bit dodgy. The idea is to only do 10624 one rounding. That clearly isn't achieveable without dedicated 10625 four-input IR primops, although in the single precision case we 10626 can sort-of simulate it by doing the inner multiply in double 10627 precision. 10628 10629 In the negated cases, the negation happens after rounding. */ 10630 10631 switch (opc1) { 10632 case 0x3B: 10633 switch (opc2) { 10634 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 10635 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10636 frD_addr, frA_addr, frC_addr, frB_addr); 10637 assign( frD, qop( Iop_MSubF64r32, rm, 10638 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10639 break; 10640 10641 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 10642 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10643 frD_addr, frA_addr, frC_addr, frB_addr); 10644 assign( frD, qop( Iop_MAddF64r32, rm, 10645 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10646 break; 10647 10648 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 10649 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 10650 10651 if (opc2 == 0x1E) { 10652 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10653 frD_addr, frA_addr, frC_addr, frB_addr); 10654 assign( tmp, qop( Iop_MSubF64r32, rm, 10655 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10656 } else { 10657 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10658 frD_addr, frA_addr, frC_addr, frB_addr); 10659 assign( tmp, qop( Iop_MAddF64r32, rm, 10660 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10661 } 10662 10663 assign( nan_mask, Check_NaN( mkexpr( tmp ), 10664 mkU32( NANmaskSingle ) ) ); 10665 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 10666 mkexpr( nan_mask ) ) ); 10667 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 10668 break; 10669 10670 default: 10671 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 10672 return False; 10673 } 10674 break; 10675 10676 case 0x3F: 10677 switch (opc2) { 10678 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 10679 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10680 frD_addr, frA_addr, frC_addr, frB_addr); 10681 assign( frD, qop( Iop_MSubF64, rm, 10682 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10683 break; 10684 10685 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 10686 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10687 frD_addr, frA_addr, frC_addr, frB_addr); 10688 assign( frD, qop( Iop_MAddF64, rm, 10689 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10690 break; 10691 10692 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 10693 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 10694 10695 if (opc2 == 0x1E) { 10696 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10697 frD_addr, frA_addr, frC_addr, frB_addr); 10698 assign( tmp, qop( Iop_MSubF64, rm, 10699 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10700 } else { 10701 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10702 frD_addr, frA_addr, frC_addr, frB_addr); 10703 assign( tmp, qop( Iop_MAddF64, rm, 10704 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10705 } 10706 10707 assign( nan_mask, Check_NaN( mkexpr( tmp ), 10708 mkU32( NANmaskDouble ) ) ); 10709 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 10710 mkexpr( nan_mask ) ) ); 10711 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 10712 break; 10713 10714 default: 10715 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 10716 return False; 10717 } 10718 break; 10719 10720 default: 10721 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 10722 return False; 10723 } 10724 10725 putFReg( frD_addr, mkexpr(frD) ); 10726 10727 if (set_FPRF) { 10728 // XXX XXX XXX FIXME 10729 // set FPRF from frD 10730 } 10731 10732 if (flag_rC && clear_CR1) { 10733 putCR321( 1, mkU8(0) ); 10734 putCR0( 1, mkU8(0) ); 10735 } 10736 10737 return True; 10738 } 10739 10740 /* 10741 * fe_flag is set to 1 if any of the following conditions occurs: 10742 * - The floating-point operand in register FRB is a Zero, a 10743 * NaN, an Infinity, or a negative value. 10744 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 10745 * Otherwise fe_flag is set to 0. 10746 * 10747 * fg_flag is set to 1 if either of the following conditions occurs. 10748 * - The floating-point operand in register FRB is a Zero, an 10749 * Infinity, or a denormalized value. 10750 * Otherwise fg_flag is set to 0. 10751 * 10752 */ 10753 10754 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 10755 { 10756 // The following temps are for holding intermediate results 10757 IRTemp e_b = newTemp(Ity_I32); 10758 IRExpr * fe_flag, * fg_flag; 10759 IRTemp frB_exp_shR = newTemp(Ity_I32); 10760 UInt bias = sp? 127 : 1023; 10761 IRExpr * frbNaN, * frbDenorm, * frBNeg; 10762 IRExpr * eb_LTE; 10763 IRTemp frbZero_tmp = newTemp(Ity_I1); 10764 IRTemp frbInf_tmp = newTemp(Ity_I1); 10765 *fe_flag_tmp = newTemp(Ity_I32); 10766 *fg_flag_tmp = newTemp(Ity_I32); 10767 10768 if ( sp ) 10769 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) ); 10770 else 10771 assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_Int ) ); 10772 10773 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 10774 10775 ////////////////// fe_flag tests BEGIN ////////////////////// 10776 /* We first do all tests that may result in setting fe_flag to '1'. 10777 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 10778 * for details.) 10779 */ 10780 if ( sp ) { 10781 frbNaN = is_NaN( Ity_I32, frB_Int ); 10782 assign( frbInf_tmp, is_Inf( Ity_I32, frB_Int ) ); 10783 assign( frbZero_tmp, is_Zero( Ity_I32, frB_Int ) ); 10784 10785 } else { 10786 frbNaN = is_NaN( Ity_I64, frB_Int ); 10787 assign( frbInf_tmp, is_Inf( Ity_I64, frB_Int ) ); 10788 assign( frbZero_tmp, is_Zero( Ity_I64, frB_Int ) ); 10789 } 10790 10791 { 10792 // Test_value = -970 for double precision 10793 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 10794 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 10795 } 10796 frBNeg = binop( Iop_CmpEQ32, 10797 binop( Iop_Shr32, 10798 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 10799 mkU8( 31 ) ), 10800 mkU32( 1 ) ); 10801 ////////////////// fe_flag tests END ////////////////////// 10802 10803 ////////////////// fg_flag tests BEGIN ////////////////////// 10804 /* 10805 * The following tests were already performed above in the fe_flag 10806 * tests. So these conditions will result in both fe_ and fg_ flags 10807 * being set. 10808 * - Test if FRB is Zero 10809 * - Test if FRB is an Infinity 10810 */ 10811 10812 /* 10813 * Test if FRB holds a denormalized value. A denormalized value is one where 10814 * the exp is 0 and the fraction is non-zero. 10815 */ 10816 if (sp) { 10817 IRTemp frac_part = newTemp(Ity_I32); 10818 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 10819 frbDenorm 10820 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 10821 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 10822 } else { 10823 IRExpr * hi32, * low32, * fraction_is_nonzero; 10824 IRTemp frac_part = newTemp(Ity_I64); 10825 10826 assign( frac_part, FP_FRAC_PART(frB_Int) ); 10827 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 10828 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 10829 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 10830 mkU32( 0 ) ); 10831 frbDenorm 10832 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 10833 fraction_is_nonzero ); 10834 } 10835 ////////////////// fg_flag tests END ////////////////////// 10836 10837 ///////////////////////// 10838 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 10839 mkOR1( frbNaN, 10840 mkOR1( mkexpr( frbInf_tmp ), 10841 mkOR1( frBNeg, eb_LTE ) ) ) ); 10842 10843 fe_flag = unop(Iop_1Uto32, fe_flag); 10844 10845 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 10846 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 10847 fg_flag = unop(Iop_1Uto32, fg_flag); 10848 assign (*fg_flag_tmp, fg_flag); 10849 assign (*fe_flag_tmp, fe_flag); 10850 } 10851 /* 10852 * fe_flag is set to 1 if any of the following conditions occurs: 10853 * - The double-precision floating-point operand in register FRA is a NaN or an 10854 * Infinity. 10855 * - The double-precision floating-point operand in register FRB is a Zero, a 10856 * NaN, or an Infinity. 10857 * - e_b is less than or equal to -1022. 10858 * - e_b is greater than or equal to 1021. 10859 * - The double-precision floating-point operand in register FRA is not a zero 10860 * and the difference, e_a - e_b, is greater than or equal to 1023. 10861 * - The double-precision floating-point operand in register FRA is not a zero 10862 * and the difference, e_a - e_b, is less than or equal to -1021. 10863 * - The double-precision floating-point operand in register FRA is not a zero 10864 * and e_a is less than or equal to -970 10865 * Otherwise fe_flag is set to 0. 10866 * 10867 * fg_flag is set to 1 if either of the following conditions occurs. 10868 * - The double-precision floating-point operand in register FRA is an Infinity. 10869 * - The double-precision floating-point operand in register FRB is a Zero, an 10870 * Infinity, or a denormalized value. 10871 * Otherwise fg_flag is set to 0. 10872 * 10873 */ 10874 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 10875 { 10876 // The following temps are for holding intermediate results 10877 IRTemp e_a = newTemp(Ity_I32); 10878 IRTemp e_b = newTemp(Ity_I32); 10879 IRTemp frA_exp_shR = newTemp(Ity_I32); 10880 IRTemp frB_exp_shR = newTemp(Ity_I32); 10881 10882 UInt bias = sp? 127 : 1023; 10883 *fe_flag_tmp = newTemp(Ity_I32); 10884 *fg_flag_tmp = newTemp(Ity_I32); 10885 10886 /* The following variables hold boolean results from tests 10887 * that are OR'ed together for setting the fe_ and fg_ flags. 10888 * For some cases, the booleans are used more than once, so 10889 * I make those IRTemp's instead of IRExpr's. 10890 */ 10891 IRExpr * fraNaN, * frbNaN, * frbDenorm; 10892 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 10893 IRTemp fraInf_tmp = newTemp(Ity_I1); 10894 IRTemp frbZero_tmp = newTemp(Ity_I1); 10895 IRTemp frbInf_tmp = newTemp(Ity_I1); 10896 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 10897 10898 /* The following are the flags that are set by OR'ing the results of 10899 * all the tests done for tdiv. These flags are the input to the specified CR. 10900 */ 10901 IRExpr * fe_flag, * fg_flag; 10902 10903 // Create temps that will be used throughout the following tests. 10904 if ( sp ) { 10905 assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) ); 10906 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) ); 10907 } else{ 10908 assign( frA_exp_shR, fp_exp_part( Ity_I64, frA_int ) ); 10909 assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_int ) ); 10910 } 10911 10912 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 10913 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 10914 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 10915 10916 10917 ////////////////// fe_flag tests BEGIN ////////////////////// 10918 /* We first do all tests that may result in setting fe_flag to '1'. */ 10919 10920 /* 10921 * Test if the double-precision floating-point operand in register FRA is 10922 * a NaN: 10923 */ 10924 fraNaN = sp ? is_NaN( Ity_I32, frA_int ) : is_NaN( Ity_I64, frA_int ); 10925 /* 10926 * Test if the double-precision floating-point operands in register FRA 10927 * and FRB is an Infinity. Test if FRB is zero. 10928 */ 10929 if ( sp ) { 10930 assign(fraInf_tmp, is_Inf( Ity_I32, frA_int ) ); 10931 assign( frbInf_tmp, is_Inf( Ity_I32, frB_int ) ); 10932 assign( frbZero_tmp, is_Zero( Ity_I32, frB_int ) ); 10933 10934 } else { 10935 assign(fraInf_tmp, is_Inf( Ity_I64, frA_int ) ); 10936 assign( frbInf_tmp, is_Inf( Ity_I64, frB_int ) ); 10937 assign( frbZero_tmp, is_Zero( Ity_I64, frB_int ) ); 10938 } 10939 /* 10940 * Test if the double-precision floating-point operand in register FRB is 10941 * a NaN: 10942 */ 10943 frbNaN = sp ? is_NaN( Ity_I32, frB_int ) : is_NaN( Ity_I64, frB_int ); 10944 10945 /* 10946 * Test if e_b <= -1022 for double precision; 10947 * or e_b <= -126 for single precision 10948 */ 10949 { 10950 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 10951 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 10952 } 10953 10954 /* 10955 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 10956 * or e_b >= -125 (125 < e_b) for single precision 10957 */ 10958 { 10959 Int test_value = sp ? 125 : 1021; 10960 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 10961 } 10962 10963 /* 10964 * Test if FRA != Zero and (e_a - e_b) >= bias 10965 */ 10966 if ( sp ) 10967 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) ); 10968 else 10969 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I64, frA_int ) ) ); 10970 10971 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 10972 binop( Iop_CmpLT32S, mkU32( bias ), 10973 binop( Iop_Sub32, mkexpr( e_a ), 10974 mkexpr( e_b ) ) ) ); 10975 10976 /* 10977 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 10978 */ 10979 { 10980 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 10981 10982 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 10983 binop( Iop_CmpLE32S, 10984 binop( Iop_Sub32, 10985 mkexpr( e_a ), 10986 mkexpr( e_b ) ), 10987 mkU32( test_value ) ) ); 10988 } 10989 10990 /* 10991 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 10992 */ 10993 { 10994 UInt test_value = 0xfffffc36; //Int test_value = -970; 10995 10996 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 10997 mkexpr( e_a ), 10998 mkU32( test_value ) ) ); 10999 } 11000 ////////////////// fe_flag tests END ////////////////////// 11001 11002 ////////////////// fg_flag tests BEGIN ////////////////////// 11003 /* 11004 * The following tests were already performed above in the fe_flag 11005 * tests. So these conditions will result in both fe_ and fg_ flags 11006 * being set. 11007 * - Test if FRA is an Infinity 11008 * - Test if FRB ix Zero 11009 * - Test if FRB is an Infinity 11010 */ 11011 11012 /* 11013 * Test if FRB holds a denormalized value. A denormalized value is one where 11014 * the exp is 0 and the fraction is non-zero. 11015 */ 11016 { 11017 IRExpr * fraction_is_nonzero; 11018 11019 if (sp) { 11020 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 11021 mkU32( 0 ) ); 11022 } else { 11023 IRExpr * hi32, * low32; 11024 IRTemp frac_part = newTemp(Ity_I64); 11025 assign( frac_part, FP_FRAC_PART(frB_int) ); 11026 11027 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 11028 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 11029 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 11030 mkU32( 0 ) ); 11031 } 11032 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 11033 mkU32( 0x0 ) ), fraction_is_nonzero ); 11034 11035 } 11036 ////////////////// fg_flag tests END ////////////////////// 11037 11038 fe_flag 11039 = mkOR1( 11040 fraNaN, 11041 mkOR1( 11042 mkexpr( fraInf_tmp ), 11043 mkOR1( 11044 mkexpr( frbZero_tmp ), 11045 mkOR1( 11046 frbNaN, 11047 mkOR1( 11048 mkexpr( frbInf_tmp ), 11049 mkOR1( eb_LTE, 11050 mkOR1( eb_GTE, 11051 mkOR1( ea_eb_GTE, 11052 mkOR1( ea_eb_LTE, 11053 ea_LTE ) ) ) ) ) ) ) ) ); 11054 11055 fe_flag = unop(Iop_1Uto32, fe_flag); 11056 11057 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 11058 mkOR1( mkexpr( frbInf_tmp ), 11059 frbDenorm ) ) ); 11060 fg_flag = unop(Iop_1Uto32, fg_flag); 11061 assign(*fe_flag_tmp, fe_flag); 11062 assign(*fg_flag_tmp, fg_flag); 11063 } 11064 11065 /* See description for _do_fp_tdiv() above. */ 11066 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 11067 { 11068 IRTemp fe_flag, fg_flag; 11069 ///////////////////////// 11070 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 11071 * where fl_flag == 1 on ppc64. 11072 */ 11073 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 11074 fe_flag = fg_flag = IRTemp_INVALID; 11075 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 11076 return binop( Iop_Or32, 11077 binop( Iop_Or32, 11078 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 11079 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 11080 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 11081 } 11082 11083 static Bool dis_fp_tests ( UInt theInstr ) 11084 { 11085 UChar opc1 = ifieldOPC(theInstr); 11086 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11087 UChar frB_addr = ifieldRegB(theInstr); 11088 UChar b0 = ifieldBIT0(theInstr); 11089 UInt opc2 = ifieldOPClo10(theInstr); 11090 IRTemp frB_I64 = newTemp(Ity_I64); 11091 11092 if (opc1 != 0x3F || b0 != 0 ){ 11093 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 11094 return False; 11095 } 11096 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 11097 11098 switch (opc2) { 11099 case 0x080: // ftdiv 11100 { 11101 UChar frA_addr = ifieldRegA(theInstr); 11102 IRTemp frA_I64 = newTemp(Ity_I64); 11103 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11104 if (b21to22 != 0 ) { 11105 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 11106 return False; 11107 } 11108 11109 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 11110 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 11111 11112 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11113 break; 11114 } 11115 case 0x0A0: // ftsqrt 11116 { 11117 IRTemp flags = newTemp(Ity_I32); 11118 IRTemp fe_flag, fg_flag; 11119 fe_flag = fg_flag = IRTemp_INVALID; 11120 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 11121 if ( b18to22 != 0) { 11122 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 11123 return False; 11124 } 11125 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 11126 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 11127 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 11128 * where fl_flag == 1 on ppc64. 11129 */ 11130 assign( flags, 11131 binop( Iop_Or32, 11132 binop( Iop_Or32, mkU32( 8 ), // fl_flag 11133 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 11134 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 11135 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 11136 break; 11137 } 11138 11139 default: 11140 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 11141 return False; 11142 11143 } 11144 return True; 11145 } 11146 11147 /* 11148 Floating Point Compare Instructions 11149 */ 11150 static Bool dis_fp_cmp ( UInt theInstr ) 11151 { 11152 /* X-Form */ 11153 UChar opc1 = ifieldOPC(theInstr); 11154 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11155 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11156 UChar frA_addr = ifieldRegA(theInstr); 11157 UChar frB_addr = ifieldRegB(theInstr); 11158 UInt opc2 = ifieldOPClo10(theInstr); 11159 UChar b0 = ifieldBIT0(theInstr); 11160 11161 IRTemp ccIR = newTemp(Ity_I32); 11162 IRTemp ccPPC32 = newTemp(Ity_I32); 11163 11164 IRTemp frA = newTemp(Ity_F64); 11165 IRTemp frB = newTemp(Ity_F64); 11166 11167 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 11168 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 11169 return False; 11170 } 11171 11172 assign( frA, getFReg(frA_addr)); 11173 assign( frB, getFReg(frB_addr)); 11174 11175 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 11176 11177 /* Map compare result from IR to PPC32 */ 11178 /* 11179 FP cmp result | PPC | IR 11180 -------------------------- 11181 UN | 0x1 | 0x45 11182 EQ | 0x2 | 0x40 11183 GT | 0x4 | 0x00 11184 LT | 0x8 | 0x01 11185 */ 11186 11187 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 11188 // | ((ccIR ^ (ccIR>>6)) & 1) 11189 assign( 11190 ccPPC32, 11191 binop( 11192 Iop_Shl32, 11193 mkU32(1), 11194 unop( 11195 Iop_32to8, 11196 binop( 11197 Iop_Or32, 11198 binop( 11199 Iop_And32, 11200 unop( 11201 Iop_Not32, 11202 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 11203 ), 11204 mkU32(2) 11205 ), 11206 binop( 11207 Iop_And32, 11208 binop( 11209 Iop_Xor32, 11210 mkexpr(ccIR), 11211 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 11212 ), 11213 mkU32(1) 11214 ) 11215 ) 11216 ) 11217 ) 11218 ); 11219 11220 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 11221 putFPCC( mkexpr( ccPPC32 ) ); 11222 11223 // XXX XXX XXX FIXME 11224 // Also write the result into FPRF (it's not entirely clear how) 11225 11226 /* Note: Differences between fcmpu and fcmpo are only in exception 11227 flag settings, which aren't supported anyway. */ 11228 switch (opc2) { 11229 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 11230 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11231 break; 11232 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 11233 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11234 break; 11235 default: 11236 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 11237 return False; 11238 } 11239 return True; 11240 } 11241 11242 11243 11244 /* 11245 Floating Point Rounding/Conversion Instructions 11246 */ 11247 static Bool dis_fp_round ( UInt theInstr ) 11248 { 11249 /* X-Form */ 11250 UChar opc1 = ifieldOPC(theInstr); 11251 UChar b16to20 = ifieldRegA(theInstr); 11252 UChar frD_addr = ifieldRegDS(theInstr); 11253 UChar frB_addr = ifieldRegB(theInstr); 11254 UInt opc2 = ifieldOPClo10(theInstr); 11255 UChar flag_rC = ifieldBIT0(theInstr); 11256 11257 IRTemp frD = newTemp(Ity_F64); 11258 IRTemp frB = newTemp(Ity_F64); 11259 IRTemp r_tmp32 = newTemp(Ity_I32); 11260 IRTemp r_tmp64 = newTemp(Ity_I64); 11261 IRExpr* rm = get_IR_roundingmode(); 11262 11263 /* By default, we will examine the results of the operation and set 11264 fpscr[FPRF] accordingly. */ 11265 Bool set_FPRF = True; 11266 11267 /* By default, if flag_RC is set, we will clear cr1 after the 11268 operation. In reality we should set cr1 to indicate the 11269 exception status of the operation, but since we're not 11270 simulating exceptions, the exception status will appear to be 11271 zero. Hence cr1 should be cleared if this is a . form insn. */ 11272 Bool clear_CR1 = True; 11273 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 11274 vex_printf("dis_fp_round(ppc)(instr)\n"); 11275 return False; 11276 } 11277 11278 assign( frB, getFReg(frB_addr)); 11279 if (opc1 == 0x3B) { 11280 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 11281 * they're very similar to the other instructions handled here, but have 11282 * a different primary opcode. 11283 */ 11284 switch (opc2) { 11285 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 11286 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11287 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11288 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 11289 mkexpr( r_tmp64 ) ) ) ); 11290 goto putFR; 11291 11292 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 11293 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11294 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11295 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 11296 goto putFR; 11297 } 11298 } 11299 11300 11301 switch (opc2) { 11302 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 11303 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11304 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 11305 break; 11306 11307 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 11308 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11309 assign( r_tmp32, 11310 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 11311 assign( frD, unop( Iop_ReinterpI64asF64, 11312 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11313 /* FPRF is undefined after fctiw. Leave unchanged. */ 11314 set_FPRF = False; 11315 break; 11316 11317 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 11318 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11319 assign( r_tmp32, 11320 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 11321 assign( frD, unop( Iop_ReinterpI64asF64, 11322 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11323 /* FPRF is undefined after fctiwz. Leave unchanged. */ 11324 set_FPRF = False; 11325 break; 11326 11327 case 0x08F: case 0x08E: // fctiwu[z] 11328 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 11329 flag_rC ? ".":"", frD_addr, frB_addr); 11330 assign( r_tmp32, 11331 binop( Iop_F64toI32U, 11332 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 11333 mkexpr( frB ) ) ); 11334 assign( frD, unop( Iop_ReinterpI64asF64, 11335 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11336 /* FPRF is undefined after fctiwz. Leave unchanged. */ 11337 set_FPRF = False; 11338 break; 11339 11340 11341 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 11342 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11343 assign( r_tmp64, 11344 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 11345 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11346 /* FPRF is undefined after fctid. Leave unchanged. */ 11347 set_FPRF = False; 11348 break; 11349 11350 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 11351 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11352 assign( r_tmp64, 11353 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 11354 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11355 /* FPRF is undefined after fctidz. Leave unchanged. */ 11356 set_FPRF = False; 11357 break; 11358 11359 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 11360 { 11361 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 11362 flag_rC ? ".":"", frD_addr, frB_addr); 11363 assign( r_tmp64, 11364 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 11365 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11366 /* FPRF is undefined after fctidz. Leave unchanged. */ 11367 set_FPRF = False; 11368 break; 11369 } 11370 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 11371 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11372 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11373 assign( frD, 11374 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 11375 break; 11376 11377 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 11378 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11379 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11380 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 11381 break; 11382 11383 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 11384 switch(opc2) { 11385 case 0x188: // frin (Floating Round to Integer Nearest) 11386 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11387 assign( r_tmp64, 11388 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 11389 break; 11390 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 11391 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11392 assign( r_tmp64, 11393 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 11394 break; 11395 case 0x1C8: // frip (Floating Round to Integer Plus) 11396 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11397 assign( r_tmp64, 11398 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 11399 break; 11400 case 0x1E8: // frim (Floating Round to Integer Minus) 11401 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11402 assign( r_tmp64, 11403 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 11404 break; 11405 } 11406 11407 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 11408 /* F64 has only log10(2**52) significant digits anyway */ 11409 /* need to preserve sign of zero */ 11410 /* frD = (fabs(frB) > 9e18) ? frB : 11411 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 11412 assign(frD, IRExpr_ITE( 11413 binop(Iop_CmpNE8, 11414 unop(Iop_32to8, 11415 binop(Iop_CmpF64, 11416 IRExpr_Const(IRConst_F64(9e18)), 11417 unop(Iop_AbsF64, mkexpr(frB)))), 11418 mkU8(0)), 11419 mkexpr(frB), 11420 IRExpr_ITE( 11421 binop(Iop_CmpNE32, 11422 binop(Iop_Shr32, 11423 unop(Iop_64HIto32, 11424 unop(Iop_ReinterpF64asI64, 11425 mkexpr(frB))), 11426 mkU8(31)), 11427 mkU32(0)), 11428 unop(Iop_NegF64, 11429 unop( Iop_AbsF64, 11430 binop(Iop_I64StoF64, mkU32(0), 11431 mkexpr(r_tmp64)) )), 11432 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 11433 ) 11434 )); 11435 break; 11436 11437 default: 11438 vex_printf("dis_fp_round(ppc)(opc2)\n"); 11439 return False; 11440 } 11441 putFR: 11442 putFReg( frD_addr, mkexpr(frD) ); 11443 11444 if (set_FPRF) { 11445 // XXX XXX XXX FIXME 11446 // set FPRF from frD 11447 } 11448 11449 if (flag_rC && clear_CR1) { 11450 putCR321( 1, mkU8(0) ); 11451 putCR0( 1, mkU8(0) ); 11452 } 11453 11454 return True; 11455 } 11456 11457 /* 11458 Floating Point Pair Instructions 11459 */ 11460 static Bool dis_fp_pair ( UInt theInstr ) 11461 { 11462 /* X-Form/DS-Form */ 11463 UChar opc1 = ifieldOPC(theInstr); 11464 UChar frT_hi_addr = ifieldRegDS(theInstr); 11465 UChar frT_lo_addr = frT_hi_addr + 1; 11466 UChar rA_addr = ifieldRegA(theInstr); 11467 UChar rB_addr = ifieldRegB(theInstr); 11468 UInt uimm16 = ifieldUIMM16(theInstr); 11469 Int simm16 = extend_s_16to32(uimm16); 11470 UInt opc2 = ifieldOPClo10(theInstr); 11471 IRType ty = mode64 ? Ity_I64 : Ity_I32; 11472 IRTemp EA_hi = newTemp(ty); 11473 IRTemp EA_lo = newTemp(ty); 11474 IRTemp frT_hi = newTemp(Ity_F64); 11475 IRTemp frT_lo = newTemp(Ity_F64); 11476 UChar b0 = ifieldBIT0(theInstr); 11477 Bool is_load = 0; 11478 11479 switch (opc1) { 11480 case 0x1F: // register offset 11481 /* These instructions work on a pair of registers. The specified 11482 * register must be even. 11483 */ 11484 if ((frT_hi_addr %2) != 0) { 11485 vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n"); 11486 return False; 11487 } 11488 11489 switch(opc2) { 11490 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 11491 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 11492 is_load = 1; 11493 break; 11494 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 11495 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 11496 break; 11497 default: 11498 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 11499 return False; 11500 } 11501 11502 if (b0 != 0) { 11503 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 11504 return False; 11505 } 11506 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 11507 break; 11508 case 0x39: 11509 { 11510 UInt DS = IFIELD( theInstr, 2, 14); 11511 UChar vRT = ifieldRegDS(theInstr); 11512 IRTemp EA = newTemp( ty ); 11513 11514 opc2 = ifieldOPC0o2(theInstr); 11515 11516 switch(opc2) { 11517 case 0x0: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 11518 /* This instruction works on a pair of registers. The specified 11519 * register must be even. 11520 */ 11521 if ((frT_hi_addr %2) != 0) { 11522 vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n"); 11523 return False; 11524 } 11525 11526 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 11527 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 11528 is_load = 1; 11529 break; 11530 11531 case 0x2: // lxsd (Load VSX Scalar Doubleword) 11532 DIP("lxsd v%u,%d(r%u)\n", vRT, DS, rA_addr); 11533 11534 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11535 11536 putVSReg( vRT+32, binop( Iop_64HLtoV128, 11537 load( Ity_I64, mkexpr( EA ) ), 11538 mkU64( 0 ) ) ); 11539 return True; 11540 11541 case 0x3: // lxssp (Load VSX Scalar Single) 11542 DIP("lxssp v%u,%d(r%u)\n", vRT, DS, rA_addr); 11543 11544 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11545 11546 putVSReg( vRT+32, binop( Iop_64HLtoV128, 11547 binop( Iop_32HLto64, 11548 load( Ity_I32, mkexpr( EA ) ), 11549 mkU32( 0 ) ), 11550 mkU64( 0 ) ) ); 11551 return True; 11552 11553 default: 11554 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); 11555 return False; 11556 } 11557 break; 11558 } 11559 case 0x3d: 11560 { 11561 UInt DS = IFIELD( theInstr, 2, 14); 11562 UChar vRS = ifieldRegDS(theInstr); 11563 IRTemp EA = newTemp( ty ); 11564 11565 opc2 = ifieldOPC0o2(theInstr); 11566 11567 switch(opc2) { 11568 case 0x0: 11569 // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 11570 /* This instruction works on a pair of registers. The specified 11571 * register must be even. 11572 */ 11573 if ((frT_hi_addr %2) != 0) { 11574 vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n"); 11575 return False; 11576 } 11577 11578 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 11579 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 11580 break; 11581 11582 case 0x1: 11583 { 11584 UInt ea_off = 8; 11585 IRTemp word[2]; 11586 IRExpr* irx_addr; 11587 UInt T = IFIELD( theInstr, 21, 5); // T or S depending on inst 11588 UInt TX = IFIELD( theInstr, 3, 1); // TX or SX field 11589 11590 word[0] = newTemp(Ity_I64); 11591 word[1] = newTemp(Ity_I64); 11592 DS = IFIELD( theInstr, 4, 12); // DQ in the instruction definition 11593 assign( EA, ea_rAor0_simm( rA_addr, DS<<4 ) ); 11594 11595 if ( IFIELD( theInstr, 0, 3) == 1) { 11596 // lxv (Load VSX Vector) 11597 DIP("lxv v%u,%d(r%u)\n", vRS, DS, rA_addr); 11598 11599 assign( word[0], load( Ity_I64, mkexpr( EA ) ) ); 11600 11601 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11602 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11603 11604 assign( word[1], load( Ity_I64, irx_addr ) ); 11605 11606 if (host_endness == VexEndnessBE) 11607 putVSReg( TX*32+T, binop( Iop_64HLtoV128, 11608 mkexpr( word[0] ), 11609 mkexpr( word[1] ) ) ); 11610 else 11611 putVSReg( TX*32+T, binop( Iop_64HLtoV128, 11612 mkexpr( word[1] ), 11613 mkexpr( word[0] ) ) ); 11614 return True; 11615 11616 } else if ( IFIELD( theInstr, 0, 3) == 5) { 11617 // stxv (Store VSX Vector) 11618 DIP("stxv v%u,%d(r%u)\n", vRS, DS, rA_addr); 11619 11620 if (host_endness == VexEndnessBE) { 11621 store( mkexpr(EA), unop( Iop_V128HIto64, 11622 getVSReg( TX*32+T ) ) ); 11623 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11624 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11625 store( irx_addr, unop( Iop_V128to64, 11626 getVSReg( TX*32+T ) ) ); 11627 } else { 11628 store( mkexpr(EA), unop( Iop_V128to64, 11629 getVSReg( TX*32+T ) ) ); 11630 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11631 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11632 store( irx_addr, unop( Iop_V128HIto64, 11633 getVSReg( TX*32+T ) ) ); 11634 } 11635 return True; 11636 11637 } else { 11638 vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n"); 11639 return False; 11640 } 11641 break; 11642 } 11643 case 0x2: 11644 // stxsd (Store VSX Scalar Doubleword) 11645 DIP("stxsd v%u,%d(r%u)\n", vRS, DS, rA_addr); 11646 11647 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11648 11649 store( mkexpr(EA), unop( Iop_V128HIto64, 11650 getVSReg( vRS+32 ) ) ); 11651 /* HW is clearing vector element 1. Don't see that in the ISA but 11652 * matching the HW. 11653 */ 11654 putVSReg( vRS+32, binop( Iop_64HLtoV128, 11655 unop( Iop_V128HIto64, 11656 getVSReg( vRS+32 ) ), 11657 mkU64( 0 ) ) ); 11658 return True; 11659 11660 case 0x3: 11661 // stxssp (Store VSX Scalar Single) 11662 DIP("stxssp v%u,%d(r%u)\n", vRS, DS, rA_addr); 11663 11664 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11665 11666 store( mkexpr(EA), unop( Iop_64HIto32, 11667 unop( Iop_V128HIto64, 11668 getVSReg( vRS+32 ) ) ) ); 11669 return True; 11670 11671 default: 11672 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); 11673 return False; 11674 } 11675 break; 11676 } 11677 default: // immediate offset 11678 vex_printf("dis_fp_pair(ppc)(instr)\n"); 11679 return False; 11680 } 11681 11682 if (mode64) 11683 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 11684 else 11685 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 11686 11687 assign( frT_hi, getFReg(frT_hi_addr) ); 11688 assign( frT_lo, getFReg(frT_lo_addr) ); 11689 11690 if (is_load) { 11691 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) ); 11692 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) ); 11693 } else { 11694 store( mkexpr(EA_hi), mkexpr(frT_hi) ); 11695 store( mkexpr(EA_lo), mkexpr(frT_lo) ); 11696 } 11697 11698 return True; 11699 } 11700 11701 11702 /* 11703 Floating Point Merge Instructions 11704 */ 11705 static Bool dis_fp_merge ( UInt theInstr ) 11706 { 11707 /* X-Form */ 11708 UInt opc2 = ifieldOPClo10(theInstr); 11709 UChar frD_addr = ifieldRegDS(theInstr); 11710 UChar frA_addr = ifieldRegA(theInstr); 11711 UChar frB_addr = ifieldRegB(theInstr); 11712 11713 IRTemp frD = newTemp(Ity_F64); 11714 IRTemp frA = newTemp(Ity_F64); 11715 IRTemp frB = newTemp(Ity_F64); 11716 11717 assign( frA, getFReg(frA_addr)); 11718 assign( frB, getFReg(frB_addr)); 11719 11720 switch (opc2) { 11721 case 0x3c6: // fmrgew floating merge even word 11722 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 11723 11724 assign( frD, unop( Iop_ReinterpI64asF64, 11725 binop( Iop_32HLto64, 11726 unop( Iop_64HIto32, 11727 unop( Iop_ReinterpF64asI64, 11728 mkexpr(frA) ) ), 11729 unop( Iop_64HIto32, 11730 unop( Iop_ReinterpF64asI64, 11731 mkexpr(frB) ) ) ) ) ); 11732 break; 11733 11734 case 0x346: // fmrgow floating merge odd word 11735 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 11736 11737 assign( frD, unop( Iop_ReinterpI64asF64, 11738 binop( Iop_32HLto64, 11739 unop( Iop_64to32, 11740 unop( Iop_ReinterpF64asI64, 11741 mkexpr(frA) ) ), 11742 unop( Iop_64to32, 11743 unop( Iop_ReinterpF64asI64, 11744 mkexpr(frB) ) ) ) ) ); 11745 break; 11746 11747 default: 11748 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 11749 return False; 11750 } 11751 11752 putFReg( frD_addr, mkexpr(frD) ); 11753 return True; 11754 } 11755 11756 /* 11757 Floating Point Move Instructions 11758 */ 11759 static Bool dis_fp_move ( UInt theInstr ) 11760 { 11761 /* X-Form */ 11762 UChar opc1 = ifieldOPC(theInstr); 11763 UChar frD_addr = ifieldRegDS(theInstr); 11764 UChar frA_addr = ifieldRegA(theInstr); 11765 UChar frB_addr = ifieldRegB(theInstr); 11766 UInt opc2 = ifieldOPClo10(theInstr); 11767 UChar flag_rC = ifieldBIT0(theInstr); 11768 11769 IRTemp frD = newTemp(Ity_F64); 11770 IRTemp frB = newTemp(Ity_F64); 11771 IRTemp itmpB = newTemp(Ity_F64); 11772 IRTemp frA; 11773 IRTemp signA; 11774 IRTemp hiD; 11775 11776 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 11777 vex_printf("dis_fp_move(ppc)(instr)\n"); 11778 return False; 11779 } 11780 11781 assign( frB, getFReg(frB_addr)); 11782 11783 switch (opc2) { 11784 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 11785 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 11786 frB_addr); 11787 signA = newTemp(Ity_I32); 11788 hiD = newTemp(Ity_I32); 11789 itmpB = newTemp(Ity_I64); 11790 frA = newTemp(Ity_F64); 11791 assign( frA, getFReg(frA_addr) ); 11792 11793 /* get A's sign bit */ 11794 assign(signA, binop(Iop_And32, 11795 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 11796 mkexpr(frA))), 11797 mkU32(0x80000000)) ); 11798 11799 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 11800 11801 /* mask off B's sign bit and or in A's sign bit */ 11802 assign(hiD, binop(Iop_Or32, 11803 binop(Iop_And32, 11804 unop(Iop_64HIto32, 11805 mkexpr(itmpB)), /* frB's high 32 bits */ 11806 mkU32(0x7fffffff)), 11807 mkexpr(signA)) ); 11808 11809 /* combine hiD/loB into frD */ 11810 assign( frD, unop(Iop_ReinterpI64asF64, 11811 binop(Iop_32HLto64, 11812 mkexpr(hiD), 11813 unop(Iop_64to32, 11814 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 11815 break; 11816 11817 case 0x028: // fneg (Floating Negate, PPC32 p416) 11818 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11819 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 11820 break; 11821 11822 case 0x048: // fmr (Floating Move Register, PPC32 p410) 11823 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11824 assign( frD, mkexpr(frB) ); 11825 break; 11826 11827 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 11828 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11829 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 11830 break; 11831 11832 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 11833 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11834 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 11835 break; 11836 11837 default: 11838 vex_printf("dis_fp_move(ppc)(opc2)\n"); 11839 return False; 11840 } 11841 11842 putFReg( frD_addr, mkexpr(frD) ); 11843 11844 /* None of these change FPRF. cr1 is set in the usual way though, 11845 if flag_rC is set. */ 11846 11847 if (flag_rC) { 11848 putCR321( 1, mkU8(0) ); 11849 putCR0( 1, mkU8(0) ); 11850 } 11851 11852 return True; 11853 } 11854 11855 11856 11857 /* 11858 Floating Point Status/Control Register Instructions 11859 */ 11860 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 11861 { 11862 /* Many forms - see each switch case */ 11863 UChar opc1 = ifieldOPC(theInstr); 11864 UInt opc2 = ifieldOPClo10(theInstr); 11865 UChar flag_rC = ifieldBIT0(theInstr); 11866 11867 if (opc1 != 0x3F) { 11868 vex_printf("dis_fp_scr(ppc)(instr)\n"); 11869 return False; 11870 } 11871 11872 switch (opc2) { 11873 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 11874 // Bit crbD of the FPSCR is set. 11875 UChar crbD = ifieldRegDS(theInstr); 11876 UInt b11to20 = IFIELD(theInstr, 11, 10); 11877 11878 if (b11to20 != 0) { 11879 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 11880 return False; 11881 } 11882 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 11883 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 11884 1ULL << ( 31 - crbD ) ); 11885 break; 11886 } 11887 11888 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 11889 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11890 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11891 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 11892 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 11893 IRTemp tmp = newTemp(Ity_I32); 11894 IRExpr* fpscr_all; 11895 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 11896 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 11897 return False; 11898 } 11899 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 11900 vassert(crfD < 8); 11901 vassert(crfS < 8); 11902 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 11903 assign( tmp, binop(Iop_And32, 11904 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 11905 mkU32(0xF)) ); 11906 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 11907 break; 11908 } 11909 11910 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 11911 // Bit crbD of the FPSCR is cleared. 11912 UChar crbD = ifieldRegDS(theInstr); 11913 UInt b11to20 = IFIELD(theInstr, 11, 10); 11914 11915 if (b11to20 != 0) { 11916 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 11917 return False; 11918 } 11919 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 11920 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 11921 break; 11922 } 11923 11924 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 11925 UInt crfD = IFIELD( theInstr, 23, 3 ); 11926 UChar b17to22 = toUChar( IFIELD( theInstr, 17, 6 ) ); 11927 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 11928 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 11929 UChar Wbit = toUChar( IFIELD( theInstr, 16, 1 ) ); 11930 11931 if (b17to22 != 0 || b11 != 0 || (Wbit && !GX_level)) { 11932 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 11933 return False; 11934 } 11935 DIP("mtfsfi%s crf%u,%d%s\n", flag_rC ? ".":"", crfD, IMM, Wbit ? ",1":""); 11936 crfD = crfD + (8 * (1 - Wbit) ); 11937 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 11938 break; 11939 } 11940 11941 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 11942 UChar frD_addr = ifieldRegDS(theInstr); 11943 UChar frB_addr = ifieldRegB(theInstr); 11944 IRTemp frB = newTemp(Ity_F64); 11945 UInt b11to12 = IFIELD(theInstr, 19, 2); 11946 UInt b13to15 = IFIELD(theInstr, 16, 3); 11947 UInt RN = IFIELD(theInstr, 11, 2); 11948 UInt DRN = IFIELD(theInstr, 11, 3); 11949 11950 /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in 11951 * their own 8-bit entries with distinct offsets. The FPSCR 11952 * register is handled as two 32-bit values. We need to 11953 * assemble the pieces into the single 64-bit value to return. 11954 */ 11955 IRExpr* fpscr_lower 11956 = binop( Iop_Or32, 11957 getGST_masked( PPC_GST_FPSCR, (MASK_FPSCR_RN | MASK_FPSCR_C_FPCC) ), 11958 binop( Iop_Or32, 11959 binop( Iop_Shl32, 11960 getC(), 11961 mkU8(63-47) ) , 11962 binop( Iop_Shl32, 11963 getFPCC(), 11964 mkU8(63-51) ) ) ); 11965 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ); 11966 11967 if ((b11to12 == 0) && (b13to15 == 0)) { 11968 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 11969 putFReg( frD_addr, 11970 unop( Iop_ReinterpI64asF64, 11971 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 11972 11973 } else if ((b11to12 == 0) && (b13to15 == 1)) { 11974 DIP("mffsce fr%u\n", frD_addr); 11975 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE, 11976 or XE but in case that changes in the future, do the masking. */ 11977 putFReg( frD_addr, 11978 unop( Iop_ReinterpI64asF64, 11979 binop( Iop_32HLto64, fpscr_upper, 11980 binop( Iop_And32, fpscr_lower, 11981 mkU32( 0xFFFFFF07 ) ) ) ) ); 11982 11983 } else if ((b11to12 == 2) && (b13to15 == 4)) { 11984 IRTemp frB_int = newTemp(Ity_I64); 11985 11986 DIP("mffscdrn fr%u,fr%u\n", frD_addr, frB_addr); 11987 11988 assign( frB, getFReg(frB_addr)); 11989 assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 11990 11991 /* Clear all of the FPSCR bits except for the DRN field, VE, 11992 OE, UE, ZE and XE bits and write the result to the frD 11993 register. Note, currently the exception bits are not tracked but 11994 will mask anyway in case that changes in the future. */ 11995 putFReg( frD_addr, 11996 unop( Iop_ReinterpI64asF64, 11997 binop( Iop_32HLto64, 11998 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 11999 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12000 12001 /* Put new_DRN bits into the FPSCR register */ 12002 putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_DRN ); 12003 12004 } else if ((b11to12 == 2) && (b13to15 == 5)) { 12005 DIP("mffscdrni fr%u,%d\n", frD_addr, DRN); 12006 12007 /* Clear all of the FPSCR bits except for the DRN field, VE, 12008 OE, UE, ZE and XE bits and write the result to the frD 12009 register. Note, currently the exception bits are not tracked but 12010 will mask anyway in case that changes in the future. */ 12011 putFReg( frD_addr, 12012 unop( Iop_ReinterpI64asF64, 12013 binop( Iop_32HLto64, 12014 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12015 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12016 12017 /* Put new_DRN bits into the FPSCR register */ 12018 putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( DRN ), 12019 mkU32( 0 ) ), MASK_FPSCR_DRN ); 12020 12021 } else if ((b11to12 == 2) && (b13to15 == 6)) { 12022 IRTemp frB_int = newTemp(Ity_I64); 12023 12024 DIP("mffscrn fr%u,fr%u\n", frD_addr,frB_addr); 12025 12026 assign( frB, getFReg(frB_addr)); 12027 assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 12028 12029 /* Clear all of the FPSCR bits except for the DRN field, VE, 12030 OE, UE, ZE and XE bits and write the result to the frD 12031 register. Note, currently the exception bits are not tracked but 12032 will mask anyway in case that changes in the future. */ 12033 putFReg( frD_addr, 12034 unop( Iop_ReinterpI64asF64, 12035 binop( Iop_32HLto64, 12036 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12037 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12038 12039 /* Put new_CRN bits into the FPSCR register */ 12040 putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_RN ); 12041 12042 } else if ((b11to12 == 2) && (b13to15 == 7)) { 12043 DIP("mffscrni fr%u,%u\n", frD_addr, RN); 12044 12045 /* Clear all of the FPSCR bits except for the DRN field, VE, 12046 OE, UE, ZE and XE bits and write the result to the frD 12047 register. Note, currently the exception bits are not tracked but 12048 will mask anyway in case that changes in the future. */ 12049 putFReg( frD_addr, 12050 unop( Iop_ReinterpI64asF64, 12051 binop( Iop_32HLto64, 12052 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12053 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12054 12055 /* Put new_RN bits into the FPSCR register */ 12056 putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( 0 ), 12057 mkU32( RN ) ), MASK_FPSCR_RN ); 12058 12059 } else if ((b11to12 == 3) && (b13to15 == 0)) { 12060 DIP("mffsl fr%u\n", frD_addr); 12061 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE, 12062 XE, FR, FI, C, FL, FG, FE, FU. Also only track DRN in the upper 12063 bits but in case that changes in the future we will do the 12064 masking. */ 12065 putFReg( frD_addr, 12066 unop( Iop_ReinterpI64asF64, 12067 binop( Iop_32HLto64, 12068 binop( Iop_And32, fpscr_upper, 12069 mkU32( 0x7 ) ), 12070 binop( Iop_And32, fpscr_lower, 12071 mkU32( 0x7F0FF ) ) ) ) ); 12072 } else { 12073 vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n"); 12074 return False; 12075 } 12076 break; 12077 } 12078 12079 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 12080 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 12081 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 12082 UChar frB_addr = ifieldRegB(theInstr); 12083 IRTemp frB = newTemp(Ity_F64); 12084 IRTemp rB_64 = newTemp( Ity_I64 ); 12085 Int i; 12086 ULong mask; 12087 UChar Wbit; 12088 #define BFP_MASK_SEED 0x3000000000000000ULL 12089 #define DFP_MASK_SEED 0x7000000000000000ULL 12090 12091 if (GX_level) { 12092 /* This implies that Decimal Floating Point is supported, and the 12093 * FPSCR must be managed as a 64-bit register. 12094 */ 12095 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 12096 } else { 12097 Wbit = 0; 12098 } 12099 12100 if (b25 == 1) { 12101 /* new 64 bit move variant for power 6. If L field (bit 25) is 12102 * a one do a full 64 bit move. Note, the FPSCR is not really 12103 * properly modeled. This instruciton only changes the value of 12104 * the rounding mode bit fields RN, FPCC and DRN. The HW exception bits 12105 * do not get set in the simulator. 1/12/09 12106 */ 12107 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 12108 mask = 0x1F0001F003; 12109 12110 } else { 12111 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 12112 // Build 32bit mask from FM: 12113 mask = 0; 12114 for (i=0; i<8; i++) { 12115 if ((FM & (1<<(7-i))) == 1) { 12116 /* FPSCR field k is set to the contents of the corresponding 12117 * field of register FRB, where k = i+8x(1-W). In the Power 12118 * ISA, register field numbering is from left to right, so field 12119 * 15 is the least significant field in a 64-bit register. To 12120 * generate the mask, we set all the appropriate rounding mode 12121 * bits in the highest order nibble (field 0) and shift right 12122 * 'k x nibble length'. 12123 */ 12124 if (Wbit) 12125 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 12126 else 12127 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 12128 } 12129 if ((FM & (1<<(7-i))) == 0x2) { //set the FPCC bits 12130 mask |= 0xF000; 12131 } 12132 if ((FM & (1<<(7-i))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit 12133 mask |= 0x10000; 12134 } 12135 } 12136 } 12137 assign( frB, getFReg(frB_addr)); 12138 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 12139 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 12140 break; 12141 } 12142 12143 default: 12144 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 12145 return False; 12146 } 12147 return True; 12148 } 12149 12150 /*------------------------------------------------------------*/ 12151 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 12152 /*------------------------------------------------------------*/ 12153 #define DFP_LONG 1 12154 #define DFP_EXTND 2 12155 #define DFP_LONG_BIAS 398 12156 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 12157 #define DFP_EXTND_BIAS 6176 12158 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 12159 #define DFP_LONG_EXP_MSK 0XFF 12160 #define DFP_EXTND_EXP_MSK 0XFFF 12161 12162 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 12163 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 12164 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 12165 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 12166 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 12167 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 12168 #define DFP_LONG_EXP_MAX 369 // biased max 12169 #define DFP_LONG_EXP_MIN 0 // biased min 12170 #define DFP_EXTND_EXP_MAX 6111 // biased max 12171 #define DFP_EXTND_EXP_MIN 0 // biased min 12172 #define DFP_LONG_MAX_SIG_DIGITS 16 12173 #define DFP_EXTND_MAX_SIG_DIGITS 34 12174 #define MAX_DIGITS_IN_STRING 8 12175 12176 12177 #define AND(x, y) binop( Iop_And32, x, y ) 12178 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 12179 #define OR(x, y) binop( Iop_Or32, x, y ) 12180 #define OR3(x, y, z) OR( x, OR( y, z ) ) 12181 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 12182 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 12183 12184 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 12185 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 12186 12187 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 12188 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 12189 ((_b1) << 1) | ((_b0) << 0)) 12190 12191 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 12192 { 12193 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 12194 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 12195 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 12196 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 12197 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 12198 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 12199 IRTemp lmd_07_val = newTemp( Ity_I32 ); 12200 IRTemp lmd_8_val = newTemp( Ity_I32 ); 12201 IRTemp lmd_9_val = newTemp( Ity_I32 ); 12202 12203 /* The encodig is as follows: 12204 * lmd - left most digit 12205 * lme - left most 2-bits of the exponent 12206 * 12207 * lmd 12208 * 0 - 7 (lmexp << 3) | lmd 12209 * 8 0b11000 (24 decimal) if lme=0b00; 12210 * 0b11010 (26 decimal) if lme=0b01; 12211 * 0b11100 (28 decimal) if lme=0b10; 12212 * 9 0b11001 (25 decimal) if lme=0b00; 12213 * 0b11011 (27 decimal) if lme=0b01; 12214 * 0b11101 (29 decimal) if lme=0b10; 12215 */ 12216 12217 /* Generate the masks for each condition */ 12218 assign( lmd_07_mask, 12219 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 12220 assign( lmd_8_mask, 12221 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 12222 assign( lmd_9_mask, 12223 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 12224 assign( lmexp_00_mask, 12225 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 12226 assign( lmexp_01_mask, 12227 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 12228 assign( lmexp_10_mask, 12229 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 12230 12231 /* Generate the values for each LMD condition, assuming the condition 12232 * is TRUE. 12233 */ 12234 assign( lmd_07_val, 12235 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 12236 assign( lmd_8_val, 12237 binop( Iop_Or32, 12238 binop( Iop_Or32, 12239 binop( Iop_And32, 12240 mkexpr( lmexp_00_mask ), 12241 mkU32( 24 ) ), 12242 binop( Iop_And32, 12243 mkexpr( lmexp_01_mask ), 12244 mkU32( 26 ) ) ), 12245 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 12246 assign( lmd_9_val, 12247 binop( Iop_Or32, 12248 binop( Iop_Or32, 12249 binop( Iop_And32, 12250 mkexpr( lmexp_00_mask ), 12251 mkU32( 25 ) ), 12252 binop( Iop_And32, 12253 mkexpr( lmexp_01_mask ), 12254 mkU32( 27 ) ) ), 12255 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 12256 12257 /* generate the result from the possible LMD values */ 12258 return binop( Iop_Or32, 12259 binop( Iop_Or32, 12260 binop( Iop_And32, 12261 mkexpr( lmd_07_mask ), 12262 mkexpr( lmd_07_val ) ), 12263 binop( Iop_And32, 12264 mkexpr( lmd_8_mask ), 12265 mkexpr( lmd_8_val ) ) ), 12266 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 12267 } 12268 12269 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 12270 { 12271 /* Extract the exponent and the left most digit of the mantissa 12272 * from the G field bits [0:4]. 12273 */ 12274 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 12275 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 12276 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 12277 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 12278 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 12279 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 12280 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 12281 12282 IRTemp lmd_07_val = newTemp( Ity_I32 ); 12283 IRTemp lmd_8_val = newTemp( Ity_I32 ); 12284 IRTemp lmd_9_val = newTemp( Ity_I32 ); 12285 12286 /* The left most digit (LMD) encoding is as follows: 12287 * lmd 12288 * 0 - 7 (lmexp << 3) | lmd 12289 * 8 0b11000 (24 decimal) if lme=0b00; 12290 * 0b11010 (26 decimal) if lme=0b01; 12291 * 0b11100 (28 decimal) if lme=0b10 12292 * 9 0b11001 (25 decimal) if lme=0b00; 12293 * 0b11011 (27 decimal) if lme=0b01; 12294 * 0b11101 (29 decimal) if lme=0b10; 12295 */ 12296 12297 /* Generate the masks for each condition of LMD and exponent bits */ 12298 assign( lmd_07_mask, 12299 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 12300 gfield_0_4, 12301 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 12302 assign( lmd_8_00_mask, 12303 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12304 gfield_0_4, 12305 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 12306 assign( lmd_8_01_mask, 12307 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12308 gfield_0_4, 12309 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 12310 assign( lmd_8_10_mask, 12311 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12312 gfield_0_4, 12313 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 12314 assign( lmd_9_00_mask, 12315 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12316 gfield_0_4, 12317 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 12318 assign( lmd_9_01_mask, 12319 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12320 gfield_0_4, 12321 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 12322 assign( lmd_9_10_mask, 12323 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12324 gfield_0_4, 12325 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 12326 12327 /* Generate the values for each LMD condition, assuming the condition 12328 * is TRUE. 12329 */ 12330 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 12331 assign( lmd_8_val, mkU32( 0x8 ) ); 12332 assign( lmd_9_val, mkU32( 0x9 ) ); 12333 12334 assign( *lmd, 12335 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 12336 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 12337 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 12338 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 12339 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 12340 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 12341 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 12342 ) ) ); 12343 } 12344 12345 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 12346 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 12347 #define DIGIT3_SHR 12 12348 #define DIGIT4_SHR 16 12349 #define DIGIT5_SHR 20 12350 #define DIGIT6_SHR 24 12351 #define DIGIT7_SHR 28 12352 12353 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 12354 { 12355 /* 60-bit BCD string stored in two 32-bit values. Check that each, 12356 * digit is a valid BCD number, i.e. less then 9. 12357 */ 12358 IRTemp valid = newTemp( Ity_I32 ); 12359 12360 assign( valid, 12361 AND4( AND4 ( unop( Iop_1Sto32, 12362 binop( Iop_CmpLE32U, 12363 binop( Iop_And32, 12364 bcd_l, 12365 mkU32 ( 0xF ) ), 12366 mkU32( 0x9 ) ) ), 12367 unop( Iop_1Sto32, 12368 binop( Iop_CmpLE32U, 12369 binop( Iop_And32, 12370 binop( Iop_Shr32, 12371 bcd_l, 12372 mkU8 ( DIGIT1_SHR ) ), 12373 mkU32 ( 0xF ) ), 12374 mkU32( 0x9 ) ) ), 12375 unop( Iop_1Sto32, 12376 binop( Iop_CmpLE32U, 12377 binop( Iop_And32, 12378 binop( Iop_Shr32, 12379 bcd_l, 12380 mkU8 ( DIGIT2_SHR ) ), 12381 mkU32 ( 0xF ) ), 12382 mkU32( 0x9 ) ) ), 12383 unop( Iop_1Sto32, 12384 binop( Iop_CmpLE32U, 12385 binop( Iop_And32, 12386 binop( Iop_Shr32, 12387 bcd_l, 12388 mkU8 ( DIGIT3_SHR ) ), 12389 mkU32 ( 0xF ) ), 12390 mkU32( 0x9 ) ) ) ), 12391 AND4 ( unop( Iop_1Sto32, 12392 binop( Iop_CmpLE32U, 12393 binop( Iop_And32, 12394 binop( Iop_Shr32, 12395 bcd_l, 12396 mkU8 ( DIGIT4_SHR ) ), 12397 mkU32 ( 0xF ) ), 12398 mkU32( 0x9 ) ) ), 12399 unop( Iop_1Sto32, 12400 binop( Iop_CmpLE32U, 12401 binop( Iop_And32, 12402 binop( Iop_Shr32, 12403 bcd_l, 12404 mkU8 ( DIGIT5_SHR ) ), 12405 mkU32 ( 0xF ) ), 12406 mkU32( 0x9 ) ) ), 12407 unop( Iop_1Sto32, 12408 binop( Iop_CmpLE32U, 12409 binop( Iop_And32, 12410 binop( Iop_Shr32, 12411 bcd_l, 12412 mkU8 ( DIGIT6_SHR ) ), 12413 mkU32 ( 0xF ) ), 12414 mkU32( 0x9 ) ) ), 12415 unop( Iop_1Sto32, 12416 binop( Iop_CmpLE32U, 12417 binop( Iop_And32, 12418 binop( Iop_Shr32, 12419 bcd_l, 12420 mkU8 ( DIGIT7_SHR ) ), 12421 mkU32 ( 0xF ) ), 12422 mkU32( 0x9 ) ) ) ), 12423 AND4( unop( Iop_1Sto32, 12424 binop( Iop_CmpLE32U, 12425 binop( Iop_And32, 12426 bcd_u, 12427 mkU32 ( 0xF ) ), 12428 mkU32( 0x9 ) ) ), 12429 unop( Iop_1Sto32, 12430 binop( Iop_CmpLE32U, 12431 binop( Iop_And32, 12432 binop( Iop_Shr32, 12433 bcd_u, 12434 mkU8 ( DIGIT1_SHR ) ), 12435 mkU32 ( 0xF ) ), 12436 mkU32( 0x9 ) ) ), 12437 unop( Iop_1Sto32, 12438 binop( Iop_CmpLE32U, 12439 binop( Iop_And32, 12440 binop( Iop_Shr32, 12441 bcd_u, 12442 mkU8 ( DIGIT2_SHR ) ), 12443 mkU32 ( 0xF ) ), 12444 mkU32( 0x9 ) ) ), 12445 unop( Iop_1Sto32, 12446 binop( Iop_CmpLE32U, 12447 binop( Iop_And32, 12448 binop( Iop_Shr32, 12449 bcd_u, 12450 mkU8 ( DIGIT3_SHR ) ), 12451 mkU32 ( 0xF ) ), 12452 mkU32( 0x9 ) ) ) ), 12453 AND4( unop( Iop_1Sto32, 12454 binop( Iop_CmpLE32U, 12455 binop( Iop_And32, 12456 binop( Iop_Shr32, 12457 bcd_u, 12458 mkU8 ( DIGIT4_SHR ) ), 12459 mkU32 ( 0xF ) ), 12460 mkU32( 0x9 ) ) ), 12461 unop( Iop_1Sto32, 12462 binop( Iop_CmpLE32U, 12463 binop( Iop_And32, 12464 binop( Iop_Shr32, 12465 bcd_u, 12466 mkU8 ( DIGIT5_SHR ) ), 12467 mkU32 ( 0xF ) ), 12468 mkU32( 0x9 ) ) ), 12469 unop( Iop_1Sto32, 12470 binop( Iop_CmpLE32U, 12471 binop( Iop_And32, 12472 binop( Iop_Shr32, 12473 bcd_u, 12474 mkU8 ( DIGIT6_SHR ) ), 12475 mkU32 ( 0xF ) ), 12476 mkU32( 0x9 ) ) ), 12477 unop( Iop_1Sto32, 12478 binop( Iop_CmpLE32U, 12479 binop( Iop_And32, 12480 binop( Iop_Shr32, 12481 bcd_u, 12482 mkU8 ( DIGIT7_SHR ) ), 12483 mkU32 ( 0xF ) ), 12484 mkU32( 0x9 ) ) ) ) ) ); 12485 12486 return unop( Iop_Not32, mkexpr( valid ) ); 12487 } 12488 #undef DIGIT1_SHR 12489 #undef DIGIT2_SHR 12490 #undef DIGIT3_SHR 12491 #undef DIGIT4_SHR 12492 #undef DIGIT5_SHR 12493 #undef DIGIT6_SHR 12494 #undef DIGIT7_SHR 12495 12496 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 12497 { 12498 return binop( Iop_Or32, 12499 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 12500 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 12501 ); 12502 } 12503 12504 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 12505 { 12506 return binop( Iop_Or32, 12507 binop( Iop_Or32, 12508 unop( Iop_1Sto32, 12509 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 12510 unop( Iop_1Sto32, 12511 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 12512 binop( Iop_Or32, 12513 unop( Iop_1Sto32, 12514 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 12515 unop( Iop_1Sto32, 12516 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 12517 } 12518 12519 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 12520 IRExpr * neg_sign_mask ) 12521 { 12522 return binop( Iop_Or32, 12523 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 12524 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 12525 } 12526 12527 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 12528 IRExpr * pos_sign_mask, 12529 IRExpr * neg_sign_mask ) 12530 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 12531 { 12532 return binop( Iop_Or32, 12533 invalid_bcd_mask, 12534 unop( Iop_1Sto32, 12535 binop( Iop_CmpEQ32, 12536 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 12537 mkU32( 0x0 ) ) ) ); 12538 } 12539 12540 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 12541 IRTemp * top_12_l, IRTemp * mid_60_u, 12542 IRTemp * mid_60_l, IRTemp * low_60_u, 12543 IRTemp * low_60_l) 12544 { 12545 IRTemp tmplow60 = newTemp( Ity_I64 ); 12546 IRTemp tmpmid60 = newTemp( Ity_I64 ); 12547 IRTemp tmptop12 = newTemp( Ity_I64 ); 12548 IRTemp low_50 = newTemp( Ity_I64 ); 12549 IRTemp mid_50 = newTemp( Ity_I64 ); 12550 IRTemp top_10 = newTemp( Ity_I64 ); 12551 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 12552 12553 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 12554 12555 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 12556 assign( low_50, 12557 binop( Iop_32HLto64, 12558 binop( Iop_And32, 12559 unop( Iop_64HIto32, frBI64_lo ), 12560 mkU32( 0x3FFFF ) ), 12561 unop( Iop_64to32, frBI64_lo ) ) ); 12562 12563 /* Convert the 50 bit densely packed BCD string to a 60 bit 12564 * BCD string. 12565 */ 12566 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 12567 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 12568 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 12569 12570 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 12571 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 12572 */ 12573 assign( mid_50, 12574 binop( Iop_32HLto64, 12575 binop( Iop_Or32, 12576 binop( Iop_Shl32, 12577 binop( Iop_And32, 12578 unop( Iop_64HIto32, frBI64_hi ), 12579 mkU32( 0xF ) ), 12580 mkU8( 14 ) ), 12581 binop( Iop_Shr32, 12582 unop( Iop_64to32, frBI64_hi ), 12583 mkU8( 18 ) ) ), 12584 binop( Iop_Or32, 12585 binop( Iop_Shl32, 12586 unop( Iop_64to32, frBI64_hi ), 12587 mkU8( 14 ) ), 12588 binop( Iop_Shr32, 12589 unop( Iop_64HIto32, frBI64_lo ), 12590 mkU8( 18 ) ) ) ) ); 12591 12592 /* Convert the 50 bit densely packed BCD string to a 60 bit 12593 * BCD string. 12594 */ 12595 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 12596 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 12597 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 12598 12599 /* top_10[49:0] = frBI64_hi[45:36]) | */ 12600 assign( top_10, 12601 binop( Iop_32HLto64, 12602 mkU32( 0 ), 12603 binop( Iop_And32, 12604 binop( Iop_Shr32, 12605 unop( Iop_64HIto32, frBI64_hi ), 12606 mkU8( 4 ) ), 12607 mkU32( 0x3FF ) ) ) ); 12608 12609 /* Convert the 10 bit densely packed BCD string to a 12 bit 12610 * BCD string. 12611 */ 12612 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 12613 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 12614 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 12615 } 12616 12617 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 12618 IRTemp * final_cnt, IRTemp * final_flag, 12619 IRExpr * string ) 12620 { 12621 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 12622 int digits = MAX_DIGITS_IN_STRING; 12623 int i; 12624 12625 cnt[start-1] = newTemp( Ity_I8 ); 12626 flag[start-1] = newTemp( Ity_I8 ); 12627 assign( cnt[start-1], init_cnt); 12628 assign( flag[start-1], init_flag); 12629 12630 for ( i = start; i <= digits; i++) { 12631 cnt[i] = newTemp( Ity_I8 ); 12632 flag[i] = newTemp( Ity_I8 ); 12633 assign( cnt[i], 12634 binop( Iop_Add8, 12635 mkexpr( cnt[i-1] ), 12636 binop(Iop_And8, 12637 unop( Iop_1Uto8, 12638 binop(Iop_CmpEQ32, 12639 binop(Iop_And32, 12640 string, 12641 mkU32( 0xF << 12642 ( ( digits - i ) * 4) ) ), 12643 mkU32( 0 ) ) ), 12644 binop( Iop_Xor8, /* complement flag */ 12645 mkexpr( flag[i - 1] ), 12646 mkU8( 0xFF ) ) ) ) ); 12647 12648 /* set flag to 1 if digit was not a zero */ 12649 assign( flag[i], 12650 binop(Iop_Or8, 12651 unop( Iop_1Sto8, 12652 binop(Iop_CmpNE32, 12653 binop(Iop_And32, 12654 string, 12655 mkU32( 0xF << 12656 ( (digits - i) * 4) ) ), 12657 mkU32( 0 ) ) ), 12658 mkexpr( flag[i - 1] ) ) ); 12659 } 12660 12661 *final_cnt = cnt[digits]; 12662 *final_flag = flag[digits]; 12663 } 12664 12665 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 12666 IRExpr * low_32 ) 12667 { 12668 IRTemp num_lmd = newTemp( Ity_I8 ); 12669 IRTemp num_upper = newTemp( Ity_I8 ); 12670 IRTemp num_low = newTemp( Ity_I8 ); 12671 IRTemp lmd_flag = newTemp( Ity_I8 ); 12672 IRTemp upper_flag = newTemp( Ity_I8 ); 12673 IRTemp low_flag = newTemp( Ity_I8 ); 12674 12675 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 12676 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 12677 12678 Count_zeros( 2, 12679 mkexpr( num_lmd ), 12680 mkexpr( lmd_flag ), 12681 &num_upper, 12682 &upper_flag, 12683 upper_28 ); 12684 12685 Count_zeros( 1, 12686 mkexpr( num_upper ), 12687 mkexpr( upper_flag ), 12688 &num_low, 12689 &low_flag, 12690 low_32 ); 12691 12692 return mkexpr( num_low ); 12693 } 12694 12695 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 12696 IRExpr * mid_60_u, IRExpr * mid_60_l, 12697 IRExpr * low_60_u, IRExpr * low_60_l) 12698 { 12699 IRTemp num_lmd = newTemp( Ity_I8 ); 12700 IRTemp num_top = newTemp( Ity_I8 ); 12701 IRTemp num_mid_u = newTemp( Ity_I8 ); 12702 IRTemp num_mid_l = newTemp( Ity_I8 ); 12703 IRTemp num_low_u = newTemp( Ity_I8 ); 12704 IRTemp num_low_l = newTemp( Ity_I8 ); 12705 12706 IRTemp lmd_flag = newTemp( Ity_I8 ); 12707 IRTemp top_flag = newTemp( Ity_I8 ); 12708 IRTemp mid_u_flag = newTemp( Ity_I8 ); 12709 IRTemp mid_l_flag = newTemp( Ity_I8 ); 12710 IRTemp low_u_flag = newTemp( Ity_I8 ); 12711 IRTemp low_l_flag = newTemp( Ity_I8 ); 12712 12713 /* Check the LMD, digit 34, to see if it is zero. */ 12714 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 12715 12716 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 12717 12718 Count_zeros( 6, 12719 mkexpr( num_lmd ), 12720 mkexpr( lmd_flag ), 12721 &num_top, 12722 &top_flag, 12723 top_12_l ); 12724 12725 Count_zeros( 2, 12726 mkexpr( num_top ), 12727 mkexpr( top_flag ), 12728 &num_mid_u, 12729 &mid_u_flag, 12730 binop( Iop_Or32, 12731 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 12732 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 12733 12734 Count_zeros( 1, 12735 mkexpr( num_mid_u ), 12736 mkexpr( mid_u_flag ), 12737 &num_mid_l, 12738 &mid_l_flag, 12739 mid_60_l ); 12740 12741 Count_zeros( 2, 12742 mkexpr( num_mid_l ), 12743 mkexpr( mid_l_flag ), 12744 &num_low_u, 12745 &low_u_flag, 12746 binop( Iop_Or32, 12747 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 12748 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 12749 12750 Count_zeros( 1, 12751 mkexpr( num_low_u ), 12752 mkexpr( low_u_flag ), 12753 &num_low_l, 12754 &low_l_flag, 12755 low_60_l ); 12756 12757 return mkexpr( num_low_l ); 12758 } 12759 12760 static IRExpr * Check_unordered(IRExpr * val) 12761 { 12762 IRTemp gfield0to5 = newTemp( Ity_I32 ); 12763 12764 /* Extract G[0:4] */ 12765 assign( gfield0to5, 12766 binop( Iop_And32, 12767 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 12768 mkU32( 0x1F ) ) ); 12769 12770 /* Check for unordered, return all 1'x if true */ 12771 return binop( Iop_Or32, /* QNaN check */ 12772 unop( Iop_1Sto32, 12773 binop( Iop_CmpEQ32, 12774 mkexpr( gfield0to5 ), 12775 mkU32( 0x1E ) ) ), 12776 unop( Iop_1Sto32, /* SNaN check */ 12777 binop( Iop_CmpEQ32, 12778 mkexpr( gfield0to5 ), 12779 mkU32( 0x1F ) ) ) ); 12780 } 12781 12782 #undef AND 12783 #undef AND4 12784 #undef OR 12785 #undef OR3 12786 #undef OR4 12787 #undef NOT 12788 #undef SHR 12789 #undef SHL 12790 #undef BITS5 12791 12792 /*------------------------------------------------------------*/ 12793 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 12794 /*------------------------------------------------------------*/ 12795 12796 /* DFP Arithmetic instructions */ 12797 static Bool dis_dfp_arith(UInt theInstr) 12798 { 12799 UInt opc2 = ifieldOPClo10( theInstr ); 12800 UChar frS_addr = ifieldRegDS( theInstr ); 12801 UChar frA_addr = ifieldRegA( theInstr ); 12802 UChar frB_addr = ifieldRegB( theInstr ); 12803 UChar flag_rC = ifieldBIT0( theInstr ); 12804 12805 IRTemp frA = newTemp( Ity_D64 ); 12806 IRTemp frB = newTemp( Ity_D64 ); 12807 IRTemp frS = newTemp( Ity_D64 ); 12808 IRExpr* round = get_IR_roundingmode_DFP(); 12809 12810 /* By default, if flag_RC is set, we will clear cr1 after the 12811 * operation. In reality we should set cr1 to indicate the 12812 * exception status of the operation, but since we're not 12813 * simulating exceptions, the exception status will appear to be 12814 * zero. Hence cr1 should be cleared if this is a . form insn. 12815 */ 12816 Bool clear_CR1 = True; 12817 12818 assign( frA, getDReg( frA_addr ) ); 12819 assign( frB, getDReg( frB_addr ) ); 12820 12821 switch (opc2) { 12822 case 0x2: // dadd 12823 DIP( "dadd%s fr%u,fr%u,fr%u\n", 12824 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12825 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12826 break; 12827 case 0x202: // dsub 12828 DIP( "dsub%s fr%u,fr%u,fr%u\n", 12829 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12830 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12831 break; 12832 case 0x22: // dmul 12833 DIP( "dmul%s fr%u,fr%u,fr%u\n", 12834 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12835 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12836 break; 12837 case 0x222: // ddiv 12838 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 12839 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12840 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12841 break; 12842 } 12843 12844 putDReg( frS_addr, mkexpr( frS ) ); 12845 12846 if (flag_rC && clear_CR1) { 12847 putCR321( 1, mkU8( 0 ) ); 12848 putCR0( 1, mkU8( 0 ) ); 12849 } 12850 12851 return True; 12852 } 12853 12854 /* Quad DFP Arithmetic instructions */ 12855 static Bool dis_dfp_arithq(UInt theInstr) 12856 { 12857 UInt opc2 = ifieldOPClo10( theInstr ); 12858 UChar frS_addr = ifieldRegDS( theInstr ); 12859 UChar frA_addr = ifieldRegA( theInstr ); 12860 UChar frB_addr = ifieldRegB( theInstr ); 12861 UChar flag_rC = ifieldBIT0( theInstr ); 12862 12863 IRTemp frA = newTemp( Ity_D128 ); 12864 IRTemp frB = newTemp( Ity_D128 ); 12865 IRTemp frS = newTemp( Ity_D128 ); 12866 IRExpr* round = get_IR_roundingmode_DFP(); 12867 12868 /* By default, if flag_RC is set, we will clear cr1 after the 12869 * operation. In reality we should set cr1 to indicate the 12870 * exception status of the operation, but since we're not 12871 * simulating exceptions, the exception status will appear to be 12872 * zero. Hence cr1 should be cleared if this is a . form insn. 12873 */ 12874 Bool clear_CR1 = True; 12875 12876 assign( frA, getDReg_pair( frA_addr ) ); 12877 assign( frB, getDReg_pair( frB_addr ) ); 12878 12879 switch (opc2) { 12880 case 0x2: // daddq 12881 DIP( "daddq%s fr%u,fr%u,fr%u\n", 12882 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12883 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12884 break; 12885 case 0x202: // dsubq 12886 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 12887 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12888 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12889 break; 12890 case 0x22: // dmulq 12891 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 12892 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12893 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12894 break; 12895 case 0x222: // ddivq 12896 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 12897 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12898 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12899 break; 12900 } 12901 12902 putDReg_pair( frS_addr, mkexpr( frS ) ); 12903 12904 if (flag_rC && clear_CR1) { 12905 putCR321( 1, mkU8( 0 ) ); 12906 putCR0( 1, mkU8( 0 ) ); 12907 } 12908 12909 return True; 12910 } 12911 12912 /* DFP 64-bit logical shift instructions */ 12913 static Bool dis_dfp_shift(UInt theInstr) { 12914 UInt opc2 = ifieldOPClo9( theInstr ); 12915 UChar frS_addr = ifieldRegDS( theInstr ); 12916 UChar frA_addr = ifieldRegA( theInstr ); 12917 UChar shift_val = IFIELD(theInstr, 10, 6); 12918 UChar flag_rC = ifieldBIT0( theInstr ); 12919 12920 IRTemp frA = newTemp( Ity_D64 ); 12921 IRTemp frS = newTemp( Ity_D64 ); 12922 Bool clear_CR1 = True; 12923 12924 assign( frA, getDReg( frA_addr ) ); 12925 12926 switch (opc2) { 12927 case 0x42: // dscli 12928 DIP( "dscli%s fr%u,fr%u,%u\n", 12929 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12930 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 12931 break; 12932 case 0x62: // dscri 12933 DIP( "dscri%s fr%u,fr%u,%u\n", 12934 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12935 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 12936 break; 12937 } 12938 12939 putDReg( frS_addr, mkexpr( frS ) ); 12940 12941 if (flag_rC && clear_CR1) { 12942 putCR321( 1, mkU8( 0 ) ); 12943 putCR0( 1, mkU8( 0 ) ); 12944 } 12945 12946 return True; 12947 } 12948 12949 /* Quad DFP logical shift instructions */ 12950 static Bool dis_dfp_shiftq(UInt theInstr) { 12951 UInt opc2 = ifieldOPClo9( theInstr ); 12952 UChar frS_addr = ifieldRegDS( theInstr ); 12953 UChar frA_addr = ifieldRegA( theInstr ); 12954 UChar shift_val = IFIELD(theInstr, 10, 6); 12955 UChar flag_rC = ifieldBIT0( theInstr ); 12956 12957 IRTemp frA = newTemp( Ity_D128 ); 12958 IRTemp frS = newTemp( Ity_D128 ); 12959 Bool clear_CR1 = True; 12960 12961 assign( frA, getDReg_pair( frA_addr ) ); 12962 12963 switch (opc2) { 12964 case 0x42: // dscliq 12965 DIP( "dscliq%s fr%u,fr%u,%u\n", 12966 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12967 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 12968 break; 12969 case 0x62: // dscriq 12970 DIP( "dscriq%s fr%u,fr%u,%u\n", 12971 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12972 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 12973 break; 12974 } 12975 12976 putDReg_pair( frS_addr, mkexpr( frS ) ); 12977 12978 if (flag_rC && clear_CR1) { 12979 putCR321( 1, mkU8( 0 ) ); 12980 putCR0( 1, mkU8( 0 ) ); 12981 } 12982 12983 return True; 12984 } 12985 12986 /* DFP 64-bit format conversion instructions */ 12987 static Bool dis_dfp_fmt_conv(UInt theInstr) { 12988 UInt opc2 = ifieldOPClo10( theInstr ); 12989 UChar frS_addr = ifieldRegDS( theInstr ); 12990 UChar frB_addr = ifieldRegB( theInstr ); 12991 IRExpr* round = get_IR_roundingmode_DFP(); 12992 UChar flag_rC = ifieldBIT0( theInstr ); 12993 IRTemp frB; 12994 IRTemp frS; 12995 Bool clear_CR1 = True; 12996 12997 switch (opc2) { 12998 case 0x102: //dctdp 12999 DIP( "dctdp%s fr%u,fr%u\n", 13000 flag_rC ? ".":"", frS_addr, frB_addr ); 13001 13002 frB = newTemp( Ity_D32 ); 13003 frS = newTemp( Ity_D64 ); 13004 assign( frB, getDReg32( frB_addr ) ); 13005 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 13006 putDReg( frS_addr, mkexpr( frS ) ); 13007 break; 13008 case 0x302: // drsp 13009 DIP( "drsp%s fr%u,fr%u\n", 13010 flag_rC ? ".":"", frS_addr, frB_addr ); 13011 frB = newTemp( Ity_D64 ); 13012 frS = newTemp( Ity_D32 ); 13013 assign( frB, getDReg( frB_addr ) ); 13014 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 13015 putDReg32( frS_addr, mkexpr( frS ) ); 13016 break; 13017 case 0x122: // dctfix 13018 { 13019 IRTemp tmp = newTemp( Ity_I64 ); 13020 13021 DIP( "dctfix%s fr%u,fr%u\n", 13022 flag_rC ? ".":"", frS_addr, frB_addr ); 13023 frB = newTemp( Ity_D64 ); 13024 frS = newTemp( Ity_D64 ); 13025 assign( frB, getDReg( frB_addr ) ); 13026 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 13027 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13028 putDReg( frS_addr, mkexpr( frS ) ); 13029 } 13030 break; 13031 case 0x322: // dcffix 13032 DIP( "dcffix%s fr%u,fr%u\n", 13033 flag_rC ? ".":"", frS_addr, frB_addr ); 13034 frB = newTemp( Ity_D64 ); 13035 frS = newTemp( Ity_D64 ); 13036 assign( frB, getDReg( frB_addr ) ); 13037 assign( frS, binop( Iop_I64StoD64, 13038 round, 13039 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 13040 putDReg( frS_addr, mkexpr( frS ) ); 13041 break; 13042 } 13043 13044 if (flag_rC && clear_CR1) { 13045 putCR321( 1, mkU8( 0 ) ); 13046 putCR0( 1, mkU8( 0 ) ); 13047 } 13048 13049 return True; 13050 } 13051 13052 /* Quad DFP format conversion instructions */ 13053 static Bool dis_dfp_fmt_convq(UInt theInstr) { 13054 UInt opc2 = ifieldOPClo10( theInstr ); 13055 UChar frS_addr = ifieldRegDS( theInstr ); 13056 UChar frB_addr = ifieldRegB( theInstr ); 13057 IRExpr* round = get_IR_roundingmode_DFP(); 13058 IRTemp frB64 = newTemp( Ity_D64 ); 13059 IRTemp frB128 = newTemp( Ity_D128 ); 13060 IRTemp frS64 = newTemp( Ity_D64 ); 13061 IRTemp frS128 = newTemp( Ity_D128 ); 13062 UChar flag_rC = ifieldBIT0( theInstr ); 13063 Bool clear_CR1 = True; 13064 13065 switch (opc2) { 13066 case 0x102: // dctqpq 13067 DIP( "dctqpq%s fr%u,fr%u\n", 13068 flag_rC ? ".":"", frS_addr, frB_addr ); 13069 assign( frB64, getDReg( frB_addr ) ); 13070 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 13071 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 13072 break; 13073 case 0x122: // dctfixq 13074 { 13075 IRTemp tmp = newTemp( Ity_I64 ); 13076 13077 DIP( "dctfixq%s fr%u,fr%u\n", 13078 flag_rC ? ".":"", frS_addr, frB_addr ); 13079 assign( frB128, getDReg_pair( frB_addr ) ); 13080 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 13081 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13082 putDReg( frS_addr, mkexpr( frS64 ) ); 13083 } 13084 break; 13085 case 0x302: //drdpq 13086 DIP( "drdpq%s fr%u,fr%u\n", 13087 flag_rC ? ".":"", frS_addr, frB_addr ); 13088 assign( frB128, getDReg_pair( frB_addr ) ); 13089 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 13090 putDReg( frS_addr, mkexpr( frS64 ) ); 13091 break; 13092 case 0x322: // dcffixq 13093 { 13094 /* Have to introduce an IOP for this instruction so it will work 13095 * on POWER 6 because emulating the instruction requires a POWER 7 13096 * DFP instruction in the emulation code. 13097 */ 13098 DIP( "dcffixq%s fr%u,fr%u\n", 13099 flag_rC ? ".":"", frS_addr, frB_addr ); 13100 assign( frB64, getDReg( frB_addr ) ); 13101 assign( frS128, unop( Iop_I64StoD128, 13102 unop( Iop_ReinterpD64asI64, 13103 mkexpr( frB64 ) ) ) ); 13104 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 13105 break; 13106 } 13107 } 13108 13109 if (flag_rC && clear_CR1) { 13110 putCR321( 1, mkU8( 0 ) ); 13111 putCR0( 1, mkU8( 0 ) ); 13112 } 13113 13114 return True; 13115 } 13116 13117 static Bool dis_dfp_round( UInt theInstr ) { 13118 UChar frS_addr = ifieldRegDS(theInstr); 13119 UChar R = IFIELD(theInstr, 16, 1); 13120 UChar RMC = IFIELD(theInstr, 9, 2); 13121 UChar frB_addr = ifieldRegB( theInstr ); 13122 UChar flag_rC = ifieldBIT0( theInstr ); 13123 IRTemp frB = newTemp( Ity_D64 ); 13124 IRTemp frS = newTemp( Ity_D64 ); 13125 UInt opc2 = ifieldOPClo8( theInstr ); 13126 Bool clear_CR1 = True; 13127 13128 switch (opc2) { 13129 /* drintn, is the same as drintx. The only difference is this 13130 * instruction does not generate an exception for an inexact operation. 13131 * Currently not supporting inexact exceptions. 13132 */ 13133 case 0x63: // drintx 13134 case 0xE3: // drintn 13135 DIP( "drintx/drintn%s fr%u,fr%u\n", 13136 flag_rC ? ".":"", frS_addr, frB_addr ); 13137 13138 /* NOTE, this instruction takes a DFP value and rounds to the 13139 * neares floating point integer value, i.e. fractional part 13140 * is zero. The result is a floating point number. 13141 */ 13142 /* pass the value of R and RMC in the same field */ 13143 assign( frB, getDReg( frB_addr ) ); 13144 assign( frS, binop( Iop_RoundD64toInt, 13145 mkU32( ( R << 3 ) | RMC ), 13146 mkexpr( frB ) ) ); 13147 putDReg( frS_addr, mkexpr( frS ) ); 13148 break; 13149 default: 13150 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 13151 return False; 13152 } 13153 13154 if (flag_rC && clear_CR1) { 13155 putCR321( 1, mkU8( 0 ) ); 13156 putCR0( 1, mkU8( 0 ) ); 13157 } 13158 13159 return True; 13160 } 13161 13162 static Bool dis_dfp_roundq(UInt theInstr) { 13163 UChar frS_addr = ifieldRegDS( theInstr ); 13164 UChar frB_addr = ifieldRegB( theInstr ); 13165 UChar R = IFIELD(theInstr, 16, 1); 13166 UChar RMC = IFIELD(theInstr, 9, 2); 13167 UChar flag_rC = ifieldBIT0( theInstr ); 13168 IRTemp frB = newTemp( Ity_D128 ); 13169 IRTemp frS = newTemp( Ity_D128 ); 13170 Bool clear_CR1 = True; 13171 UInt opc2 = ifieldOPClo8( theInstr ); 13172 13173 switch (opc2) { 13174 /* drintnq, is the same as drintxq. The only difference is this 13175 * instruction does not generate an exception for an inexact operation. 13176 * Currently not supporting inexact exceptions. 13177 */ 13178 case 0x63: // drintxq 13179 case 0xE3: // drintnq 13180 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 13181 flag_rC ? ".":"", frS_addr, frB_addr ); 13182 13183 /* pass the value of R and RMC in the same field */ 13184 assign( frB, getDReg_pair( frB_addr ) ); 13185 assign( frS, binop( Iop_RoundD128toInt, 13186 mkU32( ( R << 3 ) | RMC ), 13187 mkexpr( frB ) ) ); 13188 putDReg_pair( frS_addr, mkexpr( frS ) ); 13189 break; 13190 default: 13191 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 13192 return False; 13193 } 13194 13195 if (flag_rC && clear_CR1) { 13196 putCR321( 1, mkU8( 0 ) ); 13197 putCR0( 1, mkU8( 0 ) ); 13198 } 13199 13200 return True; 13201 } 13202 13203 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 13204 UInt opc2 = ifieldOPClo8( theInstr ); 13205 UChar frS_addr = ifieldRegDS( theInstr ); 13206 UChar frA_addr = ifieldRegA( theInstr ); 13207 UChar frB_addr = ifieldRegB( theInstr ); 13208 UChar flag_rC = ifieldBIT0( theInstr ); 13209 UInt TE_value = IFIELD(theInstr, 16, 4); 13210 UInt TE_sign = IFIELD(theInstr, 20, 1); 13211 UInt RMC = IFIELD(theInstr, 9, 2); 13212 IRTemp frA = newTemp( Ity_D64 ); 13213 IRTemp frB = newTemp( Ity_D64 ); 13214 IRTemp frS = newTemp( Ity_D64 ); 13215 Bool clear_CR1 = True; 13216 13217 assign( frB, getDReg( frB_addr ) ); 13218 13219 switch (opc2) { 13220 case 0x43: // dquai 13221 DIP( "dquai%s fr%u,fr%u,fr%u\n", 13222 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13223 IRTemp TE_I64 = newTemp( Ity_I64 ); 13224 13225 /* Generate a reference DFP value frA with the desired exponent 13226 * given by TE using significand from frB. Need to add the bias 13227 * 398 to TE. TE is stored as a 2's complement number. 13228 */ 13229 if (TE_sign == 1) { 13230 /* Take 2's complement of the 5-bit value and subtract from bias. 13231 * Bias is adjusted for the +1 required when taking 2's complement. 13232 */ 13233 assign( TE_I64, 13234 unop( Iop_32Uto64, 13235 binop( Iop_Sub32, mkU32( 397 ), 13236 binop( Iop_And32, mkU32( 0xF ), 13237 unop( Iop_Not32, mkU32( TE_value ) ) 13238 ) ) ) ); 13239 13240 } else { 13241 assign( TE_I64, 13242 unop( Iop_32Uto64, 13243 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 13244 ) ); 13245 } 13246 13247 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 13248 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 13249 13250 assign( frS, triop( Iop_QuantizeD64, 13251 mkU32( RMC ), 13252 mkexpr( frA ), 13253 mkexpr( frB ) ) ); 13254 break; 13255 13256 case 0x3: // dqua 13257 DIP( "dqua%s fr%u,fr%u,fr%u\n", 13258 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13259 assign( frA, getDReg( frA_addr ) ); 13260 assign( frS, triop( Iop_QuantizeD64, 13261 mkU32( RMC ), 13262 mkexpr( frA ), 13263 mkexpr( frB ) ) ); 13264 break; 13265 case 0x23: // drrnd 13266 { 13267 IRTemp tmp = newTemp( Ity_I8 ); 13268 13269 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 13270 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13271 assign( frA, getDReg( frA_addr ) ); 13272 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 13273 assign( tmp, unop( Iop_32to8, 13274 unop( Iop_64to32, 13275 unop( Iop_ReinterpD64asI64, 13276 mkexpr( frA ) ) ) ) ); 13277 assign( frS, triop( Iop_SignificanceRoundD64, 13278 mkU32( RMC ), 13279 mkexpr( tmp ), 13280 mkexpr( frB ) ) ); 13281 } 13282 break; 13283 default: 13284 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 13285 return False; 13286 } 13287 putDReg( frS_addr, mkexpr( frS ) ); 13288 13289 if (flag_rC && clear_CR1) { 13290 putCR321( 1, mkU8( 0 ) ); 13291 putCR0( 1, mkU8( 0 ) ); 13292 } 13293 13294 return True; 13295 } 13296 13297 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 13298 UInt opc2 = ifieldOPClo8( theInstr ); 13299 UChar frS_addr = ifieldRegDS( theInstr ); 13300 UChar frA_addr = ifieldRegA( theInstr ); 13301 UChar frB_addr = ifieldRegB( theInstr ); 13302 UChar flag_rC = ifieldBIT0( theInstr ); 13303 UInt TE_value = IFIELD(theInstr, 16, 4); 13304 UInt TE_sign = IFIELD(theInstr, 20, 1); 13305 UInt RMC = IFIELD(theInstr, 9, 2); 13306 IRTemp frA = newTemp( Ity_D128 ); 13307 IRTemp frB = newTemp( Ity_D128 ); 13308 IRTemp frS = newTemp( Ity_D128 ); 13309 Bool clear_CR1 = True; 13310 13311 assign( frB, getDReg_pair( frB_addr ) ); 13312 13313 switch (opc2) { 13314 case 0x43: // dquaiq 13315 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 13316 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13317 IRTemp TE_I64 = newTemp( Ity_I64 ); 13318 13319 /* Generate a reference DFP value frA with the desired exponent 13320 * given by TE using significand of 1. Need to add the bias 13321 * 6176 to TE. 13322 */ 13323 if (TE_sign == 1) { 13324 /* Take 2's complement of the 5-bit value and subtract from bias. 13325 * Bias adjusted for the +1 required when taking 2's complement. 13326 */ 13327 assign( TE_I64, 13328 unop( Iop_32Uto64, 13329 binop( Iop_Sub32, mkU32( 6175 ), 13330 binop( Iop_And32, mkU32( 0xF ), 13331 unop( Iop_Not32, mkU32( TE_value ) ) 13332 ) ) ) ); 13333 13334 } else { 13335 assign( TE_I64, 13336 unop( Iop_32Uto64, 13337 binop( Iop_Add32, 13338 mkU32( 6176 ), 13339 mkU32( TE_value ) ) ) ); 13340 } 13341 13342 assign( frA, 13343 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 13344 unop( Iop_D64toD128, 13345 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 13346 assign( frS, triop( Iop_QuantizeD128, 13347 mkU32( RMC ), 13348 mkexpr( frA ), 13349 mkexpr( frB ) ) ); 13350 break; 13351 case 0x3: // dquaq 13352 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 13353 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13354 assign( frA, getDReg_pair( frA_addr ) ); 13355 assign( frS, triop( Iop_QuantizeD128, 13356 mkU32( RMC ), 13357 mkexpr( frA ), 13358 mkexpr( frB ) ) ); 13359 break; 13360 case 0x23: // drrndq 13361 { 13362 IRTemp tmp = newTemp( Ity_I8 ); 13363 13364 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 13365 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13366 assign( frA, getDReg_pair( frA_addr ) ); 13367 assign( tmp, unop( Iop_32to8, 13368 unop( Iop_64to32, 13369 unop( Iop_ReinterpD64asI64, 13370 unop( Iop_D128HItoD64, 13371 mkexpr( frA ) ) ) ) ) ); 13372 assign( frS, triop( Iop_SignificanceRoundD128, 13373 mkU32( RMC ), 13374 mkexpr( tmp ), 13375 mkexpr( frB ) ) ); 13376 } 13377 break; 13378 default: 13379 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 13380 return False; 13381 } 13382 putDReg_pair( frS_addr, mkexpr( frS ) ); 13383 13384 if (flag_rC && clear_CR1) { 13385 putCR321( 1, mkU8( 0 ) ); 13386 putCR0( 1, mkU8( 0 ) ); 13387 } 13388 13389 return True; 13390 } 13391 13392 static Bool dis_dfp_extract_insert(UInt theInstr) { 13393 UInt opc2 = ifieldOPClo10( theInstr ); 13394 UChar frS_addr = ifieldRegDS( theInstr ); 13395 UChar frA_addr = ifieldRegA( theInstr ); 13396 UChar frB_addr = ifieldRegB( theInstr ); 13397 UChar flag_rC = ifieldBIT0( theInstr ); 13398 Bool clear_CR1 = True; 13399 13400 IRTemp frA = newTemp( Ity_D64 ); 13401 IRTemp frB = newTemp( Ity_D64 ); 13402 IRTemp frS = newTemp( Ity_D64 ); 13403 IRTemp tmp = newTemp( Ity_I64 ); 13404 13405 assign( frA, getDReg( frA_addr ) ); 13406 assign( frB, getDReg( frB_addr ) ); 13407 13408 switch (opc2) { 13409 case 0x162: // dxex 13410 DIP( "dxex%s fr%u,fr%u,fr%u\n", 13411 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13412 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 13413 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13414 break; 13415 case 0x362: // diex 13416 DIP( "diex%s fr%u,fr%u,fr%u\n", 13417 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13418 assign( frS, binop( Iop_InsertExpD64, 13419 unop( Iop_ReinterpD64asI64, 13420 mkexpr( frA ) ), 13421 mkexpr( frB ) ) ); 13422 break; 13423 default: 13424 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 13425 return False; 13426 } 13427 13428 putDReg( frS_addr, mkexpr( frS ) ); 13429 13430 if (flag_rC && clear_CR1) { 13431 putCR321( 1, mkU8( 0 ) ); 13432 putCR0( 1, mkU8( 0 ) ); 13433 } 13434 13435 return True; 13436 } 13437 13438 static Bool dis_dfp_extract_insertq(UInt theInstr) { 13439 UInt opc2 = ifieldOPClo10( theInstr ); 13440 UChar frS_addr = ifieldRegDS( theInstr ); 13441 UChar frA_addr = ifieldRegA( theInstr ); 13442 UChar frB_addr = ifieldRegB( theInstr ); 13443 UChar flag_rC = ifieldBIT0( theInstr ); 13444 13445 IRTemp frA = newTemp( Ity_D64 ); 13446 IRTemp frB = newTemp( Ity_D128 ); 13447 IRTemp frS64 = newTemp( Ity_D64 ); 13448 IRTemp frS = newTemp( Ity_D128 ); 13449 IRTemp tmp = newTemp( Ity_I64 ); 13450 Bool clear_CR1 = True; 13451 13452 assign( frB, getDReg_pair( frB_addr ) ); 13453 13454 switch (opc2) { 13455 case 0x162: // dxexq 13456 DIP( "dxexq%s fr%u,fr%u\n", 13457 flag_rC ? ".":"", frS_addr, frB_addr ); 13458 /* Instruction actually returns a 64-bit result. So as to be 13459 * consistent and not have to add a new struct, the emulation returns 13460 * the 64-bit result in the upper and lower register. 13461 */ 13462 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 13463 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13464 putDReg( frS_addr, mkexpr( frS64 ) ); 13465 break; 13466 case 0x362: // diexq 13467 DIP( "diexq%s fr%u,fr%u,fr%u\n", 13468 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13469 assign( frA, getDReg( frA_addr ) ); 13470 assign( frS, binop( Iop_InsertExpD128, 13471 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 13472 mkexpr( frB ) ) ); 13473 putDReg_pair( frS_addr, mkexpr( frS ) ); 13474 break; 13475 default: 13476 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 13477 return False; 13478 } 13479 13480 if (flag_rC && clear_CR1) { 13481 putCR321( 1, mkU8( 0 ) ); 13482 putCR0( 1, mkU8( 0 ) ); 13483 } 13484 13485 return True; 13486 } 13487 13488 /* DFP 64-bit comparison instructions */ 13489 static Bool dis_dfp_compare(UInt theInstr) { 13490 /* X-Form */ 13491 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 13492 UChar frA_addr = ifieldRegA( theInstr ); 13493 UChar frB_addr = ifieldRegB( theInstr ); 13494 UInt opc1 = ifieldOPC( theInstr ); 13495 IRTemp frA; 13496 IRTemp frB; 13497 13498 IRTemp ccIR = newTemp( Ity_I32 ); 13499 IRTemp ccPPC32 = newTemp( Ity_I32 ); 13500 13501 13502 /* Note: Differences between dcmpu and dcmpo are only in exception 13503 flag settings, which aren't supported anyway. */ 13504 switch (opc1) { 13505 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 13506 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 13507 frA = newTemp( Ity_D64 ); 13508 frB = newTemp( Ity_D64 ); 13509 13510 assign( frA, getDReg( frA_addr ) ); 13511 assign( frB, getDReg( frB_addr ) ); 13512 13513 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 13514 break; 13515 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 13516 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 13517 frA = newTemp( Ity_D128 ); 13518 frB = newTemp( Ity_D128 ); 13519 13520 assign( frA, getDReg_pair( frA_addr ) ); 13521 assign( frB, getDReg_pair( frB_addr ) ); 13522 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 13523 break; 13524 default: 13525 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 13526 return False; 13527 } 13528 13529 /* Map compare result from IR to PPC32 */ 13530 /* 13531 FP cmp result | PPC | IR 13532 -------------------------- 13533 UN | 0x1 | 0x45 13534 EQ | 0x2 | 0x40 13535 GT | 0x4 | 0x00 13536 LT | 0x8 | 0x01 13537 */ 13538 13539 assign( ccPPC32, 13540 binop( Iop_Shl32, 13541 mkU32( 1 ), 13542 unop( Iop_32to8, 13543 binop( Iop_Or32, 13544 binop( Iop_And32, 13545 unop( Iop_Not32, 13546 binop( Iop_Shr32, 13547 mkexpr( ccIR ), 13548 mkU8( 5 ) ) ), 13549 mkU32( 2 ) ), 13550 binop( Iop_And32, 13551 binop( Iop_Xor32, 13552 mkexpr( ccIR ), 13553 binop( Iop_Shr32, 13554 mkexpr( ccIR ), 13555 mkU8( 6 ) ) ), 13556 mkU32( 1 ) ) ) ) ) ); 13557 13558 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 13559 putFPCC( mkexpr( ccPPC32 ) ); 13560 return True; 13561 } 13562 13563 /* Test class/group/exponent/significance instructions. */ 13564 static Bool dis_dfp_exponent_test ( UInt theInstr ) 13565 { 13566 UChar frA_addr = ifieldRegA( theInstr ); 13567 UChar frB_addr = ifieldRegB( theInstr ); 13568 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13569 IRTemp frA = newTemp( Ity_D64 ); 13570 IRTemp frB = newTemp( Ity_D64 ); 13571 IRTemp frA128 = newTemp( Ity_D128 ); 13572 IRTemp frB128 = newTemp( Ity_D128 ); 13573 UInt opc1 = ifieldOPC( theInstr ); 13574 IRTemp gfield_A = newTemp( Ity_I32 ); 13575 IRTemp gfield_B = newTemp( Ity_I32 ); 13576 IRTemp gfield_mask = newTemp( Ity_I32 ); 13577 IRTemp exponent_A = newTemp( Ity_I32 ); 13578 IRTemp exponent_B = newTemp( Ity_I32 ); 13579 IRTemp A_NaN_true = newTemp( Ity_I32 ); 13580 IRTemp B_NaN_true = newTemp( Ity_I32 ); 13581 IRTemp A_inf_true = newTemp( Ity_I32 ); 13582 IRTemp B_inf_true = newTemp( Ity_I32 ); 13583 IRTemp A_equals_B = newTemp( Ity_I32 ); 13584 IRTemp finite_number = newTemp( Ity_I32 ); 13585 IRTemp cc0 = newTemp( Ity_I32 ); 13586 IRTemp cc1 = newTemp( Ity_I32 ); 13587 IRTemp cc2 = newTemp( Ity_I32 ); 13588 IRTemp cc3 = newTemp( Ity_I32 ); 13589 IRTemp cc = newTemp( Ity_I32 ); 13590 13591 /* The dtstex and dtstexg instructions only differ in the size of the 13592 * exponent field. The following switch statement takes care of the size 13593 * specific setup. Once the value of the exponents, the G-field shift 13594 * and mask is setup the remaining code is identical. 13595 */ 13596 switch (opc1) { 13597 case 0x3b: // dtstex Extended instruction setup 13598 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 13599 assign( frA, getDReg( frA_addr ) ); 13600 assign( frB, getDReg( frB_addr ) ); 13601 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 13602 assign(exponent_A, unop( Iop_64to32, 13603 unop( Iop_ExtractExpD64, 13604 mkexpr( frA ) ) ) ); 13605 assign(exponent_B, unop( Iop_64to32, 13606 unop( Iop_ExtractExpD64, 13607 mkexpr( frB ) ) ) ); 13608 break; 13609 13610 case 0x3F: // dtstexq Quad instruction setup 13611 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 13612 assign( frA128, getDReg_pair( frA_addr ) ); 13613 assign( frB128, getDReg_pair( frB_addr ) ); 13614 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 13615 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 13616 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 13617 assign( exponent_A, unop( Iop_64to32, 13618 unop( Iop_ExtractExpD128, 13619 mkexpr( frA128 ) ) ) ); 13620 assign( exponent_B, unop( Iop_64to32, 13621 unop( Iop_ExtractExpD128, 13622 mkexpr( frB128 ) ) ) ); 13623 break; 13624 default: 13625 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 13626 return False; 13627 } 13628 13629 /* Extract the Gfield */ 13630 assign( gfield_A, binop( Iop_And32, 13631 mkexpr( gfield_mask ), 13632 unop( Iop_64HIto32, 13633 unop( Iop_ReinterpD64asI64, 13634 mkexpr(frA) ) ) ) ); 13635 13636 assign( gfield_B, binop( Iop_And32, 13637 mkexpr( gfield_mask ), 13638 unop( Iop_64HIto32, 13639 unop( Iop_ReinterpD64asI64, 13640 mkexpr(frB) ) ) ) ); 13641 13642 /* check for NAN */ 13643 assign( A_NaN_true, binop(Iop_Or32, 13644 unop( Iop_1Sto32, 13645 binop( Iop_CmpEQ32, 13646 mkexpr( gfield_A ), 13647 mkU32( 0x7C000000 ) ) ), 13648 unop( Iop_1Sto32, 13649 binop( Iop_CmpEQ32, 13650 mkexpr( gfield_A ), 13651 mkU32( 0x7E000000 ) ) 13652 ) ) ); 13653 assign( B_NaN_true, binop(Iop_Or32, 13654 unop( Iop_1Sto32, 13655 binop( Iop_CmpEQ32, 13656 mkexpr( gfield_B ), 13657 mkU32( 0x7C000000 ) ) ), 13658 unop( Iop_1Sto32, 13659 binop( Iop_CmpEQ32, 13660 mkexpr( gfield_B ), 13661 mkU32( 0x7E000000 ) ) 13662 ) ) ); 13663 13664 /* check for infinity */ 13665 assign( A_inf_true, 13666 unop( Iop_1Sto32, 13667 binop( Iop_CmpEQ32, 13668 mkexpr( gfield_A ), 13669 mkU32( 0x78000000 ) ) ) ); 13670 13671 assign( B_inf_true, 13672 unop( Iop_1Sto32, 13673 binop( Iop_CmpEQ32, 13674 mkexpr( gfield_B ), 13675 mkU32( 0x78000000 ) ) ) ); 13676 13677 assign( finite_number, 13678 unop( Iop_Not32, 13679 binop( Iop_Or32, 13680 binop( Iop_Or32, 13681 mkexpr( A_NaN_true ), 13682 mkexpr( B_NaN_true ) ), 13683 binop( Iop_Or32, 13684 mkexpr( A_inf_true ), 13685 mkexpr( B_inf_true ) ) ) ) ); 13686 13687 /* Calculate the condition code bits 13688 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 13689 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 13690 * cc0, cc1 and cc0 reflect the results of the comparisons. 13691 */ 13692 assign( A_equals_B, 13693 binop( Iop_Or32, 13694 unop( Iop_1Uto32, 13695 binop( Iop_CmpEQ32, 13696 mkexpr( exponent_A ), 13697 mkexpr( exponent_B ) ) ), 13698 binop( Iop_Or32, 13699 binop( Iop_And32, 13700 mkexpr( A_inf_true ), 13701 mkexpr( B_inf_true ) ), 13702 binop( Iop_And32, 13703 mkexpr( A_NaN_true ), 13704 mkexpr( B_NaN_true ) ) ) ) ); 13705 13706 assign( cc0, binop( Iop_And32, 13707 mkexpr( finite_number ), 13708 binop( Iop_Shl32, 13709 unop( Iop_1Uto32, 13710 binop( Iop_CmpLT32U, 13711 mkexpr( exponent_A ), 13712 mkexpr( exponent_B ) ) ), 13713 mkU8( 3 ) ) ) ); 13714 13715 assign( cc1, binop( Iop_And32, 13716 mkexpr( finite_number ), 13717 binop( Iop_Shl32, 13718 unop( Iop_1Uto32, 13719 binop( Iop_CmpLT32U, 13720 mkexpr( exponent_B ), 13721 mkexpr( exponent_A ) ) ), 13722 mkU8( 2 ) ) ) ); 13723 13724 assign( cc2, binop( Iop_Shl32, 13725 binop( Iop_And32, 13726 mkexpr( A_equals_B ), 13727 mkU32( 1 ) ), 13728 mkU8( 1 ) ) ); 13729 13730 assign( cc3, binop( Iop_And32, 13731 unop( Iop_Not32, mkexpr( A_equals_B ) ), 13732 binop( Iop_And32, 13733 mkU32( 0x1 ), 13734 binop( Iop_Or32, 13735 binop( Iop_Or32, 13736 mkexpr ( A_inf_true ), 13737 mkexpr ( B_inf_true ) ), 13738 binop( Iop_Or32, 13739 mkexpr ( A_NaN_true ), 13740 mkexpr ( B_NaN_true ) ) ) 13741 ) ) ); 13742 13743 /* store the condition code */ 13744 assign( cc, binop( Iop_Or32, 13745 mkexpr( cc0 ), 13746 binop( Iop_Or32, 13747 mkexpr( cc1 ), 13748 binop( Iop_Or32, 13749 mkexpr( cc2 ), 13750 mkexpr( cc3 ) ) ) ) ); 13751 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD ); 13752 putFPCC( mkexpr( cc ) ); 13753 return True; 13754 } 13755 13756 /* Test class/group/exponent/significance instructions. */ 13757 static Bool dis_dfp_class_test ( UInt theInstr ) 13758 { 13759 UChar frA_addr = ifieldRegA( theInstr ); 13760 IRTemp frA = newTemp( Ity_D64 ); 13761 IRTemp abs_frA = newTemp( Ity_D64 ); 13762 IRTemp frAI64_hi = newTemp( Ity_I64 ); 13763 IRTemp frAI64_lo = newTemp( Ity_I64 ); 13764 UInt opc1 = ifieldOPC( theInstr ); 13765 UInt opc2 = ifieldOPClo9( theInstr ); 13766 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 13767 UInt DCM = IFIELD( theInstr, 10, 6 ); 13768 IRTemp DCM_calc = newTemp( Ity_I32 ); 13769 UInt max_exp = 0; 13770 UInt min_exp = 0; 13771 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 13772 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 13773 IRTemp significand64 = newTemp( Ity_D64 ); 13774 IRTemp significand128 = newTemp( Ity_D128 ); 13775 IRTemp exp_min_normal = newTemp( Ity_I64 ); 13776 IRTemp exponent = newTemp( Ity_I32 ); 13777 13778 IRTemp infinity_true = newTemp( Ity_I32 ); 13779 IRTemp SNaN_true = newTemp( Ity_I32 ); 13780 IRTemp QNaN_true = newTemp( Ity_I32 ); 13781 IRTemp subnormal_true = newTemp( Ity_I32 ); 13782 IRTemp normal_true = newTemp( Ity_I32 ); 13783 IRTemp extreme_true = newTemp( Ity_I32 ); 13784 IRTemp lmd = newTemp( Ity_I32 ); 13785 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 13786 IRTemp zero_true = newTemp( Ity_I32 ); 13787 IRTemp sign = newTemp( Ity_I32 ); 13788 IRTemp field = newTemp( Ity_I32 ); 13789 IRTemp ccIR_zero = newTemp( Ity_I32 ); 13790 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 13791 13792 /* UInt size = DFP_LONG; JRS:unused */ 13793 IRTemp gfield = newTemp( Ity_I32 ); 13794 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 13795 IRTemp gfield_mask = newTemp( Ity_I32 ); 13796 IRTemp dcm0 = newTemp( Ity_I32 ); 13797 IRTemp dcm1 = newTemp( Ity_I32 ); 13798 IRTemp dcm2 = newTemp( Ity_I32 ); 13799 IRTemp dcm3 = newTemp( Ity_I32 ); 13800 IRTemp dcm4 = newTemp( Ity_I32 ); 13801 IRTemp dcm5 = newTemp( Ity_I32 ); 13802 13803 /* The only difference between the dtstdc and dtstdcq instructions is 13804 * size of the T and G fields. The calculation of the 4 bit field 13805 * is the same. Setup the parameters and values that are DFP size 13806 * specific. The rest of the code is independent of the DFP size. 13807 * 13808 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 13809 * The interpretation of the ccIR values is as follows: 13810 * 13811 * DFP cmp result | IR 13812 * -------------------------- 13813 * UN | 0x45 13814 * EQ | 0x40 13815 * GT | 0x00 13816 * LT | 0x01 13817 */ 13818 13819 assign( frA, getDReg( frA_addr ) ); 13820 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 13821 13822 assign( abs_frA, unop( Iop_ReinterpI64asD64, 13823 binop( Iop_And64, 13824 unop( Iop_ReinterpD64asI64, 13825 mkexpr( frA ) ), 13826 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 13827 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 13828 switch (opc1) { 13829 case 0x3b: // dtstdc, dtstdg 13830 DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 13831 crfD, frA_addr, DCM); 13832 /* setup the parameters for the long format of the two instructions */ 13833 assign( frAI64_lo, mkU64( 0 ) ); 13834 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 13835 max_exp = DFP_LONG_EXP_MAX; 13836 min_exp = DFP_LONG_EXP_MIN; 13837 13838 assign( exponent, unop( Iop_64to32, 13839 unop( Iop_ExtractExpD64, 13840 mkexpr( frA ) ) ) ); 13841 assign( significand64, 13842 unop( Iop_ReinterpI64asD64, 13843 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 13844 assign( exp_min_normal,mkU64( 398 - 383 ) ); 13845 assign( min_subnormalD64, 13846 binop( Iop_InsertExpD64, 13847 mkexpr( exp_min_normal ), 13848 mkexpr( significand64 ) ) ); 13849 13850 assign( ccIR_subnormal, 13851 binop( Iop_CmpD64, 13852 mkexpr( abs_frA ), 13853 mkexpr( min_subnormalD64 ) ) ); 13854 13855 /* compare absolute value of frA with zero */ 13856 assign( ccIR_zero, 13857 binop( Iop_CmpD64, 13858 mkexpr( abs_frA ), 13859 unop( Iop_ReinterpI64asD64, 13860 mkU64( 0x2238000000000000ULL ) ) ) ); 13861 13862 /* size = DFP_LONG; JRS: unused */ 13863 break; 13864 13865 case 0x3F: // dtstdcq, dtstdgq 13866 DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 13867 crfD, frA_addr, DCM); 13868 /* setup the parameters for the extended format of the 13869 * two instructions 13870 */ 13871 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 13872 getDReg( frA_addr+1 ) ) ); 13873 13874 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 13875 max_exp = DFP_EXTND_EXP_MAX; 13876 min_exp = DFP_EXTND_EXP_MIN; 13877 assign( exponent, unop( Iop_64to32, 13878 unop( Iop_ExtractExpD128, 13879 getDReg_pair( frA_addr) ) ) ); 13880 13881 /* create quand exponent for minimum normal number */ 13882 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 13883 assign( significand128, 13884 unop( Iop_D64toD128, 13885 unop( Iop_ReinterpI64asD64, 13886 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 13887 13888 assign( min_subnormalD128, 13889 binop( Iop_InsertExpD128, 13890 mkexpr( exp_min_normal ), 13891 mkexpr( significand128 ) ) ); 13892 13893 assign( ccIR_subnormal, 13894 binop( Iop_CmpD128, 13895 binop( Iop_D64HLtoD128, 13896 unop( Iop_ReinterpI64asD64, 13897 binop( Iop_And64, 13898 unop( Iop_ReinterpD64asI64, 13899 mkexpr( frA ) ), 13900 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 13901 getDReg( frA_addr+1 ) ), 13902 mkexpr( min_subnormalD128 ) ) ); 13903 assign( ccIR_zero, 13904 binop( Iop_CmpD128, 13905 binop( Iop_D64HLtoD128, 13906 mkexpr( abs_frA ), 13907 getDReg( frA_addr+1 ) ), 13908 unop( Iop_D64toD128, 13909 unop( Iop_ReinterpI64asD64, 13910 mkU64( 0x0ULL ) ) ) ) ); 13911 13912 /* size = DFP_EXTND; JRS:unused */ 13913 break; 13914 default: 13915 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 13916 return False; 13917 } 13918 13919 /* The G-field is in the upper 32-bits. The I64 logical operations 13920 * do not seem to be supported in 32-bit mode so keep things as 32-bit 13921 * operations. 13922 */ 13923 assign( gfield, binop( Iop_And32, 13924 mkexpr( gfield_mask ), 13925 unop( Iop_64HIto32, 13926 mkexpr(frAI64_hi) ) ) ); 13927 13928 /* There is a lot of code that is the same to do the class and group 13929 * instructions. Later there is an if statement to handle the specific 13930 * instruction. 13931 * 13932 * Will be using I32 values, compares, shifts and logical operations for 13933 * this code as the 64-bit compare, shifts, logical operations are not 13934 * supported in 32-bit mode. 13935 */ 13936 13937 /* Check the bits for Infinity, QNaN or Signaling NaN */ 13938 assign( infinity_true, 13939 unop( Iop_1Sto32, 13940 binop( Iop_CmpEQ32, 13941 binop( Iop_And32, 13942 mkU32( 0x7C000000 ), 13943 mkexpr( gfield ) ), 13944 mkU32( 0x78000000 ) ) ) ); 13945 13946 assign( SNaN_true, 13947 unop( Iop_1Sto32, 13948 binop( Iop_CmpEQ32, 13949 binop( Iop_And32, 13950 mkU32( 0x7E000000 ), 13951 mkexpr( gfield ) ), 13952 mkU32( 0x7E000000 ) ) ) ); 13953 13954 assign( QNaN_true, 13955 binop( Iop_And32, 13956 unop( Iop_1Sto32, 13957 binop( Iop_CmpEQ32, 13958 binop( Iop_And32, 13959 mkU32( 0x7E000000 ), 13960 mkexpr( gfield ) ), 13961 mkU32( 0x7C000000 ) ) ), 13962 unop( Iop_Not32, 13963 mkexpr( SNaN_true ) ) ) ); 13964 13965 assign( zero_true, 13966 binop( Iop_And32, 13967 unop(Iop_1Sto32, 13968 binop( Iop_CmpEQ32, 13969 mkexpr( ccIR_zero ), 13970 mkU32( 0x40 ) ) ), // ccIR code for Equal 13971 unop( Iop_Not32, 13972 binop( Iop_Or32, 13973 mkexpr( infinity_true ), 13974 binop( Iop_Or32, 13975 mkexpr( QNaN_true ), 13976 mkexpr( SNaN_true ) ) ) ) ) ); 13977 13978 /* Do compare of frA the minimum normal value. Comparison is size 13979 * depenent and was done above to get the ccIR value. 13980 */ 13981 assign( subnormal_true, 13982 binop( Iop_And32, 13983 binop( Iop_Or32, 13984 unop( Iop_1Sto32, 13985 binop( Iop_CmpEQ32, 13986 mkexpr( ccIR_subnormal ), 13987 mkU32( 0x40 ) ) ), // ccIR code for Equal 13988 unop( Iop_1Sto32, 13989 binop( Iop_CmpEQ32, 13990 mkexpr( ccIR_subnormal ), 13991 mkU32( 0x1 ) ) ) ), // ccIR code for LT 13992 unop( Iop_Not32, 13993 binop( Iop_Or32, 13994 binop( Iop_Or32, 13995 mkexpr( infinity_true ), 13996 mkexpr( zero_true) ), 13997 binop( Iop_Or32, 13998 mkexpr( QNaN_true ), 13999 mkexpr( SNaN_true ) ) ) ) ) ); 14000 14001 /* Normal number is not subnormal, infinity, NaN or Zero */ 14002 assign( normal_true, 14003 unop( Iop_Not32, 14004 binop( Iop_Or32, 14005 binop( Iop_Or32, 14006 mkexpr( infinity_true ), 14007 mkexpr( zero_true ) ), 14008 binop( Iop_Or32, 14009 mkexpr( subnormal_true ), 14010 binop( Iop_Or32, 14011 mkexpr( QNaN_true ), 14012 mkexpr( SNaN_true ) ) ) ) ) ); 14013 14014 /* Calculate the DCM bit field based on the tests for the specific 14015 * instruction 14016 */ 14017 if (opc2 == 0xC2) { // dtstdc, dtstdcq 14018 /* DCM[0:5] Bit Data Class definition 14019 * 0 Zero 14020 * 1 Subnormal 14021 * 2 Normal 14022 * 3 Infinity 14023 * 4 Quiet NaN 14024 * 5 Signaling NaN 14025 */ 14026 14027 assign( dcm0, binop( Iop_Shl32, 14028 mkexpr( zero_true ), 14029 mkU8( 5 ) ) ); 14030 assign( dcm1, binop( Iop_Shl32, 14031 binop( Iop_And32, 14032 mkexpr( subnormal_true ), 14033 mkU32( 1 ) ), 14034 mkU8( 4 ) ) ); 14035 assign( dcm2, binop( Iop_Shl32, 14036 binop( Iop_And32, 14037 mkexpr( normal_true ), 14038 mkU32( 1 ) ), 14039 mkU8( 3 ) ) ); 14040 assign( dcm3, binop( Iop_Shl32, 14041 binop( Iop_And32, 14042 mkexpr( infinity_true), 14043 mkU32( 1 ) ), 14044 mkU8( 2 ) ) ); 14045 assign( dcm4, binop( Iop_Shl32, 14046 binop( Iop_And32, 14047 mkexpr( QNaN_true ), 14048 mkU32( 1 ) ), 14049 mkU8( 1 ) ) ); 14050 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 14051 14052 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 14053 /* check if the exponent is extreme */ 14054 assign( extreme_true, binop( Iop_Or32, 14055 unop( Iop_1Sto32, 14056 binop( Iop_CmpEQ32, 14057 mkexpr( exponent ), 14058 mkU32( max_exp ) ) ), 14059 unop( Iop_1Sto32, 14060 binop( Iop_CmpEQ32, 14061 mkexpr( exponent ), 14062 mkU32( min_exp ) ) ) ) ); 14063 14064 /* Check if LMD is zero */ 14065 Get_lmd( &lmd, binop( Iop_Shr32, 14066 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 14067 14068 assign( lmd_zero_true, unop( Iop_1Sto32, 14069 binop( Iop_CmpEQ32, 14070 mkexpr( lmd ), 14071 mkU32( 0 ) ) ) ); 14072 14073 /* DCM[0:5] Bit Data Class definition 14074 * 0 Zero with non-extreme exponent 14075 * 1 Zero with extreme exponent 14076 * 2 Subnormal or (Normal with extreme exponent) 14077 * 3 Normal with non-extreme exponent and 14078 * leftmost zero digit in significand 14079 * 4 Normal with non-extreme exponent and 14080 * leftmost nonzero digit in significand 14081 * 5 Special symbol (Infinity, QNaN, or SNaN) 14082 */ 14083 assign( dcm0, binop( Iop_Shl32, 14084 binop( Iop_And32, 14085 binop( Iop_And32, 14086 unop( Iop_Not32, 14087 mkexpr( extreme_true ) ), 14088 mkexpr( zero_true ) ), 14089 mkU32( 0x1 ) ), 14090 mkU8( 5 ) ) ); 14091 14092 assign( dcm1, binop( Iop_Shl32, 14093 binop( Iop_And32, 14094 binop( Iop_And32, 14095 mkexpr( extreme_true ), 14096 mkexpr( zero_true ) ), 14097 mkU32( 0x1 ) ), 14098 mkU8( 4 ) ) ); 14099 14100 assign( dcm2, binop( Iop_Shl32, 14101 binop( Iop_And32, 14102 binop( Iop_Or32, 14103 binop( Iop_And32, 14104 mkexpr( extreme_true ), 14105 mkexpr( normal_true ) ), 14106 mkexpr( subnormal_true ) ), 14107 mkU32( 0x1 ) ), 14108 mkU8( 3 ) ) ); 14109 14110 assign( dcm3, binop( Iop_Shl32, 14111 binop( Iop_And32, 14112 binop( Iop_And32, 14113 binop( Iop_And32, 14114 unop( Iop_Not32, 14115 mkexpr( extreme_true ) ), 14116 mkexpr( normal_true ) ), 14117 unop( Iop_1Sto32, 14118 binop( Iop_CmpEQ32, 14119 mkexpr( lmd ), 14120 mkU32( 0 ) ) ) ), 14121 mkU32( 0x1 ) ), 14122 mkU8( 2 ) ) ); 14123 14124 assign( dcm4, binop( Iop_Shl32, 14125 binop( Iop_And32, 14126 binop( Iop_And32, 14127 binop( Iop_And32, 14128 unop( Iop_Not32, 14129 mkexpr( extreme_true ) ), 14130 mkexpr( normal_true ) ), 14131 unop( Iop_1Sto32, 14132 binop( Iop_CmpNE32, 14133 mkexpr( lmd ), 14134 mkU32( 0 ) ) ) ), 14135 mkU32( 0x1 ) ), 14136 mkU8( 1 ) ) ); 14137 14138 assign( dcm5, binop( Iop_And32, 14139 binop( Iop_Or32, 14140 mkexpr( SNaN_true), 14141 binop( Iop_Or32, 14142 mkexpr( QNaN_true), 14143 mkexpr( infinity_true) ) ), 14144 mkU32( 0x1 ) ) ); 14145 } 14146 14147 /* create DCM field */ 14148 assign( DCM_calc, 14149 binop( Iop_Or32, 14150 mkexpr( dcm0 ), 14151 binop( Iop_Or32, 14152 mkexpr( dcm1 ), 14153 binop( Iop_Or32, 14154 mkexpr( dcm2 ), 14155 binop( Iop_Or32, 14156 mkexpr( dcm3 ), 14157 binop( Iop_Or32, 14158 mkexpr( dcm4 ), 14159 mkexpr( dcm5 ) ) ) ) ) ) ); 14160 14161 /* Get the sign of the DFP number, ignore sign for QNaN */ 14162 assign( sign, 14163 unop( Iop_1Uto32, 14164 binop( Iop_CmpEQ32, 14165 binop( Iop_Shr32, 14166 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 14167 mkU8( 63 - 32 ) ), 14168 mkU32( 1 ) ) ) ); 14169 14170 /* This instruction generates a four bit field to be stored in the 14171 * condition code register. The condition code register consists of 7 14172 * fields. The field to be written to is specified by the BF (AKA crfD) 14173 * field. 14174 * 14175 * The field layout is as follows: 14176 * 14177 * Field Meaning 14178 * 0000 Operand positive with no match 14179 * 0100 Operand positive with at least one match 14180 * 0001 Operand negative with no match 14181 * 0101 Operand negative with at least one match 14182 */ 14183 assign( field, binop( Iop_Or32, 14184 binop( Iop_Shl32, 14185 mkexpr( sign ), 14186 mkU8( 3 ) ), 14187 binop( Iop_Shl32, 14188 unop( Iop_1Uto32, 14189 binop( Iop_CmpNE32, 14190 binop( Iop_And32, 14191 mkU32( DCM ), 14192 mkexpr( DCM_calc ) ), 14193 mkU32( 0 ) ) ), 14194 mkU8( 1 ) ) ) ); 14195 14196 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 14197 putFPCC( mkexpr( field ) ); 14198 return True; 14199 } 14200 14201 static Bool dis_dfp_bcd(UInt theInstr) { 14202 UInt opc2 = ifieldOPClo10( theInstr ); 14203 ULong sp = IFIELD(theInstr, 19, 2); 14204 ULong s = IFIELD(theInstr, 20, 1); 14205 UChar frT_addr = ifieldRegDS( theInstr ); 14206 UChar frB_addr = ifieldRegB( theInstr ); 14207 IRTemp frB = newTemp( Ity_D64 ); 14208 IRTemp frBI64 = newTemp( Ity_I64 ); 14209 IRTemp result = newTemp( Ity_I64 ); 14210 IRTemp resultD64 = newTemp( Ity_D64 ); 14211 IRTemp bcd64 = newTemp( Ity_I64 ); 14212 IRTemp bcd_u = newTemp( Ity_I32 ); 14213 IRTemp bcd_l = newTemp( Ity_I32 ); 14214 IRTemp dbcd_u = newTemp( Ity_I32 ); 14215 IRTemp dbcd_l = newTemp( Ity_I32 ); 14216 IRTemp lmd = newTemp( Ity_I32 ); 14217 14218 assign( frB, getDReg( frB_addr ) ); 14219 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 14220 14221 switch ( opc2 ) { 14222 case 0x142: // ddedpd DFP Decode DPD to BCD 14223 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 14224 14225 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 14226 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 14227 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 14228 14229 if ( ( sp == 0 ) || ( sp == 1 ) ) { 14230 /* Unsigned BCD string */ 14231 Get_lmd( &lmd, 14232 binop( Iop_Shr32, 14233 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14234 mkU8( 31 - 5 ) ) ); // G-field[0:4] 14235 14236 assign( result, 14237 binop( Iop_32HLto64, 14238 binop( Iop_Or32, 14239 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 14240 mkexpr( bcd_u ) ), 14241 mkexpr( bcd_l ) ) ); 14242 14243 } else { 14244 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 14245 * the positive and negative values are encoded in the least 14246 * significant bits. 14247 */ 14248 IRTemp sign = newTemp( Ity_I32 ); 14249 14250 if (sp == 2) { 14251 /* Positive sign = 0xC, negative sign = 0xD */ 14252 14253 assign( sign, 14254 binop( Iop_Or32, 14255 binop( Iop_Shr32, 14256 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14257 mkU8( 31 ) ), 14258 mkU32( 0xC ) ) ); 14259 14260 } else if ( sp == 3 ) { 14261 /* Positive sign = 0xF, negative sign = 0xD */ 14262 IRTemp tmp32 = newTemp( Ity_I32 ); 14263 14264 /* Complement sign bit then OR into bit position 1 */ 14265 assign( tmp32, 14266 binop( Iop_Xor32, 14267 binop( Iop_Shr32, 14268 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14269 mkU8( 30 ) ), 14270 mkU32( 0x2 ) ) ); 14271 14272 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 14273 14274 } else { 14275 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 14276 } 14277 14278 /* Put sign in bottom 4 bits, move most significant 4-bits from 14279 * bcd_l to bcd_u. 14280 */ 14281 assign( result, 14282 binop( Iop_32HLto64, 14283 binop( Iop_Or32, 14284 binop( Iop_Shr32, 14285 mkexpr( bcd_l ), 14286 mkU8( 28 ) ), 14287 binop( Iop_Shl32, 14288 mkexpr( bcd_u ), 14289 mkU8( 4 ) ) ), 14290 binop( Iop_Or32, 14291 mkexpr( sign ), 14292 binop( Iop_Shl32, 14293 mkexpr( bcd_l ), 14294 mkU8( 4 ) ) ) ) ); 14295 } 14296 14297 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 14298 break; 14299 14300 case 0x342: // denbcd DFP Encode BCD to DPD 14301 { 14302 IRTemp valid_mask = newTemp( Ity_I32 ); 14303 IRTemp invalid_mask = newTemp( Ity_I32 ); 14304 IRTemp without_lmd = newTemp( Ity_I64 ); 14305 IRTemp tmp64 = newTemp( Ity_I64 ); 14306 IRTemp dbcd64 = newTemp( Ity_I64 ); 14307 IRTemp left_exp = newTemp( Ity_I32 ); 14308 IRTemp g0_4 = newTemp( Ity_I32 ); 14309 14310 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 14311 14312 if ( s == 0 ) { 14313 /* Unsigned BCD string */ 14314 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 14315 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 14316 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 14317 14318 assign( lmd, 14319 binop( Iop_Shr32, 14320 binop( Iop_And32, 14321 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14322 mkU32( 0xF0000000 ) ), 14323 mkU8( 28 ) ) ); 14324 14325 assign( invalid_mask, 14326 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14327 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 14328 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14329 14330 assign( without_lmd, 14331 unop( Iop_ReinterpD64asI64, 14332 binop( Iop_InsertExpD64, 14333 mkU64( DFP_LONG_BIAS ), 14334 unop( Iop_ReinterpI64asD64, 14335 binop( Iop_32HLto64, 14336 mkexpr( dbcd_u ), 14337 mkexpr( dbcd_l ) ) ) ) ) ); 14338 assign( left_exp, 14339 binop( Iop_Shr32, 14340 binop( Iop_And32, 14341 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 14342 mkU32( 0x60000000 ) ), 14343 mkU8( 29 ) ) ); 14344 14345 assign( g0_4, 14346 binop( Iop_Shl32, 14347 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 14348 mkU8( 26 ) ) ); 14349 14350 assign( tmp64, 14351 binop( Iop_32HLto64, 14352 binop( Iop_Or32, 14353 binop( Iop_And32, 14354 unop( Iop_64HIto32, 14355 mkexpr( without_lmd ) ), 14356 mkU32( 0x83FFFFFF ) ), 14357 mkexpr( g0_4 ) ), 14358 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 14359 14360 } else if ( s == 1 ) { 14361 IRTemp sign = newTemp( Ity_I32 ); 14362 IRTemp sign_bit = newTemp( Ity_I32 ); 14363 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 14364 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 14365 IRTemp tmp = newTemp( Ity_I64 ); 14366 14367 /* Signed BCD string, least significant 4 bits are sign bits 14368 * positive sign = 0xC, negative sign = 0xD 14369 */ 14370 assign( tmp, unop( Iop_BCDtoDPB, 14371 binop( Iop_32HLto64, 14372 binop( Iop_Shr32, 14373 unop( Iop_64HIto32, 14374 mkexpr( frBI64 ) ), 14375 mkU8( 4 ) ), 14376 binop( Iop_Or32, 14377 binop( Iop_Shr32, 14378 unop( Iop_64to32, 14379 mkexpr( frBI64 ) ), 14380 mkU8( 4 ) ), 14381 binop( Iop_Shl32, 14382 unop( Iop_64HIto32, 14383 mkexpr( frBI64 ) ), 14384 mkU8( 28 ) ) ) ) ) ); 14385 14386 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 14387 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 14388 14389 /* Get the sign of the BCD string. */ 14390 assign( sign, 14391 binop( Iop_And32, 14392 unop( Iop_64to32, mkexpr( frBI64 ) ), 14393 mkU32( 0xF ) ) ); 14394 14395 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 14396 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 14397 assign( sign_bit, 14398 Generate_sign_bit( mkexpr( pos_sign_mask ), 14399 mkexpr( neg_sign_mask ) ) ); 14400 14401 /* Check for invalid sign and BCD digit. Don't check the bottom 14402 * four bits of bcd_l as that is the sign value. 14403 */ 14404 assign( invalid_mask, 14405 Generate_inv_mask( 14406 bcd_digit_inval( unop( Iop_64HIto32, 14407 mkexpr( frBI64 ) ), 14408 binop( Iop_Shr32, 14409 unop( Iop_64to32, 14410 mkexpr( frBI64 ) ), 14411 mkU8( 4 ) ) ), 14412 mkexpr( pos_sign_mask ), 14413 mkexpr( neg_sign_mask ) ) ); 14414 14415 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14416 14417 /* Generate the result assuming the sign value was valid. */ 14418 assign( tmp64, 14419 unop( Iop_ReinterpD64asI64, 14420 binop( Iop_InsertExpD64, 14421 mkU64( DFP_LONG_BIAS ), 14422 unop( Iop_ReinterpI64asD64, 14423 binop( Iop_32HLto64, 14424 binop( Iop_Or32, 14425 mkexpr( dbcd_u ), 14426 mkexpr( sign_bit ) ), 14427 mkexpr( dbcd_l ) ) ) ) ) ); 14428 } 14429 14430 /* Generate the value to store depending on the validity of the 14431 * sign value and the validity of the BCD digits. 14432 */ 14433 assign( resultD64, 14434 unop( Iop_ReinterpI64asD64, 14435 binop( Iop_32HLto64, 14436 binop( Iop_Or32, 14437 binop( Iop_And32, 14438 mkexpr( valid_mask ), 14439 unop( Iop_64HIto32, 14440 mkexpr( tmp64 ) ) ), 14441 binop( Iop_And32, 14442 mkU32( 0x7C000000 ), 14443 mkexpr( invalid_mask ) ) ), 14444 binop( Iop_Or32, 14445 binop( Iop_And32, 14446 mkexpr( valid_mask ), 14447 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 14448 binop( Iop_And32, 14449 mkU32( 0x0 ), 14450 mkexpr( invalid_mask ) ) ) ) ) ); 14451 putDReg( frT_addr, mkexpr( resultD64 ) ); 14452 } 14453 break; 14454 default: 14455 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 14456 return False; 14457 } 14458 return True; 14459 } 14460 14461 static Bool dis_dfp_bcdq( UInt theInstr ) 14462 { 14463 UInt opc2 = ifieldOPClo10( theInstr ); 14464 ULong sp = IFIELD(theInstr, 19, 2); 14465 ULong s = IFIELD(theInstr, 20, 1); 14466 IRTemp frB_hi = newTemp( Ity_D64 ); 14467 IRTemp frB_lo = newTemp( Ity_D64 ); 14468 IRTemp frBI64_hi = newTemp( Ity_I64 ); 14469 IRTemp frBI64_lo = newTemp( Ity_I64 ); 14470 UChar frT_addr = ifieldRegDS( theInstr ); 14471 UChar frB_addr = ifieldRegB( theInstr ); 14472 14473 IRTemp lmd = newTemp( Ity_I32 ); 14474 IRTemp result_hi = newTemp( Ity_I64 ); 14475 IRTemp result_lo = newTemp( Ity_I64 ); 14476 14477 assign( frB_hi, getDReg( frB_addr ) ); 14478 assign( frB_lo, getDReg( frB_addr + 1 ) ); 14479 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 14480 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 14481 14482 switch ( opc2 ) { 14483 case 0x142: // ddedpdq DFP Decode DPD to BCD 14484 { 14485 IRTemp low_60_u = newTemp( Ity_I32 ); 14486 IRTemp low_60_l = newTemp( Ity_I32 ); 14487 IRTemp mid_60_u = newTemp( Ity_I32 ); 14488 IRTemp mid_60_l = newTemp( Ity_I32 ); 14489 IRTemp top_12_l = newTemp( Ity_I32 ); 14490 14491 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 14492 14493 /* Note, instruction only stores the lower 32 BCD digits in 14494 * the result 14495 */ 14496 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 14497 mkexpr( frBI64_lo ), 14498 &top_12_l, 14499 &mid_60_u, 14500 &mid_60_l, 14501 &low_60_u, 14502 &low_60_l ); 14503 14504 if ( ( sp == 0 ) || ( sp == 1 ) ) { 14505 /* Unsigned BCD string */ 14506 assign( result_hi, 14507 binop( Iop_32HLto64, 14508 binop( Iop_Or32, 14509 binop( Iop_Shl32, 14510 mkexpr( top_12_l ), 14511 mkU8( 24 ) ), 14512 binop( Iop_Shr32, 14513 mkexpr( mid_60_u ), 14514 mkU8( 4 ) ) ), 14515 binop( Iop_Or32, 14516 binop( Iop_Shl32, 14517 mkexpr( mid_60_u ), 14518 mkU8( 28 ) ), 14519 binop( Iop_Shr32, 14520 mkexpr( mid_60_l ), 14521 mkU8( 4 ) ) ) ) ); 14522 14523 assign( result_lo, 14524 binop( Iop_32HLto64, 14525 binop( Iop_Or32, 14526 binop( Iop_Shl32, 14527 mkexpr( mid_60_l ), 14528 mkU8( 28 ) ), 14529 mkexpr( low_60_u ) ), 14530 mkexpr( low_60_l ) ) ); 14531 14532 } else { 14533 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 14534 * the positive and negative values are encoded in the least 14535 * significant bits. 14536 */ 14537 IRTemp sign = newTemp( Ity_I32 ); 14538 14539 if ( sp == 2 ) { 14540 /* Positive sign = 0xC, negative sign = 0xD */ 14541 assign( sign, 14542 binop( Iop_Or32, 14543 binop( Iop_Shr32, 14544 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14545 mkU8( 31 ) ), 14546 mkU32( 0xC ) ) ); 14547 14548 } else if ( sp == 3 ) { 14549 IRTemp tmp32 = newTemp( Ity_I32 ); 14550 14551 /* Positive sign = 0xF, negative sign = 0xD. 14552 * Need to complement sign bit then OR into bit position 1. 14553 */ 14554 assign( tmp32, 14555 binop( Iop_Xor32, 14556 binop( Iop_Shr32, 14557 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14558 mkU8( 30 ) ), 14559 mkU32( 0x2 ) ) ); 14560 14561 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 14562 14563 } else { 14564 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 14565 } 14566 14567 assign( result_hi, 14568 binop( Iop_32HLto64, 14569 binop( Iop_Or32, 14570 binop( Iop_Shl32, 14571 mkexpr( top_12_l ), 14572 mkU8( 28 ) ), 14573 mkexpr( mid_60_u ) ), 14574 mkexpr( mid_60_l ) ) ); 14575 14576 assign( result_lo, 14577 binop( Iop_32HLto64, 14578 binop( Iop_Or32, 14579 binop( Iop_Shl32, 14580 mkexpr( low_60_u ), 14581 mkU8( 4 ) ), 14582 binop( Iop_Shr32, 14583 mkexpr( low_60_l ), 14584 mkU8( 28 ) ) ), 14585 binop( Iop_Or32, 14586 binop( Iop_Shl32, 14587 mkexpr( low_60_l ), 14588 mkU8( 4 ) ), 14589 mkexpr( sign ) ) ) ); 14590 } 14591 14592 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 14593 putDReg( frT_addr + 1, 14594 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 14595 } 14596 break; 14597 case 0x342: // denbcdq DFP Encode BCD to DPD 14598 { 14599 IRTemp valid_mask = newTemp( Ity_I32 ); 14600 IRTemp invalid_mask = newTemp( Ity_I32 ); 14601 IRTemp result128 = newTemp( Ity_D128 ); 14602 IRTemp dfp_significand = newTemp( Ity_D128 ); 14603 IRTemp tmp_hi = newTemp( Ity_I64 ); 14604 IRTemp tmp_lo = newTemp( Ity_I64 ); 14605 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 14606 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 14607 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 14608 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 14609 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 14610 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 14611 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 14612 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 14613 IRTemp sign_bit = newTemp( Ity_I32 ); 14614 IRTemp tmptop10 = newTemp( Ity_I64 ); 14615 IRTemp tmpmid50 = newTemp( Ity_I64 ); 14616 IRTemp tmplow50 = newTemp( Ity_I64 ); 14617 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 14618 14619 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 14620 14621 if ( s == 0 ) { 14622 /* Unsigned BCD string */ 14623 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 14624 14625 assign( bcd_top_8, 14626 binop( Iop_32HLto64, 14627 mkU32( 0 ), 14628 binop( Iop_And32, 14629 binop( Iop_Shr32, 14630 unop( Iop_64HIto32, 14631 mkexpr( frBI64_hi ) ), 14632 mkU8( 24 ) ), 14633 mkU32( 0xFF ) ) ) ); 14634 assign( bcd_mid_60, 14635 binop( Iop_32HLto64, 14636 binop( Iop_Or32, 14637 binop( Iop_Shr32, 14638 unop( Iop_64to32, 14639 mkexpr( frBI64_hi ) ), 14640 mkU8( 28 ) ), 14641 binop( Iop_Shl32, 14642 unop( Iop_64HIto32, 14643 mkexpr( frBI64_hi ) ), 14644 mkU8( 4 ) ) ), 14645 binop( Iop_Or32, 14646 binop( Iop_Shl32, 14647 unop( Iop_64to32, 14648 mkexpr( frBI64_hi ) ), 14649 mkU8( 4 ) ), 14650 binop( Iop_Shr32, 14651 unop( Iop_64HIto32, 14652 mkexpr( frBI64_lo ) ), 14653 mkU8( 28 ) ) ) ) ); 14654 14655 /* Note, the various helper functions ignores top 4-bits */ 14656 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 14657 14658 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 14659 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 14660 14661 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 14662 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 14663 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 14664 14665 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 14666 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 14667 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 14668 14669 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 14670 * value is not part of the final result. Only the right most 14671 * BCD digits are stored. 14672 */ 14673 assign( lmd, mkU32( 0 ) ); 14674 14675 assign( invalid_mask, 14676 binop( Iop_Or32, 14677 bcd_digit_inval( mkU32( 0 ), 14678 unop( Iop_64to32, 14679 mkexpr( bcd_top_8 ) ) ), 14680 binop( Iop_Or32, 14681 bcd_digit_inval( unop( Iop_64HIto32, 14682 mkexpr( bcd_mid_60 ) ), 14683 unop( Iop_64to32, 14684 mkexpr( bcd_mid_60 ) ) ), 14685 bcd_digit_inval( unop( Iop_64HIto32, 14686 mkexpr( bcd_low_60 ) ), 14687 unop( Iop_64to32, 14688 mkexpr( bcd_low_60 ) ) 14689 ) ) ) ); 14690 14691 } else if ( s == 1 ) { 14692 IRTemp sign = newTemp( Ity_I32 ); 14693 IRTemp zero = newTemp( Ity_I32 ); 14694 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 14695 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 14696 14697 /* The sign of the BCD string is stored in lower 4 bits */ 14698 assign( sign, 14699 binop( Iop_And32, 14700 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 14701 mkU32( 0xF ) ) ); 14702 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 14703 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 14704 assign( sign_bit, 14705 Generate_sign_bit( mkexpr( pos_sign_mask ), 14706 mkexpr( neg_sign_mask ) ) ); 14707 14708 /* Generate the value assuminig the sign and BCD digits are vaild */ 14709 assign( bcd_top_8, 14710 binop( Iop_32HLto64, 14711 mkU32( 0x0 ), 14712 binop( Iop_Shr32, 14713 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14714 mkU8( 28 ) ) ) ); 14715 14716 /* The various helper routines ignore the upper 4-bits */ 14717 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 14718 14719 /* Remove bottom four sign bits */ 14720 assign( bcd_low_60, 14721 binop( Iop_32HLto64, 14722 binop( Iop_Shr32, 14723 unop( Iop_64HIto32, 14724 mkexpr( frBI64_lo ) ), 14725 mkU8( 4 ) ), 14726 binop( Iop_Or32, 14727 binop( Iop_Shl32, 14728 unop( Iop_64HIto32, 14729 mkexpr( frBI64_lo ) ), 14730 mkU8( 28 ) ), 14731 binop( Iop_Shr32, 14732 unop( Iop_64to32, 14733 mkexpr( frBI64_lo ) ), 14734 mkU8( 4 ) ) ) ) ); 14735 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 14736 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 14737 14738 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 14739 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 14740 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 14741 14742 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 14743 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 14744 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 14745 14746 /* The entire BCD string fits in lower 110-bits. The LMD value 14747 * is not stored in the final result for the DFP Long instruction. 14748 */ 14749 assign( lmd, mkU32( 0 ) ); 14750 14751 /* Check for invalid sign and invalid BCD digit. Don't check the 14752 * bottom four bits of frBI64_lo as that is the sign value. 14753 */ 14754 assign( zero, mkU32( 0 ) ); 14755 assign( inval_bcd_digit_mask, 14756 binop( Iop_Or32, 14757 bcd_digit_inval( mkexpr( zero ), 14758 unop( Iop_64to32, 14759 mkexpr( bcd_top_8 ) ) ), 14760 binop( Iop_Or32, 14761 bcd_digit_inval( unop( Iop_64HIto32, 14762 mkexpr( bcd_mid_60 ) ), 14763 unop( Iop_64to32, 14764 mkexpr( bcd_mid_60 ) ) ), 14765 bcd_digit_inval( unop( Iop_64HIto32, 14766 mkexpr( frBI64_lo ) ), 14767 binop( Iop_Shr32, 14768 unop( Iop_64to32, 14769 mkexpr( frBI64_lo ) ), 14770 mkU8( 4 ) ) ) ) ) ); 14771 assign( invalid_mask, 14772 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 14773 mkexpr( pos_sign_mask ), 14774 mkexpr( neg_sign_mask ) ) ); 14775 14776 } 14777 14778 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14779 14780 /* Calculate the value of the result assuming sign and BCD digits 14781 * are all valid. 14782 */ 14783 assign( dfp_significand, 14784 binop( Iop_D64HLtoD128, 14785 unop( Iop_ReinterpI64asD64, 14786 binop( Iop_32HLto64, 14787 binop( Iop_Or32, 14788 mkexpr( sign_bit ), 14789 mkexpr( dbcd_top_l ) ), 14790 binop( Iop_Or32, 14791 binop( Iop_Shl32, 14792 mkexpr( dbcd_mid_u ), 14793 mkU8( 18 ) ), 14794 binop( Iop_Shr32, 14795 mkexpr( dbcd_mid_l ), 14796 mkU8( 14 ) ) ) ) ), 14797 unop( Iop_ReinterpI64asD64, 14798 binop( Iop_32HLto64, 14799 binop( Iop_Or32, 14800 mkexpr( dbcd_low_u ), 14801 binop( Iop_Shl32, 14802 mkexpr( dbcd_mid_l ), 14803 mkU8( 18 ) ) ), 14804 mkexpr( dbcd_low_l ) ) ) ) ); 14805 14806 /* Break the result back down to 32-bit chunks and replace chunks. 14807 * If there was an invalid BCD digit or invalid sign value, replace 14808 * the calculated result with the invalid bit string. 14809 */ 14810 assign( result128, 14811 binop( Iop_InsertExpD128, 14812 mkU64( DFP_EXTND_BIAS ), 14813 mkexpr( dfp_significand ) ) ); 14814 14815 assign( tmp_hi, 14816 unop( Iop_ReinterpD64asI64, 14817 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 14818 14819 assign( tmp_lo, 14820 unop( Iop_ReinterpD64asI64, 14821 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 14822 14823 assign( result_hi, 14824 binop( Iop_32HLto64, 14825 binop( Iop_Or32, 14826 binop( Iop_And32, 14827 mkexpr( valid_mask ), 14828 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 14829 binop( Iop_And32, 14830 mkU32( 0x7C000000 ), 14831 mkexpr( invalid_mask ) ) ), 14832 binop( Iop_Or32, 14833 binop( Iop_And32, 14834 mkexpr( valid_mask ), 14835 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 14836 binop( Iop_And32, 14837 mkU32( 0x0 ), 14838 mkexpr( invalid_mask ) ) ) ) ); 14839 14840 assign( result_lo, 14841 binop( Iop_32HLto64, 14842 binop( Iop_Or32, 14843 binop( Iop_And32, 14844 mkexpr( valid_mask ), 14845 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 14846 binop( Iop_And32, 14847 mkU32( 0x0 ), 14848 mkexpr( invalid_mask ) ) ), 14849 binop( Iop_Or32, 14850 binop( Iop_And32, 14851 mkexpr( valid_mask ), 14852 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 14853 binop( Iop_And32, 14854 mkU32( 0x0 ), 14855 mkexpr( invalid_mask ) ) ) ) ); 14856 14857 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 14858 putDReg( frT_addr + 1, 14859 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 14860 14861 } 14862 break; 14863 default: 14864 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 14865 break; 14866 } 14867 return True; 14868 } 14869 14870 static Bool dis_dfp_significant_digits( UInt theInstr ) 14871 { 14872 UInt opc1 = ifieldOPC( theInstr ); 14873 UInt opc2 = ifieldOPClo10(theInstr); 14874 UChar frA_addr = ifieldRegA( theInstr ); 14875 UChar frB_addr = ifieldRegB( theInstr ); 14876 IRTemp frA = newTemp( Ity_D64 ); 14877 IRTemp B_sig = newTemp( Ity_I8 ); 14878 IRTemp K = newTemp( Ity_I8 ); 14879 IRTemp lmd_B = newTemp( Ity_I32 ); 14880 IRTemp field = newTemp( Ity_I32 ); 14881 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 14882 IRTemp Unordered_true = newTemp( Ity_I32 ); 14883 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 14884 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 14885 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 14886 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 14887 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 14888 IRTemp cc = newTemp( Ity_I32 ); 14889 UChar UIM = toUChar( IFIELD( theInstr, 16, 6 ) ); 14890 IRTemp BCD_valid = newTemp( Ity_I32 ); 14891 14892 if (opc2 == 0x2A2) { // dtstsf DFP Test Significance 14893 // dtstsfq DFP Test Significance Quad 14894 /* Get the reference singificance stored in frA */ 14895 assign( frA, getDReg( frA_addr ) ); 14896 14897 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 14898 * supported in 32-bit mode. 14899 */ 14900 assign( K, unop( Iop_32to8, 14901 binop( Iop_And32, 14902 unop( Iop_64to32, 14903 unop( Iop_ReinterpD64asI64, 14904 mkexpr( frA ) ) ), 14905 mkU32( 0x3F ) ) ) ); 14906 14907 } else if (opc2 == 0x2A3) { // dtstsfi DFP Test Significance Immediate 14908 // dtstsfiq DFP Test Significance Quad Immediate 14909 /* get the significane from the immediate field */ 14910 assign( K, mkU8( UIM) ); 14911 14912 } else { 14913 vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n"); 14914 return False; 14915 } 14916 14917 switch ( opc1 ) { 14918 case 0x3b: // dtstsf DFP Test Significance 14919 // dtstsfi DFP Test Significance Immediate 14920 { 14921 IRTemp frB = newTemp( Ity_D64 ); 14922 IRTemp frBI64 = newTemp( Ity_I64 ); 14923 IRTemp B_bcd_u = newTemp( Ity_I32 ); 14924 IRTemp B_bcd_l = newTemp( Ity_I32 ); 14925 IRTemp tmp64 = newTemp( Ity_I64 ); 14926 14927 if (opc2 == 0x2A2) { 14928 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 14929 } else { 14930 DIP( "dtstsfi %u,%u,r%u\n", crfD, UIM, frB_addr ); 14931 } 14932 14933 assign( frB, getDReg( frB_addr ) ); 14934 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 14935 14936 /* Get the BCD string for the value stored in a series of I32 values. 14937 * Count the number of leading zeros. Subtract the number of leading 14938 * zeros from 16 (maximum number of significant digits in DFP 14939 * Long). 14940 */ 14941 Get_lmd( &lmd_B, 14942 binop( Iop_Shr32, 14943 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14944 mkU8( 31 - 5 ) ) ); // G-field[0:4] 14945 14946 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 14947 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 14948 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 14949 14950 assign( B_sig, 14951 binop( Iop_Sub8, 14952 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 14953 Count_leading_zeros_60( mkexpr( lmd_B ), 14954 mkexpr( B_bcd_u ), 14955 mkexpr( B_bcd_l ) ) ) ); 14956 14957 assign( BCD_valid, 14958 binop( Iop_Or32, 14959 bcd_digit_inval( mkexpr( B_bcd_u), mkexpr( B_bcd_l) ), 14960 bcd_digit_inval( mkexpr( lmd_B), mkU32( 0 ) ) ) ); 14961 14962 /* Set unordered to True if the number is NaN, Inf or an invalid 14963 * digit. 14964 */ 14965 assign( Unordered_true, 14966 binop( Iop_Or32, 14967 Check_unordered( mkexpr( frBI64 ) ), 14968 mkexpr( BCD_valid) ) ); 14969 } 14970 break; 14971 case 0x3F: // dtstsfq DFP Test Significance 14972 // dtstsfqi DFP Test Significance Immediate 14973 { 14974 IRTemp frB_hi = newTemp( Ity_D64 ); 14975 IRTemp frB_lo = newTemp( Ity_D64 ); 14976 IRTemp frBI64_hi = newTemp( Ity_I64 ); 14977 IRTemp frBI64_lo = newTemp( Ity_I64 ); 14978 IRTemp B_low_60_u = newTemp( Ity_I32 ); 14979 IRTemp B_low_60_l = newTemp( Ity_I32 ); 14980 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 14981 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 14982 IRTemp B_top_12_l = newTemp( Ity_I32 ); 14983 14984 if (opc2 == 0x2A2) { 14985 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 14986 } else { 14987 DIP( "dtstsfiq %u,%u,r%u\n", crfD, UIM, frB_addr ); 14988 } 14989 14990 assign( frB_hi, getDReg( frB_addr ) ); 14991 assign( frB_lo, getDReg( frB_addr + 1 ) ); 14992 14993 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 14994 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 14995 14996 /* Get the BCD string for the value stored in a series of I32 values. 14997 * Count the number of leading zeros. Subtract the number of leading 14998 * zeros from 32 (maximum number of significant digits in DFP 14999 * extended). 15000 */ 15001 Get_lmd( &lmd_B, 15002 binop( Iop_Shr32, 15003 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 15004 mkU8( 31 - 5 ) ) ); // G-field[0:4] 15005 15006 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 15007 mkexpr( frBI64_lo ), 15008 &B_top_12_l, 15009 &B_mid_60_u, 15010 &B_mid_60_l, 15011 &B_low_60_u, 15012 &B_low_60_l ); 15013 15014 assign( BCD_valid, 15015 binop( Iop_Or32, 15016 binop( Iop_Or32, 15017 bcd_digit_inval( mkexpr( lmd_B ), 15018 mkexpr( B_top_12_l ) ), 15019 bcd_digit_inval( mkexpr( B_mid_60_u ), 15020 mkexpr( B_mid_60_l ) ) ), 15021 bcd_digit_inval( mkexpr( B_low_60_u ), 15022 mkexpr( B_low_60_l ) ) ) ); 15023 15024 assign( B_sig, 15025 binop( Iop_Sub8, 15026 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 15027 Count_leading_zeros_128( mkexpr( lmd_B ), 15028 mkexpr( B_top_12_l ), 15029 mkexpr( B_mid_60_u ), 15030 mkexpr( B_mid_60_l ), 15031 mkexpr( B_low_60_u ), 15032 mkexpr( B_low_60_l ) ) ) ); 15033 15034 /* Set unordered to True if the number is NaN, Inf or an invalid 15035 * digit. 15036 */ 15037 assign( Unordered_true, 15038 binop( Iop_Or32, 15039 Check_unordered( mkexpr( frBI64_hi ) ), 15040 mkexpr( BCD_valid) ) ); 15041 } 15042 break; 15043 } 15044 15045 /* Compare (16 - cnt[0]) against K and set the condition code field 15046 * accordingly. 15047 * 15048 * The field layout is as follows: 15049 * 15050 * bit[3:0] Description 15051 * 3 K != 0 and K < Number of significant digits if FRB 15052 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 15053 * 1 K != 0 and K = Number of significant digits if FRB 15054 * 0 K ? Number of significant digits if FRB 15055 */ 15056 assign( Eq_true_mask, 15057 unop( Iop_1Sto32, 15058 binop( Iop_CmpEQ32, 15059 unop( Iop_8Uto32, mkexpr( K ) ), 15060 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 15061 assign( Lt_true_mask, 15062 unop( Iop_1Sto32, 15063 binop( Iop_CmpLT32U, 15064 unop( Iop_8Uto32, mkexpr( K ) ), 15065 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 15066 assign( Gt_true_mask, 15067 unop( Iop_1Sto32, 15068 binop( Iop_CmpLT32U, 15069 unop( Iop_8Uto32, mkexpr( B_sig ) ), 15070 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 15071 15072 assign( KisZero_true_mask, 15073 unop( Iop_1Sto32, 15074 binop( Iop_CmpEQ32, 15075 unop( Iop_8Uto32, mkexpr( K ) ), 15076 mkU32( 0 ) ) ) ); 15077 assign( KisZero_false_mask, 15078 unop( Iop_1Sto32, 15079 binop( Iop_CmpNE32, 15080 unop( Iop_8Uto32, mkexpr( K ) ), 15081 mkU32( 0 ) ) ) ); 15082 15083 assign( field, 15084 binop( Iop_Or32, 15085 binop( Iop_And32, 15086 mkexpr( KisZero_false_mask ), 15087 binop( Iop_Or32, 15088 binop( Iop_And32, 15089 mkexpr( Lt_true_mask ), 15090 mkU32( 0x8 ) ), 15091 binop( Iop_Or32, 15092 binop( Iop_And32, 15093 mkexpr( Gt_true_mask ), 15094 mkU32( 0x4 ) ), 15095 binop( Iop_And32, 15096 mkexpr( Eq_true_mask ), 15097 mkU32( 0x2 ) ) ) ) ), 15098 binop( Iop_And32, 15099 mkexpr( KisZero_true_mask ), 15100 mkU32( 0x4 ) ) ) ); 15101 15102 assign( cc, binop( Iop_Or32, 15103 binop( Iop_And32, 15104 mkexpr( Unordered_true ), 15105 mkU32( 0x1 ) ), 15106 binop( Iop_And32, 15107 unop( Iop_Not32, mkexpr( Unordered_true ) ), 15108 mkexpr( field ) ) ) ); 15109 15110 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD ); 15111 putFPCC( mkexpr( cc ) ); 15112 15113 return True; 15114 } 15115 /*------------------------------------------------------------*/ 15116 /*--- AltiVec Instruction Translation ---*/ 15117 /*------------------------------------------------------------*/ 15118 15119 /* 15120 Altivec Cache Control Instructions (Data Streams) 15121 */ 15122 static Bool dis_av_datastream ( UInt theInstr ) 15123 { 15124 /* X-Form */ 15125 UChar opc1 = ifieldOPC(theInstr); 15126 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 15127 UChar flag_A = flag_T; 15128 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 15129 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 15130 UChar rA_addr = ifieldRegA(theInstr); 15131 UChar rB_addr = ifieldRegB(theInstr); 15132 UInt opc2 = ifieldOPClo10(theInstr); 15133 UChar b0 = ifieldBIT0(theInstr); 15134 15135 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 15136 vex_printf("dis_av_datastream(ppc)(instr)\n"); 15137 return False; 15138 } 15139 15140 switch (opc2) { 15141 case 0x156: // dst (Data Stream Touch, AV p115) 15142 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 15143 rA_addr, rB_addr, STRM); 15144 break; 15145 15146 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 15147 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 15148 rA_addr, rB_addr, STRM); 15149 break; 15150 15151 case 0x336: // dss (Data Stream Stop, AV p114) 15152 if (rA_addr != 0 || rB_addr != 0) { 15153 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 15154 return False; 15155 } 15156 if (flag_A == 0) { 15157 DIP("dss %d\n", STRM); 15158 } else { 15159 DIP("dssall\n"); 15160 } 15161 break; 15162 15163 default: 15164 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 15165 return False; 15166 } 15167 return True; 15168 } 15169 15170 /* 15171 AltiVec Processor Control Instructions 15172 */ 15173 static Bool dis_av_procctl ( UInt theInstr ) 15174 { 15175 /* VX-Form */ 15176 UChar opc1 = ifieldOPC(theInstr); 15177 UChar vD_addr = ifieldRegDS(theInstr); 15178 UChar vA_addr = ifieldRegA(theInstr); 15179 UChar vB_addr = ifieldRegB(theInstr); 15180 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15181 15182 if (opc1 != 0x4) { 15183 vex_printf("dis_av_procctl(ppc)(instr)\n"); 15184 return False; 15185 } 15186 15187 switch (opc2) { 15188 case 0x604: // mfvscr (Move from VSCR, AV p129) 15189 if (vA_addr != 0 || vB_addr != 0) { 15190 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 15191 return False; 15192 } 15193 DIP("mfvscr v%d\n", vD_addr); 15194 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 15195 break; 15196 15197 case 0x644: { // mtvscr (Move to VSCR, AV p130) 15198 IRTemp vB = newTemp(Ity_V128); 15199 if (vD_addr != 0 || vA_addr != 0) { 15200 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 15201 return False; 15202 } 15203 DIP("mtvscr v%d\n", vB_addr); 15204 assign( vB, getVReg(vB_addr)); 15205 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 15206 break; 15207 } 15208 default: 15209 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 15210 return False; 15211 } 15212 return True; 15213 } 15214 15215 /* 15216 Vector Extend Sign Instructions 15217 */ 15218 static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 ) 15219 { 15220 /* VX-Form, sort of, the A register field is used to select the specific 15221 * sign extension instruction or count leading/trailing zero LSB 15222 * instruction. 15223 */ 15224 15225 UChar opc1 = ifieldOPC( theInstr ); 15226 UChar rT_addr = ifieldRegDS (theInstr ); 15227 UChar rA_addr = ifieldRegA( theInstr ); 15228 UChar vB_addr = ifieldRegB( theInstr ); 15229 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15230 15231 IRTemp vB = newTemp( Ity_V128 ); 15232 IRTemp vT = newTemp( Ity_V128 ); 15233 15234 assign( vB, getVReg ( vB_addr ) ); 15235 15236 if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) ) { 15237 vex_printf("dis_av_extend_sign(ppc)(instr)\n"); 15238 return False; 15239 } 15240 15241 switch ( rA_addr ) { 15242 case 0: 15243 case 1: 15244 { 15245 UInt i; 15246 IRTemp count[17]; 15247 IRTemp bit_zero[16]; 15248 IRTemp byte_mask[17]; 15249 15250 /* These instructions store the result in the general purpose 15251 * register in the rT_addr field. 15252 */ 15253 15254 byte_mask[0] = newTemp( Ity_I32 ); 15255 count[0] = newTemp( Ity_I32 ); 15256 assign( count[0], mkU32( 0 ) ); 15257 assign( byte_mask[0], mkU32( 0x1 ) ); 15258 15259 if ( rA_addr == 0 ) { 15260 // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte) 15261 DIP("vclzlsbb %d,v%d\n", rT_addr, vB_addr); 15262 15263 } else { 15264 // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte) 15265 DIP("vctzlsbb %d,v%d\n", rT_addr, vB_addr); 15266 } 15267 15268 for( i = 0; i < 16; i++ ) { 15269 byte_mask[i+1] = newTemp( Ity_I32 ); 15270 count[i+1] = newTemp( Ity_I32 ); 15271 bit_zero[i] = newTemp( Ity_I1 ); 15272 15273 /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of 15274 * byte. When the first 1 bit is found it causes the byte_mask 15275 * to change from 0x1 to 0x0. Thus the AND of the lsb and byte_mask 15276 * will be zero which will be equal to the zero byte_mask causing 15277 * the value of bit_zero[i] to be equal to 0x1 for all remaining bits. 15278 */ 15279 15280 if ( rA_addr == 0 ) 15281 /* leading zero bit in byte count, 15282 work bytes from left to right 15283 */ 15284 assign( bit_zero[i], 15285 binop( Iop_CmpEQ32, 15286 binop( Iop_And32, 15287 unop( Iop_V128to32, 15288 binop( Iop_ShrV128, 15289 mkexpr( vB ), 15290 mkU8( ( 15 - i) * 8 ) ) ), 15291 mkexpr( byte_mask[i] ) ), 15292 mkexpr( byte_mask[i] ) ) ); 15293 15294 else if ( rA_addr == 1 ) 15295 /* trailing zero bit in byte count, 15296 * work bytes from right to left 15297 */ 15298 assign( bit_zero[i], 15299 binop( Iop_CmpEQ32, 15300 binop( Iop_And32, 15301 unop( Iop_V128to32, 15302 binop( Iop_ShrV128, 15303 mkexpr( vB ), 15304 mkU8( i * 8 ) ) ), 15305 mkexpr( byte_mask[i] ) ), 15306 mkexpr( byte_mask[i] ) ) ); 15307 15308 /* Increment count as long as bit_zero = 0 */ 15309 assign( count[i+1], binop( Iop_Add32, 15310 mkexpr( count[i] ), 15311 unop( Iop_1Uto32, 15312 unop( Iop_Not1, 15313 mkexpr( bit_zero[i] ) ) ) ) ); 15314 15315 /* If comparison fails to find a zero bit, set the byte_mask to zero 15316 * for all future comparisons so there will be no more matches. 15317 */ 15318 assign( byte_mask[i+1], 15319 binop( Iop_And32, 15320 unop( Iop_1Uto32, 15321 unop( Iop_Not1, 15322 mkexpr( bit_zero[i] ) ) ), 15323 mkexpr( byte_mask[i] ) ) ); 15324 } 15325 putIReg( rT_addr, unop( Iop_32Uto64, mkexpr( count[16] ) ) ); 15326 return True; 15327 } 15328 15329 case 6: // vnegw, Vector Negate Word 15330 DIP("vnegw v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15331 15332 /* multiply each word by -1 */ 15333 assign( vT, binop( Iop_Mul32x4, mkexpr( vB ), mkV128( 0xFFFF ) ) ); 15334 break; 15335 15336 case 7: // vnegd, Vector Negate Doubleword 15337 DIP("vnegd v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15338 15339 /* multiply each word by -1 */ 15340 assign( vT, binop( Iop_64HLtoV128, 15341 binop( Iop_Mul64, 15342 unop( Iop_V128HIto64, 15343 mkexpr( vB ) ), 15344 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 15345 binop( Iop_Mul64, 15346 unop( Iop_V128to64, 15347 mkexpr( vB ) ), 15348 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ); 15349 break; 15350 15351 case 8: // vprtybw, Vector Parity Byte Word 15352 case 9: // vprtybd, Vector Parity Byte Doubleword 15353 case 10: // vprtybq, Vector Parity Byte Quadword 15354 { 15355 UInt i; 15356 IRTemp bit_in_byte[16]; 15357 IRTemp word_parity[4]; 15358 15359 for( i = 0; i < 16; i++ ) { 15360 bit_in_byte[i] = newTemp( Ity_I32 ); 15361 assign( bit_in_byte[i], 15362 binop( Iop_And32, 15363 unop( Iop_V128to32, 15364 binop( Iop_ShrV128, 15365 mkexpr( vB ), 15366 mkU8( ( 15 - i ) * 8 ) ) ), 15367 mkU32( 0x1 ) ) ); 15368 } 15369 15370 for( i = 0; i < 4; i++ ) { 15371 word_parity[i] = newTemp(Ity_I32); 15372 assign( word_parity[i], 15373 mkXOr4_32( bit_in_byte[0 + i * 4], 15374 bit_in_byte[1 + i * 4], 15375 bit_in_byte[2 + i * 4], 15376 bit_in_byte[3 + i * 4] ) ); 15377 } 15378 15379 if ( rA_addr == 8 ) { 15380 DIP("vprtybw v%d,v%d", rT_addr, vB_addr); 15381 15382 assign( vT, mkV128from32( word_parity[0], word_parity[1], 15383 word_parity[2], word_parity[3] ) ); 15384 15385 } else if ( rA_addr == 9 ) { 15386 DIP("vprtybd v%d,v%d", rT_addr, vB_addr); 15387 15388 assign( vT, 15389 binop( Iop_64HLtoV128, 15390 binop( Iop_32HLto64, 15391 mkU32( 0 ), 15392 binop( Iop_Xor32, 15393 mkexpr( word_parity[0] ), 15394 mkexpr( word_parity[1] ) ) ), 15395 binop( Iop_32HLto64, 15396 mkU32( 0 ), 15397 binop( Iop_Xor32, 15398 mkexpr( word_parity[2] ), 15399 mkexpr( word_parity[3] ) ) ) ) ); 15400 15401 } else if ( rA_addr == 10 ) { 15402 DIP("vprtybq v%d,v%d", rT_addr, vB_addr); 15403 15404 assign( vT, 15405 binop( Iop_64HLtoV128, 15406 mkU64( 0 ), 15407 unop( Iop_32Uto64, 15408 mkXOr4_32( word_parity[0], 15409 word_parity[1], 15410 word_parity[2], 15411 word_parity[3] ) ) ) ); 15412 } 15413 } 15414 break; 15415 15416 case 16: // vextsb2w, Vector Extend Sign Byte to Word 15417 DIP("vextsb2w v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15418 15419 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to 15420 * two byte sign extended result. Then do a two byte to four byte sign 15421 * extended multiply. Note contents of upper three bytes in word are 15422 * "over written". So just take source and multiply by 1. 15423 */ 15424 assign( vT, binop( Iop_MullEven16Sx8, 15425 binop( Iop_64HLtoV128, 15426 mkU64( 0x0000000100000001 ), 15427 mkU64( 0x0000000100000001 ) ), 15428 binop( Iop_MullEven8Sx16, 15429 mkexpr( vB ), 15430 binop( Iop_64HLtoV128, 15431 mkU64( 0x0001000100010001 ), 15432 mkU64( 0x0001000100010001 ) ) ) ) ); 15433 break; 15434 15435 case 17: // vextsh2w, Vector Extend Sign Halfword to Word 15436 DIP("vextsh2w v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15437 15438 /* Iop_MullEven16Sx8 does a signed widening multiply of four byte 15439 * 8 bytes. Note contents of upper two bytes in word are 15440 * "over written". So just take source and multiply by 1. 15441 */ 15442 assign( vT, binop( Iop_MullEven16Sx8, 15443 binop( Iop_64HLtoV128, 15444 mkU64( 0x0000000100000001 ), 15445 mkU64( 0x0000000100000001 ) ), 15446 mkexpr( vB ) ) ); 15447 15448 break; 15449 15450 case 24: // vextsb2d, Vector Extend Sign Byte to Doubleword 15451 DIP("vextsb2d v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15452 15453 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to 15454 * two byte sign extended result. Then do a two byte to four byte sign 15455 * extended multiply. Then do four byte to eight byte multiply. 15456 */ 15457 assign( vT, binop( Iop_MullEven32Sx4, 15458 binop( Iop_64HLtoV128, 15459 mkU64( 0x0000000000000001 ), 15460 mkU64( 0x0000000000000001 ) ), 15461 binop( Iop_MullEven16Sx8, 15462 binop( Iop_64HLtoV128, 15463 mkU64( 0x0000000100000001 ), 15464 mkU64( 0x0000000100000001 ) ), 15465 binop( Iop_MullEven8Sx16, 15466 binop( Iop_64HLtoV128, 15467 mkU64( 0x0001000100010001 ), 15468 mkU64( 0x0001000100010001 ) ), 15469 mkexpr( vB ) ) ) ) ); 15470 break; 15471 15472 case 25: // vextsh2d, Vector Extend Sign Halfword to Doubleword 15473 DIP("vextsh2d v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15474 15475 assign( vT, binop( Iop_MullEven32Sx4, 15476 binop( Iop_64HLtoV128, 15477 mkU64( 0x0000000000000001 ), 15478 mkU64( 0x0000000000000001 ) ), 15479 binop( Iop_MullEven16Sx8, 15480 binop( Iop_64HLtoV128, 15481 mkU64( 0x0000000100000001 ), 15482 mkU64( 0x0000000100000001 ) ), 15483 mkexpr( vB ) ) ) ); 15484 break; 15485 15486 case 26: // vextsw2d, Vector Extend Sign Word to Doubleword 15487 DIP("vextsw2d v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15488 15489 assign( vT, binop( Iop_MullEven32Sx4, 15490 binop( Iop_64HLtoV128, 15491 mkU64( 0x0000000000000001 ), 15492 mkU64( 0x0000000000000001 ) ), 15493 mkexpr( vB ) ) ); 15494 break; 15495 15496 case 28: // vctzb, Vector Count Trailing Zeros Byte 15497 { 15498 DIP("vctzb v%d,v%d", rT_addr, vB_addr); 15499 15500 /* This instruction is only available in the ISA 3.0 */ 15501 if ( !mode64 || !allow_isa_3_0 ) { 15502 vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n"); 15503 return False; 15504 } 15505 assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) ); 15506 } 15507 break; 15508 15509 case 29: // vctzh, Vector Count Trailing Zeros Halfword 15510 { 15511 DIP("vctzh v%d,v%d", rT_addr, vB_addr); 15512 15513 /* This instruction is only available in the ISA 3.0 */ 15514 if ( !mode64 || !allow_isa_3_0 ) { 15515 vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n"); 15516 return False; 15517 } 15518 assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) ); 15519 } 15520 break; 15521 15522 case 30: // vctzw, Vector Count Trailing Zeros Word 15523 { 15524 DIP("vctzw v%d,v%d", rT_addr, vB_addr); 15525 15526 /* This instruction is only available in the ISA 3.0 */ 15527 if ( !mode64 || !allow_isa_3_0 ) { 15528 vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n"); 15529 return False; 15530 } 15531 assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) ); 15532 } 15533 break; 15534 15535 case 31: // vctzd, Vector Count Trailing Zeros Double word 15536 { 15537 DIP("vctzd v%d,v%d", rT_addr, vB_addr); 15538 15539 /* This instruction is only available in the ISA 3.0 */ 15540 if ( !mode64 || !allow_isa_3_0 ) { 15541 vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n"); 15542 return False; 15543 } 15544 assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) ); 15545 } 15546 break; 15547 15548 default: 15549 vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n"); 15550 return False; 15551 } 15552 15553 putVReg( rT_addr, mkexpr( vT ) ); 15554 return True; 15555 } 15556 15557 /* 15558 Vector Rotate Instructions 15559 */ 15560 static Bool dis_av_rotate ( UInt theInstr ) 15561 { 15562 /* VX-Form */ 15563 15564 UChar opc1 = ifieldOPC( theInstr ); 15565 UChar vT_addr = ifieldRegDS( theInstr ); 15566 UChar vA_addr = ifieldRegA( theInstr ); 15567 UChar vB_addr = ifieldRegB( theInstr ); 15568 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15569 15570 IRTemp vA = newTemp( Ity_V128 ); 15571 IRTemp vB = newTemp( Ity_V128 ); 15572 IRTemp src3 = newTemp( Ity_V128 ); 15573 IRTemp vT = newTemp( Ity_V128 ); 15574 IRTemp field_mask = newTemp( Ity_V128 ); 15575 IRTemp mask128 = newTemp( Ity_V128 ); 15576 IRTemp vA_word[4]; 15577 IRTemp left_bits[4]; 15578 IRTemp right_bits[4]; 15579 IRTemp shift[4]; 15580 IRTemp mask[4]; 15581 IRTemp tmp128[4]; 15582 UInt i; 15583 UInt num_words; 15584 UInt word_size; 15585 unsigned long long word_mask; 15586 15587 if ( opc1 != 0x4 ) { 15588 vex_printf("dis_av_rotate(ppc)(instr)\n"); 15589 return False; 15590 } 15591 15592 assign( vA, getVReg( vA_addr ) ); 15593 assign( vB, getVReg( vB_addr ) ); 15594 15595 switch (opc2) { 15596 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert 15597 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask 15598 num_words = 4; 15599 word_size = 32; 15600 assign( field_mask, binop( Iop_64HLtoV128, 15601 mkU64( 0 ), 15602 mkU64( 0x1F ) ) ); 15603 word_mask = 0xFFFFFFFF; 15604 break; 15605 15606 case 0x0C5: // vrldmi, Vector Rotate Left Doubleword then Mask Insert 15607 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask 15608 num_words = 2; 15609 word_size = 64; 15610 assign( field_mask, binop( Iop_64HLtoV128, 15611 mkU64( 0 ), 15612 mkU64( 0x3F ) ) ); 15613 word_mask = 0xFFFFFFFFFFFFFFFFULL; 15614 break; 15615 default: 15616 vex_printf("dis_av_rotate(ppc)(opc2)\n"); 15617 return False; 15618 } 15619 15620 for( i = 0; i < num_words; i++ ) { 15621 left_bits[i] = newTemp( Ity_I8 ); 15622 right_bits[i] = newTemp( Ity_I8 ); 15623 shift[i] = newTemp( Ity_I8 ); 15624 mask[i] = newTemp( Ity_V128 ); 15625 tmp128[i] = newTemp( Ity_V128 ); 15626 vA_word[i] = newTemp( Ity_V128 ); 15627 15628 assign( shift[i], 15629 unop( Iop_64to8, 15630 unop( Iop_V128to64, 15631 binop( Iop_AndV128, 15632 binop( Iop_ShrV128, 15633 mkexpr( vB ), 15634 mkU8( (num_words - 1 - i ) 15635 * word_size ) ), 15636 mkexpr( field_mask ) ) ) ) ); 15637 15638 /* left_bits = 63 - mb. Tells us how many bits to the left 15639 * of mb to clear. Note for a word left_bits = 32+mb, for a double 15640 * word left_bits = mb 15641 */ 15642 assign( left_bits[i], 15643 unop( Iop_64to8, 15644 binop( Iop_Add64, 15645 mkU64( 64 - word_size ), 15646 unop( Iop_V128to64, 15647 binop( Iop_AndV128, 15648 binop( Iop_ShrV128, 15649 mkexpr( vB ), 15650 mkU8( ( num_words - 1 - i ) 15651 * word_size + 16 ) ), 15652 mkexpr( field_mask ) ) ) ) ) ); 15653 /* right_bits = 63 - me. Tells us how many bits to the right 15654 * of me to clear. Note for a word, left_bits = me+32, for a double 15655 * word left_bits = me 15656 */ 15657 assign( right_bits[i], 15658 unop( Iop_64to8, 15659 binop( Iop_Sub64, 15660 mkU64( word_size - 1 ), 15661 unop( Iop_V128to64, 15662 binop( Iop_AndV128, 15663 binop( Iop_ShrV128, 15664 mkexpr( vB ), 15665 mkU8( ( num_words - 1 - i ) 15666 * word_size + 8 ) ), 15667 mkexpr( field_mask ) ) ) ) ) ); 15668 15669 /* create mask for 32-bit word or 64-bit word */ 15670 assign( mask[i], 15671 binop( Iop_64HLtoV128, 15672 mkU64( 0 ), 15673 binop( Iop_Shl64, 15674 binop( Iop_Shr64, 15675 binop( Iop_Shr64, 15676 binop( Iop_Shl64, 15677 mkU64( 0xFFFFFFFFFFFFFFFF ), 15678 mkexpr( left_bits[i] ) ), 15679 mkexpr( left_bits[i] ) ), 15680 mkexpr( right_bits[i] ) ), 15681 mkexpr( right_bits[i] ) ) ) ); 15682 15683 /* Need to rotate vA using a left and right shift of vA OR'd together 15684 * then ANDed with the mask. 15685 */ 15686 assign( vA_word[i], binop( Iop_AndV128, 15687 mkexpr( vA ), 15688 binop( Iop_ShlV128, 15689 binop( Iop_64HLtoV128, 15690 mkU64( 0 ), 15691 mkU64( word_mask ) ), 15692 mkU8( ( num_words - 1 - i ) 15693 * word_size ) ) ) ); 15694 assign( tmp128[i], 15695 binop( Iop_AndV128, 15696 binop( Iop_ShlV128, 15697 mkexpr( mask[i] ), 15698 mkU8( ( num_words - 1 - i) * word_size ) ), 15699 binop( Iop_OrV128, 15700 binop( Iop_ShlV128, 15701 mkexpr( vA_word[i] ), 15702 mkexpr( shift[i] ) ), 15703 binop( Iop_ShrV128, 15704 mkexpr( vA_word[i] ), 15705 unop( Iop_32to8, 15706 binop(Iop_Sub32, 15707 mkU32( word_size ), 15708 unop( Iop_8Uto32, 15709 mkexpr( shift[i] ) ) ) 15710 ) ) ) ) ); 15711 } 15712 15713 switch (opc2) { 15714 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert 15715 DIP("vrlwmi %d,%d,v%d", vT_addr, vA_addr, vB_addr); 15716 15717 assign( src3, getVReg( vT_addr ) ); 15718 assign( mask128, unop( Iop_NotV128, 15719 mkOr4_V128_expr( binop( Iop_ShlV128, 15720 mkexpr( mask[0] ), 15721 mkU8( 96 ) ), 15722 binop( Iop_ShlV128, 15723 mkexpr( mask[1] ), 15724 mkU8( 64 ) ), 15725 binop( Iop_ShlV128, 15726 mkexpr( mask[2] ), 15727 mkU8( 32 ) ), 15728 mkexpr( mask[3] ) ) ) ); 15729 assign( vT, binop( Iop_OrV128, 15730 binop( Iop_AndV128, 15731 mkexpr( src3 ), 15732 mkexpr( mask128 ) ), 15733 mkOr4_V128( tmp128[0], tmp128[1], 15734 tmp128[2], tmp128[3] ) ) ); 15735 break; 15736 15737 case 0xC5: // vrldmi, Vector Rotate Left Double word then Mask Insert 15738 DIP("vrldmi %d,%d,v%d", vT_addr, vA_addr, vB_addr); 15739 15740 assign( src3, getVReg( vT_addr ) ); 15741 assign( mask128, unop( Iop_NotV128, 15742 binop( Iop_OrV128, 15743 binop( Iop_ShlV128, 15744 mkexpr( mask[0] ), 15745 mkU8( 64 ) ), 15746 mkexpr( mask[1] ) ) ) ); 15747 15748 assign( vT, binop( Iop_OrV128, 15749 binop( Iop_AndV128, 15750 mkexpr( src3 ), 15751 mkexpr( mask128 ) ), 15752 binop( Iop_OrV128, 15753 mkexpr( tmp128[0] ), 15754 mkexpr( tmp128[1] ) ) ) ); 15755 break; 15756 15757 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask 15758 DIP("vrlwnm %d,%d,v%d", vT_addr, vA_addr, vB_addr); 15759 assign( vT, mkOr4_V128( tmp128[0], tmp128[1], tmp128[2], tmp128[3] ) ); 15760 break; 15761 15762 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask 15763 DIP("vrldnm %d,%d,v%d", vT_addr, vA_addr, vB_addr); 15764 assign( vT, binop( Iop_OrV128, 15765 mkexpr( tmp128[0] ), 15766 mkexpr( tmp128[1] ) ) ); 15767 break; 15768 } 15769 15770 putVReg( vT_addr, mkexpr( vT ) ); 15771 return True; 15772 } 15773 15774 /* 15775 AltiVec Vector Extract Element Instructions 15776 */ 15777 static Bool dis_av_extract_element ( UInt theInstr ) 15778 { 15779 /* VX-Form, 15780 * sorta destination and first source are GPR not vector registers 15781 */ 15782 15783 UChar opc1 = ifieldOPC( theInstr ); 15784 UChar rT_addr = ifieldRegDS( theInstr ); 15785 UChar rA_addr = ifieldRegA( theInstr ); 15786 UChar vB_addr = ifieldRegB( theInstr ); 15787 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15788 15789 IRTemp vB = newTemp( Ity_V128 ); 15790 IRTemp rA = newTemp( Ity_I64 ); 15791 IRTemp rT = newTemp( Ity_I64 ); 15792 15793 assign( vB, getVReg( vB_addr ) ); 15794 assign( rA, getIReg( rA_addr ) ); 15795 15796 if ( opc1 != 0x4 ) { 15797 vex_printf("dis_av_extract_element(ppc)(instr)\n"); 15798 return False; 15799 } 15800 15801 switch ( opc2 ) { 15802 case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed 15803 DIP("vextublx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15804 15805 assign( rT, extract_field_from_vector( vB, 15806 binop( Iop_Sub64, 15807 mkU64( 15 ), 15808 mkexpr( rA ) ), 15809 0xFF ) ); 15810 15811 break; 15812 15813 case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed 15814 DIP("vextuhlx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15815 15816 assign( rT, extract_field_from_vector( vB, 15817 binop( Iop_Sub64, 15818 mkU64( 14 ), 15819 mkexpr( rA ) ), 15820 0xFFFF ) ); 15821 break; 15822 15823 case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed 15824 DIP("vextuwlx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15825 15826 assign( rT, extract_field_from_vector( vB, 15827 binop( Iop_Sub64, 15828 mkU64( 12 ), 15829 mkexpr( rA ) ), 15830 0xFFFFFFFF ) ); 15831 break; 15832 15833 case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed 15834 DIP("vextubrx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15835 15836 assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFF ) ); 15837 break; 15838 15839 case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed 15840 DIP("vextuhrx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15841 15842 assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFF ) ); 15843 break; 15844 15845 case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed 15846 DIP("vextuwrx %d,%d,v%d", rT_addr, rA_addr, vB_addr); 15847 15848 assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFFFFFF ) ); 15849 break; 15850 15851 default: 15852 vex_printf("dis_av_extract_element(ppc)(opc2)\n"); 15853 return False; 15854 } 15855 putIReg( rT_addr, mkexpr( rT ) ); 15856 return True; 15857 } 15858 15859 /* 15860 * VSX scalar and vector convert instructions 15861 */ 15862 static Bool 15863 dis_vx_conv ( UInt theInstr, UInt opc2 ) 15864 { 15865 /* XX2-Form */ 15866 UChar opc1 = ifieldOPC( theInstr ); 15867 UChar XT = ifieldRegXT( theInstr ); 15868 UChar XB = ifieldRegXB( theInstr ); 15869 IRTemp xB, xB2; 15870 IRTemp b3, b2, b1, b0; 15871 xB = xB2 = IRTemp_INVALID; 15872 15873 if (opc1 != 0x3C) { 15874 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 15875 return False; 15876 } 15877 15878 /* Create and assign temps only as needed for the given instruction. */ 15879 switch (opc2) { 15880 // scalar double-precision floating point argument 15881 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090: 15882 xB = newTemp(Ity_F64); 15883 assign( xB, 15884 unop( Iop_ReinterpI64asF64, 15885 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 15886 break; 15887 // vector double-precision floating point arguments 15888 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 15889 15890 xB = newTemp(Ity_F64); 15891 xB2 = newTemp(Ity_F64); 15892 assign( xB, 15893 unop( Iop_ReinterpI64asF64, 15894 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 15895 assign( xB2, 15896 unop( Iop_ReinterpI64asF64, 15897 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 15898 break; 15899 // vector single precision or [un]signed integer word arguments 15900 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 15901 case 0x1f0: case 0x1d0: 15902 b3 = b2 = b1 = b0 = IRTemp_INVALID; 15903 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 15904 break; 15905 // vector [un]signed integer doubleword argument 15906 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 15907 xB = newTemp(Ity_I64); 15908 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 15909 xB2 = newTemp(Ity_I64); 15910 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 15911 break; 15912 // scalar [un]signed integer doubleword argument 15913 case 0x250: case 0x270: case 0x2D0: case 0x2F0: 15914 xB = newTemp(Ity_I64); 15915 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 15916 break; 15917 // scalar single precision argument 15918 case 0x292: // xscvspdp 15919 xB = newTemp(Ity_I32); 15920 15921 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32, 15922 unop( Iop_V128HIto64, 15923 getVSReg( XB ) ) ) ) ); 15924 break; 15925 case 0x296: // xscvspdpn (non signaling version of xscvpdp) 15926 xB = newTemp(Ity_I32); 15927 assign( xB, 15928 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 15929 break; 15930 15931 /* Certain instructions have their complete implementation in the main switch statement 15932 * that follows this one; thus we have a "do nothing" case for those instructions here. 15933 */ 15934 case 0x170: case 0x150: 15935 break; // do nothing 15936 15937 default: 15938 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 15939 return False; 15940 } 15941 15942 15943 switch (opc2) { 15944 case 0x2B0: 15945 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 15946 // to Signed Integer Doubleword format with Saturate) 15947 DIP("xscvdpsxds v%u,v%u\n", XT, XB); 15948 putVSReg( XT, 15949 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 15950 mkU32( Irrm_ZERO ), 15951 mkexpr( xB ) ), mkU64( 0 ) ) ); 15952 break; 15953 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 15954 // Convert to Signed Integer Word format with Saturate) 15955 DIP("xscvdpsxws v%u,v%u\n", XT, XB); 15956 putVSReg( XT, 15957 binop( Iop_64HLtoV128, 15958 unop( Iop_32Sto64, 15959 binop( Iop_F64toI32S, 15960 mkU32( Irrm_ZERO ), 15961 mkexpr( xB ) ) ), 15962 mkU64( 0ULL ) ) ); 15963 break; 15964 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 15965 // to Unsigned Integer Doubleword format with Saturate) 15966 DIP("xscvdpuxds v%u,v%u\n", XT, XB); 15967 putVSReg( XT, 15968 binop( Iop_64HLtoV128, 15969 binop( Iop_F64toI64U, 15970 mkU32( Irrm_ZERO ), 15971 mkexpr( xB ) ), 15972 mkU64( 0ULL ) ) ); 15973 break; 15974 case 0x270: 15975 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword 15976 // to Single-Precision format) 15977 DIP("xscvsxdsp v%u,v%u\n", XT, XB); 15978 putVSReg( XT, 15979 binop( Iop_64HLtoV128, 15980 unop( Iop_ReinterpF64asI64, 15981 binop( Iop_RoundF64toF32, 15982 get_IR_roundingmode(), 15983 binop( Iop_I64StoF64, 15984 get_IR_roundingmode(), 15985 mkexpr( xB ) ) ) ), 15986 mkU64( 0 ) ) ); 15987 break; 15988 case 0x2F0: 15989 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 15990 // Double-Precision format) 15991 DIP("xscvsxddp v%u,v%u\n", XT, XB); 15992 putVSReg( XT, 15993 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 15994 binop( Iop_I64StoF64, get_IR_roundingmode(), 15995 mkexpr( xB ) ) ), 15996 mkU64( 0 ) ) ); 15997 break; 15998 case 0x250: 15999 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer 16000 // Doubleword to Singel-Precision format) 16001 DIP("xscvuxdsp v%u,v%u\n", XT, XB); 16002 putVSReg( XT, 16003 binop( Iop_64HLtoV128, 16004 unop( Iop_ReinterpF64asI64, 16005 binop( Iop_RoundF64toF32, 16006 get_IR_roundingmode(), 16007 binop( Iop_I64UtoF64, 16008 get_IR_roundingmode(), 16009 mkexpr( xB ) ) ) ), 16010 mkU64( 0 ) ) ); 16011 break; 16012 case 0x2D0: 16013 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 16014 // Double-Precision format) 16015 DIP("xscvuxddp v%u,v%u\n", XT, XB); 16016 putVSReg( XT, 16017 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 16018 binop( Iop_I64UtoF64, get_IR_roundingmode(), 16019 mkexpr( xB ) ) ), 16020 mkU64( 0 ) ) ); 16021 break; 16022 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 16023 // to Signed Integer Word format with Saturate) 16024 { 16025 IRTemp hiResult_32 = newTemp(Ity_I32); 16026 IRTemp loResult_32 = newTemp(Ity_I32); 16027 IRExpr* rmZero = mkU32(Irrm_ZERO); 16028 16029 DIP("xvcvdpsxws v%u,v%u\n", XT, XB); 16030 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 16031 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 16032 putVSReg( XT, 16033 binop( Iop_64HLtoV128, 16034 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 16035 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 16036 break; 16037 } 16038 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 16039 // (VSX Vector truncate Single-Precision to integer and 16040 // Convert to [Un]signed Integer Word format with Saturate) 16041 { 16042 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 16043 IRTemp tempResult = newTemp(Ity_V128); 16044 IRTemp res0 = newTemp(Ity_I32); 16045 IRTemp res1 = newTemp(Ity_I32); 16046 IRTemp res2 = newTemp(Ity_I32); 16047 IRTemp res3 = newTemp(Ity_I32); 16048 IRTemp hi64 = newTemp(Ity_I64); 16049 IRTemp lo64 = newTemp(Ity_I64); 16050 Bool un_signed = (opc2 == 0x110); 16051 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 16052 16053 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB); 16054 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 16055 * then result is set to 0x80000000. */ 16056 assign(tempResult, unop(op, getVSReg(XB))); 16057 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 16058 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 16059 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 16060 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 16061 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 16062 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 16063 16064 b3_result = IRExpr_ITE(is_NaN(Ity_I32, b3), 16065 // then: result is 0x{8|0}80000000 16066 mkU32(un_signed ? 0x00000000 : 0x80000000), 16067 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 16068 mkexpr(res3)); 16069 b2_result = IRExpr_ITE(is_NaN(Ity_I32, b2), 16070 // then: result is 0x{8|0}80000000 16071 mkU32(un_signed ? 0x00000000 : 0x80000000), 16072 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 16073 mkexpr(res2)); 16074 b1_result = IRExpr_ITE(is_NaN(Ity_I32, b1), 16075 // then: result is 0x{8|0}80000000 16076 mkU32(un_signed ? 0x00000000 : 0x80000000), 16077 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 16078 mkexpr(res1)); 16079 b0_result = IRExpr_ITE(is_NaN(Ity_I32, b0), 16080 // then: result is 0x{8|0}80000000 16081 mkU32(un_signed ? 0x00000000 : 0x80000000), 16082 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 16083 mkexpr(res0)); 16084 16085 putVSReg( XT, 16086 binop( Iop_64HLtoV128, 16087 binop( Iop_32HLto64, b3_result, b2_result ), 16088 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 16089 break; 16090 } 16091 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 16092 // Convert to Single-Precision format 16093 DIP("xscvdpsp v%u,v%u\n", XT, XB); 16094 putVSReg( XT, 16095 binop( Iop_64HLtoV128, 16096 binop( Iop_32HLto64, 16097 unop( Iop_ReinterpF32asI32, 16098 unop( Iop_TruncF64asF32, 16099 binop( Iop_RoundF64toF32, 16100 get_IR_roundingmode(), 16101 mkexpr( xB ) ) ) ), 16102 mkU32( 0 ) ), 16103 mkU64( 0ULL ) ) ); 16104 break; 16105 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to 16106 vector Single-Precision non-signalling */ 16107 DIP("xscvdpspn v%u,v%u\n", XT, XB); 16108 putVSReg( XT, 16109 binop( Iop_64HLtoV128, 16110 binop( Iop_32HLto64, 16111 unop( Iop_ReinterpF32asI32, 16112 unop( Iop_TruncF64asF32, 16113 mkexpr( xB ) ) ), 16114 mkU32( 0 ) ), 16115 mkU64( 0ULL ) ) ); 16116 break; 16117 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 16118 // and Convert to Unsigned Integer Word format with Saturate) 16119 DIP("xscvdpuxws v%u,v%u\n", XT, XB); 16120 putVSReg( XT, 16121 binop( Iop_64HLtoV128, 16122 binop( Iop_32HLto64, 16123 mkU32( 0 ), 16124 binop( Iop_F64toI32U, 16125 mkU32( Irrm_ZERO ), 16126 mkexpr( xB ) ) ), 16127 mkU64( 0ULL ) ) ); 16128 break; 16129 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling) 16130 DIP("xscvspdp v%u,v%u\n", XT, XB); 16131 putVSReg( XT, 16132 binop( Iop_64HLtoV128, 16133 unop( Iop_ReinterpF64asI64, 16134 unop( Iop_F32toF64, 16135 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 16136 mkU64( 0ULL ) ) ); 16137 break; 16138 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling) 16139 DIP("xscvspdpn v%u,v%u\n", XT, XB); 16140 putVSReg( XT, 16141 binop( Iop_64HLtoV128, 16142 unop( Iop_ReinterpF64asI64, 16143 unop( Iop_F32toF64, 16144 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 16145 mkU64( 0ULL ) ) ); 16146 break; 16147 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 16148 // and Convert to Single-Precision format) 16149 DIP("xvcvdpsp v%u,v%u\n", XT, XB); 16150 putVSReg( XT, 16151 binop( Iop_64HLtoV128, 16152 binop( Iop_32HLto64, 16153 unop( Iop_ReinterpF32asI32, 16154 unop( Iop_TruncF64asF32, 16155 binop( Iop_RoundF64toF32, 16156 get_IR_roundingmode(), 16157 mkexpr( xB ) ) ) ), 16158 mkU32( 0 ) ), 16159 binop( Iop_32HLto64, 16160 unop( Iop_ReinterpF32asI32, 16161 unop( Iop_TruncF64asF32, 16162 binop( Iop_RoundF64toF32, 16163 get_IR_roundingmode(), 16164 mkexpr( xB2 ) ) ) ), 16165 mkU32( 0 ) ) ) ); 16166 break; 16167 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 16168 // and Convert to Unsigned Integer Doubleword format 16169 // with Saturate) 16170 DIP("xvcvdpuxds v%u,v%u\n", XT, XB); 16171 putVSReg( XT, 16172 binop( Iop_64HLtoV128, 16173 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 16174 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 16175 break; 16176 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 16177 // Convert to Unsigned Integer Word format with Saturate) 16178 DIP("xvcvdpuxws v%u,v%u\n", XT, XB); 16179 putVSReg( XT, 16180 binop( Iop_64HLtoV128, 16181 binop( Iop_32HLto64, 16182 binop( Iop_F64toI32U, 16183 mkU32( Irrm_ZERO ), 16184 mkexpr( xB ) ), 16185 mkU32( 0 ) ), 16186 binop( Iop_32HLto64, 16187 binop( Iop_F64toI32U, 16188 mkU32( Irrm_ZERO ), 16189 mkexpr( xB2 ) ), 16190 mkU32( 0 ) ) ) ); 16191 break; 16192 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 16193 DIP("xvcvspdp v%u,v%u\n", XT, XB); 16194 putVSReg( XT, 16195 binop( Iop_64HLtoV128, 16196 unop( Iop_ReinterpF64asI64, 16197 unop( Iop_F32toF64, 16198 unop( Iop_ReinterpI32asF32, 16199 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ), 16200 unop( Iop_ReinterpF64asI64, 16201 unop( Iop_F32toF64, 16202 unop( Iop_ReinterpI32asF32, 16203 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) ); 16204 break; 16205 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 16206 // Convert to Signed Integer Doubleword format with Saturate) 16207 DIP("xvcvspsxds v%u,v%u\n", XT, XB); 16208 putVSReg( XT, 16209 binop( Iop_64HLtoV128, 16210 binop( Iop_F64toI64S, 16211 mkU32( Irrm_ZERO ), 16212 unop( Iop_F32toF64, 16213 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 16214 binop( Iop_F64toI64S, 16215 mkU32( Irrm_ZERO ), 16216 unop( Iop_F32toF64, 16217 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 16218 break; 16219 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 16220 // Convert to Unsigned Integer Doubleword format with Saturate) 16221 DIP("xvcvspuxds v%u,v%u\n", XT, XB); 16222 putVSReg( XT, 16223 binop( Iop_64HLtoV128, 16224 binop( Iop_F64toI64U, 16225 mkU32( Irrm_ZERO ), 16226 unop( Iop_F32toF64, 16227 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 16228 binop( Iop_F64toI64U, 16229 mkU32( Irrm_ZERO ), 16230 unop( Iop_F32toF64, 16231 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 16232 break; 16233 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 16234 // Convert to Signed Integer Doubleword format with Saturate) 16235 DIP("xvcvdpsxds v%u,v%u\n", XT, XB); 16236 putVSReg( XT, 16237 binop( Iop_64HLtoV128, 16238 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 16239 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 16240 break; 16241 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 16242 // to Double-Precision format) 16243 DIP("xvcvsxddp v%u,v%u\n", XT, XB); 16244 putVSReg( XT, 16245 binop( Iop_64HLtoV128, 16246 unop( Iop_ReinterpF64asI64, 16247 binop( Iop_I64StoF64, 16248 get_IR_roundingmode(), 16249 mkexpr( xB ) ) ), 16250 unop( Iop_ReinterpF64asI64, 16251 binop( Iop_I64StoF64, 16252 get_IR_roundingmode(), 16253 mkexpr( xB2 ) ) ) ) ); 16254 break; 16255 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 16256 // to Double-Precision format) 16257 DIP("xvcvuxddp v%u,v%u\n", XT, XB); 16258 putVSReg( XT, 16259 binop( Iop_64HLtoV128, 16260 unop( Iop_ReinterpF64asI64, 16261 binop( Iop_I64UtoF64, 16262 get_IR_roundingmode(), 16263 mkexpr( xB ) ) ), 16264 unop( Iop_ReinterpF64asI64, 16265 binop( Iop_I64UtoF64, 16266 get_IR_roundingmode(), 16267 mkexpr( xB2 ) ) ) ) ); 16268 16269 break; 16270 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 16271 // to Single-Precision format) 16272 DIP("xvcvsxddp v%u,v%u\n", XT, XB); 16273 putVSReg( XT, 16274 binop( Iop_64HLtoV128, 16275 binop( Iop_32HLto64, 16276 unop( Iop_ReinterpF32asI32, 16277 unop( Iop_TruncF64asF32, 16278 binop( Iop_RoundF64toF32, 16279 get_IR_roundingmode(), 16280 binop( Iop_I64StoF64, 16281 get_IR_roundingmode(), 16282 mkexpr( xB ) ) ) ) ), 16283 mkU32( 0 ) ), 16284 binop( Iop_32HLto64, 16285 unop( Iop_ReinterpF32asI32, 16286 unop( Iop_TruncF64asF32, 16287 binop( Iop_RoundF64toF32, 16288 get_IR_roundingmode(), 16289 binop( Iop_I64StoF64, 16290 get_IR_roundingmode(), 16291 mkexpr( xB2 ) ) ) ) ), 16292 mkU32( 0 ) ) ) ); 16293 break; 16294 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 16295 // to Single-Precision format) 16296 DIP("xvcvuxddp v%u,v%u\n", XT, XB); 16297 putVSReg( XT, 16298 binop( Iop_64HLtoV128, 16299 binop( Iop_32HLto64, 16300 unop( Iop_ReinterpF32asI32, 16301 unop( Iop_TruncF64asF32, 16302 binop( Iop_RoundF64toF32, 16303 get_IR_roundingmode(), 16304 binop( Iop_I64UtoF64, 16305 get_IR_roundingmode(), 16306 mkexpr( xB ) ) ) ) ), 16307 mkU32( 0 ) ), 16308 binop( Iop_32HLto64, 16309 unop( Iop_ReinterpF32asI32, 16310 unop( Iop_TruncF64asF32, 16311 binop( Iop_RoundF64toF32, 16312 get_IR_roundingmode(), 16313 binop( Iop_I64UtoF64, 16314 get_IR_roundingmode(), 16315 mkexpr( xB2 ) ) ) ) ), 16316 mkU32( 0 ) ) ) ); 16317 break; 16318 16319 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 16320 DIP("xvcvsxwdp v%u,v%u\n", XT, XB); 16321 putVSReg( XT, 16322 binop( Iop_64HLtoV128, 16323 unop( Iop_ReinterpF64asI64, 16324 binop( Iop_I64StoF64, get_IR_roundingmode(), 16325 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 16326 unop( Iop_ReinterpF64asI64, 16327 binop( Iop_I64StoF64, get_IR_roundingmode(), 16328 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 16329 break; 16330 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 16331 DIP("xvcvuxwdp v%u,v%u\n", XT, XB); 16332 putVSReg( XT, 16333 binop( Iop_64HLtoV128, 16334 unop( Iop_ReinterpF64asI64, 16335 binop( Iop_I64UtoF64, get_IR_roundingmode(), 16336 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 16337 unop( Iop_ReinterpF64asI64, 16338 binop( Iop_I64UtoF64, get_IR_roundingmode(), 16339 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 16340 break; 16341 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 16342 DIP("xvcvsxwsp v%u,v%u\n", XT, XB); 16343 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 16344 break; 16345 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 16346 DIP("xvcvuxwsp v%u,v%u\n", XT, XB); 16347 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 16348 break; 16349 16350 default: 16351 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 16352 return False; 16353 } 16354 return True; 16355 } 16356 16357 /* 16358 * VSX vector Double Precision Floating Point Arithmetic Instructions 16359 */ 16360 static Bool 16361 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 16362 { 16363 /* XX3-Form */ 16364 UChar opc1 = ifieldOPC( theInstr ); 16365 UChar XT = ifieldRegXT( theInstr ); 16366 UChar XA = ifieldRegXA( theInstr ); 16367 UChar XB = ifieldRegXB( theInstr ); 16368 IRExpr* rm = get_IR_roundingmode(); 16369 IRTemp frA = newTemp(Ity_F64); 16370 IRTemp frB = newTemp(Ity_F64); 16371 IRTemp frA2 = newTemp(Ity_F64); 16372 IRTemp frB2 = newTemp(Ity_F64); 16373 16374 if (opc1 != 0x3C) { 16375 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 16376 return False; 16377 } 16378 16379 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 16380 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 16381 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 16382 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 16383 16384 switch (opc2) { 16385 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 16386 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 16387 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 16388 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 16389 { 16390 IROp mOp; 16391 const HChar * oper_name; 16392 switch (opc2) { 16393 case 0x1E0: 16394 mOp = Iop_DivF64; 16395 oper_name = "div"; 16396 break; 16397 case 0x1C0: 16398 mOp = Iop_MulF64; 16399 oper_name = "mul"; 16400 break; 16401 case 0x180: 16402 mOp = Iop_AddF64; 16403 oper_name = "add"; 16404 break; 16405 case 0x1A0: 16406 mOp = Iop_SubF64; 16407 oper_name = "sub"; 16408 break; 16409 16410 default: 16411 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 16412 } 16413 IRTemp hiResult = newTemp(Ity_I64); 16414 IRTemp loResult = newTemp(Ity_I64); 16415 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB); 16416 16417 assign( hiResult, 16418 unop( Iop_ReinterpF64asI64, 16419 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 16420 assign( loResult, 16421 unop( Iop_ReinterpF64asI64, 16422 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 16423 putVSReg( XT, 16424 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 16425 break; 16426 } 16427 case 0x196: // xvsqrtdp 16428 { 16429 IRTemp hiResult = newTemp(Ity_I64); 16430 IRTemp loResult = newTemp(Ity_I64); 16431 DIP("xvsqrtdp v%d,v%d\n", XT, XB); 16432 16433 assign( hiResult, 16434 unop( Iop_ReinterpF64asI64, 16435 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 16436 assign( loResult, 16437 unop( Iop_ReinterpF64asI64, 16438 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 16439 putVSReg( XT, 16440 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 16441 break; 16442 } 16443 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 16444 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 16445 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 16446 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 16447 { 16448 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 16449 * XT == FRC 16450 * XA == FRA 16451 * XB == FRB 16452 * 16453 * and for xvm{add|sub}adp . . . 16454 * XT == FRB 16455 * XA == FRA 16456 * XB == FRC 16457 */ 16458 Bool negate; 16459 IROp mOp = Iop_INVALID; 16460 const HChar * oper_name = NULL; 16461 Bool mdp = False; 16462 16463 switch (opc2) { 16464 case 0x184: case 0x1A4: 16465 case 0x384: case 0x3A4: 16466 mOp = Iop_MAddF64; 16467 oper_name = "add"; 16468 mdp = (opc2 & 0x0FF) == 0x0A4; 16469 break; 16470 16471 case 0x1C4: case 0x1E4: 16472 case 0x3C4: case 0x3E4: 16473 mOp = Iop_MSubF64; 16474 oper_name = "sub"; 16475 mdp = (opc2 & 0x0FF) == 0x0E4; 16476 break; 16477 16478 default: 16479 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 16480 } 16481 16482 switch (opc2) { 16483 case 0x384: case 0x3A4: 16484 case 0x3C4: case 0x3E4: 16485 negate = True; 16486 break; 16487 default: 16488 negate = False; 16489 } 16490 IRTemp hiResult = newTemp(Ity_I64); 16491 IRTemp loResult = newTemp(Ity_I64); 16492 IRTemp frT = newTemp(Ity_F64); 16493 IRTemp frT2 = newTemp(Ity_F64); 16494 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 16495 XT, XA, XB); 16496 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 16497 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 16498 16499 assign( hiResult, 16500 unop( Iop_ReinterpF64asI64, 16501 qop( mOp, 16502 rm, 16503 mkexpr( frA ), 16504 mkexpr( mdp ? frT : frB ), 16505 mkexpr( mdp ? frB : frT ) ) ) ); 16506 assign( loResult, 16507 unop( Iop_ReinterpF64asI64, 16508 qop( mOp, 16509 rm, 16510 mkexpr( frA2 ), 16511 mkexpr( mdp ? frT2 : frB2 ), 16512 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 16513 putVSReg( XT, 16514 binop( Iop_64HLtoV128, 16515 mkexpr( negate ? getNegatedResult( hiResult ) 16516 : hiResult ), 16517 mkexpr( negate ? getNegatedResult( loResult ) 16518 : loResult ) ) ); 16519 break; 16520 } 16521 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 16522 { 16523 IRTemp frBHi_I64 = newTemp(Ity_I64); 16524 IRTemp frBLo_I64 = newTemp(Ity_I64); 16525 IRTemp flagsHi = newTemp(Ity_I32); 16526 IRTemp flagsLo = newTemp(Ity_I32); 16527 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 16528 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 16529 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 16530 16531 DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB); 16532 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 16533 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 16534 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 16535 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 16536 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 16537 * where fl_flag == 1 on ppc64. 16538 */ 16539 assign( flagsHi, 16540 binop( Iop_Or32, 16541 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16542 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 16543 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 16544 assign( flagsLo, 16545 binop( Iop_Or32, 16546 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16547 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 16548 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 16549 putGST_field( PPC_GST_CR, 16550 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 16551 crfD ); 16552 break; 16553 } 16554 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 16555 { 16556 IRTemp frBHi_I64 = newTemp(Ity_I64); 16557 IRTemp frBLo_I64 = newTemp(Ity_I64); 16558 IRTemp frAHi_I64 = newTemp(Ity_I64); 16559 IRTemp frALo_I64 = newTemp(Ity_I64); 16560 IRTemp flagsHi = newTemp(Ity_I32); 16561 IRTemp flagsLo = newTemp(Ity_I32); 16562 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 16563 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 16564 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 16565 16566 DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB); 16567 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 16568 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 16569 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 16570 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 16571 16572 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 16573 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 16574 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 16575 * where fl_flag == 1 on ppc64. 16576 */ 16577 assign( flagsHi, 16578 binop( Iop_Or32, 16579 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16580 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 16581 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 16582 assign( flagsLo, 16583 binop( Iop_Or32, 16584 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16585 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 16586 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 16587 putGST_field( PPC_GST_CR, 16588 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 16589 crfD ); 16590 break; 16591 } 16592 16593 default: 16594 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 16595 return False; 16596 } 16597 return True; 16598 } 16599 16600 /* 16601 * VSX vector Single Precision Floating Point Arithmetic Instructions 16602 */ 16603 static Bool 16604 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 16605 { 16606 /* XX3-Form */ 16607 UChar opc1 = ifieldOPC( theInstr ); 16608 UChar XT = ifieldRegXT( theInstr ); 16609 UChar XA = ifieldRegXA( theInstr ); 16610 UChar XB = ifieldRegXB( theInstr ); 16611 IRExpr* rm = get_IR_roundingmode(); 16612 IRTemp a3, a2, a1, a0; 16613 IRTemp b3, b2, b1, b0; 16614 IRTemp res0 = newTemp(Ity_I32); 16615 IRTemp res1 = newTemp(Ity_I32); 16616 IRTemp res2 = newTemp(Ity_I32); 16617 IRTemp res3 = newTemp(Ity_I32); 16618 16619 a3 = a2 = a1 = a0 = IRTemp_INVALID; 16620 b3 = b2 = b1 = b0 = IRTemp_INVALID; 16621 16622 if (opc1 != 0x3C) { 16623 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 16624 return False; 16625 } 16626 16627 switch (opc2) { 16628 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 16629 DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB); 16630 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4 16631 putVSReg( XT, triop(Iop_Add32Fx4, rm, 16632 getVSReg( XA ), getVSReg( XB )) ); 16633 break; 16634 16635 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 16636 DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB); 16637 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4 16638 putVSReg( XT, triop(Iop_Mul32Fx4, rm, 16639 getVSReg( XA ), getVSReg( XB )) ); 16640 break; 16641 16642 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 16643 DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB); 16644 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4 16645 putVSReg( XT, triop(Iop_Sub32Fx4, rm, 16646 getVSReg( XA ), getVSReg( XB )) ); 16647 break; 16648 16649 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 16650 { 16651 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 16652 * So there are two choices: 16653 * 1. Implement the xvdivsp with a native insn; or 16654 * 2. Extract the 4 single precision floats from each vector 16655 * register inputs and perform fdivs on each pair 16656 * I will do the latter, due to the general philosophy of 16657 * reusing existing implementations when practical. 16658 */ 16659 DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB); 16660 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 16661 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 16662 16663 assign( res0, 16664 unop( Iop_ReinterpF32asI32, 16665 unop( Iop_TruncF64asF32, 16666 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 16667 assign( res1, 16668 unop( Iop_ReinterpF32asI32, 16669 unop( Iop_TruncF64asF32, 16670 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 16671 assign( res2, 16672 unop( Iop_ReinterpF32asI32, 16673 unop( Iop_TruncF64asF32, 16674 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 16675 assign( res3, 16676 unop( Iop_ReinterpF32asI32, 16677 unop( Iop_TruncF64asF32, 16678 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 16679 16680 putVSReg( XT, 16681 binop( Iop_64HLtoV128, 16682 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 16683 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 16684 break; 16685 } 16686 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 16687 { 16688 DIP("xvsqrtsp v%d,v%d\n", XT, XB); 16689 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 16690 /* Note: The native xvsqrtsp insruction does not always give the same precision 16691 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 16692 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 16693 * to the actual instruction. 16694 */ 16695 16696 assign( res0, 16697 unop( Iop_ReinterpF32asI32, 16698 unop( Iop_TruncF64asF32, 16699 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 16700 assign( res1, 16701 unop( Iop_ReinterpF32asI32, 16702 unop( Iop_TruncF64asF32, 16703 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 16704 assign( res2, 16705 unop( Iop_ReinterpF32asI32, 16706 unop( Iop_TruncF64asF32, 16707 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 16708 assign( res3, 16709 unop( Iop_ReinterpF32asI32, 16710 unop( Iop_TruncF64asF32, 16711 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 16712 16713 putVSReg( XT, 16714 binop( Iop_64HLtoV128, 16715 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 16716 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 16717 break; 16718 } 16719 16720 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 16721 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 16722 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 16723 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 16724 { 16725 IRTemp t3, t2, t1, t0; 16726 Bool msp = False; 16727 Bool negate; 16728 const HChar * oper_name = NULL; 16729 IROp mOp = Iop_INVALID; 16730 switch (opc2) { 16731 case 0x104: case 0x124: 16732 case 0x304: case 0x324: 16733 msp = (opc2 & 0x0FF) == 0x024; 16734 mOp = Iop_MAddF64r32; 16735 oper_name = "madd"; 16736 break; 16737 16738 case 0x144: case 0x164: 16739 case 0x344: case 0x364: 16740 msp = (opc2 & 0x0FF) == 0x064; 16741 mOp = Iop_MSubF64r32; 16742 oper_name = "sub"; 16743 break; 16744 16745 default: 16746 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 16747 } 16748 16749 switch (opc2) { 16750 case 0x304: case 0x324: 16751 case 0x344: case 0x364: 16752 negate = True; 16753 break; 16754 16755 default: 16756 negate = False; 16757 } 16758 16759 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, 16760 msp ? "msp" : "asp", XT, XA, XB); 16761 16762 t3 = t2 = t1 = t0 = IRTemp_INVALID; 16763 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 16764 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 16765 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 16766 16767 assign( res0, 16768 unop( Iop_ReinterpF32asI32, 16769 unop( Iop_TruncF64asF32, 16770 qop( mOp, 16771 rm, 16772 mkexpr( a0 ), 16773 mkexpr( msp ? t0 : b0 ), 16774 mkexpr( msp ? b0 : t0 ) ) ) ) ); 16775 assign( res1, 16776 unop( Iop_ReinterpF32asI32, 16777 unop( Iop_TruncF64asF32, 16778 qop( mOp, 16779 rm, 16780 mkexpr( a1 ), 16781 mkexpr( msp ? t1 : b1 ), 16782 mkexpr( msp ? b1 : t1 ) ) ) ) ); 16783 assign( res2, 16784 unop( Iop_ReinterpF32asI32, 16785 unop( Iop_TruncF64asF32, 16786 qop( mOp, 16787 rm, 16788 mkexpr( a2 ), 16789 mkexpr( msp ? t2 : b2 ), 16790 mkexpr( msp ? b2 : t2 ) ) ) ) ); 16791 assign( res3, 16792 unop( Iop_ReinterpF32asI32, 16793 unop( Iop_TruncF64asF32, 16794 qop( mOp, 16795 rm, 16796 mkexpr( a3 ), 16797 mkexpr( msp ? t3 : b3 ), 16798 mkexpr( msp ? b3 : t3 ) ) ) ) ); 16799 16800 putVSReg( XT, 16801 binop( Iop_64HLtoV128, 16802 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 16803 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 16804 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 16805 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 16806 16807 break; 16808 } 16809 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 16810 { 16811 IRTemp flags0 = newTemp(Ity_I32); 16812 IRTemp flags1 = newTemp(Ity_I32); 16813 IRTemp flags2 = newTemp(Ity_I32); 16814 IRTemp flags3 = newTemp(Ity_I32); 16815 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 16816 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 16817 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 16818 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 16819 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 16820 DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB); 16821 16822 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 16823 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 16824 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 16825 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 16826 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 16827 16828 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 16829 * where fl_flag == 1 on ppc64. 16830 */ 16831 assign( flags0, 16832 binop( Iop_Or32, 16833 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16834 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 16835 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 16836 assign( flags1, 16837 binop( Iop_Or32, 16838 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16839 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 16840 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 16841 assign( flags2, 16842 binop( Iop_Or32, 16843 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16844 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 16845 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 16846 assign( flags3, 16847 binop( Iop_Or32, 16848 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16849 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 16850 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 16851 putGST_field( PPC_GST_CR, 16852 binop( Iop_Or32, 16853 mkexpr( flags0 ), 16854 binop( Iop_Or32, 16855 mkexpr( flags1 ), 16856 binop( Iop_Or32, 16857 mkexpr( flags2 ), 16858 mkexpr( flags3 ) ) ) ), 16859 crfD ); 16860 16861 break; 16862 } 16863 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 16864 { 16865 IRTemp flags0 = newTemp(Ity_I32); 16866 IRTemp flags1 = newTemp(Ity_I32); 16867 IRTemp flags2 = newTemp(Ity_I32); 16868 IRTemp flags3 = newTemp(Ity_I32); 16869 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 16870 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 16871 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 16872 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 16873 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 16874 DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB); 16875 16876 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 16877 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 16878 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 16879 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 16880 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 16881 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 16882 16883 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 16884 * where fl_flag == 1 on ppc64. 16885 */ 16886 assign( flags0, 16887 binop( Iop_Or32, 16888 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16889 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 16890 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 16891 assign( flags1, 16892 binop( Iop_Or32, 16893 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16894 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 16895 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 16896 assign( flags2, 16897 binop( Iop_Or32, 16898 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16899 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 16900 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 16901 assign( flags3, 16902 binop( Iop_Or32, 16903 binop( Iop_Or32, mkU32( 8 ), // fl_flag 16904 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 16905 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 16906 putGST_field( PPC_GST_CR, 16907 binop( Iop_Or32, 16908 mkexpr( flags0 ), 16909 binop( Iop_Or32, 16910 mkexpr( flags1 ), 16911 binop( Iop_Or32, 16912 mkexpr( flags2 ), 16913 mkexpr( flags3 ) ) ) ), 16914 crfD ); 16915 16916 break; 16917 } 16918 16919 default: 16920 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 16921 return False; 16922 } 16923 return True; 16924 } 16925 16926 /* 16927 * Vector Population Count/bit matrix transpose 16928 */ 16929 static Bool 16930 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) 16931 { 16932 UChar vRB_addr = ifieldRegB(theInstr); 16933 UChar vRT_addr = ifieldRegDS(theInstr); 16934 UChar opc1 = ifieldOPC( theInstr ); 16935 IRTemp vB = newTemp(Ity_V128); 16936 assign( vB, getVReg(vRB_addr)); 16937 16938 if (opc1 != 0x4) { 16939 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" ); 16940 return False; 16941 } 16942 16943 switch (opc2) { 16944 case 0x702: // vclzb 16945 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr); 16946 putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) ); 16947 break; 16948 16949 case 0x742: // vclzh 16950 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr); 16951 putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) ); 16952 break; 16953 16954 case 0x782: // vclzw 16955 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr); 16956 putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) ); 16957 break; 16958 16959 case 0x7C2: // vclzd 16960 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr); 16961 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) ); 16962 break; 16963 16964 case 0x703: // vpopcntb 16965 { 16966 /* Break vector into 32-bit words and do the population count 16967 * on byte in the words 16968 */ 16969 IRType ty = Ity_I32; 16970 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 16971 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 16972 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 16973 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 16974 16975 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr); 16976 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 16977 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE); 16978 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE); 16979 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE); 16980 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE); 16981 16982 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 16983 cnt_bits32_63, cnt_bits0_31) ); 16984 break; 16985 } 16986 16987 case 0x743: // vpopcnth 16988 { 16989 /* Break vector into 32-bit words and do the population count 16990 * for each half word 16991 */ 16992 IRType ty = Ity_I32; 16993 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 16994 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 16995 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 16996 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 16997 16998 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr); 16999 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 17000 17001 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD); 17002 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD); 17003 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD); 17004 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD); 17005 17006 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 17007 cnt_bits32_63, cnt_bits0_31) ); 17008 break; 17009 } 17010 17011 case 0x783: // vpopcntw 17012 { 17013 /* Break vector into 32-bit words and do the population count 17014 * on each word. 17015 */ 17016 IRType ty = Ity_I32; 17017 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 17018 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 17019 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 17020 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 17021 17022 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr); 17023 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 17024 17025 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD); 17026 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD); 17027 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD); 17028 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD); 17029 17030 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 17031 cnt_bits32_63, cnt_bits0_31) ); 17032 break; 17033 } 17034 17035 case 0x7C3: // vpopcntd 17036 { 17037 if (mode64) { 17038 /* Break vector into 64-bit double words and do the population count 17039 * on each double word. 17040 */ 17041 IRType ty = Ity_I64; 17042 IRTemp bits0_63 = newTemp(Ity_I64); 17043 IRTemp bits64_127 = newTemp(Ity_I64); 17044 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 17045 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 17046 17047 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 17048 17049 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) ); 17050 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 17051 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD); 17052 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD); 17053 17054 putVReg( vRT_addr, binop( Iop_64HLtoV128, 17055 mkexpr( cnt_bits64_127 ), 17056 mkexpr( cnt_bits0_63 ) ) ); 17057 } else { 17058 /* Break vector into 32-bit words and do the population count 17059 * on each doubleword. 17060 */ 17061 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 17062 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 17063 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 17064 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 17065 17066 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 17067 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 17068 17069 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63); 17070 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127); 17071 17072 putVReg( vRT_addr, binop( Iop_64HLtoV128, 17073 mkexpr( cnt_bits64_127 ), 17074 mkexpr( cnt_bits0_63 ) ) ); 17075 } 17076 break; 17077 } 17078 17079 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword 17080 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr); 17081 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) ); 17082 break; 17083 17084 case 0x5CC: // vbpermd Vector Bit Permute Doubleword 17085 { 17086 UChar vRA_addr = ifieldRegA( theInstr ); 17087 IRTemp vA = newTemp( Ity_V128 ); 17088 UInt j; 17089 IRTemp index_dword_hi[8]; // index in double word 17090 IRTemp index_dword_lo[8]; 17091 IRTemp index_dword_hi_valid[8]; 17092 IRTemp index_dword_lo_valid[8]; 17093 IRTemp pb_dword_hi[8]; // permute bit 17094 IRTemp pb_dword_lo[8]; 17095 IRTemp tmp_hi[9]; 17096 IRTemp tmp_lo[9]; 17097 17098 DIP("vbpermd v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17099 17100 tmp_hi[0] = newTemp( Ity_I64 ); 17101 tmp_lo[0] = newTemp( Ity_I64 ); 17102 17103 assign( vA, getVReg(vRA_addr) ); 17104 assign( tmp_hi[0], mkU64( 0 ) ); 17105 assign( tmp_lo[0], mkU64( 0 ) ); 17106 17107 for (j=0; j<8; j++) { 17108 index_dword_hi[j] = newTemp( Ity_I64 ); 17109 index_dword_lo[j] = newTemp( Ity_I64 ); 17110 index_dword_hi_valid[j] = newTemp( Ity_I64 ); 17111 index_dword_lo_valid[j] = newTemp( Ity_I64 ); 17112 pb_dword_hi[j] = newTemp( Ity_I64 ); 17113 pb_dword_lo[j] = newTemp( Ity_I64 ); 17114 tmp_hi[j+1] = newTemp( Ity_I64 ); 17115 tmp_lo[j+1] = newTemp( Ity_I64 ); 17116 17117 assign( index_dword_hi[j], 17118 binop( Iop_And64, 17119 binop( Iop_Shr64, 17120 unop( Iop_V128HIto64, 17121 mkexpr( vB ) ), 17122 mkU8( ( 7 - j ) * 8 ) ), 17123 mkU64( 0xFF ) ) ); 17124 17125 assign( index_dword_lo[j], 17126 binop( Iop_And64, 17127 binop( Iop_Shr64, 17128 unop( Iop_V128to64, 17129 mkexpr( vB ) ), 17130 mkU8( ( 7 - j ) * 8 ) ), 17131 mkU64( 0xFF ) ) ); 17132 17133 assign( index_dword_hi_valid[j], 17134 unop( Iop_1Sto64, 17135 binop( Iop_CmpLT64U, 17136 mkexpr( index_dword_hi[j] ), 17137 mkU64( 64 ) ) ) ); 17138 17139 assign( index_dword_lo_valid[j], 17140 unop( Iop_1Sto64, 17141 binop( Iop_CmpLT64U, 17142 mkexpr( index_dword_lo[j] ), 17143 mkU64( 64 ) ) ) ); 17144 assign( pb_dword_hi[j], 17145 binop( Iop_And64, 17146 binop( Iop_Shr64, 17147 unop( Iop_V128HIto64, 17148 mkexpr( vA ) ), 17149 unop( Iop_64to8, 17150 binop( Iop_Sub64, 17151 mkU64( 63 ), 17152 mkexpr( index_dword_hi[j] ) 17153 ) ) ), 17154 mkU64( 0x1 ) ) ); 17155 17156 assign( pb_dword_lo[j], 17157 binop( Iop_And64, 17158 binop( Iop_Shr64, 17159 unop( Iop_V128to64, 17160 mkexpr( vA ) ), 17161 unop( Iop_64to8, 17162 binop( Iop_Sub64, 17163 mkU64( 63 ), 17164 mkexpr( index_dword_lo[j] ) 17165 ) ) ), 17166 mkU64( 0x1 ) ) ); 17167 17168 assign( tmp_hi[j+1], 17169 binop( Iop_Or64, 17170 binop( Iop_And64, 17171 mkexpr( index_dword_hi_valid[j] ), 17172 binop( Iop_Shl64, 17173 mkexpr( pb_dword_hi[j] ), 17174 mkU8( 7 - j ) ) ), 17175 mkexpr( tmp_hi[j] ) ) ); 17176 17177 assign( tmp_lo[j+1], 17178 binop( Iop_Or64, 17179 binop( Iop_And64, 17180 mkexpr( index_dword_lo_valid[j] ), 17181 binop( Iop_Shl64, 17182 mkexpr( pb_dword_lo[j] ), 17183 mkU8( 7 - j ) ) ), 17184 mkexpr( tmp_lo[j] ) ) ); 17185 } 17186 17187 putVReg( vRT_addr, 17188 binop( Iop_64HLtoV128, 17189 mkexpr( tmp_hi[8] ), 17190 mkexpr( tmp_lo[8] ) ) ); 17191 } 17192 break; 17193 17194 default: 17195 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n"); 17196 return False; 17197 break; 17198 } 17199 return True; 17200 } 17201 17202 typedef enum { 17203 PPC_CMP_EQ = 2, 17204 PPC_CMP_GT = 4, 17205 PPC_CMP_GE = 6, 17206 PPC_CMP_LT = 8 17207 } ppc_cmp_t; 17208 17209 17210 /* 17211 This helper function takes as input the IRExpr returned 17212 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 17213 in IR form. This helper function converts it to PPC form. 17214 17215 Map compare result from IR to PPC 17216 17217 FP cmp result | PPC | IR 17218 -------------------------- 17219 UN | 0x1 | 0x45 17220 EQ | 0x2 | 0x40 17221 GT | 0x4 | 0x00 17222 LT | 0x8 | 0x01 17223 17224 condcode = Shl(1, (~(ccIR>>5) & 2) 17225 | ((ccIR ^ (ccIR>>6)) & 1) 17226 */ 17227 static IRTemp 17228 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 17229 { 17230 IRTemp condcode = newTemp( Ity_I32 ); 17231 IRTemp ccIR = newTemp( Ity_I32 ); 17232 17233 assign(ccIR, ccIR_expr); 17234 assign( condcode, 17235 binop( Iop_Shl32, 17236 mkU32( 1 ), 17237 unop( Iop_32to8, 17238 binop( Iop_Or32, 17239 binop( Iop_And32, 17240 unop( Iop_Not32, 17241 binop( Iop_Shr32, 17242 mkexpr( ccIR ), 17243 mkU8( 5 ) ) ), 17244 mkU32( 2 ) ), 17245 binop( Iop_And32, 17246 binop( Iop_Xor32, 17247 mkexpr( ccIR ), 17248 binop( Iop_Shr32, 17249 mkexpr( ccIR ), 17250 mkU8( 6 ) ) ), 17251 mkU32( 1 ) ) ) ) ) ); 17252 return condcode; 17253 } 17254 17255 /* 17256 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 17257 * following these special rules: 17258 * - The max/min of a QNaN and any value is that value 17259 * (When two QNaNs are being compared, the frA QNaN is the return value.) 17260 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 17261 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 17262 */ 17263 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 17264 { 17265 IRTemp frA_isNaN = newTemp(Ity_I1); 17266 IRTemp frB_isNaN = newTemp(Ity_I1); 17267 IRTemp frA_isSNaN = newTemp(Ity_I1); 17268 IRTemp frB_isSNaN = newTemp(Ity_I1); 17269 IRTemp frA_isQNaN = newTemp(Ity_I1); 17270 IRTemp frB_isQNaN = newTemp(Ity_I1); 17271 17272 assign( frA_isNaN, is_NaN( Ity_I64, frA_I64 ) ); 17273 assign( frB_isNaN, is_NaN( Ity_I64, frB_I64 ) ); 17274 // If operand is a NAN and bit 12 is '0', then it's an SNaN 17275 assign( frA_isSNaN, 17276 mkAND1( mkexpr(frA_isNaN), 17277 binop( Iop_CmpEQ32, 17278 binop( Iop_And32, 17279 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 17280 mkU32( 0x00080000 ) ), 17281 mkU32( 0 ) ) ) ); 17282 assign( frB_isSNaN, 17283 mkAND1( mkexpr(frB_isNaN), 17284 binop( Iop_CmpEQ32, 17285 binop( Iop_And32, 17286 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 17287 mkU32( 0x00080000 ) ), 17288 mkU32( 0 ) ) ) ); 17289 assign( frA_isQNaN, 17290 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 17291 assign( frB_isQNaN, 17292 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 17293 17294 /* Based on the rules specified in the function prologue, the algorithm is as follows: 17295 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 17296 * if frA is a SNaN 17297 * result = frA converted to QNaN 17298 * else if frB is a SNaN 17299 * result = frB converted to QNaN 17300 * else if frB is a QNaN 17301 * result = frA 17302 * // One of frA or frB was a NaN in order for this function to be called, so 17303 * // if we get to this point, we KNOW that frA must be a QNaN. 17304 * else // frA is a QNaN 17305 * result = frB 17306 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 17307 */ 17308 17309 #define SNAN_MASK 0x0008000000000000ULL 17310 return 17311 IRExpr_ITE(mkexpr(frA_isSNaN), 17312 /* then: result = frA converted to QNaN */ 17313 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)), 17314 /* else: if frB is a SNaN */ 17315 IRExpr_ITE(mkexpr(frB_isSNaN), 17316 /* then: result = frB converted to QNaN */ 17317 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)), 17318 /* else: if frB is a QNaN */ 17319 IRExpr_ITE(mkexpr(frB_isQNaN), 17320 /* then: result = frA */ 17321 mkexpr(frA_I64), 17322 /* else: frA is a QNaN, so result = frB */ 17323 mkexpr(frB_I64)))); 17324 } 17325 17326 /* 17327 * Helper function for get_max_min_fp. 17328 */ 17329 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 17330 { 17331 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 17332 unop( Iop_ReinterpI64asF64, 17333 mkexpr( src1 ) ), 17334 unop( Iop_ReinterpI64asF64, 17335 mkexpr( src2 ) ) ) ); 17336 17337 return IRExpr_ITE( binop( Iop_CmpEQ32, 17338 mkexpr( src1cmpsrc2 ), 17339 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ), 17340 /* then: use src1 */ 17341 mkexpr( src1 ), 17342 /* else: use src2 */ 17343 mkexpr( src2 ) ); 17344 } 17345 17346 /* 17347 * Helper function for "Maximum/Minimum Double Precision" operations. 17348 * Arguments: frA and frb are Ity_I64 17349 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 17350 */ 17351 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 17352 { 17353 /* There are three special cases where get_fp_cmp_CR_val is not helpful 17354 * for ascertaining the maximum between two doubles: 17355 * 1. The max/min of +0 and -0 is +0. 17356 * 2. The max/min of a QNaN and any value is that value. 17357 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 17358 * We perform the check for [+/-]0 here in this function and use the 17359 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 17360 * to do the standard comparison function. 17361 */ 17362 IRTemp anyNaN = newTemp(Ity_I1); 17363 IRTemp frA_isZero = newTemp(Ity_I1); 17364 IRTemp frB_isZero = newTemp(Ity_I1); 17365 assign( frA_isZero, is_Zero( Ity_I64, frA_I64 ) ); 17366 assign( frB_isZero, is_Zero( Ity_I64, frB_I64 ) ); 17367 assign( anyNaN, mkOR1( is_NaN( Ity_I64, frA_I64 ), 17368 is_NaN(Ity_I64, frB_I64 ) ) ); 17369 #define MINUS_ZERO 0x8000000000000000ULL 17370 17371 return IRExpr_ITE( /* If both arguments are zero . . . */ 17372 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ), 17373 /* then: if frA is -0 and isMin==True, return -0; 17374 * else if frA is +0 and isMin==False; return +0; 17375 * otherwise, simply return frB. */ 17376 IRExpr_ITE( binop( Iop_CmpEQ32, 17377 unop( Iop_64HIto32, 17378 mkexpr( frA_I64 ) ), 17379 mkU32( isMin ? 0x80000000 : 0 ) ), 17380 mkU64( isMin ? MINUS_ZERO : 0ULL ), 17381 mkexpr( frB_I64 ) ), 17382 /* else: check if either input is a NaN*/ 17383 IRExpr_ITE( mkexpr( anyNaN ), 17384 /* then: use "NaN helper" */ 17385 _get_maxmin_fp_NaN( frA_I64, frB_I64 ), 17386 /* else: use "comparison helper" */ 17387 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) )); 17388 } 17389 17390 static const HChar * _get_vsx_rdpi_suffix(UInt opc2) 17391 { 17392 switch (opc2 & 0x7F) { 17393 case 0x72: 17394 return "m"; 17395 case 0x52: 17396 return "p"; 17397 case 0x56: 17398 return "c"; 17399 case 0x32: 17400 return "z"; 17401 case 0x12: 17402 return ""; 17403 17404 default: // Impossible to get here 17405 vex_printf("Unrecognized opcode %x\n", opc2); 17406 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)"); 17407 } 17408 } 17409 17410 /* 17411 * Helper function for vector/scalar double precision fp round to integer instructions. 17412 */ 17413 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) 17414 { 17415 17416 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 17417 IRTemp frB = newTemp(Ity_F64); 17418 IRTemp frD = newTemp(Ity_F64); 17419 IRTemp intermediateResult = newTemp(Ity_I64); 17420 IRTemp is_SNAN = newTemp(Ity_I1); 17421 IRExpr * hi32; 17422 IRExpr * rxpi_rm; 17423 switch (opc2 & 0x7F) { 17424 case 0x72: 17425 rxpi_rm = mkU32(Irrm_NegINF); 17426 break; 17427 case 0x52: 17428 rxpi_rm = mkU32(Irrm_PosINF); 17429 break; 17430 case 0x56: 17431 rxpi_rm = get_IR_roundingmode(); 17432 break; 17433 case 0x32: 17434 rxpi_rm = mkU32(Irrm_ZERO); 17435 break; 17436 case 0x12: 17437 rxpi_rm = mkU32(Irrm_NEAREST); 17438 break; 17439 17440 default: // Impossible to get here 17441 vex_printf("Unrecognized opcode %x\n", opc2); 17442 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)"); 17443 } 17444 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 17445 assign( intermediateResult, 17446 binop( Iop_F64toI64S, rxpi_rm, 17447 mkexpr( frB ) ) ); 17448 17449 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 17450 /* F64 has only log10(2**52) significant digits anyway */ 17451 /* need to preserve sign of zero */ 17452 /* frD = (fabs(frB) > 9e18) ? frB : 17453 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 17454 assign( frD, 17455 IRExpr_ITE( 17456 binop( Iop_CmpNE8, 17457 unop( Iop_32to8, 17458 binop( Iop_CmpF64, 17459 IRExpr_Const( IRConst_F64( 9e18 ) ), 17460 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 17461 mkU8(0) ), 17462 mkexpr( frB ), 17463 IRExpr_ITE( 17464 binop( Iop_CmpNE32, 17465 binop( Iop_Shr32, 17466 unop( Iop_64HIto32, 17467 mkexpr( frB_I64 ) ), 17468 mkU8( 31 ) ), 17469 mkU32(0) ), 17470 unop( Iop_NegF64, 17471 unop( Iop_AbsF64, 17472 binop( Iop_I64StoF64, 17473 mkU32( 0 ), 17474 mkexpr( intermediateResult ) ) ) ), 17475 binop( Iop_I64StoF64, 17476 mkU32( 0 ), 17477 mkexpr( intermediateResult ) ) 17478 ) 17479 ) 17480 ); 17481 17482 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 17483 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 17484 */ 17485 #define SNAN_MASK 0x0008000000000000ULL 17486 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 17487 assign( is_SNAN, 17488 mkAND1( is_NaN( Ity_I64, frB_I64 ), 17489 binop( Iop_CmpEQ32, 17490 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 17491 mkU32( 0 ) ) ) ); 17492 17493 return IRExpr_ITE( mkexpr( is_SNAN ), 17494 unop( Iop_ReinterpI64asF64, 17495 binop( Iop_Xor64, 17496 mkU64( SNAN_MASK ), 17497 mkexpr( frB_I64 ) ) ), 17498 mkexpr( frD )); 17499 } 17500 17501 /* 17502 * Miscellaneous VSX vector instructions 17503 */ 17504 static Bool 17505 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 17506 { 17507 /* XX3-Form */ 17508 UChar opc1 = ifieldOPC( theInstr ); 17509 UChar XT = ifieldRegXT( theInstr ); 17510 UChar XB = ifieldRegXB( theInstr ); 17511 17512 if (opc1 != 0x3C) { 17513 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 17514 return False; 17515 } 17516 17517 switch (opc2) { 17518 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 17519 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 17520 // Double-Precision) 17521 { 17522 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 17523 IRExpr* rm = get_IR_roundingmode(); 17524 IRTemp frB = newTemp(Ity_I64); 17525 IRTemp frB2 = newTemp(Ity_I64); 17526 Bool redp = opc2 == 0x1B4; 17527 IRTemp sqrtHi = newTemp(Ity_F64); 17528 IRTemp sqrtLo = newTemp(Ity_F64); 17529 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 17530 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 17531 17532 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB); 17533 17534 if (!redp) { 17535 assign( sqrtHi, 17536 binop( Iop_SqrtF64, 17537 rm, 17538 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 17539 assign( sqrtLo, 17540 binop( Iop_SqrtF64, 17541 rm, 17542 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 17543 } 17544 putVSReg( XT, 17545 binop( Iop_64HLtoV128, 17546 unop( Iop_ReinterpF64asI64, 17547 triop( Iop_DivF64, 17548 rm, 17549 ieee_one, 17550 redp ? unop( Iop_ReinterpI64asF64, 17551 mkexpr( frB ) ) 17552 : mkexpr( sqrtHi ) ) ), 17553 unop( Iop_ReinterpF64asI64, 17554 triop( Iop_DivF64, 17555 rm, 17556 ieee_one, 17557 redp ? unop( Iop_ReinterpI64asF64, 17558 mkexpr( frB2 ) ) 17559 : mkexpr( sqrtLo ) ) ) ) ); 17560 break; 17561 17562 } 17563 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 17564 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 17565 { 17566 IRTemp b3, b2, b1, b0; 17567 IRTemp res0 = newTemp(Ity_I32); 17568 IRTemp res1 = newTemp(Ity_I32); 17569 IRTemp res2 = newTemp(Ity_I32); 17570 IRTemp res3 = newTemp(Ity_I32); 17571 IRTemp sqrt3 = newTemp(Ity_F64); 17572 IRTemp sqrt2 = newTemp(Ity_F64); 17573 IRTemp sqrt1 = newTemp(Ity_F64); 17574 IRTemp sqrt0 = newTemp(Ity_F64); 17575 IRExpr* rm = get_IR_roundingmode(); 17576 Bool resp = opc2 == 0x134; 17577 17578 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 17579 17580 b3 = b2 = b1 = b0 = IRTemp_INVALID; 17581 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB); 17582 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 17583 17584 if (!resp) { 17585 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 17586 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 17587 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 17588 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 17589 } 17590 17591 assign( res0, 17592 unop( Iop_ReinterpF32asI32, 17593 unop( Iop_TruncF64asF32, 17594 triop( Iop_DivF64r32, 17595 rm, 17596 ieee_one, 17597 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 17598 assign( res1, 17599 unop( Iop_ReinterpF32asI32, 17600 unop( Iop_TruncF64asF32, 17601 triop( Iop_DivF64r32, 17602 rm, 17603 ieee_one, 17604 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 17605 assign( res2, 17606 unop( Iop_ReinterpF32asI32, 17607 unop( Iop_TruncF64asF32, 17608 triop( Iop_DivF64r32, 17609 rm, 17610 ieee_one, 17611 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 17612 assign( res3, 17613 unop( Iop_ReinterpF32asI32, 17614 unop( Iop_TruncF64asF32, 17615 triop( Iop_DivF64r32, 17616 rm, 17617 ieee_one, 17618 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 17619 putVSReg( XT, 17620 binop( Iop_64HLtoV128, 17621 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 17622 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 17623 break; 17624 } 17625 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 17626 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 17627 { 17628 UChar XA = ifieldRegXA( theInstr ); 17629 IRTemp a3, a2, a1, a0; 17630 IRTemp b3, b2, b1, b0; 17631 IRTemp res0 = newTemp( Ity_I32 ); 17632 IRTemp res1 = newTemp( Ity_I32 ); 17633 IRTemp res2 = newTemp( Ity_I32 ); 17634 IRTemp res3 = newTemp( Ity_I32 ); 17635 IRTemp a0_I64 = newTemp( Ity_I64 ); 17636 IRTemp a1_I64 = newTemp( Ity_I64 ); 17637 IRTemp a2_I64 = newTemp( Ity_I64 ); 17638 IRTemp a3_I64 = newTemp( Ity_I64 ); 17639 IRTemp b0_I64 = newTemp( Ity_I64 ); 17640 IRTemp b1_I64 = newTemp( Ity_I64 ); 17641 IRTemp b2_I64 = newTemp( Ity_I64 ); 17642 IRTemp b3_I64 = newTemp( Ity_I64 ); 17643 17644 Bool isMin = opc2 == 0x320 ? True : False; 17645 17646 a3 = a2 = a1 = a0 = IRTemp_INVALID; 17647 b3 = b2 = b1 = b0 = IRTemp_INVALID; 17648 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB); 17649 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 17650 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 17651 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 17652 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 17653 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 17654 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 17655 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 17656 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 17657 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 17658 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 17659 assign( res0, 17660 unop( Iop_ReinterpF32asI32, 17661 unop( Iop_TruncF64asF32, 17662 unop( Iop_ReinterpI64asF64, 17663 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 17664 assign( res1, 17665 unop( Iop_ReinterpF32asI32, 17666 unop( Iop_TruncF64asF32, 17667 unop( Iop_ReinterpI64asF64, 17668 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 17669 assign( res2, 17670 unop( Iop_ReinterpF32asI32, 17671 unop( Iop_TruncF64asF32, 17672 unop( Iop_ReinterpI64asF64, 17673 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 17674 assign( res3, 17675 unop( Iop_ReinterpF32asI32, 17676 unop( Iop_TruncF64asF32, 17677 unop( Iop_ReinterpI64asF64, 17678 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 17679 putVSReg( XT, 17680 binop( Iop_64HLtoV128, 17681 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 17682 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 17683 break; 17684 } 17685 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 17686 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 17687 { 17688 UChar XA = ifieldRegXA( theInstr ); 17689 IRTemp frA = newTemp(Ity_I64); 17690 IRTemp frB = newTemp(Ity_I64); 17691 IRTemp frA2 = newTemp(Ity_I64); 17692 IRTemp frB2 = newTemp(Ity_I64); 17693 Bool isMin = opc2 == 0x3A0 ? True : False; 17694 17695 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 17696 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 17697 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 17698 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 17699 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB); 17700 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 17701 17702 break; 17703 } 17704 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 17705 { 17706 UChar XA = ifieldRegXA( theInstr ); 17707 IRTemp frA = newTemp(Ity_I64); 17708 IRTemp frB = newTemp(Ity_I64); 17709 IRTemp frA2 = newTemp(Ity_I64); 17710 IRTemp frB2 = newTemp(Ity_I64); 17711 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 17712 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 17713 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 17714 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 17715 17716 DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB); 17717 putVSReg( XT, 17718 binop( Iop_64HLtoV128, 17719 binop( Iop_Or64, 17720 binop( Iop_And64, 17721 mkexpr( frA ), 17722 mkU64( SIGN_BIT ) ), 17723 binop( Iop_And64, 17724 mkexpr( frB ), 17725 mkU64( SIGN_MASK ) ) ), 17726 binop( Iop_Or64, 17727 binop( Iop_And64, 17728 mkexpr( frA2 ), 17729 mkU64( SIGN_BIT ) ), 17730 binop( Iop_And64, 17731 mkexpr( frB2 ), 17732 mkU64( SIGN_MASK ) ) ) ) ); 17733 break; 17734 } 17735 case 0x340: // xvcpsgnsp 17736 { 17737 UChar XA = ifieldRegXA( theInstr ); 17738 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 17739 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 17740 IRTemp resHi = newTemp(Ity_I64); 17741 IRTemp resLo = newTemp(Ity_I64); 17742 17743 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 17744 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 17745 DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB); 17746 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 17747 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 17748 17749 assign( resHi, 17750 binop( Iop_32HLto64, 17751 binop( Iop_Or32, 17752 binop( Iop_And32, 17753 unop(Iop_64to32, mkexpr( a3_I64 ) ), 17754 mkU32( SIGN_BIT32 ) ), 17755 binop( Iop_And32, 17756 unop(Iop_64to32, mkexpr( b3_I64 ) ), 17757 mkU32( SIGN_MASK32) ) ), 17758 17759 binop( Iop_Or32, 17760 binop( Iop_And32, 17761 unop(Iop_64to32, mkexpr( a2_I64 ) ), 17762 mkU32( SIGN_BIT32 ) ), 17763 binop( Iop_And32, 17764 unop(Iop_64to32, mkexpr( b2_I64 ) ), 17765 mkU32( SIGN_MASK32 ) ) ) ) ); 17766 assign( resLo, 17767 binop( Iop_32HLto64, 17768 binop( Iop_Or32, 17769 binop( Iop_And32, 17770 unop(Iop_64to32, mkexpr( a1_I64 ) ), 17771 mkU32( SIGN_BIT32 ) ), 17772 binop( Iop_And32, 17773 unop(Iop_64to32, mkexpr( b1_I64 ) ), 17774 mkU32( SIGN_MASK32 ) ) ), 17775 17776 binop( Iop_Or32, 17777 binop( Iop_And32, 17778 unop(Iop_64to32, mkexpr( a0_I64 ) ), 17779 mkU32( SIGN_BIT32 ) ), 17780 binop( Iop_And32, 17781 unop(Iop_64to32, mkexpr( b0_I64 ) ), 17782 mkU32( SIGN_MASK32 ) ) ) ) ); 17783 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 17784 break; 17785 } 17786 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 17787 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 17788 { 17789 IRTemp frB = newTemp(Ity_F64); 17790 IRTemp frB2 = newTemp(Ity_F64); 17791 IRTemp abs_resultHi = newTemp(Ity_F64); 17792 IRTemp abs_resultLo = newTemp(Ity_F64); 17793 Bool make_negative = (opc2 == 0x3D2) ? True : False; 17794 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 17795 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 17796 17797 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB); 17798 if (make_negative) { 17799 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 17800 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 17801 17802 } else { 17803 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 17804 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 17805 } 17806 putVSReg( XT, binop( Iop_64HLtoV128, 17807 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 17808 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 17809 break; 17810 } 17811 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 17812 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 17813 { 17814 /* 17815 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 17816 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 17817 * of this function is so easy using shifts, I choose to emulate this instruction that 17818 * way versus a native instruction method of implementation. 17819 */ 17820 Bool make_negative = (opc2 == 0x352) ? True : False; 17821 IRTemp shiftVector = newTemp(Ity_V128); 17822 IRTemp absVal_vector = newTemp(Ity_V128); 17823 assign( shiftVector, 17824 binop( Iop_64HLtoV128, 17825 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 17826 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 17827 assign( absVal_vector, 17828 binop( Iop_Shr32x4, 17829 binop( Iop_Shl32x4, 17830 getVSReg( XB ), 17831 mkexpr( shiftVector ) ), 17832 mkexpr( shiftVector ) ) ); 17833 if (make_negative) { 17834 IRTemp signBit_vector = newTemp(Ity_V128); 17835 assign( signBit_vector, 17836 binop( Iop_64HLtoV128, 17837 binop( Iop_32HLto64, 17838 mkU32( 0x80000000 ), 17839 mkU32( 0x80000000 ) ), 17840 binop( Iop_32HLto64, 17841 mkU32( 0x80000000 ), 17842 mkU32( 0x80000000 ) ) ) ); 17843 putVSReg( XT, 17844 binop( Iop_OrV128, 17845 mkexpr( absVal_vector ), 17846 mkexpr( signBit_vector ) ) ); 17847 } else { 17848 putVSReg( XT, mkexpr( absVal_vector ) ); 17849 } 17850 break; 17851 } 17852 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 17853 { 17854 IRTemp frB = newTemp(Ity_F64); 17855 IRTemp frB2 = newTemp(Ity_F64); 17856 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 17857 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 17858 DIP("xvnegdp v%d,v%d\n", XT, XB); 17859 putVSReg( XT, 17860 binop( Iop_64HLtoV128, 17861 unop( Iop_ReinterpF64asI64, 17862 unop( Iop_NegF64, mkexpr( frB ) ) ), 17863 unop( Iop_ReinterpF64asI64, 17864 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 17865 break; 17866 } 17867 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 17868 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 17869 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 17870 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 17871 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 17872 { 17873 IRTemp frBHi_I64 = newTemp(Ity_I64); 17874 IRTemp frBLo_I64 = newTemp(Ity_I64); 17875 IRExpr * frD_fp_roundHi = NULL; 17876 IRExpr * frD_fp_roundLo = NULL; 17877 17878 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 17879 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2); 17880 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 17881 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2); 17882 17883 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB); 17884 putVSReg( XT, 17885 binop( Iop_64HLtoV128, 17886 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 17887 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 17888 break; 17889 } 17890 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 17891 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 17892 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 17893 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 17894 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 17895 { 17896 const HChar * insn_suffix = NULL; 17897 IROp op; 17898 if (opc2 != 0x156) { 17899 // Use pre-defined IRop's for vrfi{m|n|p|z} 17900 switch (opc2) { 17901 case 0x112: 17902 insn_suffix = ""; 17903 op = Iop_RoundF32x4_RN; 17904 break; 17905 case 0x172: 17906 insn_suffix = "m"; 17907 op = Iop_RoundF32x4_RM; 17908 break; 17909 case 0x152: 17910 insn_suffix = "p"; 17911 op = Iop_RoundF32x4_RP; 17912 break; 17913 case 0x132: 17914 insn_suffix = "z"; 17915 op = Iop_RoundF32x4_RZ; 17916 break; 17917 17918 default: 17919 vex_printf("Unrecognized opcode %x\n", opc2); 17920 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n"); 17921 } 17922 DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB); 17923 putVSReg( XT, unop( op, getVSReg(XB) ) ); 17924 } else { 17925 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 17926 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 17927 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 17928 IRTemp b3_I64 = newTemp(Ity_I64); 17929 IRTemp b2_I64 = newTemp(Ity_I64); 17930 IRTemp b1_I64 = newTemp(Ity_I64); 17931 IRTemp b0_I64 = newTemp(Ity_I64); 17932 17933 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 17934 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 17935 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 17936 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 17937 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 17938 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 17939 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 17940 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 17941 _do_vsx_fp_roundToInt(b3_I64, opc2)); 17942 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 17943 _do_vsx_fp_roundToInt(b2_I64, opc2)); 17944 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 17945 _do_vsx_fp_roundToInt(b1_I64, opc2)); 17946 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 17947 _do_vsx_fp_roundToInt(b0_I64, opc2)); 17948 DIP("xvrspic v%d,v%d\n", XT, XB); 17949 putVSReg( XT, 17950 binop( Iop_64HLtoV128, 17951 binop( Iop_32HLto64, 17952 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 17953 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 17954 binop( Iop_32HLto64, 17955 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 17956 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 17957 } 17958 break; 17959 } 17960 17961 default: 17962 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 17963 return False; 17964 } 17965 return True; 17966 } 17967 17968 17969 /* 17970 * VSX Scalar Floating Point Arithmetic Instructions 17971 */ 17972 static Bool 17973 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 17974 { 17975 /* XX3-Form */ 17976 UChar opc1 = ifieldOPC( theInstr ); 17977 UChar XT = ifieldRegXT( theInstr ); 17978 UChar XA = ifieldRegXA( theInstr ); 17979 UChar XB = ifieldRegXB( theInstr ); 17980 IRExpr* rm = get_IR_roundingmode(); 17981 IRTemp frA = newTemp(Ity_F64); 17982 IRTemp frB = newTemp(Ity_F64); 17983 17984 if (opc1 != 0x3C) { 17985 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 17986 return False; 17987 } 17988 17989 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 17990 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 17991 17992 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 17993 * of VSX[XT] are undefined after the operation; therefore, we can simply set 17994 * element to zero where it makes sense to do so. 17995 */ 17996 switch (opc2) { 17997 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision) 17998 DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB); 17999 putVSReg( XT, binop( Iop_64HLtoV128, 18000 unop( Iop_ReinterpF64asI64, 18001 binop( Iop_RoundF64toF32, rm, 18002 triop( Iop_AddF64, rm, 18003 mkexpr( frA ), 18004 mkexpr( frB ) ) ) ), 18005 mkU64( 0 ) ) ); 18006 break; 18007 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision) 18008 DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB); 18009 putVSReg( XT, binop( Iop_64HLtoV128, 18010 unop( Iop_ReinterpF64asI64, 18011 binop( Iop_RoundF64toF32, rm, 18012 triop( Iop_SubF64, rm, 18013 mkexpr( frA ), 18014 mkexpr( frB ) ) ) ), 18015 mkU64( 0 ) ) ); 18016 break; 18017 case 0x080: // xsadddp (VSX scalar add double-precision) 18018 DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB); 18019 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18020 triop( Iop_AddF64, rm, 18021 mkexpr( frA ), 18022 mkexpr( frB ) ) ), 18023 mkU64( 0 ) ) ); 18024 break; 18025 case 0x060: // xsdivsp (VSX scalar divide single-precision) 18026 DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB); 18027 putVSReg( XT, binop( Iop_64HLtoV128, 18028 unop( Iop_ReinterpF64asI64, 18029 binop( Iop_RoundF64toF32, rm, 18030 triop( Iop_DivF64, rm, 18031 mkexpr( frA ), 18032 mkexpr( frB ) ) ) ), 18033 mkU64( 0 ) ) ); 18034 break; 18035 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 18036 DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB); 18037 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18038 triop( Iop_DivF64, rm, 18039 mkexpr( frA ), 18040 mkexpr( frB ) ) ), 18041 mkU64( 0 ) ) ); 18042 break; 18043 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add 18044 * single-precision) 18045 */ 18046 { 18047 IRTemp frT = newTemp(Ity_F64); 18048 Bool mdp = opc2 == 0x024; 18049 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18050 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18051 getVSReg( XT ) ) ) ); 18052 putVSReg( XT, 18053 binop( Iop_64HLtoV128, 18054 unop( Iop_ReinterpF64asI64, 18055 binop( Iop_RoundF64toF32, rm, 18056 qop( Iop_MAddF64, rm, 18057 mkexpr( frA ), 18058 mkexpr( mdp ? frT : frB ), 18059 mkexpr( mdp ? frB : frT ) ) ) ), 18060 mkU64( 0 ) ) ); 18061 break; 18062 } 18063 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 18064 { 18065 IRTemp frT = newTemp(Ity_F64); 18066 Bool mdp = opc2 == 0x0A4; 18067 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18068 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18069 getVSReg( XT ) ) ) ); 18070 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18071 qop( Iop_MAddF64, rm, 18072 mkexpr( frA ), 18073 mkexpr( mdp ? frT : frB ), 18074 mkexpr( mdp ? frB : frT ) ) ), 18075 mkU64( 0 ) ) ); 18076 break; 18077 } 18078 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar 18079 * multiply-subtract single-precision) 18080 */ 18081 { 18082 IRTemp frT = newTemp(Ity_F64); 18083 Bool mdp = opc2 == 0x064; 18084 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18085 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18086 getVSReg( XT ) ) ) ); 18087 putVSReg( XT, 18088 binop( Iop_64HLtoV128, 18089 unop( Iop_ReinterpF64asI64, 18090 binop( Iop_RoundF64toF32, rm, 18091 qop( Iop_MSubF64, rm, 18092 mkexpr( frA ), 18093 mkexpr( mdp ? frT : frB ), 18094 mkexpr( mdp ? frB : frT ) ) ) ), 18095 mkU64( 0 ) ) ); 18096 break; 18097 } 18098 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 18099 { 18100 IRTemp frT = newTemp(Ity_F64); 18101 Bool mdp = opc2 == 0x0E4; 18102 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18103 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18104 getVSReg( XT ) ) ) ); 18105 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18106 qop( Iop_MSubF64, rm, 18107 mkexpr( frA ), 18108 mkexpr( mdp ? frT : frB ), 18109 mkexpr( mdp ? frB : frT ) ) ), 18110 mkU64( 0 ) ) ); 18111 break; 18112 } 18113 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 18114 { 18115 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 18116 * of fnmadd and use pretty much the same code. However, that code has a bug in the 18117 * way it blindly negates the signbit, even if the floating point result is a NaN. 18118 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 18119 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 18120 * bit for NaN result. 18121 */ 18122 Bool mdp = opc2 == 0x2A4; 18123 IRTemp frT = newTemp(Ity_F64); 18124 IRTemp maddResult = newTemp(Ity_I64); 18125 18126 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18127 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18128 getVSReg( XT ) ) ) ); 18129 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 18130 mkexpr( frA ), 18131 mkexpr( mdp ? frT : frB ), 18132 mkexpr( mdp ? frB : frT ) ) ) ); 18133 18134 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 18135 mkU64( 0 ) ) ); 18136 break; 18137 } 18138 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar 18139 * multiply-add single-precision) 18140 */ 18141 { 18142 Bool mdp = opc2 == 0x224; 18143 IRTemp frT = newTemp(Ity_F64); 18144 IRTemp maddResult = newTemp(Ity_I64); 18145 18146 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18147 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18148 getVSReg( XT ) ) ) ); 18149 assign( maddResult, 18150 unop( Iop_ReinterpF64asI64, 18151 binop( Iop_RoundF64toF32, rm, 18152 qop( Iop_MAddF64, rm, 18153 mkexpr( frA ), 18154 mkexpr( mdp ? frT : frB ), 18155 mkexpr( mdp ? frB : frT ) ) ) ) ); 18156 18157 putVSReg( XT, binop( Iop_64HLtoV128, 18158 mkexpr( getNegatedResult(maddResult) ), 18159 mkU64( 0 ) ) ); 18160 break; 18161 } 18162 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative 18163 * Multiply-Subtract Single-Precision) 18164 */ 18165 { 18166 IRTemp frT = newTemp(Ity_F64); 18167 Bool mdp = opc2 == 0x264; 18168 IRTemp msubResult = newTemp(Ity_I64); 18169 18170 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18171 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18172 getVSReg( XT ) ) ) ); 18173 assign( msubResult, 18174 unop( Iop_ReinterpF64asI64, 18175 binop( Iop_RoundF64toF32, rm, 18176 qop( Iop_MSubF64, rm, 18177 mkexpr( frA ), 18178 mkexpr( mdp ? frT : frB ), 18179 mkexpr( mdp ? frB : frT ) ) ) ) ); 18180 18181 putVSReg( XT, binop( Iop_64HLtoV128, 18182 mkexpr( getNegatedResult(msubResult) ), 18183 mkU64( 0 ) ) ); 18184 18185 break; 18186 } 18187 18188 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 18189 { 18190 IRTemp frT = newTemp(Ity_F64); 18191 Bool mdp = opc2 == 0x2E4; 18192 IRTemp msubResult = newTemp(Ity_I64); 18193 18194 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB); 18195 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 18196 getVSReg( XT ) ) ) ); 18197 assign(msubResult, unop( Iop_ReinterpF64asI64, 18198 qop( Iop_MSubF64, 18199 rm, 18200 mkexpr( frA ), 18201 mkexpr( mdp ? frT : frB ), 18202 mkexpr( mdp ? frB : frT ) ) )); 18203 18204 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 18205 18206 break; 18207 } 18208 18209 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision) 18210 DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB); 18211 putVSReg( XT, binop( Iop_64HLtoV128, 18212 unop( Iop_ReinterpF64asI64, 18213 binop( Iop_RoundF64toF32, rm, 18214 triop( Iop_MulF64, rm, 18215 mkexpr( frA ), 18216 mkexpr( frB ) ) ) ), 18217 mkU64( 0 ) ) ); 18218 break; 18219 18220 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 18221 DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB); 18222 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18223 triop( Iop_MulF64, rm, 18224 mkexpr( frA ), 18225 mkexpr( frB ) ) ), 18226 mkU64( 0 ) ) ); 18227 break; 18228 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 18229 DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB); 18230 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18231 triop( Iop_SubF64, rm, 18232 mkexpr( frA ), 18233 mkexpr( frB ) ) ), 18234 mkU64( 0 ) ) ); 18235 break; 18236 18237 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision) 18238 DIP("xssqrtsp v%d,v%d\n", XT, XB); 18239 putVSReg( XT, 18240 binop( Iop_64HLtoV128, 18241 unop( Iop_ReinterpF64asI64, 18242 binop( Iop_RoundF64toF32, rm, 18243 binop( Iop_SqrtF64, rm, 18244 mkexpr( frB ) ) ) ), 18245 mkU64( 0 ) ) ); 18246 break; 18247 18248 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 18249 DIP("xssqrtdp v%d,v%d\n", XT, XB); 18250 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 18251 binop( Iop_SqrtF64, rm, 18252 mkexpr( frB ) ) ), 18253 mkU64( 0 ) ) ); 18254 break; 18255 18256 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 18257 { 18258 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 18259 IRTemp frA_I64 = newTemp(Ity_I64); 18260 IRTemp frB_I64 = newTemp(Ity_I64); 18261 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB); 18262 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 18263 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 18264 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 18265 break; 18266 } 18267 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 18268 { 18269 IRTemp frB_I64 = newTemp(Ity_I64); 18270 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 18271 IRTemp flags = newTemp(Ity_I32); 18272 IRTemp fe_flag, fg_flag; 18273 fe_flag = fg_flag = IRTemp_INVALID; 18274 DIP("xstsqrtdp v%d,v%d\n", XT, XB); 18275 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 18276 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 18277 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 18278 * where fl_flag == 1 on ppc64. 18279 */ 18280 assign( flags, 18281 binop( Iop_Or32, 18282 binop( Iop_Or32, mkU32( 8 ), // fl_flag 18283 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 18284 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 18285 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 18286 break; 18287 } 18288 18289 default: 18290 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 18291 return False; 18292 } 18293 18294 return True; 18295 } 18296 18297 18298 /* 18299 * VSX Floating Point Compare Instructions 18300 */ 18301 static Bool 18302 dis_vx_cmp( UInt theInstr, UInt opc2 ) 18303 { 18304 /* XX3-Form and XX2-Form */ 18305 UChar opc1 = ifieldOPC( theInstr ); 18306 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 18307 IRTemp ccPPC32; 18308 UChar XA = ifieldRegXA ( theInstr ); 18309 UChar XB = ifieldRegXB ( theInstr ); 18310 IRTemp frA = newTemp(Ity_F64); 18311 IRTemp frB = newTemp(Ity_F64); 18312 18313 if (opc1 != 0x3C) { 18314 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 18315 return False; 18316 } 18317 18318 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 18319 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 18320 switch (opc2) { 18321 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 18322 /* Note: Differences between xscmpudp and xscmpodp are only in 18323 * exception flag settings, which aren't supported anyway. */ 18324 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 18325 crfD, XA, XB); 18326 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 18327 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 18328 putFPCC( mkexpr( ccPPC32 ) ); 18329 break; 18330 18331 default: 18332 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 18333 return False; 18334 } 18335 return True; 18336 } 18337 18338 static void 18339 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 18340 ppc_cmp_t cmp_type ) 18341 { 18342 IRTemp frA_hi = newTemp(Ity_F64); 18343 IRTemp frB_hi = newTemp(Ity_F64); 18344 IRTemp frA_lo = newTemp(Ity_F64); 18345 IRTemp frB_lo = newTemp(Ity_F64); 18346 IRTemp ccPPC32 = newTemp(Ity_I32); 18347 IRTemp ccIR_hi; 18348 IRTemp ccIR_lo; 18349 18350 IRTemp hiResult = newTemp(Ity_I64); 18351 IRTemp loResult = newTemp(Ity_I64); 18352 IRTemp hiEQlo = newTemp(Ity_I1); 18353 IRTemp all_elem_true = newTemp(Ity_I32); 18354 IRTemp all_elem_false = newTemp(Ity_I32); 18355 18356 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 18357 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 18358 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 18359 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 18360 18361 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 18362 mkexpr( frA_hi ), 18363 mkexpr( frB_hi ) ) ); 18364 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 18365 mkexpr( frA_lo ), 18366 mkexpr( frB_lo ) ) ); 18367 18368 if (cmp_type != PPC_CMP_GE) { 18369 assign( hiResult, 18370 unop( Iop_1Sto64, 18371 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 18372 assign( loResult, 18373 unop( Iop_1Sto64, 18374 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 18375 } else { 18376 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 18377 // the other element compare may return "2" (for "equal to"). 18378 IRTemp lo_GE = newTemp(Ity_I1); 18379 IRTemp hi_GE = newTemp(Ity_I1); 18380 18381 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 18382 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 18383 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 18384 18385 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 18386 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 18387 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 18388 } 18389 18390 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 18391 assign( hiEQlo, 18392 binop( Iop_CmpEQ32, 18393 unop( Iop_64to32, mkexpr( hiResult ) ), 18394 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 18395 putVSReg( XT, 18396 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 18397 18398 assign( all_elem_true, 18399 unop( Iop_1Uto32, 18400 mkAND1( mkexpr( hiEQlo ), 18401 binop( Iop_CmpEQ32, 18402 mkU32( 0xffffffff ), 18403 unop( Iop_64to32, 18404 mkexpr( hiResult ) ) ) ) ) ); 18405 18406 assign( all_elem_false, 18407 unop( Iop_1Uto32, 18408 mkAND1( mkexpr( hiEQlo ), 18409 binop( Iop_CmpEQ32, 18410 mkU32( 0 ), 18411 unop( Iop_64to32, 18412 mkexpr( hiResult ) ) ) ) ) ); 18413 assign( ccPPC32, 18414 binop( Iop_Or32, 18415 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 18416 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 18417 18418 if (flag_rC) { 18419 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 18420 } 18421 } 18422 18423 /* 18424 * VSX Vector Compare Instructions 18425 */ 18426 static Bool 18427 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 18428 { 18429 /* XX3-Form */ 18430 UChar opc1 = ifieldOPC( theInstr ); 18431 UChar XT = ifieldRegXT ( theInstr ); 18432 UChar XA = ifieldRegXA ( theInstr ); 18433 UChar XB = ifieldRegXB ( theInstr ); 18434 UChar flag_rC = ifieldBIT10(theInstr); 18435 IRTemp vA = newTemp( Ity_V128 ); 18436 IRTemp vB = newTemp( Ity_V128 ); 18437 18438 if (opc1 != 0x3C) { 18439 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 18440 return False; 18441 } 18442 18443 assign( vA, getVSReg( XA ) ); 18444 assign( vB, getVSReg( XB ) ); 18445 18446 switch (opc2) { 18447 case 0x18C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 18448 { 18449 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18450 XT, XA, XB); 18451 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 18452 break; 18453 } 18454 18455 case 0x1CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 18456 { 18457 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18458 XT, XA, XB); 18459 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 18460 break; 18461 } 18462 18463 case 0x1AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 18464 { 18465 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18466 XT, XA, XB); 18467 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 18468 break; 18469 } 18470 18471 case 0x10C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 18472 { 18473 IRTemp vD = newTemp(Ity_V128); 18474 18475 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18476 XT, XA, XB); 18477 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 18478 putVSReg( XT, mkexpr(vD) ); 18479 if (flag_rC) { 18480 set_AV_CR6( mkexpr(vD), True ); 18481 } 18482 break; 18483 } 18484 18485 case 0x14C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 18486 { 18487 IRTemp vD = newTemp(Ity_V128); 18488 18489 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18490 XT, XA, XB); 18491 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 18492 putVSReg( XT, mkexpr(vD) ); 18493 if (flag_rC) { 18494 set_AV_CR6( mkexpr(vD), True ); 18495 } 18496 break; 18497 } 18498 18499 case 0x12C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 18500 { 18501 IRTemp vD = newTemp(Ity_V128); 18502 18503 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 18504 XT, XA, XB); 18505 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 18506 putVSReg( XT, mkexpr(vD) ); 18507 if (flag_rC) { 18508 set_AV_CR6( mkexpr(vD), True ); 18509 } 18510 break; 18511 } 18512 18513 default: 18514 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 18515 return False; 18516 } 18517 return True; 18518 } 18519 /* 18520 * Miscellaneous VSX Scalar Instructions 18521 */ 18522 static Bool 18523 dis_vxs_misc( UInt theInstr, UInt opc2, int allow_isa_3_0 ) 18524 { 18525 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL 18526 /* XX3-Form and XX2-Form */ 18527 UChar opc1 = ifieldOPC( theInstr ); 18528 UChar XT = ifieldRegXT ( theInstr ); 18529 UChar XA = ifieldRegXA ( theInstr ); 18530 UChar XB = ifieldRegXB ( theInstr ); 18531 IRTemp vA = newTemp( Ity_V128 ); 18532 IRTemp vB = newTemp( Ity_V128 ); 18533 18534 if (opc1 != 0x3C) { 18535 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 18536 return False; 18537 } 18538 18539 assign( vA, getVSReg( XA ) ); 18540 assign( vB, getVSReg( XB ) ); 18541 18542 /* For all the VSX move instructions, the contents of doubleword element 1 18543 * of VSX[XT] are undefined after the operation; therefore, we can simply 18544 * move the entire array element where it makes sense to do so. 18545 */ 18546 if (( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) ) 18547 { 18548 /* Special case of XX1-Form with immediate value 18549 * xxspltib (VSX Vector Splat Immediate Byte) 18550 */ 18551 UInt uim = IFIELD( theInstr, 11, 8 ); 18552 UInt word_value = ( uim << 24 ) | ( uim << 16 ) | ( uim << 8 ) | uim; 18553 18554 DIP("xxspltib v%d,%d\n", (UInt)XT, uim); 18555 putVSReg(XT, binop( Iop_64HLtoV128, 18556 binop( Iop_32HLto64, 18557 mkU32( word_value ), 18558 mkU32( word_value ) ), 18559 binop( Iop_32HLto64, 18560 mkU32( word_value ), 18561 mkU32( word_value ) ) ) ); 18562 return True; 18563 } 18564 18565 switch ( opc2 ) { 18566 case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision) 18567 { 18568 /* Compare 64-bit data, 128-bit layout: 18569 src1[0:63] is double word, src1[64:127] is unused 18570 src2[0:63] is double word, src2[64:127] is unused 18571 */ 18572 IRExpr *bit4, *bit5, *bit6, *bit7; 18573 UInt BF = IFIELD( theInstr, 23, 3 ); 18574 IRTemp eq_lt_gt = newTemp( Ity_I32 ); 18575 IRTemp CC = newTemp( Ity_I32 ); 18576 IRTemp vA_hi = newTemp( Ity_I64 ); 18577 IRTemp vB_hi = newTemp( Ity_I64 ); 18578 IRExpr *mask = mkU64( 0x7FF0000000000000 ); 18579 18580 DIP("xscmpexpdp %d,v%d,v%d\n", BF, XA, XB); 18581 18582 assign( vA_hi, unop( Iop_V128HIto64, mkexpr( vA ) ) ); 18583 assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 18584 18585 /* A exp < B exp */ 18586 bit4 = binop( Iop_CmpLT64U, 18587 binop( Iop_And64, 18588 mkexpr( vA_hi ), 18589 mask ), 18590 binop( Iop_And64, 18591 mkexpr( vB_hi ), 18592 mask ) ); 18593 /* A exp > B exp */ 18594 bit5 = binop( Iop_CmpLT64U, 18595 binop( Iop_And64, 18596 mkexpr( vB_hi ), 18597 mask ), 18598 binop( Iop_And64, 18599 mkexpr( vA_hi ), 18600 mask ) ); 18601 /* test equal */ 18602 bit6 = binop( Iop_CmpEQ64, 18603 binop( Iop_And64, 18604 mkexpr( vA_hi ), 18605 mask ), 18606 binop( Iop_And64, 18607 mkexpr( vB_hi ), 18608 mask ) ); 18609 18610 /* exp A or exp B is NaN */ 18611 bit7 = mkOR1( is_NaN( Ity_I64, vA_hi ), 18612 is_NaN( Ity_I64, vB_hi ) ); 18613 18614 assign( eq_lt_gt, binop( Iop_Or32, 18615 binop( Iop_Shl32, 18616 unop( Iop_1Uto32, bit4 ), 18617 mkU8( 3) ), 18618 binop( Iop_Or32, 18619 binop( Iop_Shl32, 18620 unop( Iop_1Uto32, bit5 ), 18621 mkU8( 2) ), 18622 binop( Iop_Shl32, 18623 unop( Iop_1Uto32, bit6 ), 18624 mkU8( 1 ) ) ) ) ); 18625 assign(CC, binop( Iop_Or32, 18626 binop( Iop_And32, 18627 mkexpr( eq_lt_gt ) , 18628 unop( Iop_Not32, unop( Iop_1Sto32, bit7 ) ) ), 18629 unop( Iop_1Uto32, bit7 ) ) ); 18630 18631 putGST_field( PPC_GST_CR, mkexpr( CC ), BF ); 18632 putFPCC( mkexpr( CC ) ); 18633 return True; 18634 } 18635 break; 18636 18637 case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word) 18638 { 18639 UInt uim = IFIELD( theInstr, 16, 4 ); 18640 18641 DIP("xxextractuw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim); 18642 18643 putVSReg( XT, 18644 binop( Iop_ShlV128, 18645 binop( Iop_AndV128, 18646 binop( Iop_ShrV128, 18647 mkexpr( vB ), 18648 mkU8( ( 12 - uim ) * 8 ) ), 18649 binop(Iop_64HLtoV128, 18650 mkU64( 0 ), 18651 mkU64( 0xFFFFFFFF ) ) ), 18652 mkU8( ( 32*2 ) ) ) ); 18653 break; 18654 } 18655 case 0x16A: // xxinsertw (VSX Vector insert Word) 18656 { 18657 UInt uim = IFIELD( theInstr, 16, 4 ); 18658 IRTemp vT = newTemp( Ity_V128 ); 18659 IRTemp tmp = newTemp( Ity_V128 ); 18660 18661 DIP("xxinsertw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim); 18662 18663 assign( vT, getVSReg( XT ) ); 18664 assign( tmp, binop( Iop_AndV128, 18665 mkexpr( vT ), 18666 unop( Iop_NotV128, 18667 binop( Iop_ShlV128, 18668 binop( Iop_64HLtoV128, 18669 mkU64( 0x0 ), 18670 mkU64( 0xFFFFFFFF) ), 18671 mkU8( ( 12 - uim ) * 8 ) ) ) ) ); 18672 18673 putVSReg( XT, 18674 binop( Iop_OrV128, 18675 binop( Iop_ShlV128, 18676 binop( Iop_AndV128, 18677 binop( Iop_ShrV128, 18678 mkexpr( vB ), 18679 mkU8( 32 * 2 ) ), 18680 binop( Iop_64HLtoV128, 18681 mkU64( 0 ), 18682 mkU64( 0xFFFFFFFF ) ) ), 18683 mkU8( ( 12 - uim ) * 8 ) ), 18684 mkexpr( tmp ) ) ); 18685 break; 18686 } 18687 18688 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 18689 { 18690 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 18691 IRTemp absVal = newTemp(Ity_V128); 18692 if (host_endness == VexEndnessLE) { 18693 IRTemp hi64 = newTemp(Ity_I64); 18694 IRTemp lo64 = newTemp(Ity_I64); 18695 assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) ); 18696 assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) ); 18697 assign( absVal, binop( Iop_64HLtoV128, 18698 binop( Iop_And64, mkexpr(hi64), 18699 mkU64(VG_PPC_SIGN_MASK) ), 18700 mkexpr(lo64) ) ); 18701 } else { 18702 assign(absVal, binop(Iop_ShrV128, 18703 binop(Iop_ShlV128, mkexpr(vB), 18704 mkU8(1)), mkU8(1))); 18705 } 18706 DIP("xsabsdp v%d,v%d\n", XT, XB); 18707 putVSReg(XT, mkexpr(absVal)); 18708 break; 18709 } 18710 18711 case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision) 18712 // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision) 18713 // xsvhpdp (VSX Scalar Convert Half-Precision format 18714 // to Double-Precision format) 18715 // xscvdphp (VSX Scalar round & convert Double-precision 18716 // format to Half-precision format) 18717 { 18718 IRTemp rT = newTemp( Ity_I64 ); 18719 UInt inst_select = IFIELD( theInstr, 16, 5); 18720 18721 if (inst_select == 0) { 18722 DIP("xsxexpd %d,v%d\n", (UInt)XT, (UInt)XB); 18723 18724 assign( rT, binop( Iop_Shr64, 18725 binop( Iop_And64, 18726 unop( Iop_V128HIto64, mkexpr( vB ) ), 18727 mkU64( 0x7FF0000000000000 ) ), 18728 mkU8 ( 52 ) ) ); 18729 } else if (inst_select == 1) { 18730 IRExpr *normal; 18731 IRTemp tmp = newTemp(Ity_I64); 18732 18733 DIP("xsxsigdp v%d,v%d\n", (UInt)XT, (UInt)XB); 18734 18735 assign( tmp, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 18736 18737 /* Value is normal if it isn't infinite, zero or denormalized */ 18738 normal = mkNOT1( mkOR1( 18739 mkOR1( is_NaN( Ity_I64, tmp ), 18740 is_Inf( Ity_I64, tmp ) ), 18741 mkOR1( is_Zero( Ity_I64, tmp ), 18742 is_Denorm( Ity_I64, tmp ) ) ) ); 18743 18744 assign( rT, binop( Iop_Or64, 18745 binop( Iop_And64, 18746 mkexpr( tmp ), 18747 mkU64( 0xFFFFFFFFFFFFF ) ), 18748 binop( Iop_Shl64, 18749 unop( Iop_1Uto64, normal), 18750 mkU8( 52 ) ) ) ); 18751 putIReg( XT, mkexpr( rT ) ); 18752 18753 } else if (inst_select == 16) { 18754 IRTemp result = newTemp( Ity_V128 ); 18755 IRTemp value = newTemp( Ity_I64 ); 18756 /* Note: PPC only coverts the 16-bit value in the upper 64-bits 18757 * of the source V128 to a 64-bit value stored in the upper 18758 * 64-bits of the V128 result. The contents of the lower 64-bits 18759 * is undefined. 18760 */ 18761 18762 DIP("xscvhpdp v%d, v%d\n", (UInt)XT, (UInt)XB); 18763 assign( result, unop( Iop_F16toF64x2, mkexpr( vB ) ) ); 18764 18765 putVSReg( XT, mkexpr( result ) ); 18766 18767 assign( value, unop( Iop_V128HIto64, mkexpr( result ) ) ); 18768 generate_store_FPRF( Ity_I64, value ); 18769 return True; 18770 18771 } else if (inst_select == 17) { // xscvdphp 18772 IRTemp value = newTemp( Ity_I32 ); 18773 IRTemp result = newTemp( Ity_V128 ); 18774 /* Note: PPC only coverts the 64-bit value in the upper 64-bits of 18775 * the V128 and stores the 16-bit result in the upper word of the 18776 * V128 result. The contents of the lower 64-bits is undefined. 18777 */ 18778 DIP("xscvdphp v%d, v%d\n", (UInt)XT, (UInt)XB); 18779 assign( result, unop( Iop_F64toF16x2, mkexpr( vB ) ) ); 18780 assign( value, unop( Iop_64to32, unop( Iop_V128HIto64, 18781 mkexpr( result ) ) ) ); 18782 putVSReg( XT, mkexpr( result ) ); 18783 generate_store_FPRF( Ity_I16, value ); 18784 return True; 18785 18786 } else { 18787 vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" ); 18788 vex_printf("inst_select = %d\n", inst_select); 18789 return False; 18790 } 18791 } 18792 break; 18793 18794 case 0x254: // xststdcsp (VSX Scalar Test Data Class Single-Precision) 18795 case 0x2D4: // xststdcdp (VSX Scalar Test Data Class Double-Precision) 18796 { 18797 /* These instructions only differ in that the single precision 18798 instruction, xststdcsp, has the additional constraint on the 18799 denormal test that the exponent be greater then zero and 18800 less then 0x381. */ 18801 IRTemp vB_hi = newTemp( Ity_I64 ); 18802 UInt BF = IFIELD( theInstr, 23, 3 ); 18803 UInt DCMX_mask = IFIELD( theInstr, 16, 7 ); 18804 IRTemp NaN = newTemp( Ity_I64 ); 18805 IRTemp inf = newTemp( Ity_I64 ); 18806 IRTemp zero = newTemp( Ity_I64 ); 18807 IRTemp dnorm = newTemp( Ity_I64 ); 18808 IRTemp pos = newTemp( Ity_I64 ); 18809 IRTemp not_sp = newTemp( Ity_I64 ); 18810 IRTemp DCM = newTemp( Ity_I64 ); 18811 IRTemp CC = newTemp( Ity_I64 ); 18812 IRTemp exponent = newTemp( Ity_I64 ); 18813 IRTemp tmp = newTemp( Ity_I64 ); 18814 18815 assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 18816 18817 assign( pos, unop( Iop_1Uto64, 18818 binop( Iop_CmpEQ64, 18819 binop( Iop_Shr64, 18820 mkexpr( vB_hi ), 18821 mkU8( 63 ) ), 18822 mkU64( 0 ) ) ) ); 18823 18824 assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_I64, vB_hi ) ) ); 18825 assign( inf, unop( Iop_1Uto64, is_Inf( Ity_I64, vB_hi ) ) ); 18826 assign( zero, unop( Iop_1Uto64, is_Zero( Ity_I64, vB_hi ) ) ); 18827 18828 if (opc2 == 0x254) { 18829 DIP("xststdcsp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask); 18830 18831 /* The least significant bit of the CC is set to 1 if the double 18832 precision value is not representable as a single precision 18833 value. The spec says the bit is set if: 18834 src != convert_SPtoDP(convert_DPtoSP(src)) 18835 */ 18836 assign( tmp, 18837 unop( Iop_ReinterpF64asI64, 18838 unop( Iop_F32toF64, 18839 unop( Iop_TruncF64asF32, 18840 unop( Iop_ReinterpI64asF64, 18841 mkexpr( vB_hi ) ) ) ) ) ); 18842 assign( not_sp, unop( Iop_1Uto64, 18843 mkNOT1( binop( Iop_CmpEQ64, 18844 mkexpr( vB_hi ), 18845 mkexpr( tmp ) ) ) ) ); 18846 assign( exponent, 18847 binop( Iop_Shr64, 18848 binop( Iop_And64, 18849 mkexpr( vB_hi ), 18850 mkU64( 0x7ff0000000000000 ) ), 18851 mkU8( 52 ) ) ); 18852 assign( dnorm, unop( Iop_1Uto64, 18853 mkOR1( is_Denorm( Ity_I64, vB_hi ), 18854 mkAND1( binop( Iop_CmpLT64U, 18855 mkexpr( exponent ), 18856 mkU64( 0x381 ) ), 18857 binop( Iop_CmpNE64, 18858 mkexpr( exponent ), 18859 mkU64( 0x0 ) ) ) ) ) ); 18860 18861 } else { 18862 DIP("xststdcdp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask); 18863 assign( not_sp, mkU64( 0 ) ); 18864 assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_I64, vB_hi ) ) ); 18865 } 18866 18867 assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) ); 18868 assign( CC, 18869 binop( Iop_Or64, 18870 binop( Iop_And64, /* vB sign bit */ 18871 binop( Iop_Shr64, 18872 mkexpr( vB_hi ), 18873 mkU8( 60 ) ), 18874 mkU64( 0x8 ) ), 18875 binop( Iop_Or64, 18876 binop( Iop_Shl64, 18877 unop( Iop_1Uto64, 18878 binop( Iop_CmpNE64, 18879 binop( Iop_And64, 18880 mkexpr( DCM ), 18881 mkU64( DCMX_mask ) ), 18882 mkU64( 0 ) ) ), 18883 mkU8( 1 ) ), 18884 mkexpr( not_sp ) ) ) ); 18885 putGST_field( PPC_GST_CR, unop( Iop_64to32, mkexpr( CC ) ), BF ); 18886 putFPCC( unop( Iop_64to32, mkexpr( CC ) ) ); 18887 } 18888 return True; 18889 18890 case 0x2C0: // xscpsgndp 18891 { 18892 /* Scalar copy sign double-precision */ 18893 IRTemp vecA_signed = newTemp(Ity_I64); 18894 IRTemp vecB_unsigned = newTemp(Ity_I64); 18895 IRTemp vec_result = newTemp(Ity_V128); 18896 DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB); 18897 assign( vecA_signed, binop( Iop_And64, 18898 unop( Iop_V128HIto64, 18899 mkexpr(vA)), 18900 mkU64(~VG_PPC_SIGN_MASK) ) ); 18901 assign( vecB_unsigned, binop( Iop_And64, 18902 unop( Iop_V128HIto64, 18903 mkexpr(vB) ), 18904 mkU64(VG_PPC_SIGN_MASK) ) ); 18905 assign( vec_result, binop( Iop_64HLtoV128, 18906 binop( Iop_Or64, 18907 mkexpr(vecA_signed), 18908 mkexpr(vecB_unsigned) ), 18909 mkU64(0x0ULL))); 18910 putVSReg(XT, mkexpr(vec_result)); 18911 break; 18912 } 18913 case 0x2D2: // xsnabsdp 18914 { 18915 /* Scalar negative absolute value double-precision */ 18916 IRTemp BHi_signed = newTemp(Ity_I64); 18917 DIP("xsnabsdp v%d,v%d\n", XT, XB); 18918 assign( BHi_signed, binop( Iop_Or64, 18919 unop( Iop_V128HIto64, 18920 mkexpr(vB) ), 18921 mkU64(~VG_PPC_SIGN_MASK) ) ); 18922 putVSReg(XT, binop( Iop_64HLtoV128, 18923 mkexpr(BHi_signed), mkU64(0x0ULL) ) ); 18924 break; 18925 } 18926 case 0x2F2: // xsnegdp 18927 { 18928 /* Scalar negate double-precision */ 18929 IRTemp BHi_signed = newTemp(Ity_I64); 18930 IRTemp BHi_unsigned = newTemp(Ity_I64); 18931 IRTemp BHi_negated = newTemp(Ity_I64); 18932 IRTemp BHi_negated_signbit = newTemp(Ity_I1); 18933 IRTemp vec_result = newTemp(Ity_V128); 18934 DIP("xsnabsdp v%d,v%d\n", XT, XB); 18935 assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) ); 18936 assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed), 18937 mkU64(VG_PPC_SIGN_MASK) ) ); 18938 assign( BHi_negated_signbit, 18939 unop( Iop_Not1, 18940 unop( Iop_32to1, 18941 binop( Iop_Shr32, 18942 unop( Iop_64HIto32, 18943 binop( Iop_And64, 18944 mkexpr(BHi_signed), 18945 mkU64(~VG_PPC_SIGN_MASK) ) 18946 ), 18947 mkU8(31) ) ) ) ); 18948 assign( BHi_negated, 18949 binop( Iop_Or64, 18950 binop( Iop_32HLto64, 18951 binop( Iop_Shl32, 18952 unop( Iop_1Uto32, 18953 mkexpr(BHi_negated_signbit) ), 18954 mkU8(31) ), 18955 mkU32(0) ), 18956 mkexpr(BHi_unsigned) ) ); 18957 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated), 18958 mkU64(0x0ULL))); 18959 putVSReg( XT, mkexpr(vec_result)); 18960 break; 18961 } 18962 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 18963 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 18964 { 18965 IRTemp frA = newTemp(Ity_I64); 18966 IRTemp frB = newTemp(Ity_I64); 18967 Bool isMin = opc2 == 0x2A0 ? True : False; 18968 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB); 18969 18970 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 18971 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 18972 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 18973 18974 break; 18975 } 18976 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 18977 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 18978 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 18979 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 18980 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 18981 { 18982 IRTemp frB_I64 = newTemp(Ity_I64); 18983 IRExpr * frD_fp_round = NULL; 18984 18985 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 18986 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2); 18987 18988 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB); 18989 putVSReg( XT, 18990 binop( Iop_64HLtoV128, 18991 unop( Iop_ReinterpF64asI64, frD_fp_round), 18992 mkU64( 0 ) ) ); 18993 break; 18994 } 18995 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision) 18996 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate 18997 * single-Precision) 18998 */ 18999 { 19000 IRTemp frB = newTemp(Ity_F64); 19001 IRTemp sqrt = newTemp(Ity_F64); 19002 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 19003 IRExpr* rm = get_IR_roundingmode(); 19004 Bool redp = opc2 == 0x034; 19005 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT, 19006 XB); 19007 19008 assign( frB, 19009 unop( Iop_ReinterpI64asF64, 19010 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 19011 19012 if (!redp) 19013 assign( sqrt, 19014 binop( Iop_SqrtF64, 19015 rm, 19016 mkexpr(frB) ) ); 19017 putVSReg( XT, 19018 binop( Iop_64HLtoV128, 19019 unop( Iop_ReinterpF64asI64, 19020 binop( Iop_RoundF64toF32, rm, 19021 triop( Iop_DivF64, 19022 rm, 19023 ieee_one, 19024 redp ? mkexpr( frB ) : 19025 mkexpr( sqrt ) ) ) ), 19026 mkU64( 0 ) ) ); 19027 break; 19028 } 19029 19030 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 19031 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 19032 19033 { 19034 IRTemp frB = newTemp(Ity_F64); 19035 IRTemp sqrt = newTemp(Ity_F64); 19036 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 19037 IRExpr* rm = get_IR_roundingmode(); 19038 Bool redp = opc2 == 0x0B4; 19039 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB); 19040 assign( frB, 19041 unop( Iop_ReinterpI64asF64, 19042 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 19043 19044 if (!redp) 19045 assign( sqrt, 19046 binop( Iop_SqrtF64, 19047 rm, 19048 mkexpr(frB) ) ); 19049 putVSReg( XT, 19050 binop( Iop_64HLtoV128, 19051 unop( Iop_ReinterpF64asI64, 19052 triop( Iop_DivF64, 19053 rm, 19054 ieee_one, 19055 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 19056 mkU64( 0 ) ) ); 19057 break; 19058 } 19059 19060 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision) 19061 { 19062 IRTemp frB = newTemp(Ity_F64); 19063 IRExpr* rm = get_IR_roundingmode(); 19064 DIP("xsrsp v%d, v%d\n", XT, XB); 19065 assign( frB, 19066 unop( Iop_ReinterpI64asF64, 19067 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 19068 19069 putVSReg( XT, binop( Iop_64HLtoV128, 19070 unop( Iop_ReinterpF64asI64, 19071 binop( Iop_RoundF64toF32, 19072 rm, 19073 mkexpr( frB ) ) ), 19074 mkU64( 0 ) ) ); 19075 break; 19076 } 19077 19078 case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision) 19079 { 19080 UInt DX_mask = IFIELD( theInstr, 16, 5 ); 19081 UInt DC_mask = IFIELD( theInstr, 6, 1 ); 19082 UInt DM_mask = IFIELD( theInstr, 2, 1 ); 19083 UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask; 19084 19085 IRTemp match_value[4]; 19086 IRTemp value[4]; 19087 IRTemp NaN[4]; 19088 IRTemp inf[4]; 19089 IRTemp pos[4]; 19090 IRTemp DCM[4]; 19091 IRTemp zero[4]; 19092 IRTemp dnorm[4]; 19093 Int i; 19094 19095 DIP("xvtstdcsp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask); 19096 19097 for (i = 0; i < 4; i++) { 19098 NaN[i] = newTemp(Ity_I32); 19099 inf[i] = newTemp(Ity_I32); 19100 pos[i] = newTemp(Ity_I32); 19101 DCM[i] = newTemp(Ity_I32); 19102 zero[i] = newTemp(Ity_I32); 19103 dnorm[i] = newTemp(Ity_I32); 19104 19105 value[i] = newTemp(Ity_I32); 19106 match_value[i] = newTemp(Ity_I32); 19107 19108 assign( value[i], 19109 unop( Iop_64to32, 19110 unop( Iop_V128to64, 19111 binop( Iop_AndV128, 19112 binop( Iop_ShrV128, 19113 mkexpr( vB ), 19114 mkU8( (3-i)*32 ) ), 19115 binop( Iop_64HLtoV128, 19116 mkU64( 0x0 ), 19117 mkU64( 0xFFFFFFFF ) ) ) ) ) ); 19118 19119 assign( pos[i], unop( Iop_1Uto32, 19120 binop( Iop_CmpEQ32, 19121 binop( Iop_Shr32, 19122 mkexpr( value[i] ), 19123 mkU8( 31 ) ), 19124 mkU32( 0 ) ) ) ); 19125 19126 assign( NaN[i], unop( Iop_1Uto32, is_NaN( Ity_I32, value[i] ) )); 19127 assign( inf[i], unop( Iop_1Uto32, is_Inf( Ity_I32, value[i] ) ) ); 19128 assign( zero[i], unop( Iop_1Uto32, is_Zero( Ity_I32, value[i] ) ) ); 19129 19130 assign( dnorm[i], unop( Iop_1Uto32, is_Denorm( Ity_I32, 19131 value[i] ) ) ); 19132 assign( DCM[i], create_DCM( Ity_I32, NaN[i], inf[i], zero[i], 19133 dnorm[i], pos[i] ) ); 19134 19135 assign( match_value[i], 19136 unop( Iop_1Sto32, 19137 binop( Iop_CmpNE32, 19138 binop( Iop_And32, 19139 mkU32( DCMX_mask ), 19140 mkexpr( DCM[i] ) ), 19141 mkU32( 0 ) ) ) ); 19142 } 19143 19144 putVSReg( XT, binop( Iop_64HLtoV128, 19145 binop( Iop_32HLto64, 19146 mkexpr( match_value[0] ), 19147 mkexpr( match_value[1] ) ), 19148 binop( Iop_32HLto64, 19149 mkexpr( match_value[2] ), 19150 mkexpr( match_value[3] ) ) ) ); 19151 } 19152 break; 19153 19154 case 0x360: // xviexpsp (VSX Vector Insert Exponent Single-Precision) 19155 { 19156 Int i; 19157 IRTemp new_XT[5]; 19158 IRTemp A_value[4]; 19159 IRTemp B_value[4]; 19160 IRExpr *sign[4], *expr[4], *fract[4]; 19161 19162 DIP("xviexpsp v%d,v%d\n", XT, XB); 19163 new_XT[0] = newTemp(Ity_V128); 19164 assign( new_XT[0], binop( Iop_64HLtoV128, 19165 mkU64( 0x0 ), 19166 mkU64( 0x0 ) ) ); 19167 19168 for (i = 0; i < 4; i++) { 19169 A_value[i] = newTemp(Ity_I32); 19170 B_value[i] = newTemp(Ity_I32); 19171 19172 assign( A_value[i], 19173 unop( Iop_64to32, 19174 unop( Iop_V128to64, 19175 binop( Iop_AndV128, 19176 binop( Iop_ShrV128, 19177 mkexpr( vA ), 19178 mkU8( (3-i)*32 ) ), 19179 binop( Iop_64HLtoV128, 19180 mkU64( 0x0 ), 19181 mkU64( 0xFFFFFFFF ) ) ) ) ) ); 19182 assign( B_value[i], 19183 unop( Iop_64to32, 19184 unop( Iop_V128to64, 19185 binop( Iop_AndV128, 19186 binop( Iop_ShrV128, 19187 mkexpr( vB ), 19188 mkU8( (3-i)*32 ) ), 19189 binop( Iop_64HLtoV128, 19190 mkU64( 0x0 ), 19191 mkU64( 0xFFFFFFFF ) ) ) ) ) ); 19192 19193 sign[i] = binop( Iop_And32, mkexpr( A_value[i] ), 19194 mkU32( 0x80000000 ) ); 19195 expr[i] = binop( Iop_Shl32, 19196 binop( Iop_And32, mkexpr( B_value[i] ), 19197 mkU32( 0xFF ) ), 19198 mkU8( 23 ) ); 19199 fract[i] = binop( Iop_And32, mkexpr( A_value[i] ), 19200 mkU32( 0x007FFFFF ) ); 19201 19202 new_XT[i+1] = newTemp(Ity_V128); 19203 assign( new_XT[i+1], 19204 binop( Iop_OrV128, 19205 binop( Iop_ShlV128, 19206 binop( Iop_64HLtoV128, 19207 mkU64( 0 ), 19208 binop( Iop_32HLto64, 19209 mkU32( 0 ), 19210 binop( Iop_Or32, 19211 binop( Iop_Or32, 19212 sign[i], 19213 expr[i] ), 19214 fract[i] ) ) ), 19215 mkU8( (3-i)*32 ) ), 19216 mkexpr( new_XT[i] ) ) ); 19217 } 19218 putVSReg( XT, mkexpr( new_XT[4] ) ); 19219 } 19220 break; 19221 19222 case 0x396: // xsiexpdp (VSX Scalar Insert Exponent Double-Precision) 19223 { 19224 IRExpr *sign, *expr, *fract; 19225 UChar rA_addr = ifieldRegA(theInstr); 19226 UChar rB_addr = ifieldRegB(theInstr); 19227 IRTemp rA = newTemp( Ity_I64 ); 19228 IRTemp rB = newTemp( Ity_I64 ); 19229 19230 DIP("xsiexpdp v%d,%d,%d\n", (UInt)XT, (UInt)rA_addr, (UInt)rB_addr); 19231 assign( rA, getIReg(rA_addr)); 19232 assign( rB, getIReg(rB_addr)); 19233 19234 sign = binop( Iop_And64, mkexpr( rA ), mkU64( 0x8000000000000000 ) ); 19235 expr = binop( Iop_Shl64, 19236 binop( Iop_And64, mkexpr( rB ), mkU64( 0x7FF ) ), 19237 mkU8( 52 ) ); 19238 fract = binop( Iop_And64, mkexpr( rA ), mkU64( 0x000FFFFFFFFFFFFF ) ); 19239 19240 putVSReg( XT, binop( Iop_64HLtoV128, 19241 binop( Iop_Or64, 19242 binop( Iop_Or64, sign, expr ), 19243 fract ), 19244 mkU64( 0 ) ) ); 19245 } 19246 break; 19247 19248 case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision) 19249 // xvxsigdp (VSX Vector Extract Significand Double-Precision) 19250 // xxbrh 19251 // xvxexpsp (VSX Vector Extract Exponent Single-Precision) 19252 // xvxsigsp (VSX Vector Extract Significand Single-Precision) 19253 // xxbrw 19254 // xxbrd 19255 // xxbrq 19256 // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format) 19257 // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format) 19258 { 19259 UInt inst_select = IFIELD( theInstr, 16, 5); 19260 19261 if (inst_select == 0) { 19262 DIP("xvxexpdp v%d,v%d\n", XT, XB); 19263 19264 putVSReg( XT, binop( Iop_ShrV128, 19265 binop( Iop_AndV128, 19266 mkexpr( vB ), 19267 binop( Iop_64HLtoV128, 19268 mkU64( 0x7FF0000000000000 ), 19269 mkU64( 0x7FF0000000000000 ) ) ), 19270 mkU8( 52 ) ) ); 19271 19272 } else if (inst_select == 1) { 19273 Int i; 19274 IRExpr *normal[2]; 19275 IRTemp value[2]; 19276 IRTemp new_XT[3]; 19277 19278 DIP("xvxsigdp v%d,v%d\n", XT, XB); 19279 new_XT[0] = newTemp(Ity_V128); 19280 assign( new_XT[0], binop( Iop_64HLtoV128, 19281 mkU64( 0x0 ), 19282 mkU64( 0x0 ) ) ); 19283 19284 for (i = 0; i < 2; i++) { 19285 value[i] = newTemp(Ity_I64); 19286 assign( value[i], 19287 unop( Iop_V128to64, 19288 binop( Iop_AndV128, 19289 binop( Iop_ShrV128, 19290 mkexpr( vB ), 19291 mkU8( (1-i)*64 ) ), 19292 binop( Iop_64HLtoV128, 19293 mkU64( 0x0 ), 19294 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) ); 19295 19296 /* Value is normal if it isn't infinite, zero or denormalized */ 19297 normal[i] = mkNOT1( mkOR1( 19298 mkOR1( is_NaN( Ity_I64, value[i] ), 19299 is_Inf( Ity_I64, value[i] ) ), 19300 mkOR1( is_Zero( Ity_I64, value[i] ), 19301 is_Denorm( Ity_I64, 19302 value[i] ) ) ) ); 19303 new_XT[i+1] = newTemp(Ity_V128); 19304 19305 assign( new_XT[i+1], 19306 binop( Iop_OrV128, 19307 binop( Iop_ShlV128, 19308 binop( Iop_64HLtoV128, 19309 mkU64( 0x0 ), 19310 binop( Iop_Or64, 19311 binop( Iop_And64, 19312 mkexpr( value[i] ), 19313 mkU64( 0xFFFFFFFFFFFFF ) ), 19314 binop( Iop_Shl64, 19315 unop( Iop_1Uto64, 19316 normal[i]), 19317 mkU8( 52 ) ) ) ), 19318 mkU8( (1-i)*64 ) ), 19319 mkexpr( new_XT[i] ) ) ); 19320 } 19321 putVSReg( XT, mkexpr( new_XT[2] ) ); 19322 19323 } else if (inst_select == 7) { 19324 IRTemp sub_element0 = newTemp( Ity_V128 ); 19325 IRTemp sub_element1 = newTemp( Ity_V128 ); 19326 19327 DIP("xxbrh v%d, v%d\n", (UInt)XT, (UInt)XB); 19328 19329 assign( sub_element0, 19330 binop( Iop_ShrV128, 19331 binop( Iop_AndV128, 19332 binop(Iop_64HLtoV128, 19333 mkU64( 0xFF00FF00FF00FF00 ), 19334 mkU64( 0xFF00FF00FF00FF00 ) ), 19335 mkexpr( vB ) ), 19336 mkU8( 8 ) ) ); 19337 assign( sub_element1, 19338 binop( Iop_ShlV128, 19339 binop( Iop_AndV128, 19340 binop(Iop_64HLtoV128, 19341 mkU64( 0x00FF00FF00FF00FF ), 19342 mkU64( 0x00FF00FF00FF00FF ) ), 19343 mkexpr( vB ) ), 19344 mkU8( 8 ) ) ); 19345 19346 putVSReg(XT, binop( Iop_OrV128, 19347 mkexpr( sub_element1 ), 19348 mkexpr( sub_element0 ) ) ); 19349 19350 } else if (inst_select == 8) { 19351 DIP("xvxexpsp v%d,v%d\n", XT, XB); 19352 19353 putVSReg( XT, binop( Iop_ShrV128, 19354 binop( Iop_AndV128, 19355 mkexpr( vB ), 19356 binop( Iop_64HLtoV128, 19357 mkU64( 0x7F8000007F800000 ), 19358 mkU64( 0x7F8000007F800000 ) ) ), 19359 mkU8( 23 ) ) ); 19360 } else if (inst_select == 9) { 19361 Int i; 19362 IRExpr *normal[4]; 19363 IRTemp value[4]; 19364 IRTemp new_value[4]; 19365 IRTemp new_XT[5]; 19366 19367 DIP("xvxsigsp v%d,v%d\n", XT, XB); 19368 new_XT[0] = newTemp(Ity_V128); 19369 assign( new_XT[0], binop( Iop_64HLtoV128, 19370 mkU64( 0x0 ), 19371 mkU64( 0x0 ) ) ); 19372 19373 for (i = 0; i < 4; i++) { 19374 value[i] = newTemp(Ity_I32); 19375 assign( value[i], 19376 unop( Iop_64to32, 19377 unop( Iop_V128to64, 19378 binop( Iop_AndV128, 19379 binop( Iop_ShrV128, 19380 mkexpr( vB ), 19381 mkU8( (3-i)*32 ) ), 19382 binop( Iop_64HLtoV128, 19383 mkU64( 0x0 ), 19384 mkU64( 0xFFFFFFFF ) ) ) ) ) ); 19385 19386 new_XT[i+1] = newTemp(Ity_V128); 19387 19388 /* Value is normal if it isn't infinite, zero or denormalized */ 19389 normal[i] = mkNOT1( mkOR1( 19390 mkOR1( is_NaN( Ity_I32, value[i] ), 19391 is_Inf( Ity_I32, value[i] ) ), 19392 mkOR1( is_Zero( Ity_I32, value[i] ), 19393 is_Denorm( Ity_I32, 19394 value[i] ) ) ) ); 19395 new_value[i] = newTemp(Ity_I32); 19396 assign( new_value[i], 19397 binop( Iop_Or32, 19398 binop( Iop_And32, 19399 mkexpr( value[i] ), 19400 mkU32( 0x7FFFFF ) ), 19401 binop( Iop_Shl32, 19402 unop( Iop_1Uto32, 19403 normal[i]), 19404 mkU8( 23 ) ) ) ); 19405 19406 assign( new_XT[i+1], 19407 binop( Iop_OrV128, 19408 binop( Iop_ShlV128, 19409 binop( Iop_64HLtoV128, 19410 mkU64( 0x0 ), 19411 binop( Iop_32HLto64, 19412 mkU32( 0x0 ), 19413 mkexpr( new_value[i] ) ) ), 19414 mkU8( (3-i)*32 ) ), 19415 mkexpr( new_XT[i] ) ) ); 19416 } 19417 putVSReg( XT, mkexpr( new_XT[4] ) ); 19418 19419 } else if (inst_select == 15) { 19420 IRTemp sub_element0 = newTemp( Ity_V128 ); 19421 IRTemp sub_element1 = newTemp( Ity_V128 ); 19422 IRTemp sub_element2 = newTemp( Ity_V128 ); 19423 IRTemp sub_element3 = newTemp( Ity_V128 ); 19424 19425 DIP("xxbrw v%d, v%d\n", (UInt)XT, (UInt)XB); 19426 19427 assign( sub_element0, 19428 binop( Iop_ShrV128, 19429 binop( Iop_AndV128, 19430 binop(Iop_64HLtoV128, 19431 mkU64( 0xFF000000FF000000 ), 19432 mkU64( 0xFF000000FF000000 ) ), 19433 mkexpr( vB ) ), 19434 mkU8( 24 ) ) ); 19435 assign( sub_element1, 19436 binop( Iop_ShrV128, 19437 binop( Iop_AndV128, 19438 binop(Iop_64HLtoV128, 19439 mkU64( 0x00FF000000FF0000 ), 19440 mkU64( 0x00FF000000FF0000 ) ), 19441 mkexpr( vB ) ), 19442 mkU8( 8 ) ) ); 19443 assign( sub_element2, 19444 binop( Iop_ShlV128, 19445 binop( Iop_AndV128, 19446 binop(Iop_64HLtoV128, 19447 mkU64( 0x0000FF000000FF00 ), 19448 mkU64( 0x0000FF000000FF00 ) ), 19449 mkexpr( vB ) ), 19450 mkU8( 8 ) ) ); 19451 assign( sub_element3, 19452 binop( Iop_ShlV128, 19453 binop( Iop_AndV128, 19454 binop(Iop_64HLtoV128, 19455 mkU64( 0x00000000FF000000FF ), 19456 mkU64( 0x00000000FF000000FF ) ), 19457 mkexpr( vB ) ), 19458 mkU8( 24 ) ) ); 19459 19460 putVSReg( XT, 19461 binop( Iop_OrV128, 19462 binop( Iop_OrV128, 19463 mkexpr( sub_element3 ), 19464 mkexpr( sub_element2 ) ), 19465 binop( Iop_OrV128, 19466 mkexpr( sub_element1 ), 19467 mkexpr( sub_element0 ) ) ) ); 19468 19469 } else if (inst_select == 23) { 19470 DIP("xxbrd v%d, v%d\n", (UInt)XT, (UInt)XB); 19471 19472 int i; 19473 int shift = 56; 19474 IRTemp sub_element[16]; 19475 IRTemp new_xT[17]; 19476 19477 new_xT[0] = newTemp( Ity_V128 ); 19478 assign( new_xT[0], binop( Iop_64HLtoV128, 19479 mkU64( 0 ), 19480 mkU64( 0 ) ) ); 19481 19482 for ( i = 0; i < 4; i++ ) { 19483 new_xT[i+1] = newTemp( Ity_V128 ); 19484 sub_element[i] = newTemp( Ity_V128 ); 19485 sub_element[i+4] = newTemp( Ity_V128 ); 19486 19487 assign( sub_element[i], 19488 binop( Iop_ShrV128, 19489 binop( Iop_AndV128, 19490 binop( Iop_64HLtoV128, 19491 mkU64( (0xFFULL << (7 - i) * 8) ), 19492 mkU64( (0xFFULL << (7 - i) * 8) ) ), 19493 mkexpr( vB ) ), 19494 mkU8( shift ) ) ); 19495 19496 assign( sub_element[i+4], 19497 binop( Iop_ShlV128, 19498 binop( Iop_AndV128, 19499 binop( Iop_64HLtoV128, 19500 mkU64( (0xFFULL << i*8) ), 19501 mkU64( (0xFFULL << i*8) ) ), 19502 mkexpr( vB ) ), 19503 mkU8( shift ) ) ); 19504 shift = shift - 16; 19505 19506 assign( new_xT[i+1], 19507 binop( Iop_OrV128, 19508 mkexpr( new_xT[i] ), 19509 binop( Iop_OrV128, 19510 mkexpr ( sub_element[i] ), 19511 mkexpr ( sub_element[i+4] ) ) ) ); 19512 } 19513 19514 putVSReg( XT, mkexpr( new_xT[4] ) ); 19515 19516 } else if (inst_select == 24) { 19517 // xvcvhpsp, (VSX Vector Convert half-precision format to 19518 // Single-precision format) 19519 /* only supported on ISA 3.0 and newer */ 19520 IRTemp result = newTemp( Ity_V128 ); 19521 IRTemp src = newTemp( Ity_I64 ); 19522 19523 if (!allow_isa_3_0) return False; 19524 19525 DIP("xvcvhpsp v%d,v%d\n", XT,XB); 19526 /* The instruction does not set the C or FPCC fields. The 19527 * instruction takes four 16-bit values stored in a 128-bit value 19528 * as follows: x V | x V | x V | x V where V is a 16-bit 19529 * value and x is an unused 16-bit value. To use Iop_F16toF32x4 19530 * the four 16-bit values will be gathered into a single 64 bit 19531 * value. The backend will scatter the four 16-bit values back 19532 * into a 128-bit operand before issuing the instruction. 19533 */ 19534 /* Gather 16-bit float values from V128 source into new 64-bit 19535 * source value for the Iop. 19536 */ 19537 assign( src, 19538 unop( Iop_V128to64, 19539 binop( Iop_Perm8x16, 19540 mkexpr( vB ), 19541 binop ( Iop_64HLtoV128, 19542 mkU64( 0 ), 19543 mkU64( 0x020306070A0B0E0F) ) ) ) ); 19544 19545 assign( result, unop( Iop_F16toF32x4, mkexpr( src ) ) ); 19546 19547 putVSReg( XT, mkexpr( result ) ); 19548 19549 } else if (inst_select == 25) { 19550 // xvcvsphp, (VSX Vector round and Convert single-precision 19551 // format to half-precision format) 19552 /* only supported on ISA 3.0 and newer */ 19553 IRTemp result = newTemp( Ity_V128 ); 19554 IRTemp tmp64 = newTemp( Ity_I64 ); 19555 19556 if (!allow_isa_3_0) return False; 19557 DIP("xvcvsphp v%d,v%d\n", XT,XB); 19558 19559 /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the 19560 * I64 result to the V128 register to store. 19561 */ 19562 assign( tmp64, unop( Iop_F32toF16x4, mkexpr( vB ) ) ); 19563 19564 /* Scatter 16-bit float values from returned 64-bit value 19565 * of V128 result. 19566 */ 19567 if (host_endness == VexEndnessLE) 19568 /* Note location 0 may have a valid number in it. Location 19569 * 15 should always be zero. Use 0xF to put zeros in the 19570 * desired bytes. 19571 */ 19572 assign( result, 19573 binop( Iop_Perm8x16, 19574 binop( Iop_64HLtoV128, 19575 mkexpr( tmp64 ), 19576 mkU64( 0 ) ), 19577 binop ( Iop_64HLtoV128, 19578 mkU64( 0x0F0F00010F0F0203 ), 19579 mkU64( 0x0F0F04050F0F0607 ) ) ) ); 19580 else 19581 assign( result, 19582 binop( Iop_Perm8x16, 19583 binop( Iop_64HLtoV128, 19584 mkexpr( tmp64 ), 19585 mkU64( 0 ) ), 19586 binop ( Iop_64HLtoV128, 19587 mkU64( 0x0F0F06070F0F0405 ), 19588 mkU64( 0x0F0F02030F0F0001 ) ) ) ); 19589 putVSReg( XT, mkexpr( result ) ); 19590 19591 } else if ( inst_select == 31 ) { 19592 int i; 19593 int shift_left = 8; 19594 int shift_right = 120; 19595 IRTemp sub_element[16]; 19596 IRTemp new_xT[9]; 19597 19598 DIP("xxbrq v%d, v%d\n", (UInt) XT, (UInt) XB); 19599 19600 new_xT[0] = newTemp( Ity_V128 ); 19601 assign( new_xT[0], binop( Iop_64HLtoV128, 19602 mkU64( 0 ), 19603 mkU64( 0 ) ) ); 19604 19605 for ( i = 0; i < 8; i++ ) { 19606 new_xT[i+1] = newTemp( Ity_V128 ); 19607 sub_element[i] = newTemp( Ity_V128 ); 19608 sub_element[i+8] = newTemp( Ity_V128 ); 19609 19610 assign( sub_element[i], 19611 binop( Iop_ShrV128, 19612 binop( Iop_AndV128, 19613 binop( Iop_64HLtoV128, 19614 mkU64( ( 0xFFULL << (7 - i) * 8 ) ), 19615 mkU64( 0x0ULL ) ), 19616 mkexpr( vB ) ), 19617 mkU8( shift_right ) ) ); 19618 shift_right = shift_right - 16; 19619 19620 assign( sub_element[i+8], 19621 binop( Iop_ShlV128, 19622 binop( Iop_AndV128, 19623 binop( Iop_64HLtoV128, 19624 mkU64( 0x0ULL ), 19625 mkU64( ( 0xFFULL << (7 - i) * 8 ) ) ), 19626 mkexpr( vB ) ), 19627 mkU8( shift_left ) ) ); 19628 shift_left = shift_left + 16; 19629 19630 assign( new_xT[i+1], 19631 binop( Iop_OrV128, 19632 mkexpr( new_xT[i] ), 19633 binop( Iop_OrV128, 19634 mkexpr ( sub_element[i] ), 19635 mkexpr ( sub_element[i+8] ) ) ) ); 19636 } 19637 19638 putVSReg( XT, mkexpr( new_xT[8] ) ); 19639 19640 } else { 19641 vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n"); 19642 return False; 19643 } 19644 break; 19645 } 19646 19647 case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision) 19648 { 19649 UInt DX_mask = IFIELD( theInstr, 16, 5 ); 19650 UInt DC_mask = IFIELD( theInstr, 6, 1 ); 19651 UInt DM_mask = IFIELD( theInstr, 2, 1 ); 19652 UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask; 19653 19654 IRTemp NaN[2], inf[2], zero[2], dnorm[2], pos[2], DCM[2]; 19655 IRTemp match_value[2]; 19656 IRTemp value[2]; 19657 Int i; 19658 19659 DIP("xvtstdcdp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask); 19660 19661 for (i = 0; i < 2; i++) { 19662 NaN[i] = newTemp(Ity_I64); 19663 inf[i] = newTemp(Ity_I64); 19664 pos[i] = newTemp(Ity_I64); 19665 DCM[i] = newTemp(Ity_I64); 19666 zero[i] = newTemp(Ity_I64); 19667 dnorm[i] = newTemp(Ity_I64); 19668 19669 value[i] = newTemp(Ity_I64); 19670 match_value[i] = newTemp(Ity_I64); 19671 19672 assign( value[i], 19673 unop( Iop_V128to64, 19674 binop( Iop_AndV128, 19675 binop( Iop_ShrV128, 19676 mkexpr( vB ), 19677 mkU8( (1-i)*64 ) ), 19678 binop( Iop_64HLtoV128, 19679 mkU64( 0x0 ), 19680 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) ); 19681 19682 assign( pos[i], unop( Iop_1Uto64, 19683 binop( Iop_CmpEQ64, 19684 binop( Iop_Shr64, 19685 mkexpr( value[i] ), 19686 mkU8( 63 ) ), 19687 mkU64( 0 ) ) ) ); 19688 19689 assign( NaN[i], unop( Iop_1Uto64, is_NaN( Ity_I64, value[i] ) ) ); 19690 assign( inf[i], unop( Iop_1Uto64, is_Inf( Ity_I64, value[i] ) ) ); 19691 assign( zero[i], unop( Iop_1Uto64, is_Zero( Ity_I64, value[i] ) ) ); 19692 assign( dnorm[i], unop( Iop_1Uto64, is_Denorm( Ity_I64, 19693 value[i] ) ) ); 19694 19695 assign( DCM[i], create_DCM( Ity_I64, NaN[i], inf[i], zero[i], 19696 dnorm[i], pos[i] ) ); 19697 19698 assign( match_value[i], 19699 unop( Iop_1Sto64, 19700 binop( Iop_CmpNE64, 19701 binop( Iop_And64, 19702 mkU64( DCMX_mask ), 19703 mkexpr( DCM[i] ) ), 19704 mkU64( 0 ) ) ) ); 19705 } 19706 putVSReg( XT, binop( Iop_64HLtoV128, 19707 mkexpr( match_value[0] ), 19708 mkexpr( match_value[1] ) ) ); 19709 } 19710 break; 19711 19712 case 0x3E0: // xviexpdp (VSX Vector Insert Exponent Double-Precision) 19713 { 19714 Int i; 19715 IRTemp new_XT[3]; 19716 IRTemp A_value[2]; 19717 IRTemp B_value[2]; 19718 IRExpr *sign[2], *expr[2], *fract[2]; 19719 19720 DIP("xviexpdp v%d,v%d\n", XT, XB); 19721 new_XT[0] = newTemp(Ity_V128); 19722 assign( new_XT[0], binop( Iop_64HLtoV128, 19723 mkU64( 0x0 ), 19724 mkU64( 0x0 ) ) ); 19725 19726 for (i = 0; i < 2; i++) { 19727 A_value[i] = newTemp(Ity_I64); 19728 B_value[i] = newTemp(Ity_I64); 19729 19730 assign( A_value[i], 19731 unop( Iop_V128to64, 19732 binop( Iop_AndV128, 19733 binop( Iop_ShrV128, 19734 mkexpr( vA ), 19735 mkU8( (1-i)*64 ) ), 19736 binop( Iop_64HLtoV128, 19737 mkU64( 0x0 ), 19738 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) ); 19739 assign( B_value[i], 19740 unop( Iop_V128to64, 19741 binop( Iop_AndV128, 19742 binop( Iop_ShrV128, 19743 mkexpr( vB ), 19744 mkU8( (1-i)*64 ) ), 19745 binop( Iop_64HLtoV128, 19746 mkU64( 0x0 ), 19747 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) ); 19748 19749 sign[i] = binop( Iop_And64, mkexpr( A_value[i] ), 19750 mkU64( 0x8000000000000000 ) ); 19751 expr[i] = binop( Iop_Shl64, 19752 binop( Iop_And64, mkexpr( B_value[i] ), 19753 mkU64( 0x7FF ) ), 19754 mkU8( 52 ) ); 19755 fract[i] = binop( Iop_And64, mkexpr( A_value[i] ), 19756 mkU64( 0x000FFFFFFFFFFFFF ) ); 19757 19758 new_XT[i+1] = newTemp(Ity_V128); 19759 assign( new_XT[i+1], 19760 binop( Iop_OrV128, 19761 binop( Iop_ShlV128, 19762 binop( Iop_64HLtoV128, 19763 mkU64( 0 ), 19764 binop( Iop_Or64, 19765 binop( Iop_Or64, 19766 sign[i], 19767 expr[i] ), 19768 fract[i] ) ), 19769 mkU8( (1-i)*64 ) ), 19770 mkexpr( new_XT[i] ) ) ); 19771 } 19772 putVSReg( XT, mkexpr( new_XT[2] ) ); 19773 } 19774 break; 19775 19776 default: 19777 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 19778 return False; 19779 } 19780 return True; 19781 } 19782 19783 /* 19784 * VSX Logical Instructions 19785 */ 19786 static Bool 19787 dis_vx_logic ( UInt theInstr, UInt opc2 ) 19788 { 19789 /* XX3-Form */ 19790 UChar opc1 = ifieldOPC( theInstr ); 19791 UChar XT = ifieldRegXT ( theInstr ); 19792 UChar XA = ifieldRegXA ( theInstr ); 19793 UChar XB = ifieldRegXB ( theInstr ); 19794 IRTemp vA = newTemp( Ity_V128 ); 19795 IRTemp vB = newTemp( Ity_V128 ); 19796 19797 if (opc1 != 0x3C) { 19798 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 19799 return False; 19800 } 19801 19802 assign( vA, getVSReg( XA ) ); 19803 assign( vB, getVSReg( XB ) ); 19804 19805 switch (opc2) { 19806 case 0x268: // xxlxor 19807 DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB); 19808 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 19809 break; 19810 case 0x248: // xxlor 19811 DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB); 19812 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 19813 break; 19814 case 0x288: // xxlnor 19815 DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB); 19816 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 19817 mkexpr( vB ) ) ) ); 19818 break; 19819 case 0x208: // xxland 19820 DIP("xxland v%d,v%d,v%d\n", XT, XA, XB); 19821 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 19822 break; 19823 case 0x228: //xxlandc 19824 DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB); 19825 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 19826 mkexpr( vB ) ) ) ); 19827 break; 19828 case 0x2A8: // xxlorc (VSX Logical OR with complement) 19829 DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB); 19830 putVSReg( XT, binop( Iop_OrV128, 19831 mkexpr( vA ), 19832 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 19833 break; 19834 case 0x2C8: // xxlnand (VSX Logical NAND) 19835 DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB); 19836 putVSReg( XT, unop( Iop_NotV128, 19837 binop( Iop_AndV128, mkexpr( vA ), 19838 mkexpr( vB ) ) ) ); 19839 break; 19840 case 0x2E8: // xxleqv (VSX Logical Equivalence) 19841 DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB); 19842 putVSReg( XT, unop( Iop_NotV128, 19843 binop( Iop_XorV128, 19844 mkexpr( vA ), mkexpr( vB ) ) ) ); 19845 break; 19846 default: 19847 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 19848 return False; 19849 } 19850 return True; 19851 } 19852 19853 /* 19854 * VSX Load Instructions 19855 * NOTE: VSX supports word-aligned storage access. 19856 */ 19857 static Bool 19858 dis_vx_load ( UInt theInstr ) 19859 { 19860 /* XX1-Form */ 19861 UChar opc1 = ifieldOPC( theInstr ); 19862 UChar XT = ifieldRegXT ( theInstr ); 19863 UChar rA_addr = ifieldRegA( theInstr ); 19864 UChar rB_addr = ifieldRegB( theInstr ); 19865 UInt opc2 = ifieldOPClo10( theInstr ); 19866 19867 IRType ty = mode64 ? Ity_I64 : Ity_I32; 19868 IRTemp EA = newTemp( ty ); 19869 19870 if (opc1 != 0x1F) { 19871 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 19872 return False; 19873 } 19874 19875 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 19876 19877 switch (opc2) { 19878 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) 19879 { 19880 IRExpr * exp; 19881 DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 19882 19883 if (host_endness == VexEndnessLE) 19884 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 19885 else 19886 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 19887 19888 putVSReg( XT, binop( Iop_64HLtoV128, 19889 unop( Iop_32Uto64, exp), 19890 mkU64(0) ) ); 19891 break; 19892 } 19893 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) 19894 { 19895 IRExpr * exp; 19896 DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr); 19897 19898 if (host_endness == VexEndnessLE) 19899 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 19900 else 19901 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 19902 19903 putVSReg( XT, binop( Iop_64HLtoV128, 19904 unop( Iop_32Sto64, exp), 19905 mkU64(0) ) ); 19906 break; 19907 } 19908 case 0x10C: // lxvx 19909 { 19910 UInt ea_off = 0; 19911 IRExpr* irx_addr; 19912 IRTemp word[4]; 19913 int i; 19914 19915 DIP("lxvx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 19916 19917 if ( host_endness == VexEndnessBE ) { 19918 for ( i = 3; i>= 0; i-- ) { 19919 word[i] = newTemp( Ity_I64 ); 19920 19921 irx_addr = 19922 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 19923 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 19924 19925 assign( word[i], unop( Iop_32Uto64, 19926 load( Ity_I32, irx_addr ) ) ); 19927 ea_off += 4; 19928 } 19929 19930 putVSReg( XT, binop( Iop_64HLtoV128, 19931 binop( Iop_Or64, 19932 mkexpr( word[2] ), 19933 binop( Iop_Shl64, 19934 mkexpr( word[3] ), 19935 mkU8( 32 ) ) ), 19936 binop( Iop_Or64, 19937 mkexpr( word[0] ), 19938 binop( Iop_Shl64, 19939 mkexpr( word[1] ), 19940 mkU8( 32 ) ) ) ) ); 19941 } else { 19942 for ( i = 0; i< 4; i++ ) { 19943 word[i] = newTemp( Ity_I64 ); 19944 19945 irx_addr = 19946 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 19947 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 19948 19949 assign( word[i], unop( Iop_32Uto64, 19950 load( Ity_I32, irx_addr ) ) ); 19951 ea_off += 4; 19952 } 19953 19954 putVSReg( XT, binop( Iop_64HLtoV128, 19955 binop( Iop_Or64, 19956 mkexpr( word[2] ), 19957 binop( Iop_Shl64, 19958 mkexpr( word[3] ), 19959 mkU8( 32 ) ) ), 19960 binop( Iop_Or64, 19961 mkexpr( word[0] ), 19962 binop( Iop_Shl64, 19963 mkexpr( word[1] ), 19964 mkU8( 32 ) ) ) ) ); 19965 } 19966 break; 19967 } 19968 19969 case 0x10D: // lxvl 19970 { 19971 DIP("lxvl %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 19972 19973 IRTemp byte[16]; 19974 UInt i; 19975 UInt ea_off = 0; 19976 IRExpr* irx_addr; 19977 IRTemp tmp_low[9]; 19978 IRTemp tmp_hi[9]; 19979 IRTemp shift = newTemp( Ity_I8 ); 19980 IRTemp nb_gt16 = newTemp( Ity_I8 ); 19981 IRTemp ld_result = newTemp( Ity_V128 ); 19982 IRTemp nb_not_zero = newTemp( Ity_I64 ); 19983 19984 IRTemp base_addr = newTemp( ty ); 19985 19986 tmp_low[0] = newTemp( Ity_I64 ); 19987 tmp_hi[0] = newTemp( Ity_I64 ); 19988 19989 assign( base_addr, ea_rAor0( rA_addr ) ); 19990 assign( tmp_low[0], mkU64( 0 ) ); 19991 assign( tmp_hi[0], mkU64( 0 ) ); 19992 19993 /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */ 19994 assign( nb_not_zero, unop( Iop_1Sto64, 19995 binop( Iop_CmpNE64, 19996 mkU64( 0 ), 19997 binop( Iop_Shr64, 19998 getIReg( rB_addr ), 19999 mkU8( 56 ) ) ) ) ); 20000 20001 assign( nb_gt16, unop( Iop_1Sto8, 20002 binop( Iop_CmpLT64U, 20003 binop( Iop_Shr64, 20004 getIReg( rB_addr ), 20005 mkU8( 60 ) ), 20006 mkU64( 1 ) ) ) ); 20007 20008 /* Set the shift to 0, by ANDing with nb_gt16. nb_gt16 will be all 20009 * zeros if nb > 16. This will result in quad word load being stored. 20010 */ 20011 assign( shift, 20012 binop( Iop_And8, 20013 unop( Iop_64to8, 20014 binop( Iop_Mul64, 20015 binop( Iop_Sub64, 20016 mkU64 ( 16 ), 20017 binop( Iop_Shr64, 20018 getIReg( rB_addr ), 20019 mkU8( 56 ) ) ), 20020 mkU64( 8 ) ) ), 20021 mkexpr( nb_gt16 ) ) ); 20022 20023 /* fetch all 16 bytes, we will remove what we don't want later */ 20024 if ( host_endness == VexEndnessBE ) { 20025 for ( i = 0; i < 8; i++ ) { 20026 byte[i] = newTemp( Ity_I64 ); 20027 tmp_hi[i+1] = newTemp( Ity_I64 ); 20028 20029 irx_addr = 20030 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20031 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20032 ea_off += 1; 20033 20034 assign( byte[i], binop( Iop_Shl64, 20035 unop( Iop_8Uto64, 20036 load( Ity_I8, irx_addr ) ), 20037 mkU8( 8 * ( 7 - i ) ) ) ); 20038 20039 assign( tmp_hi[i+1], binop( Iop_Or64, 20040 mkexpr( byte[i] ), 20041 mkexpr( tmp_hi[i] ) ) ); 20042 } 20043 20044 for ( i = 0; i < 8; i++ ) { 20045 byte[i+8] = newTemp( Ity_I64 ); 20046 tmp_low[i+1] = newTemp( Ity_I64 ); 20047 20048 irx_addr = 20049 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20050 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20051 ea_off += 1; 20052 20053 assign( byte[i+8], binop( Iop_Shl64, 20054 unop( Iop_8Uto64, 20055 load( Ity_I8, irx_addr ) ), 20056 mkU8( 8 * ( 7 - i ) ) ) ); 20057 20058 assign( tmp_low[i+1], binop( Iop_Or64, 20059 mkexpr( byte[i+8] ), 20060 mkexpr( tmp_low[i] ) ) ); 20061 } 20062 assign( ld_result, binop( Iop_ShlV128, 20063 binop( Iop_ShrV128, 20064 binop( Iop_64HLtoV128, 20065 mkexpr( tmp_hi[8] ), 20066 mkexpr( tmp_low[8] ) ), 20067 mkexpr( shift ) ), 20068 mkexpr( shift ) ) ); 20069 } else { 20070 for ( i = 0; i < 8; i++ ) { 20071 byte[i] = newTemp( Ity_I64 ); 20072 tmp_low[i+1] = newTemp( Ity_I64 ); 20073 20074 irx_addr = 20075 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20076 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20077 ea_off += 1; 20078 20079 assign( byte[i], binop( Iop_Shl64, 20080 unop( Iop_8Uto64, 20081 load( Ity_I8, irx_addr ) ), 20082 mkU8( 8 * i ) ) ); 20083 20084 assign( tmp_low[i+1], 20085 binop( Iop_Or64, 20086 mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) ); 20087 } 20088 20089 for ( i = 0; i < 8; i++ ) { 20090 byte[i + 8] = newTemp( Ity_I64 ); 20091 tmp_hi[i+1] = newTemp( Ity_I64 ); 20092 20093 irx_addr = 20094 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20095 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20096 ea_off += 1; 20097 20098 assign( byte[i+8], binop( Iop_Shl64, 20099 unop( Iop_8Uto64, 20100 load( Ity_I8, irx_addr ) ), 20101 mkU8( 8 * i ) ) ); 20102 20103 assign( tmp_hi[i+1], binop( Iop_Or64, 20104 mkexpr( byte[i+8] ), 20105 mkexpr( tmp_hi[i] ) ) ); 20106 } 20107 assign( ld_result, binop( Iop_ShrV128, 20108 binop( Iop_ShlV128, 20109 binop( Iop_64HLtoV128, 20110 mkexpr( tmp_hi[8] ), 20111 mkexpr( tmp_low[8] ) ), 20112 mkexpr( shift ) ), 20113 mkexpr( shift ) ) ); 20114 } 20115 20116 20117 /* If nb = 0, mask out the calculated load result so the stored 20118 * value is zero. 20119 */ 20120 20121 putVSReg( XT, binop( Iop_AndV128, 20122 mkexpr( ld_result ), 20123 binop( Iop_64HLtoV128, 20124 mkexpr( nb_not_zero ), 20125 mkexpr( nb_not_zero ) ) ) ); 20126 break; 20127 } 20128 20129 case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form) 20130 { 20131 IRTemp byte[16]; 20132 IRTemp tmp_low[9]; 20133 IRTemp tmp_hi[9]; 20134 IRTemp mask = newTemp(Ity_V128); 20135 IRTemp rB = newTemp( Ity_I64 ); 20136 IRTemp nb = newTemp( Ity_I64 ); 20137 IRTemp nb_zero = newTemp(Ity_V128); 20138 IRTemp mask_shift = newTemp(Ity_I64); 20139 Int i; 20140 UInt ea_off = 0; 20141 IRExpr* irx_addr; 20142 IRTemp base_addr = newTemp( ty ); 20143 IRTemp nb_compare_zero = newTemp( Ity_I64 ); 20144 20145 DIP("lxvll %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20146 20147 tmp_low[0] = newTemp(Ity_I64); 20148 tmp_hi[0] = newTemp(Ity_I64); 20149 20150 assign( rB, getIReg(rB_addr)); 20151 assign( base_addr, ea_rAor0( rA_addr ) ); 20152 assign( tmp_low[0], mkU64( 0 ) ); 20153 assign( tmp_hi[0], mkU64( 0 ) ); 20154 20155 /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */ 20156 assign( nb, binop( Iop_Shr64, mkexpr( rB ), mkU8( 56 ) ) ); 20157 20158 assign( nb_compare_zero, unop( Iop_1Sto64, 20159 binop( Iop_CmpEQ64, 20160 mkexpr( nb ), 20161 mkU64( 0 ) ) ) ); 20162 20163 /* nb_zero is 0xFF..FF if the nb_field = 0 */ 20164 assign( nb_zero, binop( Iop_64HLtoV128, 20165 mkexpr( nb_compare_zero ), 20166 mkexpr( nb_compare_zero ) ) ); 20167 20168 assign( mask_shift, binop( Iop_Sub64, 20169 mkU64( 16*8 ), 20170 binop( Iop_Mul64, 20171 mkexpr( nb ), 20172 mkU64( 8 ) ) ) ); 20173 20174 /* fetch all 16 bytes, we will remove what we don't want later */ 20175 for (i = 0; i < 8; i++) { 20176 byte[i] = newTemp(Ity_I64); 20177 tmp_hi[i+1] = newTemp(Ity_I64); 20178 20179 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20180 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20181 ea_off += 1; 20182 20183 /* Instruction always loads in Big Endian format */ 20184 assign( byte[i], binop( Iop_Shl64, 20185 unop( Iop_8Uto64, 20186 load( Ity_I8, irx_addr ) ), 20187 mkU8( 8 * (7 - i) ) ) ); 20188 assign( tmp_hi[i+1], 20189 binop( Iop_Or64, 20190 mkexpr( byte[i] ), mkexpr( tmp_hi[i] ) ) ); 20191 } 20192 20193 for (i = 0; i < 8; i++) { 20194 byte[i + 8] = newTemp(Ity_I64); 20195 tmp_low[i+1] = newTemp(Ity_I64); 20196 20197 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20198 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20199 ea_off += 1; 20200 20201 /* Instruction always loads in Big Endian format */ 20202 assign( byte[i+8], binop( Iop_Shl64, 20203 unop( Iop_8Uto64, 20204 load( Ity_I8, irx_addr ) ), 20205 mkU8( 8 * (7 - i) ) ) ); 20206 assign( tmp_low[i+1], binop( Iop_Or64, 20207 mkexpr( byte[i+8] ), 20208 mkexpr( tmp_low[i] ) ) ); 20209 } 20210 20211 /* Create mask to clear the right most 16 - nb bytes, set to zero 20212 * if nb= 0. 20213 */ 20214 assign( mask, binop( Iop_AndV128, 20215 binop( Iop_ShlV128, 20216 binop( Iop_ShrV128, 20217 mkV128( 0xFFFF ), 20218 unop( Iop_64to8, mkexpr( mask_shift ) ) ), 20219 unop( Iop_64to8, mkexpr( mask_shift ) ) ), 20220 unop( Iop_NotV128, mkexpr( nb_zero ) ) ) ); 20221 20222 putVSReg( XT, binop( Iop_AndV128, 20223 mkexpr( mask ), 20224 binop( Iop_64HLtoV128, 20225 mkexpr( tmp_hi[8] ), 20226 mkexpr( tmp_low[8] ) ) ) ); 20227 break; 20228 } 20229 20230 case 0x16C: // lxvwsx 20231 { 20232 IRTemp data = newTemp( Ity_I64 ); 20233 20234 DIP("lxvwsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20235 20236 /* The load is a 64-bit fetch that is Endian aware, just want 20237 * the lower 32 bits. */ 20238 if ( host_endness == VexEndnessBE ) { 20239 UInt ea_off = 4; 20240 IRExpr* irx_addr; 20241 20242 irx_addr = 20243 binop( mkSzOp( ty, Iop_Sub8 ), mkexpr( EA ), 20244 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20245 20246 assign( data, binop( Iop_And64, 20247 load( Ity_I64, irx_addr ), 20248 mkU64( 0xFFFFFFFF ) ) ); 20249 20250 } else { 20251 assign( data, binop( Iop_And64, 20252 load( Ity_I64, mkexpr( EA ) ), 20253 mkU64( 0xFFFFFFFF ) ) ); 20254 } 20255 20256 /* Take lower 32-bits and spat across the four word positions */ 20257 putVSReg( XT, 20258 binop( Iop_64HLtoV128, 20259 binop( Iop_Or64, 20260 mkexpr( data ), 20261 binop( Iop_Shl64, 20262 mkexpr( data ), 20263 mkU8( 32 ) ) ), 20264 binop( Iop_Or64, 20265 mkexpr( data ), 20266 binop( Iop_Shl64, 20267 mkexpr( data ), 20268 mkU8( 32 ) ) ) ) ); 20269 break; 20270 } 20271 20272 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed) 20273 { 20274 IRExpr * exp; 20275 DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 20276 /* Take 32-bit floating point value in the upper half of the fetched 20277 * 64-bit value, convert to 64-bit floating point value and load into 20278 * top word of V128. 20279 */ 20280 exp = unop( Iop_ReinterpF64asI64, 20281 unop( Iop_F32toF64, 20282 unop( Iop_ReinterpI32asF32, 20283 load( Ity_I32, mkexpr( EA ) ) ) ) ); 20284 20285 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); 20286 break; 20287 } 20288 case 0x24C: // lxsdx 20289 { 20290 IRExpr * exp; 20291 DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 20292 exp = load( Ity_I64, mkexpr( EA ) ); 20293 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 20294 // we just performed is only a DW. But since the contents of VSR[XT] element 1 20295 // are undefined after this operation, we can just do a splat op. 20296 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 20297 break; 20298 } 20299 20300 case 0x30D: // lxsibzx 20301 { 20302 IRExpr *byte; 20303 IRExpr* irx_addr; 20304 20305 DIP("lxsibzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20306 20307 if ( host_endness == VexEndnessBE ) 20308 irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 7 ) ); 20309 20310 else 20311 irx_addr = mkexpr( EA ); 20312 20313 byte = load( Ity_I64, irx_addr ); 20314 putVSReg( XT, binop( Iop_64HLtoV128, 20315 binop( Iop_And64, 20316 byte, 20317 mkU64( 0xFF ) ), 20318 mkU64( 0 ) ) ); 20319 break; 20320 } 20321 20322 case 0x32D: // lxsihzx 20323 { 20324 IRExpr *byte; 20325 IRExpr* irx_addr; 20326 20327 DIP("lxsihzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20328 20329 if ( host_endness == VexEndnessBE ) 20330 irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 6 ) ); 20331 20332 else 20333 irx_addr = mkexpr( EA ); 20334 20335 byte = load( Ity_I64, irx_addr ); 20336 putVSReg( XT, binop( Iop_64HLtoV128, 20337 binop( Iop_And64, 20338 byte, 20339 mkU64( 0xFFFF ) ), 20340 mkU64( 0 ) ) ); 20341 break; 20342 } 20343 case 0x34C: // lxvd2x 20344 { 20345 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 20346 IRExpr * high, *low; 20347 ULong ea_off = 8; 20348 IRExpr* high_addr; 20349 DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr); 20350 high = load( Ity_I64, mkexpr( EA ) ); 20351 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 20352 : mkU32( ea_off ) ); 20353 low = load( Ity_I64, high_addr ); 20354 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 20355 break; 20356 } 20357 case 0x14C: // lxvdsx 20358 { 20359 IRTemp data = newTemp(Ity_I64); 20360 DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr); 20361 assign( data, load( Ity_I64, mkexpr( EA ) ) ); 20362 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 20363 break; 20364 } 20365 case 0x30C: 20366 { 20367 IRExpr *t0; 20368 20369 DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr); 20370 20371 /* The load will result in the data being in BE order. */ 20372 if (host_endness == VexEndnessLE) { 20373 IRExpr *t0_BE; 20374 IRTemp perm_LE = newTemp(Ity_V128); 20375 20376 t0_BE = load( Ity_V128, mkexpr( EA ) ); 20377 20378 /* Permute the data to LE format */ 20379 assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL), 20380 mkU64(0x0405060700010203ULL))); 20381 20382 t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) ); 20383 } else { 20384 t0 = load( Ity_V128, mkexpr( EA ) ); 20385 } 20386 20387 putVSReg( XT, t0 ); 20388 break; 20389 } 20390 20391 case 0x32C: // lxvh8x 20392 { 20393 DIP("lxvh8x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20394 20395 IRTemp h_word[8]; 20396 int i; 20397 UInt ea_off = 0; 20398 IRExpr* irx_addr; 20399 IRTemp tmp_low[5]; 20400 IRTemp tmp_hi[5]; 20401 20402 tmp_low[0] = newTemp( Ity_I64 ); 20403 tmp_hi[0] = newTemp( Ity_I64 ); 20404 assign( tmp_low[0], mkU64( 0 ) ); 20405 assign( tmp_hi[0], mkU64( 0 ) ); 20406 20407 for ( i = 0; i < 4; i++ ) { 20408 h_word[i] = newTemp(Ity_I64); 20409 tmp_low[i+1] = newTemp(Ity_I64); 20410 20411 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20412 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20413 ea_off += 2; 20414 20415 assign( h_word[i], binop( Iop_Shl64, 20416 unop( Iop_16Uto64, 20417 load( Ity_I16, irx_addr ) ), 20418 mkU8( 16 * ( 3 - i ) ) ) ); 20419 20420 assign( tmp_low[i+1], 20421 binop( Iop_Or64, 20422 mkexpr( h_word[i] ), mkexpr( tmp_low[i] ) ) ); 20423 } 20424 20425 for ( i = 0; i < 4; i++ ) { 20426 h_word[i+4] = newTemp( Ity_I64 ); 20427 tmp_hi[i+1] = newTemp( Ity_I64 ); 20428 20429 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20430 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20431 ea_off += 2; 20432 20433 assign( h_word[i+4], binop( Iop_Shl64, 20434 unop( Iop_16Uto64, 20435 load( Ity_I16, irx_addr ) ), 20436 mkU8( 16 * ( 3 - i ) ) ) ); 20437 20438 assign( tmp_hi[i+1], binop( Iop_Or64, 20439 mkexpr( h_word[i+4] ), 20440 mkexpr( tmp_hi[i] ) ) ); 20441 } 20442 putVSReg( XT, binop( Iop_64HLtoV128, 20443 mkexpr( tmp_low[4] ), mkexpr( tmp_hi[4] ) ) ); 20444 break; 20445 } 20446 20447 case 0x36C: // lxvb16x 20448 { 20449 DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 20450 20451 IRTemp byte[16]; 20452 int i; 20453 UInt ea_off = 0; 20454 IRExpr* irx_addr; 20455 IRTemp tmp_low[9]; 20456 IRTemp tmp_hi[9]; 20457 20458 tmp_low[0] = newTemp( Ity_I64 ); 20459 tmp_hi[0] = newTemp( Ity_I64 ); 20460 assign( tmp_low[0], mkU64( 0 ) ); 20461 assign( tmp_hi[0], mkU64( 0 ) ); 20462 20463 for ( i = 0; i < 8; i++ ) { 20464 byte[i] = newTemp( Ity_I64 ); 20465 tmp_low[i+1] = newTemp( Ity_I64 ); 20466 20467 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20468 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20469 ea_off += 1; 20470 20471 assign( byte[i], binop( Iop_Shl64, 20472 unop( Iop_8Uto64, 20473 load( Ity_I8, irx_addr ) ), 20474 mkU8( 8 * ( 7 - i ) ) ) ); 20475 20476 assign( tmp_low[i+1], 20477 binop( Iop_Or64, 20478 mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) ); 20479 } 20480 20481 for ( i = 0; i < 8; i++ ) { 20482 byte[i + 8] = newTemp( Ity_I64 ); 20483 tmp_hi[i+1] = newTemp( Ity_I64 ); 20484 20485 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20486 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20487 ea_off += 1; 20488 20489 assign( byte[i+8], binop( Iop_Shl64, 20490 unop( Iop_8Uto64, 20491 load( Ity_I8, irx_addr ) ), 20492 mkU8( 8 * ( 7 - i ) ) ) ); 20493 assign( tmp_hi[i+1], binop( Iop_Or64, 20494 mkexpr( byte[i+8] ), 20495 mkexpr( tmp_hi[i] ) ) ); 20496 } 20497 putVSReg( XT, binop( Iop_64HLtoV128, 20498 mkexpr( tmp_low[8] ), mkexpr( tmp_hi[8] ) ) ); 20499 break; 20500 } 20501 20502 default: 20503 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 20504 return False; 20505 } 20506 return True; 20507 } 20508 20509 /* 20510 * VSX Move Instructions 20511 */ 20512 static Bool 20513 dis_vx_move ( UInt theInstr ) 20514 { 20515 /* XX1-Form */ 20516 UChar opc1 = ifieldOPC( theInstr ); 20517 UChar XS = ifieldRegXS( theInstr ); 20518 UChar rA_addr = ifieldRegA( theInstr ); 20519 UChar rB_addr = ifieldRegB( theInstr ); 20520 IRTemp vS = newTemp( Ity_V128 ); 20521 UInt opc2 = ifieldOPClo10( theInstr ); 20522 IRType ty = Ity_I64; 20523 20524 if ( opc1 != 0x1F ) { 20525 vex_printf( "dis_vx_move(ppc)(instr)\n" ); 20526 return False; 20527 } 20528 20529 switch (opc2) { 20530 case 0x133: // mfvsrld RA,XS Move From VSR Lower Doubleword 20531 DIP("mfvsrld %d,r%u\n", (UInt)XS, rA_addr); 20532 20533 assign( vS, getVSReg( XS ) ); 20534 putIReg( rA_addr, unop(Iop_V128to64, mkexpr( vS) ) ); 20535 20536 break; 20537 20538 case 0x193: // mfvsrdd XT,RA,RB Move to VSR Double Doubleword 20539 { 20540 IRTemp tmp = newTemp( Ity_I32 ); 20541 20542 DIP("mfvsrdd %d,r%u\n", (UInt)XS, rA_addr); 20543 20544 assign( tmp, unop( Iop_64to32, getIReg(rA_addr) ) ); 20545 assign( vS, binop( Iop_64HLtoV128, 20546 binop( Iop_32HLto64, 20547 mkexpr( tmp ), 20548 mkexpr( tmp ) ), 20549 binop( Iop_32HLto64, 20550 mkexpr( tmp ), 20551 mkexpr( tmp ) ) ) ); 20552 putVSReg( XS, mkexpr( vS ) ); 20553 } 20554 break; 20555 20556 case 0x1B3: // mtvsrws XT,RA Move to VSR word & Splat 20557 { 20558 IRTemp rA = newTemp( ty ); 20559 IRTemp rB = newTemp( ty ); 20560 20561 DIP("mfvsrws %d,r%u\n", (UInt)XS, rA_addr); 20562 20563 if ( rA_addr == 0 ) 20564 assign( rA, mkU64 ( 0 ) ); 20565 else 20566 assign( rA, getIReg(rA_addr) ); 20567 20568 assign( rB, getIReg(rB_addr) ); 20569 assign( vS, binop( Iop_64HLtoV128, mkexpr( rA ), mkexpr( rB ) ) ); 20570 putVSReg( XS, mkexpr( vS ) ); 20571 } 20572 break; 20573 20574 default: 20575 vex_printf( "dis_vx_move(ppc)(opc2)\n" ); 20576 return False; 20577 } 20578 return True; 20579 } 20580 20581 /* 20582 * VSX Store Instructions 20583 * NOTE: VSX supports word-aligned storage access. 20584 */ 20585 static Bool 20586 dis_vx_store ( UInt theInstr ) 20587 { 20588 /* XX1-Form */ 20589 UChar opc1 = ifieldOPC( theInstr ); 20590 UChar XS = ifieldRegXS( theInstr ); 20591 UChar rA_addr = ifieldRegA( theInstr ); 20592 UChar rB_addr = ifieldRegB( theInstr ); 20593 IRTemp vS = newTemp( Ity_V128 ); 20594 UInt opc2 = ifieldOPClo10( theInstr ); 20595 20596 IRType ty = mode64 ? Ity_I64 : Ity_I32; 20597 IRTemp EA = newTemp( ty ); 20598 20599 if (opc1 != 0x1F) { 20600 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 20601 return False; 20602 } 20603 20604 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 20605 assign( vS, getVSReg( XS ) ); 20606 20607 switch (opc2) { 20608 case 0x08C: 20609 { 20610 /* Need the next to the most significant 32-bit word from 20611 * the 128-bit vector. 20612 */ 20613 IRExpr * high64, * low32; 20614 DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr); 20615 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 20616 low32 = unop( Iop_64to32, high64 ); 20617 store( mkexpr( EA ), low32 ); 20618 break; 20619 } 20620 20621 case 0x18C: // stxvx Store VSX Vector Indexed 20622 { 20623 UInt ea_off = 0; 20624 IRExpr* irx_addr; 20625 IRTemp word0 = newTemp( Ity_I64 ); 20626 IRTemp word1 = newTemp( Ity_I64 ); 20627 IRTemp word2 = newTemp( Ity_I64 ); 20628 IRTemp word3 = newTemp( Ity_I64 ); 20629 DIP("stxvx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 20630 20631 assign( word0, binop( Iop_Shr64, 20632 unop( Iop_V128HIto64, mkexpr( vS ) ), 20633 mkU8( 32 ) ) ); 20634 20635 assign( word1, binop( Iop_And64, 20636 unop( Iop_V128HIto64, mkexpr( vS ) ), 20637 mkU64( 0xFFFFFFFF ) ) ); 20638 20639 assign( word2, binop( Iop_Shr64, 20640 unop( Iop_V128to64, mkexpr( vS ) ), 20641 mkU8( 32 ) ) ); 20642 20643 assign( word3, binop( Iop_And64, 20644 unop( Iop_V128to64, mkexpr( vS ) ), 20645 mkU64( 0xFFFFFFFF ) ) ); 20646 20647 if (host_endness == VexEndnessBE) { 20648 store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word0 ) ) ); 20649 20650 ea_off += 4; 20651 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20652 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20653 20654 store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) ); 20655 20656 ea_off += 4; 20657 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20658 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20659 20660 store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) ); 20661 ea_off += 4; 20662 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20663 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20664 20665 store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) ); 20666 } else { 20667 store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word3 ) ) ); 20668 20669 ea_off += 4; 20670 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20671 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20672 20673 store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) ); 20674 20675 ea_off += 4; 20676 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20677 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20678 20679 store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) ); 20680 ea_off += 4; 20681 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 20682 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20683 20684 store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) ); 20685 } 20686 break; 20687 } 20688 20689 case 0x18D: // stxvl Store VSX Vector Indexed 20690 { 20691 UInt ea_off = 0; 20692 IRExpr* irx_addr; 20693 IRTemp word0 = newTemp( Ity_I64 ); 20694 IRTemp word1 = newTemp( Ity_I64 ); 20695 IRTemp word2 = newTemp( Ity_I64 ); 20696 IRTemp word3 = newTemp( Ity_I64 ); 20697 IRTemp shift = newTemp( Ity_I8 ); 20698 IRTemp nb_gt16 = newTemp( Ity_I8 ); 20699 IRTemp nb_zero = newTemp( Ity_V128 ); 20700 IRTemp nb = newTemp( Ity_I8 ); 20701 IRTemp nb_field = newTemp( Ity_I64 ); 20702 IRTemp n_bytes = newTemp( Ity_I8 ); 20703 IRTemp base_addr = newTemp( ty ); 20704 IRTemp current_mem = newTemp( Ity_V128 ); 20705 IRTemp store_val = newTemp( Ity_V128 ); 20706 IRTemp nb_mask = newTemp( Ity_V128 ); 20707 20708 DIP("stxvl %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 20709 20710 assign( nb_field, binop( Iop_Shr64, 20711 getIReg(rB_addr), 20712 mkU8( 56 ) ) ); 20713 20714 assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) ); 20715 20716 /* nb_gt16 will be all zeros if nb > 16 */ 20717 assign( nb_gt16, unop( Iop_1Sto8, 20718 binop( Iop_CmpLT64U, 20719 binop( Iop_Shr64, 20720 mkexpr( nb_field ), 20721 mkU8( 4 ) ), 20722 mkU64( 1 ) ) ) ); 20723 20724 /* nb_zero is 0xFF..FF if the nb_field = 0 */ 20725 assign( nb_zero, binop( Iop_64HLtoV128, 20726 unop( Iop_1Sto64, 20727 binop( Iop_CmpEQ64, 20728 mkexpr( nb_field ), 20729 mkU64( 0 ) ) ), 20730 unop( Iop_1Sto64, 20731 binop( Iop_CmpEQ64, 20732 mkexpr( nb_field ), 20733 mkU64( 0 ) ) ) ) ); 20734 20735 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */ 20736 assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) ); 20737 assign( shift, unop( Iop_64to8, 20738 binop( Iop_Mul64, 20739 binop( Iop_Sub64, 20740 mkU64( 16 ), 20741 unop( Iop_8Uto64, 20742 mkexpr( n_bytes ) ) ), 20743 mkU64( 8 ) ) ) ); 20744 20745 /* We only have a 32-bit store function. So, need to fetch the 20746 * contents of memory merge with the store value and do two 20747 * 32-byte stores so we preserve the contents of memory not 20748 * addressed by nb. 20749 */ 20750 assign( base_addr, ea_rAor0( rA_addr ) ); 20751 20752 assign( current_mem, 20753 binop( Iop_64HLtoV128, 20754 load( Ity_I64, mkexpr( base_addr ) ), 20755 load( Ity_I64, 20756 binop( mkSzOp( ty, Iop_Add8 ), 20757 mkexpr( base_addr ), 20758 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) 20759 ) ) ) ); 20760 20761 /* Set the nb_mask to all zeros if nb = 0 so the current contents 20762 * of memory get written back without modifications. 20763 * 20764 * The store_val is a combination of the current memory value 20765 * and the bytes you want to store. The nb_mask selects the 20766 * bytes you want stored from Vs. 20767 */ 20768 if (host_endness == VexEndnessBE) { 20769 assign( nb_mask, 20770 binop( Iop_OrV128, 20771 binop( Iop_AndV128, 20772 binop( Iop_ShlV128, 20773 mkV128( 0xFFFF ), 20774 mkexpr( shift ) ), 20775 unop( Iop_NotV128, mkexpr( nb_zero ) ) ), 20776 binop( Iop_AndV128, 20777 mkexpr( nb_zero ), 20778 mkV128( 0 ) ) ) ); 20779 20780 assign( store_val, 20781 binop( Iop_OrV128, 20782 binop( Iop_AndV128, 20783 binop( Iop_ShrV128, 20784 mkexpr( vS ), 20785 mkexpr( shift ) ), 20786 mkexpr( nb_mask ) ), 20787 binop( Iop_AndV128, 20788 unop( Iop_NotV128, mkexpr( nb_mask ) ), 20789 mkexpr( current_mem) ) ) ); 20790 20791 } else { 20792 assign( nb_mask, 20793 binop( Iop_OrV128, 20794 binop( Iop_AndV128, 20795 binop( Iop_ShrV128, 20796 binop( Iop_ShlV128, 20797 mkV128( 0xFFFF ), 20798 mkexpr( shift ) ), 20799 mkexpr( shift ) ), 20800 unop( Iop_NotV128, mkexpr( nb_zero ) ) ), 20801 binop( Iop_AndV128, 20802 mkexpr( nb_zero ), 20803 mkV128( 0 ) ) ) ); 20804 20805 assign( store_val, 20806 binop( Iop_OrV128, 20807 binop( Iop_AndV128, 20808 binop( Iop_ShrV128, 20809 binop( Iop_ShlV128, 20810 mkexpr( vS ), 20811 mkexpr( shift ) ), 20812 mkexpr( shift ) ), 20813 mkexpr( nb_mask ) ), 20814 binop( Iop_AndV128, 20815 unop( Iop_NotV128, mkexpr( nb_mask ) ), 20816 mkexpr( current_mem) ) ) ); 20817 } 20818 20819 /* Store the value in 32-byte chunks */ 20820 assign( word0, binop( Iop_Shr64, 20821 unop( Iop_V128HIto64, mkexpr( store_val ) ), 20822 mkU8( 32 ) ) ); 20823 20824 assign( word1, binop( Iop_And64, 20825 unop( Iop_V128HIto64, mkexpr( store_val ) ), 20826 mkU64( 0xFFFFFFFF ) ) ); 20827 20828 assign( word2, binop( Iop_Shr64, 20829 unop( Iop_V128to64, mkexpr( store_val ) ), 20830 mkU8( 32 ) ) ); 20831 20832 assign( word3, binop( Iop_And64, 20833 unop( Iop_V128to64, mkexpr( store_val ) ), 20834 mkU64( 0xFFFFFFFF ) ) ); 20835 20836 ea_off = 0; 20837 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20838 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20839 20840 store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) ); 20841 20842 ea_off += 4; 20843 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20844 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20845 20846 store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) ); 20847 20848 ea_off += 4; 20849 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20850 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20851 20852 store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) ); 20853 20854 ea_off += 4; 20855 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20856 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20857 20858 store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) ); 20859 break; 20860 } 20861 20862 case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form) 20863 { 20864 UInt ea_off = 0; 20865 IRExpr* irx_addr; 20866 IRTemp word0[5]; 20867 IRTemp word1[5]; 20868 IRTemp word2[5]; 20869 IRTemp word3[5]; 20870 IRTemp shift = newTemp(Ity_I8); 20871 IRTemp nb_gt16 = newTemp(Ity_I8); 20872 IRTemp nb_zero = newTemp(Ity_V128); 20873 IRTemp nb = newTemp(Ity_I8); 20874 IRTemp nb_field = newTemp(Ity_I64); 20875 IRTemp n_bytes = newTemp(Ity_I8); 20876 IRTemp base_addr = newTemp( ty ); 20877 IRTemp current_mem = newTemp(Ity_V128); 20878 IRTemp store_val = newTemp(Ity_V128); 20879 IRTemp nb_mask = newTemp(Ity_V128); 20880 IRTemp mask = newTemp( Ity_I64 ); 20881 IRTemp byte[16]; 20882 IRTemp tmp_low[9]; 20883 IRTemp tmp_hi[9]; 20884 IRTemp nb_field_compare_zero = newTemp( Ity_I64 ); 20885 Int i; 20886 20887 DIP("stxvll %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 20888 20889 assign( nb_field, binop( Iop_Shr64, 20890 getIReg(rB_addr), 20891 mkU8( 56 ) ) ); 20892 assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) ); 20893 assign( mask, mkU64( 0xFFFFFFFFFFFFFFFFULL ) ); 20894 20895 /* nb_gt16 will be all zeros if nb > 16 */ 20896 assign( nb_gt16, unop( Iop_1Sto8, 20897 binop( Iop_CmpLT64U, 20898 binop( Iop_Shr64, 20899 mkexpr( nb_field ), 20900 mkU8( 4 ) ), 20901 mkU64( 1 ) ) ) ); 20902 20903 assign( nb_field_compare_zero, unop( Iop_1Sto64, 20904 binop( Iop_CmpEQ64, 20905 mkexpr( nb_field ), 20906 mkU64( 0 ) ) ) ); 20907 20908 /* nb_zero is 0xFF..FF if the nb_field = 0 */ 20909 assign( nb_zero, binop( Iop_64HLtoV128, 20910 mkexpr( nb_field_compare_zero ), 20911 mkexpr( nb_field_compare_zero ) ) ); 20912 20913 20914 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */ 20915 assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) ); 20916 assign( shift, 20917 unop( Iop_64to8, 20918 binop( Iop_Mul64, 20919 binop( Iop_Sub64, 20920 mkU64( 16 ), 20921 unop( Iop_8Uto64, mkexpr( n_bytes ) )), 20922 mkU64( 8 ) ) ) ); 20923 20924 /* We only have a 32-bit store function. So, need to fetch the 20925 * contents of memory merge with the store value and do two 20926 * 32-byte stores so we preserve the contents of memory not 20927 * addressed by nb. 20928 */ 20929 assign( base_addr, ea_rAor0( rA_addr ) ); 20930 /* fetch all 16 bytes and store in Big Endian format */ 20931 word0[0] = newTemp(Ity_I64); 20932 assign( word0[0], mkU64( 0 ) ); 20933 20934 word1[0] = newTemp(Ity_I64); 20935 assign( word1[0], mkU64( 0 ) ); 20936 20937 word2[0] = newTemp(Ity_I64); 20938 assign( word2[0], mkU64( 0 ) ); 20939 20940 word3[0] = newTemp(Ity_I64); 20941 assign( word3[0], mkU64( 0 ) ); 20942 20943 for (i = 0; i < 4; i++) { 20944 word0[i+1] = newTemp(Ity_I64); 20945 20946 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20947 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20948 ea_off += 1; 20949 20950 /* Instruction always loads in Big Endian format */ 20951 assign( word0[i+1], 20952 binop( Iop_Or64, 20953 binop( Iop_Shl64, 20954 unop( Iop_8Uto64, 20955 load( Ity_I8, 20956 irx_addr ) ), 20957 mkU8( (3-i)*8 ) ), 20958 mkexpr( word0[i] ) ) ); 20959 } 20960 20961 for (i = 0; i < 4; i++) { 20962 word1[i+1] = newTemp(Ity_I64); 20963 20964 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20965 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20966 ea_off += 1; 20967 20968 /* Instruction always loads in Big Endian format */ 20969 assign( word1[i+1], 20970 binop( Iop_Or64, 20971 binop( Iop_Shl64, 20972 unop( Iop_8Uto64, 20973 load( Ity_I8, 20974 irx_addr ) ), 20975 mkU8( (3-i)*8 ) ), 20976 mkexpr( word1[i] ) ) ); 20977 } 20978 for (i = 0; i < 4; i++) { 20979 word2[i+1] = newTemp(Ity_I64); 20980 20981 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20982 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 20983 ea_off += 1; 20984 20985 /* Instruction always loads in Big Endian format */ 20986 assign( word2[i+1], 20987 binop( Iop_Or64, 20988 binop( Iop_Shl64, 20989 unop( Iop_8Uto64, 20990 load( Ity_I8, 20991 irx_addr ) ), 20992 mkU8( (3-i)*8 ) ), 20993 mkexpr( word2[i] ) ) ); 20994 } 20995 for (i = 0; i < 4; i++) { 20996 word3[i+1] = newTemp(Ity_I64); 20997 20998 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 20999 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21000 ea_off += 1; 21001 21002 /* Instruction always loads in Big Endian format */ 21003 assign( word3[i+1], 21004 binop( Iop_Or64, 21005 binop( Iop_Shl64, 21006 unop( Iop_8Uto64, 21007 load( Ity_I8, 21008 irx_addr ) ), 21009 mkU8( (3-i)*8 ) ), 21010 mkexpr( word3[i] ) ) ); 21011 } 21012 21013 21014 assign( current_mem, 21015 binop( Iop_64HLtoV128, 21016 binop( Iop_Or64, 21017 binop( Iop_Shl64, 21018 mkexpr( word0[4] ), 21019 mkU8( 32 ) ), 21020 mkexpr( word1[4] ) ), 21021 binop( Iop_Or64, 21022 binop( Iop_Shl64, 21023 mkexpr( word2[4] ), 21024 mkU8( 32 ) ), 21025 mkexpr( word3[4] ) ) ) ); 21026 21027 /* Set the nb_mask to all zeros if nb = 0 so the current contents 21028 * of memory get written back without modifications. 21029 * 21030 * The store_val is a combination of the current memory value 21031 * and the bytes you want to store. The nb_mask selects the 21032 * bytes you want stored from Vs. 21033 */ 21034 /* The instruction always uses Big Endian order */ 21035 assign( nb_mask, 21036 binop( Iop_OrV128, 21037 binop( Iop_AndV128, 21038 binop( Iop_ShlV128, 21039 binop( Iop_ShrV128, 21040 binop( Iop_64HLtoV128, 21041 mkexpr( mask ), 21042 mkexpr( mask ) ), 21043 mkexpr( shift ) ), 21044 mkexpr( shift ) ), 21045 unop( Iop_NotV128, mkexpr( nb_zero ) ) ), 21046 binop( Iop_AndV128, 21047 mkexpr( nb_zero ), 21048 binop( Iop_64HLtoV128, 21049 mkU64( 0x0 ), 21050 mkU64( 0x0 ) ) ) ) ); 21051 21052 assign( store_val, 21053 binop( Iop_OrV128, 21054 binop( Iop_AndV128, 21055 mkexpr( vS ), 21056 mkexpr( nb_mask ) ), 21057 binop( Iop_AndV128, 21058 unop( Iop_NotV128, mkexpr( nb_mask ) ), 21059 mkexpr( current_mem) ) ) ); 21060 21061 /* store the merged value in Big Endian format */ 21062 tmp_low[0] = newTemp(Ity_I64); 21063 tmp_hi[0] = newTemp(Ity_I64); 21064 assign( tmp_low[0], mkU64( 0 ) ); 21065 assign( tmp_hi[0], mkU64( 0 ) ); 21066 21067 for (i = 0; i < 8; i++) { 21068 byte[i] = newTemp(Ity_I64); 21069 byte[i+8] = newTemp(Ity_I64); 21070 tmp_low[i+1] = newTemp(Ity_I64); 21071 tmp_hi[i+1] = newTemp(Ity_I64); 21072 21073 assign( byte[i], binop( Iop_And64, 21074 binop( Iop_Shr64, 21075 unop( Iop_V128HIto64, 21076 mkexpr( store_val ) ), 21077 mkU8( (7-i)*8 ) ), 21078 mkU64( 0xFF ) ) ); 21079 assign( byte[i+8], binop( Iop_And64, 21080 binop( Iop_Shr64, 21081 unop( Iop_V128to64, 21082 mkexpr( store_val ) ), 21083 mkU8( (7-i)*8 ) ), 21084 mkU64( 0xFF ) ) ); 21085 21086 assign( tmp_low[i+1], 21087 binop( Iop_Or64, 21088 mkexpr( tmp_low[i] ), 21089 binop( Iop_Shl64, mkexpr( byte[i] ), mkU8( i*8 ) ) ) ); 21090 assign( tmp_hi[i+1], 21091 binop( Iop_Or64, 21092 mkexpr( tmp_hi[i] ), 21093 binop( Iop_Shl64, mkexpr( byte[i+8] ), 21094 mkU8( i*8 ) ) ) ); 21095 } 21096 21097 /* Store the value in 32-byte chunks */ 21098 ea_off = 0; 21099 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 21100 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21101 21102 store( irx_addr, unop( Iop_64to32, mkexpr( tmp_low[8] ) ) ); 21103 21104 ea_off += 4; 21105 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 21106 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21107 21108 store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_low[8] ) ) ); 21109 21110 ea_off += 4; 21111 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 21112 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21113 21114 store( irx_addr, unop( Iop_64to32, mkexpr( tmp_hi[8] ) ) ); 21115 21116 ea_off += 4; 21117 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ), 21118 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21119 21120 store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_hi[8] ) ) ); 21121 21122 break; 21123 } 21124 21125 case 0x28C: 21126 { 21127 IRTemp high64 = newTemp(Ity_F64); 21128 IRTemp val32 = newTemp(Ity_I32); 21129 DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21130 assign(high64, unop( Iop_ReinterpI64asF64, 21131 unop( Iop_V128HIto64, mkexpr( vS ) ) ) ); 21132 assign(val32, unop( Iop_ReinterpF32asI32, 21133 unop( Iop_TruncF64asF32, 21134 mkexpr(high64) ) ) ); 21135 store( mkexpr( EA ), mkexpr( val32 ) ); 21136 break; 21137 } 21138 case 0x2CC: 21139 { 21140 IRExpr * high64; 21141 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21142 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 21143 store( mkexpr( EA ), high64 ); 21144 break; 21145 } 21146 21147 case 0x38D: // stxsibx 21148 { 21149 IRExpr *stored_word; 21150 IRTemp byte_to_store = newTemp( Ity_I64 ); 21151 21152 DIP("stxsibx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21153 21154 /* Can't store just a byte, need to fetch the word at EA merge data 21155 * and store. 21156 */ 21157 stored_word = load( Ity_I64, mkexpr( EA ) ); 21158 assign( byte_to_store, binop( Iop_And64, 21159 unop( Iop_V128HIto64, 21160 mkexpr( vS ) ), 21161 mkU64( 0xFF ) ) ); 21162 21163 store( mkexpr( EA ), binop( Iop_Or64, 21164 binop( Iop_And64, 21165 stored_word, 21166 mkU64( 0xFFFFFFFFFFFFFF00 ) ), 21167 mkexpr( byte_to_store ) ) ); 21168 break; 21169 } 21170 21171 case 0x3AD: // stxsihx 21172 { 21173 IRExpr *stored_word; 21174 IRTemp byte_to_store = newTemp( Ity_I64 ); 21175 21176 DIP("stxsihx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21177 21178 /* Can't store just a halfword, need to fetch the word at EA merge data 21179 * and store. 21180 */ 21181 stored_word = load( Ity_I64, mkexpr( EA ) ); 21182 assign( byte_to_store, binop( Iop_And64, 21183 unop( Iop_V128HIto64, 21184 mkexpr( vS ) ), 21185 mkU64( 0xFFFF ) ) ); 21186 21187 store( mkexpr( EA ), binop( Iop_Or64, 21188 binop( Iop_And64, 21189 stored_word, 21190 mkU64( 0xFFFFFFFFFFFF0000 ) ), 21191 mkexpr( byte_to_store ) ) ); 21192 break; 21193 } 21194 21195 case 0x3CC: 21196 { 21197 IRExpr * high64, *low64; 21198 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21199 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 21200 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 21201 store( mkexpr( EA ), high64 ); 21202 store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21203 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 ); 21204 break; 21205 } 21206 case 0x38C: 21207 { 21208 UInt ea_off = 0; 21209 IRExpr* irx_addr; 21210 IRTemp hi64 = newTemp( Ity_I64 ); 21211 IRTemp lo64 = newTemp( Ity_I64 ); 21212 21213 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21214 21215 // This instruction supports word-aligned stores, so EA may not be 21216 // quad-word aligned. Therefore, do 4 individual word-size stores. 21217 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 21218 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 21219 store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 21220 ea_off += 4; 21221 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21222 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21223 store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 21224 ea_off += 4; 21225 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21226 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21227 store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 21228 ea_off += 4; 21229 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21230 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21231 store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 21232 21233 break; 21234 } 21235 case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed 21236 { 21237 UInt ea_off = 0; 21238 IRExpr* irx_addr; 21239 IRTemp half_word0 = newTemp( Ity_I64 ); 21240 IRTemp half_word1 = newTemp( Ity_I64 ); 21241 IRTemp half_word2 = newTemp( Ity_I64 ); 21242 IRTemp half_word3 = newTemp( Ity_I64 ); 21243 IRTemp half_word4 = newTemp( Ity_I64 ); 21244 IRTemp half_word5 = newTemp( Ity_I64 ); 21245 IRTemp half_word6 = newTemp( Ity_I64 ); 21246 IRTemp half_word7 = newTemp( Ity_I64 ); 21247 21248 DIP("stxvb8x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21249 21250 assign( half_word0, binop( Iop_Shr64, 21251 unop( Iop_V128HIto64, mkexpr( vS ) ), 21252 mkU8( 48 ) ) ); 21253 21254 assign( half_word1, binop( Iop_And64, 21255 binop( Iop_Shr64, 21256 unop( Iop_V128HIto64, mkexpr( vS ) ), 21257 mkU8( 32 ) ), 21258 mkU64( 0xFFFF ) ) ); 21259 21260 assign( half_word2, binop( Iop_And64, 21261 binop( Iop_Shr64, 21262 unop( Iop_V128HIto64, mkexpr( vS ) ), 21263 mkU8( 16 ) ), 21264 mkU64( 0xFFFF ) ) ); 21265 21266 assign( half_word3, binop( Iop_And64, 21267 unop( Iop_V128HIto64, mkexpr( vS ) ), 21268 mkU64( 0xFFFF ) ) ); 21269 21270 assign( half_word4, binop( Iop_Shr64, 21271 unop( Iop_V128to64, mkexpr( vS ) ), 21272 mkU8( 48 ) ) ); 21273 21274 assign( half_word5, binop( Iop_And64, 21275 binop( Iop_Shr64, 21276 unop( Iop_V128to64, mkexpr( vS ) ), 21277 mkU8( 32 ) ), 21278 mkU64( 0xFFFF ) ) ); 21279 21280 assign( half_word6, binop( Iop_And64, 21281 binop( Iop_Shr64, 21282 unop( Iop_V128to64, mkexpr( vS ) ), 21283 mkU8( 16 ) ), 21284 mkU64( 0xFFFF ) ) ); 21285 21286 assign( half_word7, binop( Iop_And64, 21287 unop( Iop_V128to64, mkexpr( vS ) ), 21288 mkU64( 0xFFFF ) ) ); 21289 21290 /* Do the 32-bit stores. The store() does an Endian aware store. */ 21291 if ( host_endness == VexEndnessBE ) { 21292 store( mkexpr( EA ), unop( Iop_64to32, 21293 binop( Iop_Or64, 21294 mkexpr( half_word1 ), 21295 binop( Iop_Shl64, 21296 mkexpr( half_word0 ), 21297 mkU8( 16 ) ) ) ) ); 21298 21299 ea_off += 4; 21300 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21301 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21302 21303 21304 store( irx_addr, unop( Iop_64to32, 21305 binop( Iop_Or64, 21306 mkexpr( half_word3 ), 21307 binop( Iop_Shl64, 21308 mkexpr( half_word2 ), 21309 mkU8( 16 ) ) ) ) ); 21310 21311 ea_off += 4; 21312 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21313 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21314 21315 store( irx_addr, unop( Iop_64to32, 21316 binop( Iop_Or64, 21317 mkexpr( half_word5 ), 21318 binop( Iop_Shl64, 21319 mkexpr( half_word4 ), 21320 mkU8( 16 ) ) ) ) ); 21321 ea_off += 4; 21322 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21323 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21324 21325 store( irx_addr, unop( Iop_64to32, 21326 binop( Iop_Or64, 21327 mkexpr( half_word7 ), 21328 binop( Iop_Shl64, 21329 mkexpr( half_word6 ), 21330 mkU8( 16 ) ) ) ) ); 21331 21332 } else { 21333 store( mkexpr( EA ), unop( Iop_64to32, 21334 binop( Iop_Or64, 21335 mkexpr( half_word0 ), 21336 binop( Iop_Shl64, 21337 mkexpr( half_word1 ), 21338 mkU8( 16 ) ) ) ) ); 21339 21340 ea_off += 4; 21341 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21342 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21343 21344 store( irx_addr, unop( Iop_64to32, 21345 binop( Iop_Or64, 21346 mkexpr( half_word2 ), 21347 binop( Iop_Shl64, 21348 mkexpr( half_word3 ), 21349 mkU8( 16 ) ) ) ) ); 21350 ea_off += 4; 21351 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21352 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21353 21354 store( irx_addr, unop( Iop_64to32, 21355 binop( Iop_Or64, 21356 mkexpr( half_word4 ), 21357 binop( Iop_Shl64, 21358 mkexpr( half_word5 ), 21359 mkU8( 16 ) ) ) ) ); 21360 ea_off += 4; 21361 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21362 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21363 21364 store( irx_addr, unop( Iop_64to32, 21365 binop( Iop_Or64, 21366 mkexpr( half_word6 ), 21367 binop( Iop_Shl64, 21368 mkexpr( half_word7 ), 21369 mkU8( 16 ) ) ) ) ); 21370 } 21371 break; 21372 } 21373 21374 case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed 21375 { 21376 UInt ea_off = 0; 21377 int i; 21378 IRExpr* irx_addr; 21379 IRTemp byte[16]; 21380 21381 DIP("stxvb16x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 21382 21383 for ( i = 0; i < 8; i++ ) { 21384 byte[i] = newTemp( Ity_I64 ); 21385 byte[i+8] = newTemp( Ity_I64 ); 21386 21387 assign( byte[i], binop( Iop_And64, 21388 binop( Iop_Shr64, 21389 unop( Iop_V128HIto64, mkexpr( vS ) ), 21390 mkU8( 56 - i*8 ) ), 21391 mkU64( 0xFF ) ) ); 21392 21393 assign( byte[i+8], binop( Iop_And64, 21394 binop( Iop_Shr64, 21395 unop( Iop_V128to64, mkexpr( vS ) ), 21396 mkU8( 56 - i*8) ), 21397 mkU64( 0xFF ) ) ); 21398 } 21399 21400 if ( host_endness == VexEndnessBE ) { 21401 for ( i = 0; i < 16; i = i + 4) { 21402 irx_addr = 21403 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21404 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21405 21406 store( irx_addr, 21407 unop( Iop_64to32, 21408 binop( Iop_Or64, 21409 binop( Iop_Or64, 21410 mkexpr( byte[i+3] ), 21411 binop( Iop_Shl64, 21412 mkexpr( byte[i+2] ), 21413 mkU8( 8 ) ) ), 21414 binop( Iop_Or64, 21415 binop( Iop_Shl64, 21416 mkexpr( byte[i+1] ), 21417 mkU8( 16 ) ), 21418 binop( Iop_Shl64, 21419 mkexpr( byte[i] ), 21420 mkU8( 24 ) ) ) ) ) ); 21421 ea_off += 4; 21422 } 21423 21424 } else { 21425 for ( i = 0; i < 16; i = i + 4) { 21426 irx_addr = 21427 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 21428 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 21429 21430 store( irx_addr, 21431 unop( Iop_64to32, 21432 binop( Iop_Or64, 21433 binop( Iop_Or64, 21434 mkexpr( byte[i] ), 21435 binop( Iop_Shl64, 21436 mkexpr( byte[i+1] ), 21437 mkU8( 8 ) ) ), 21438 binop( Iop_Or64, 21439 binop( Iop_Shl64, 21440 mkexpr( byte[i+2] ), 21441 mkU8( 16 ) ), 21442 binop( Iop_Shl64, 21443 mkexpr( byte[i+3] ), 21444 mkU8( 24 ) ) ) ) ) ); 21445 21446 ea_off += 4; 21447 } 21448 } 21449 break; 21450 } 21451 21452 default: 21453 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 21454 return False; 21455 } 21456 return True; 21457 } 21458 21459 static Bool 21460 dis_vx_Scalar_Round_to_quad_integer( UInt theInstr ) 21461 { 21462 /* The ISA 3.0 instructions supported in this function require 21463 * the underlying hardware platform that supports the ISA3.0 21464 * instruction set. 21465 */ 21466 /* XX1-Form */ 21467 UChar opc1 = ifieldOPC( theInstr ); 21468 UInt opc2 = IFIELD( theInstr, 1, 8 ); 21469 UChar vT_addr = ifieldRegDS( theInstr ); 21470 UChar vB_addr = ifieldRegB( theInstr ); 21471 IRTemp vB = newTemp( Ity_F128 ); 21472 IRTemp vT = newTemp( Ity_F128 ); 21473 UChar EX = IFIELD( theInstr, 0, 1 ); 21474 21475 assign( vB, getF128Reg( vB_addr ) ); 21476 if (opc1 != 0x3F) { 21477 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" ); 21478 return False; 21479 } 21480 switch (opc2) { 21481 case 0x005: // VSX Scalar Round to Quad-Precision Integer [with Inexact] 21482 { 21483 UChar R = IFIELD( theInstr, 16, 1 ); 21484 UChar RMC = IFIELD( theInstr, 9, 2 ); 21485 21486 /* Store the rm specification bits. Will extract them later when 21487 * the isntruction is issued. 21488 */ 21489 IRExpr* rm = mkU32( R << 3 | RMC << 1 | EX); 21490 21491 if ( EX == 0 ) { // xsrqpi 21492 DIP("xsrqpi %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC); 21493 assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) ); 21494 21495 } else { // xsrqpix 21496 DIP("xsrqpix %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC); 21497 assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) ); 21498 } 21499 generate_store_FPRF( Ity_F128, vT ); 21500 } /* case 0x005 */ 21501 break; 21502 case 0x025: // xsrqpxp VSX Scalar Round Quad-Precision to 21503 // Double-Extended Precision 21504 { 21505 UChar R = IFIELD( theInstr, 16, 1 ); 21506 UChar RMC = IFIELD( theInstr, 9, 2 ); 21507 21508 /* Store the rm specification bits. Will extract them later when 21509 * the isntruction is issued. 21510 */ 21511 IRExpr* rm = mkU32( R << 3 | RMC << 1 ); 21512 21513 DIP("xsrqpxp %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC); 21514 assign( vT, binop( Iop_RndF128, rm, mkexpr( vB ) ) ); 21515 generate_store_FPRF( Ity_F128, vT ); 21516 } /* case 0x025 */ 21517 break; 21518 default: 21519 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" ); 21520 return False; 21521 } /* switch opc2 */ 21522 putF128Reg( vT_addr, mkexpr( vT ) ); 21523 return True; 21524 } 21525 21526 static Bool 21527 dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr ) 21528 { 21529 /* The ISA 3.0 instructions supported in this function require 21530 * the underlying hardware platform that supports the ISA 3.0 21531 * instruction set. 21532 */ 21533 /* XX1-Form */ 21534 UChar opc1 = ifieldOPC( theInstr ); 21535 UInt opc2 = ifieldOPClo10( theInstr ); 21536 UChar vT_addr = ifieldRegDS( theInstr ); 21537 UChar vA_addr = ifieldRegA( theInstr ); 21538 UChar vB_addr = ifieldRegB( theInstr ); 21539 IRTemp vA = newTemp( Ity_F128 ); 21540 IRTemp vB = newTemp( Ity_F128 ); 21541 IRTemp vT = newTemp( Ity_F128 ); 21542 IRExpr* rm = get_IR_roundingmode(); 21543 UChar R0 = IFIELD( theInstr, 0, 1 ); 21544 21545 assign( vB, getF128Reg( vB_addr ) ); 21546 21547 if ( opc1 != 0x3F ) { 21548 vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" ); 21549 return False; 21550 } 21551 switch ( opc2 ) { 21552 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd]) 21553 { 21554 assign( vA, getF128Reg( vA_addr ) ); 21555 21556 if ( R0 == 0 ) { 21557 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21558 DIP("xsaddqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21559 assign( vT, triop( Iop_AddF128, rm, mkexpr( vA ), mkexpr( vB ) ) ); 21560 21561 } else { 21562 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21563 DIP("xsaddqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21564 assign( vT, triop( Iop_AddF128, set_round_to_Oddmode(), 21565 mkexpr( vA ), mkexpr( vB ) ) ); 21566 } 21567 generate_store_FPRF( Ity_F128, vT ); 21568 break; 21569 } 21570 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd]) 21571 { 21572 assign( vA, getF128Reg( vA_addr ) ); 21573 21574 if ( R0 == 0 ) { 21575 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21576 DIP("xsmulqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21577 assign( vT, triop( Iop_MulF128, rm, mkexpr( vA ), mkexpr( vB ) ) ); 21578 21579 } else { 21580 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21581 DIP("xsmulqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21582 assign( vT, triop( Iop_MulF128, set_round_to_Oddmode(), mkexpr( vA ), 21583 mkexpr( vB ) ) ); 21584 } 21585 generate_store_FPRF( Ity_F128, vT ); 21586 break; 21587 } 21588 case 0x184: // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd]) 21589 { 21590 /* instruction computes (vA * vB) + vC */ 21591 IRTemp vC = newTemp( Ity_F128 ); 21592 21593 assign( vA, getF128Reg( vA_addr ) ); 21594 assign( vC, getF128Reg( vT_addr ) ); 21595 21596 if ( R0 == 0 ) { 21597 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21598 DIP("xsmaddqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21599 assign( vT, 21600 qop( Iop_MAddF128, rm, mkexpr( vA ), 21601 mkexpr( vC ), mkexpr( vB ) ) ); 21602 21603 } else { 21604 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21605 DIP("xsmaddqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21606 assign( vT, 21607 qop( Iop_MAddF128, set_round_to_Oddmode(), mkexpr( vA ), 21608 mkexpr( vC ), mkexpr( vB ) ) ); 21609 } 21610 generate_store_FPRF( Ity_F128, vT ); 21611 break; 21612 } 21613 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd]) 21614 { 21615 IRTemp vC = newTemp( Ity_F128 ); 21616 21617 assign( vA, getF128Reg( vA_addr ) ); 21618 assign( vC, getF128Reg( vT_addr ) ); 21619 21620 if ( R0 == 0 ) { 21621 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21622 DIP("xsmsubqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21623 assign( vT, 21624 qop( Iop_MSubF128, rm, mkexpr( vA ), 21625 mkexpr( vC ), mkexpr( vB ) ) ); 21626 21627 } else { 21628 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21629 DIP("xsmsubqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21630 assign( vT, 21631 qop( Iop_MSubF128, set_round_to_Oddmode(), 21632 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) ); 21633 } 21634 generate_store_FPRF( Ity_F128, vT ); 21635 break; 21636 } 21637 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd]) 21638 { 21639 IRTemp vC = newTemp( Ity_F128 ); 21640 21641 assign( vA, getF128Reg( vA_addr ) ); 21642 assign( vC, getF128Reg( vT_addr ) ); 21643 21644 if ( R0 == 0 ) { 21645 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21646 DIP("xsnmaddqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21647 assign( vT, 21648 qop( Iop_NegMAddF128, rm, mkexpr( vA ), 21649 mkexpr( vC ), mkexpr( vB ) ) ); 21650 21651 } else { 21652 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21653 DIP("xsnmaddqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21654 assign( vT, 21655 qop( Iop_NegMAddF128, set_round_to_Oddmode(), 21656 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) ); 21657 } 21658 generate_store_FPRF( Ity_F128, vT ); 21659 break; 21660 } 21661 case 0x1E4: // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd]) 21662 { 21663 IRTemp vC = newTemp( Ity_F128 ); 21664 21665 assign( vA, getF128Reg( vA_addr ) ); 21666 assign( vC, getF128Reg( vT_addr ) ); 21667 21668 if ( R0 == 0 ) { 21669 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21670 DIP("xsnmsubqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21671 assign( vT, 21672 qop( Iop_NegMSubF128, rm, mkexpr( vA ), 21673 mkexpr( vC ), mkexpr( vB ) ) ); 21674 21675 } else { 21676 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21677 DIP("xsnmsubqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21678 assign( vT, 21679 qop( Iop_NegMSubF128, set_round_to_Oddmode(), 21680 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) ); 21681 } 21682 generate_store_FPRF( Ity_F128, vT ); 21683 break; 21684 } 21685 case 0x204: // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd]) 21686 { 21687 assign( vA, getF128Reg( vA_addr ) ); 21688 if ( R0 == 0 ) { 21689 /* use rounding mode specified by RN. Issue inst with R0 = 0 */ 21690 DIP("xssubqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21691 assign( vT, triop( Iop_SubF128, rm, mkexpr( vA ), mkexpr( vB ) ) ); 21692 21693 } else { 21694 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21695 DIP("xssubqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21696 assign( vT, triop( Iop_SubF128, set_round_to_Oddmode(), mkexpr( vA ), 21697 mkexpr( vB ) ) ); 21698 } 21699 generate_store_FPRF( Ity_F128, vT ); 21700 break; 21701 } 21702 case 0x224: // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd]) 21703 { 21704 assign( vA, getF128Reg( vA_addr ) ); 21705 if ( R0 == 0 ) { 21706 /* use rounding mode specified by RN. Issue inst with R0 = 0 */ 21707 DIP("xsdivqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21708 assign( vT, triop( Iop_DivF128, rm, mkexpr( vA ), mkexpr( vB ) ) ); 21709 21710 } else { 21711 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */ 21712 DIP("xsdivqpo v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21713 assign( vT, triop( Iop_DivF128, set_round_to_Oddmode(), mkexpr( vA ), 21714 mkexpr( vB ) ) ); 21715 } 21716 generate_store_FPRF( Ity_F128, vT ); 21717 break; 21718 } 21719 case 0x324: // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd]) 21720 { 21721 UInt inst_select = IFIELD( theInstr, 16, 5 ); 21722 21723 switch (inst_select) { 21724 case 27: 21725 { 21726 if ( R0 == 0 ) { // xssqrtqp 21727 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21728 DIP("xssqrtqp v%d,v%d\n", vT_addr, vB_addr); 21729 assign( vT, binop( Iop_SqrtF128, rm, mkexpr( vB ) ) ); 21730 21731 } else { // xssqrtqpo 21732 /* rounding mode is Round to odd. Issue inst with R0 = 1 */ 21733 DIP("xssqrtqpo v%d,v%d\n", vT_addr, vB_addr); 21734 assign( vT, binop( Iop_SqrtF128, set_round_to_Oddmode(), 21735 mkexpr( vB ) ) ); 21736 } 21737 generate_store_FPRF( Ity_F128, vT ); 21738 break; 21739 } /* end case 27 */ 21740 default: 21741 vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n"); 21742 return False; 21743 } /* end switch inst_select */ 21744 break; 21745 } /* end case 0x324 */ 21746 21747 case 0x344: 21748 { 21749 UInt inst_select = IFIELD( theInstr, 16, 5); 21750 21751 switch (inst_select) { 21752 case 1: // xscvqpuwz VSX Scalar Truncate & Convert Quad-Precision 21753 // format to Unsigned Word format 21754 { 21755 DIP("xscvqpuwz v%d,v%d\n", vT_addr, vB_addr); 21756 assign( vT, unop( Iop_TruncF128toI32U, mkexpr( vB ) ) ); 21757 break; 21758 } 21759 case 2: // xscvudqp VSX Scalar Convert from Unsigned Doubleword 21760 // format to Quad-Precision format 21761 { 21762 IRTemp tmp = newTemp( Ity_I64 ); 21763 21764 DIP("xscvudqp v%d,v%d\n", vT_addr, vB_addr); 21765 assign( tmp, unop( Iop_ReinterpF64asI64, 21766 unop( Iop_F128HItoF64, mkexpr( vB ) ) ) ); 21767 assign( vT, unop( Iop_I64UtoF128, mkexpr( tmp ) ) ); 21768 generate_store_FPRF( Ity_F128, vT ); 21769 break; 21770 } 21771 case 9: // xsvqpswz VSX Scalar Truncate & Convert Quad-Precision 21772 // format to Signed Word format 21773 { 21774 DIP("xscvqpswz v%d,v%d\n", vT_addr, vB_addr); 21775 assign( vT, unop( Iop_TruncF128toI32S, mkexpr( vB ) ) ); 21776 break; 21777 } 21778 case 10: // xscvsdqp VSX Scalar from Signed Doubleword format 21779 // Quad-Precision format 21780 { 21781 IRTemp tmp = newTemp( Ity_I64 ); 21782 21783 DIP("xscvsdqp v%d,v%d\n", vT_addr, vB_addr); 21784 21785 assign( tmp, unop( Iop_ReinterpF64asI64, 21786 unop( Iop_F128HItoF64, mkexpr( vB ) ) ) ); 21787 assign( vT, unop( Iop_I64StoF128, mkexpr( tmp ) ) ); 21788 generate_store_FPRF( Ity_F128, vT ); 21789 break; 21790 } 21791 case 17: // xsvqpudz VSX Scalar Truncate & Convert Quad-Precision 21792 // format to Unigned Doubleword format 21793 { 21794 DIP("xscvqpudz v%d,v%d\n", vT_addr, vB_addr); 21795 assign( vT, unop( Iop_TruncF128toI64U, mkexpr( vB ) ) ); 21796 break; 21797 } 21798 case 20: // xscvqpdp Scalar round & Conver Quad-Precision 21799 // format to Double-Precision format [using round to Odd] 21800 { 21801 IRTemp ftmp = newTemp( Ity_F64 ); 21802 IRTemp tmp = newTemp( Ity_I64 ); 21803 21804 /* This instruction takes a 128-bit floating point value and 21805 * converts it to a 64-bit floating point value. The 64-bit 21806 * result is stored in the upper 64-bit of the 128-bit result 21807 * register. The lower 64-bit are undefined. 21808 */ 21809 if (R0 == 0) { // xscvqpdp 21810 /* rounding mode specified by RN. Issue inst with R0 = 0 */ 21811 DIP("xscvqpdp v%d,v%d\n", vT_addr, vB_addr); 21812 21813 assign( ftmp, binop( Iop_F128toF64, rm, mkexpr( vB ) ) ); 21814 21815 } else { // xscvqpdpo 21816 /* rounding mode is Round to odd. Issue inst with R0 = 1 */ 21817 DIP("xscvqpdpo v%d,v%d\n", vT_addr, vB_addr); 21818 assign( ftmp, 21819 binop( Iop_F128toF64, 21820 set_round_to_Oddmode(), mkexpr( vB ) ) ); 21821 } 21822 21823 /* store 64-bit float in upper 64-bits of 128-bit register, 21824 * lower 64-bits are zero. 21825 */ 21826 if (host_endness == VexEndnessLE) 21827 assign( vT, 21828 binop( Iop_F64HLtoF128, 21829 mkexpr( ftmp ), 21830 unop( Iop_ReinterpI64asF64, mkU64( 0 ) ) ) ); 21831 else 21832 assign( vT, 21833 binop( Iop_F64HLtoF128, 21834 unop( Iop_ReinterpI64asF64, mkU64( 0 ) ), 21835 mkexpr( ftmp ) ) ); 21836 21837 assign( tmp, unop( Iop_ReinterpF64asI64, 21838 unop( Iop_F128HItoF64, mkexpr( vT ) ) ) ); 21839 21840 generate_store_FPRF( Ity_I64, tmp ); 21841 break; 21842 } 21843 case 22: // xscvdpqp VSX Scalar Convert from Double-Precision 21844 // format to Quad-Precision format 21845 { 21846 DIP("xscvdpqp v%d,v%d\n", vT_addr, vB_addr); 21847 /* The 64-bit value is in the upper 64 bit of the src */ 21848 assign( vT, unop( Iop_F64toF128, 21849 unop( Iop_F128HItoF64, mkexpr( vB ) ) ) ); 21850 21851 generate_store_FPRF( Ity_F128, vT ); 21852 break; 21853 } 21854 case 25: // xsvqpsdz VSX Scalar Truncate & Convert Quad-Precision 21855 // format to Signed Doubleword format 21856 { 21857 DIP("xscvqpsdz v%d,v%d\n", vT_addr, vB_addr); 21858 assign( vT, unop( Iop_TruncF128toI64S, mkexpr( vB ) ) ); 21859 break; 21860 } 21861 default: 21862 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" ); 21863 return False; 21864 } /* switch inst_select */ 21865 } /* end case 0x344 */ 21866 break; 21867 default: /* switch opc2 */ 21868 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" ); 21869 return False; 21870 } 21871 putF128Reg( vT_addr, mkexpr( vT ) ); 21872 return True; 21873 } 21874 21875 21876 /* VSX Scalar Quad-Precision instructions */ 21877 static Bool 21878 dis_vx_scalar_quad_precision ( UInt theInstr ) 21879 { 21880 /* This function emulates the 128-bit floating point instructions 21881 * using existing 128-bit vector instructions (Iops). The 128-bit 21882 * floating point instructions use the same 128-bit vector register 21883 * set. 21884 */ 21885 /* XX1-Form */ 21886 UChar opc1 = ifieldOPC( theInstr ); 21887 UInt opc2 = ifieldOPClo10( theInstr ); 21888 UChar vT_addr = ifieldRegDS( theInstr ) + 32; 21889 UChar vA_addr = ifieldRegA( theInstr ) + 32; 21890 UChar vB_addr = ifieldRegB( theInstr ) + 32; 21891 IRTemp vA = newTemp( Ity_V128 ); 21892 IRTemp vB = newTemp( Ity_V128 ); 21893 IRTemp vT = newTemp( Ity_V128 ); 21894 21895 assign( vB, getVSReg( vB_addr ) ); 21896 21897 if (opc1 != 0x3F) { 21898 vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" ); 21899 return False; 21900 } 21901 21902 switch (opc2) { 21903 21904 case 0x064: // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision) 21905 { 21906 IRTemp sign_vA = newTemp( Ity_I64 ); 21907 IRTemp vB_hi = newTemp( Ity_I64 ); 21908 21909 DIP("xscpsgnqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 21910 21911 assign( vA, getVSReg(vA_addr) ); 21912 21913 assign( sign_vA, binop( Iop_And64, 21914 unop( Iop_V128HIto64, 21915 mkexpr( vA ) ), 21916 mkU64( 0x8000000000000000ULL ) ) ); 21917 assign( vB_hi, binop( Iop_Or64, 21918 binop( Iop_And64, 21919 unop( Iop_V128HIto64, 21920 mkexpr( vB ) ), 21921 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ), 21922 mkexpr( sign_vA ) ) ); 21923 assign( vT, binop( Iop_64HLtoV128, 21924 mkexpr( vB_hi ), 21925 unop( Iop_V128to64, mkexpr( vB ) ) ) ); 21926 break; 21927 } 21928 21929 case 0x084: // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision) 21930 case 0x284: // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision) 21931 { 21932 /* Note, only differece between xscmoqp and xscmpuqp is the 21933 exception flag settings which are not supported anyway. */ 21934 IRExpr *bit4, *bit5, *bit6, *bit7; 21935 IRExpr *bit_zero, *bit_inf, *same_sign; 21936 UInt BF = IFIELD( theInstr, 23, 3 ); 21937 IRTemp eq_lt_gt = newTemp( Ity_I32 ); 21938 IRTemp CC = newTemp( Ity_I32 ); 21939 21940 if (opc2 == 0x084) { 21941 DIP("xscmpoqp %d,v%d,v%d\n", BF, vA_addr, vB_addr); 21942 } else { 21943 DIP("xscmpuqp %d,v%d,v%d\n", BF, vA_addr, vB_addr); 21944 } 21945 21946 assign( vA, getVSReg(vA_addr)); 21947 21948 /* A and B have the same sign */ 21949 same_sign = binop( Iop_CmpEQ64, 21950 binop( Iop_Shr64, 21951 unop( Iop_V128HIto64, 21952 mkexpr( vA ) ), 21953 mkU8( 63 ) ), 21954 binop( Iop_Shr64, 21955 unop( Iop_V128HIto64, 21956 mkexpr( vB ) ), 21957 mkU8( 63 ) ) ); 21958 21959 /* A < B */ 21960 bit4 = Quad_precision_gt( vB, vA ); 21961 21962 /* A > B */ 21963 bit5 = Quad_precision_gt( vA, vB ); 21964 21965 /* A equal B */ 21966 bit6 = mkAND1( binop( Iop_CmpEQ64, 21967 unop( Iop_V128HIto64, 21968 mkexpr( vA ) ), 21969 unop( Iop_V128HIto64, 21970 mkexpr( vB ) ) ), 21971 binop( Iop_CmpEQ64, 21972 unop( Iop_V128to64, 21973 mkexpr( vA ) ), 21974 unop( Iop_V128to64, 21975 mkexpr( vB ) ) ) ); 21976 21977 /* test both zero don't care about sign */ 21978 bit_zero = mkAND1( is_Zero( Ity_V128, vA ), is_Zero( Ity_V128, vB ) ); 21979 21980 /* test both for infinity, don't care about sign */ 21981 bit_inf = mkAND1( 21982 mkAND1( is_Inf( Ity_V128, vA ), is_Inf( Ity_V128, vB ) ), 21983 binop( Iop_CmpEQ64, 21984 binop( Iop_And64, 21985 unop( Iop_V128to64, 21986 mkexpr( vA ) ), 21987 mkU64( 0x80000000) ), 21988 binop( Iop_And64, 21989 unop( Iop_V128to64, 21990 mkexpr( vB ) ), 21991 mkU64( 0x80000000) ) ) ); 21992 21993 /* exp A or exp B is NaN */ 21994 bit7 = mkOR1( is_NaN( Ity_V128, vA ), 21995 is_NaN( Ity_V128, vB ) ); 21996 21997 assign( eq_lt_gt, 21998 binop( Iop_Or32, 21999 binop( Iop_Or32, 22000 binop( Iop_Shl32, 22001 unop( Iop_1Uto32, bit4 ), 22002 mkU8( 3 ) ), 22003 binop( Iop_Shl32, 22004 unop( Iop_1Uto32, bit5 ), 22005 mkU8( 2 ) ) ), 22006 binop( Iop_Or32, 22007 binop( Iop_Shl32, 22008 unop( Iop_1Uto32, bit6 ), 22009 mkU8( 1 ) ), 22010 binop( Iop_Or32, 22011 binop( Iop_Shl32, 22012 unop( Iop_1Uto32, 22013 bit_zero ), 22014 mkU8( 1 ) ), 22015 binop( Iop_Shl32, 22016 unop( Iop_1Uto32, 22017 mkAND1( bit_inf, same_sign ) ), 22018 mkU8( 1 ) ) ) ) ) ); 22019 22020 assign(CC, binop( Iop_Or32, 22021 binop( Iop_And32, 22022 unop( Iop_Not32, 22023 unop( Iop_1Sto32, bit7 ) ), 22024 mkexpr( eq_lt_gt ) ), 22025 unop( Iop_1Uto32, bit7 ) ) ); 22026 22027 /* put result of the comparison into CC and FPCC */ 22028 putGST_field( PPC_GST_CR, mkexpr( CC ), BF ); 22029 putFPCC( mkexpr( CC ) ); 22030 return True; 22031 } 22032 break; 22033 22034 case 0xA4: // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision) 22035 { 22036 IRExpr *bit4, *bit5, *bit6, *bit7; 22037 UInt BF = IFIELD( theInstr, 23, 3 ); 22038 22039 IRTemp eq_lt_gt = newTemp( Ity_I32 ); 22040 IRTemp CC = newTemp( Ity_I32 ); 22041 22042 DIP("xscmpexpqp %d,v%d,v%d\n", BF, vA_addr, vB_addr); 22043 22044 assign( vA, getVSReg(vA_addr)); 22045 22046 /* A exp < B exp */ 22047 bit4 = binop( Iop_CmpLT64U, 22048 binop( Iop_And64, 22049 unop( Iop_V128HIto64, 22050 mkexpr( vA ) ), 22051 mkU64( 0x7FFF000000000000 ) ), 22052 binop( Iop_And64, 22053 unop( Iop_V128HIto64, 22054 mkexpr( vB ) ), 22055 mkU64( 0x7FFF000000000000 ) ) ); 22056 /* exp > B exp */ 22057 bit5 = binop( Iop_CmpLT64U, 22058 binop( Iop_And64, 22059 unop( Iop_V128HIto64, 22060 mkexpr( vB ) ), 22061 mkU64( 0x7FFF000000000000 ) ), 22062 binop( Iop_And64, 22063 unop( Iop_V128HIto64, 22064 mkexpr( vA ) ), 22065 mkU64( 0x7FFF000000000000 ) ) ); 22066 /* test equal */ 22067 bit6 = binop( Iop_CmpEQ64, 22068 binop( Iop_And64, 22069 unop( Iop_V128HIto64, 22070 mkexpr( vA ) ), 22071 mkU64( 0x7FFF000000000000 ) ), 22072 binop( Iop_And64, 22073 unop( Iop_V128HIto64, 22074 mkexpr( vB ) ), 22075 mkU64( 0x7FFF000000000000 ) ) ); 22076 22077 /* exp A or exp B is NaN */ 22078 bit7 = mkOR1( is_NaN( Ity_V128, vA ), 22079 is_NaN( Ity_V128, vB ) ); 22080 22081 /* NaN over rules the other comparisons */ 22082 assign( eq_lt_gt, binop( Iop_Or32, 22083 binop( Iop_Shl32, 22084 unop( Iop_1Uto32, bit4 ), 22085 mkU8( 3) ), 22086 binop( Iop_Or32, 22087 binop( Iop_Shl32, 22088 unop( Iop_1Uto32, bit5 ), 22089 mkU8( 2) ), 22090 binop( Iop_Shl32, 22091 unop( Iop_1Uto32, bit6 ), 22092 mkU8( 1 ) ) ) ) ); 22093 assign(CC, binop( Iop_Or32, 22094 binop( Iop_And32, 22095 unop( Iop_Not32, 22096 unop( Iop_1Sto32, bit7 ) ), 22097 mkexpr( eq_lt_gt ) ), 22098 unop( Iop_1Uto32, bit7 ) ) ); 22099 22100 /* put result of the comparison into CC and FPCC */ 22101 putGST_field( PPC_GST_CR, mkexpr( CC ), BF ); 22102 putFPCC( mkexpr( CC ) ); 22103 return True; 22104 } 22105 break; 22106 22107 case 0x2C4: // xststdcqp (VSX Scalar Quad-Precision Test Data Class) 22108 { 22109 UInt BF = IFIELD( theInstr, 23, 3 ); 22110 UInt DCMX_mask = IFIELD( theInstr, 16, 7 ); 22111 IRTemp CC = newTemp( Ity_I64 ); 22112 IRTemp NaN = newTemp( Ity_I64 ); 22113 IRTemp inf = newTemp( Ity_I64 ); 22114 IRTemp pos = newTemp( Ity_I64 ); 22115 IRTemp DCM = newTemp( Ity_I64 ); 22116 IRTemp zero = newTemp( Ity_I64 ); 22117 IRTemp dnorm = newTemp( Ity_I64 ); 22118 22119 DIP("xststdcqp %d,v%d,%d\n", BF, vB_addr, DCMX_mask); 22120 22121 assign( zero, unop( Iop_1Uto64, is_Zero( Ity_V128, vB ) ) ); 22122 assign( pos, unop( Iop_1Uto64, 22123 binop( Iop_CmpEQ64, 22124 binop( Iop_Shr64, 22125 unop( Iop_V128HIto64, 22126 mkexpr( vB ) ), 22127 mkU8( 63 ) ), 22128 mkU64( 0 ) ) ) ); 22129 22130 assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_V128, vB ) ) ); 22131 assign( inf, unop( Iop_1Uto64, is_Inf( Ity_V128, vB ) ) ); 22132 22133 assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_V128, vB ) ) ); 22134 assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) ); 22135 assign( CC, binop( Iop_Or64, 22136 binop( Iop_And64, /* vB sign bit */ 22137 binop( Iop_Shr64, 22138 unop( Iop_V128HIto64, mkexpr( vB ) ), 22139 mkU8( 60 ) ), 22140 mkU64( 0x8 ) ), 22141 binop( Iop_Shl64, 22142 unop( Iop_1Uto64, 22143 binop( Iop_CmpNE64, 22144 binop( Iop_And64, 22145 mkexpr( DCM ), 22146 mkU64( DCMX_mask ) ), 22147 mkU64( 0 ) ) ), 22148 mkU8( 1 ) ) ) ); 22149 22150 putGST_field( PPC_GST_CR, unop(Iop_64to32, mkexpr( CC ) ), BF ); 22151 putFPCC( unop(Iop_64to32, mkexpr( CC ) ) ); 22152 return True; 22153 } 22154 break; 22155 22156 case 0x324: // xsabsqp (VSX Scalar Absolute Quad-Precision) 22157 // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision) 22158 // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision) 22159 // xsnegqp (VSX Scalar Negate Quad-Precision) 22160 // xsxsigqp (VSX Scalar Extract Significand Quad-Precision) 22161 { 22162 UInt inst_select = IFIELD( theInstr, 16, 5); 22163 22164 switch (inst_select) { 22165 case 0: 22166 DIP("xsabsqp v%d,v%d\n", vT_addr, vB_addr); 22167 assign( vT, binop( Iop_AndV128, mkexpr( vB ), 22168 binop( Iop_64HLtoV128, 22169 mkU64( 0x7FFFFFFFFFFFFFFF ), 22170 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ); 22171 break; 22172 22173 case 2: 22174 DIP("xsxexpqp v%d,v%d\n", vT_addr, vB_addr); 22175 assign( vT, binop( Iop_ShrV128, 22176 binop( Iop_AndV128, mkexpr( vB ), 22177 binop( Iop_64HLtoV128, 22178 mkU64( 0x7FFF000000000000 ), 22179 mkU64( 0x0000000000000000 ) ) ), 22180 mkU8( 48 ) ) ); 22181 break; 22182 22183 case 8: 22184 DIP("xsnabsqp v%d,v%d\n", vT_addr, vB_addr); 22185 assign( vT, binop( Iop_OrV128, mkexpr( vB ), 22186 binop( Iop_64HLtoV128, 22187 mkU64( 0x8000000000000000 ), 22188 mkU64( 0x0000000000000000 ) ) ) ); 22189 break; 22190 22191 case 16: 22192 DIP("xsnegqp v%d,v%d\n", vT_addr, vB_addr); 22193 assign( vT, binop( Iop_XorV128, mkexpr( vB ), 22194 binop( Iop_64HLtoV128, 22195 mkU64( 0x8000000000000000 ), 22196 mkU64( 0x0000000000000000 ) ) ) ); 22197 break; 22198 22199 case 18: 22200 { 22201 IRTemp expZero = newTemp( Ity_I64 ); 22202 IRTemp expInfinity = newTemp( Ity_I64 ); 22203 22204 DIP("xsxsigqp v%d,v%d\n", vT_addr, vB_addr); 22205 22206 assign( expZero, unop( Iop_1Uto64, 22207 binop( Iop_CmpNE64, 22208 binop( Iop_And64, 22209 unop( Iop_V128HIto64, 22210 mkexpr( vB ) ), 22211 mkU64( 0x7FFF000000000000 ) ), 22212 mkU64( 0x0 ) ) ) ); 22213 22214 assign( expInfinity, 22215 unop( Iop_1Uto64, 22216 binop( Iop_CmpNE64, 22217 binop( Iop_And64, 22218 unop( Iop_V128HIto64, 22219 mkexpr( vB ) ), 22220 mkU64( 0x7FFF000000000000 ) ), 22221 mkU64( 0x7FFF000000000000 ) ) ) ); 22222 22223 /* Clear upper 16 bits to 0x0000. If the exp was zero or infinity 22224 * set bit 48 (lsb = 0) to 0, otherwise set bit 48 to 1. 22225 */ 22226 assign( vT, 22227 binop( Iop_OrV128, 22228 binop( Iop_ShrV128, 22229 binop( Iop_ShlV128, 22230 mkexpr( vB ), 22231 mkU8( 16 ) ), 22232 mkU8( 16 ) ), 22233 binop( Iop_64HLtoV128, 22234 binop( Iop_Shl64, 22235 binop( Iop_And64, 22236 mkexpr( expZero ), 22237 mkexpr( expInfinity ) ), 22238 mkU8( 48 ) ), 22239 mkU64( 0 ) ) ) ); 22240 } 22241 break; 22242 22243 default: 22244 vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" ); 22245 return False; 22246 } 22247 } 22248 break; 22249 case 0x364: // xsiexpqp (VST Scalar Insert Exponent Quad-Precision) 22250 { 22251 IRTemp exp = newTemp( Ity_I64 ); 22252 22253 DIP("xsiexpqp v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 22254 22255 assign( vA, getVSReg( vA_addr ) ); 22256 assign( exp, binop( Iop_And64, 22257 unop( Iop_V128HIto64, 22258 mkexpr( vB ) ), 22259 mkU64( 0x7FFFULL ) ) ); 22260 assign( vT, binop( Iop_64HLtoV128, 22261 binop( Iop_Or64, 22262 binop( Iop_And64, 22263 unop( Iop_V128HIto64, 22264 mkexpr( vA ) ), 22265 mkU64( 0x8000FFFFFFFFFFFFULL ) ), 22266 binop( Iop_Shl64, 22267 mkexpr( exp ), 22268 mkU8( 48 ) ) ), 22269 unop( Iop_V128to64, 22270 mkexpr( vA ) ) ) ); 22271 } 22272 break; 22273 22274 default: 22275 vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" ); 22276 22277 return False; 22278 } 22279 22280 putVSReg( vT_addr, mkexpr( vT ) ); 22281 return True; 22282 } 22283 22284 /* 22285 * VSX permute and other miscealleous instructions 22286 */ 22287 static Bool 22288 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 22289 { 22290 /* XX3-Form */ 22291 UChar opc1 = ifieldOPC( theInstr ); 22292 UChar XT = ifieldRegXT ( theInstr ); 22293 UChar XA = ifieldRegXA ( theInstr ); 22294 UChar XB = ifieldRegXB ( theInstr ); 22295 IRTemp vT = newTemp( Ity_V128 ); 22296 IRTemp vA = newTemp( Ity_V128 ); 22297 IRTemp vB = newTemp( Ity_V128 ); 22298 22299 if (opc1 != 0x3C) { 22300 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 22301 return False; 22302 } 22303 22304 assign( vA, getVSReg( XA ) ); 22305 assign( vB, getVSReg( XB ) ); 22306 22307 switch (opc2) { 22308 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 22309 { 22310 UChar SHW = ifieldSHW ( theInstr ); 22311 IRTemp result = newTemp(Ity_V128); 22312 if ( SHW != 0 ) { 22313 IRTemp hi = newTemp(Ity_V128); 22314 IRTemp lo = newTemp(Ity_V128); 22315 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 22316 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 22317 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 22318 } else 22319 assign ( result, mkexpr(vA) ); 22320 DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW); 22321 putVSReg( XT, mkexpr(result) ); 22322 break; 22323 } 22324 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 22325 { 22326 UChar DM = ifieldDM ( theInstr ); 22327 IRTemp hi = newTemp(Ity_I64); 22328 IRTemp lo = newTemp(Ity_I64); 22329 22330 if (DM & 0x2) 22331 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 22332 else 22333 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 22334 22335 if (DM & 0x1) 22336 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 22337 else 22338 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 22339 22340 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 22341 22342 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM); 22343 putVSReg( XT, mkexpr( vT ) ); 22344 break; 22345 } 22346 case 0x48: // xxmrghw (VSX Merge High Word) 22347 case 0xc8: // xxmrglw (VSX Merge Low Word) 22348 { 22349 const HChar type = (opc2 == 0x48) ? 'h' : 'l'; 22350 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 22351 IRTemp a64 = newTemp(Ity_I64); 22352 IRTemp ahi32 = newTemp(Ity_I32); 22353 IRTemp alo32 = newTemp(Ity_I32); 22354 IRTemp b64 = newTemp(Ity_I64); 22355 IRTemp bhi32 = newTemp(Ity_I32); 22356 IRTemp blo32 = newTemp(Ity_I32); 22357 22358 assign( a64, unop(word_op, mkexpr(vA)) ); 22359 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 22360 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 22361 22362 assign( b64, unop(word_op, mkexpr(vB)) ); 22363 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 22364 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 22365 22366 assign( vT, binop(Iop_64HLtoV128, 22367 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 22368 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 22369 22370 DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB); 22371 putVSReg( XT, mkexpr( vT ) ); 22372 break; 22373 } 22374 case 0x018: // xxsel (VSX Select) 22375 { 22376 UChar XC = ifieldRegXC(theInstr); 22377 IRTemp vC = newTemp( Ity_V128 ); 22378 assign( vC, getVSReg( XC ) ); 22379 DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC); 22380 /* vD = (vA & ~vC) | (vB & vC) */ 22381 putVSReg( XT, binop(Iop_OrV128, 22382 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 22383 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 22384 break; 22385 } 22386 22387 case 0x68: // xxperm (VSX Permute ) 22388 case 0xE8: // xxpermr (VSX Permute right-index ) 22389 { 22390 int i; 22391 IRTemp new_Vt[17]; 22392 IRTemp perm_val[16]; 22393 IRTemp perm_val_gt16[16]; 22394 IRTemp tmp_val[16]; 22395 IRTemp perm_idx[16]; 22396 IRTemp perm_mask = newTemp( Ity_V128 ); 22397 IRTemp val_mask = newTemp( Ity_V128 ); 22398 int dest_shift_amount = 0; 22399 22400 if ( opc2 == 0x68 ) { 22401 DIP("xxperm v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 22402 22403 } else { 22404 /* Same as xperm just the index is 31 - idx */ 22405 DIP("xxpermr v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 22406 } 22407 22408 new_Vt[0] = newTemp( Ity_V128 ); 22409 22410 assign( vT, getVSReg( XT ) ); 22411 22412 assign( new_Vt[0], binop( Iop_64HLtoV128, 22413 mkU64( 0x0 ), mkU64( 0x0 ) ) ); 22414 assign( perm_mask, binop( Iop_64HLtoV128, 22415 mkU64( 0x0 ), mkU64( 0x1F ) ) ); 22416 assign( val_mask, binop( Iop_64HLtoV128, 22417 mkU64( 0x0 ), mkU64( 0xFF ) ) ); 22418 22419 /* For each permute index in XB, the permute list, select the byte 22420 * from XA indexed by the permute index if the permute index is less 22421 * then 16. Copy the selected byte to the destination location in 22422 * the result. 22423 */ 22424 for ( i = 0; i < 16; i++ ) { 22425 perm_val_gt16[i] = newTemp( Ity_V128 ); 22426 perm_val[i] = newTemp( Ity_V128 ); 22427 perm_idx[i] = newTemp( Ity_I8 ); 22428 tmp_val[i] = newTemp( Ity_V128 ); 22429 new_Vt[i+1] = newTemp( Ity_V128 ); 22430 22431 /* create mask to extract the permute index value from vB, 22432 * store value in least significant bits of perm_val 22433 */ 22434 if ( opc2 == 0x68 ) 22435 /* xxperm, the perm value is the index value in XB */ 22436 assign( perm_val[i], binop( Iop_ShrV128, 22437 binop( Iop_AndV128, 22438 mkexpr(vB), 22439 binop( Iop_ShlV128, 22440 mkexpr( perm_mask ), 22441 mkU8( (15 - i) * 8 ) ) ), 22442 mkU8( (15 - i) * 8 ) ) ); 22443 22444 else 22445 /* xxpermr, the perm value is 31 - index value in XB */ 22446 assign( perm_val[i], 22447 binop( Iop_Sub8x16, 22448 binop( Iop_64HLtoV128, 22449 mkU64( 0 ), mkU64( 31 ) ), 22450 binop( Iop_ShrV128, 22451 binop( Iop_AndV128, 22452 mkexpr( vB ), 22453 binop( Iop_ShlV128, 22454 mkexpr( perm_mask ), 22455 mkU8( ( 15 - i ) * 8 ) ) ), 22456 mkU8( ( 15 - i ) * 8 ) ) ) ); 22457 22458 /* Determine if the perm_val[] > 16. If it is, then the value 22459 * will come from xT otherwise it comes from xA. Either way, 22460 * create the mask to get the value from the source using the 22461 * lower 3 bits of perm_val[]. Create a 128 bit mask from the 22462 * upper bit of perm_val[] to be used to select from xT or xA. 22463 */ 22464 assign( perm_val_gt16[i], 22465 binop(Iop_64HLtoV128, 22466 unop( Iop_1Sto64, 22467 unop( Iop_64to1, 22468 unop( Iop_V128to64, 22469 binop( Iop_ShrV128, 22470 mkexpr( perm_val[i] ), 22471 mkU8( 4 ) ) ) ) ), 22472 unop( Iop_1Sto64, 22473 unop( Iop_64to1, 22474 unop( Iop_V128to64, 22475 binop( Iop_ShrV128, 22476 mkexpr( perm_val[i] ), 22477 mkU8( 4 ) ) ) ) ) ) ); 22478 22479 assign( perm_idx[i], 22480 unop(Iop_32to8, 22481 binop( Iop_Mul32, 22482 binop( Iop_Sub32, 22483 mkU32( 15 ), 22484 unop( Iop_64to32, 22485 binop( Iop_And64, 22486 unop( Iop_V128to64, 22487 mkexpr( perm_val[i] ) ), 22488 mkU64( 0xF ) ) ) ), 22489 mkU32( 8 ) ) ) ); 22490 22491 dest_shift_amount = ( 15 - i )*8; 22492 22493 /* Use perm_val_gt16 to select value from vA or vT */ 22494 assign( tmp_val[i], 22495 binop( Iop_ShlV128, 22496 binop( Iop_ShrV128, 22497 binop( Iop_OrV128, 22498 binop( Iop_AndV128, 22499 mkexpr( vA ), 22500 binop( Iop_AndV128, 22501 unop( Iop_NotV128, 22502 mkexpr( perm_val_gt16[i] ) ), 22503 binop( Iop_ShlV128, 22504 mkexpr( val_mask ), 22505 mkexpr( perm_idx[i] ) ) ) ), 22506 binop( Iop_AndV128, 22507 mkexpr( vT ), 22508 binop( Iop_AndV128, 22509 mkexpr( perm_val_gt16[i] ), 22510 binop( Iop_ShlV128, 22511 mkexpr( val_mask ), 22512 mkexpr( perm_idx[i] ) ) ) ) ), 22513 mkexpr( perm_idx[i] ) ), 22514 mkU8( dest_shift_amount ) ) ); 22515 22516 assign( new_Vt[i+1], binop( Iop_OrV128, 22517 mkexpr( tmp_val[i] ), 22518 mkexpr( new_Vt[i] ) ) ); 22519 } 22520 putVSReg( XT, mkexpr( new_Vt[16] ) ); 22521 break; 22522 } 22523 22524 case 0x148: // xxspltw (VSX Splat Word) 22525 { 22526 UChar UIM = ifieldRegA(theInstr) & 3; 22527 UChar sh_uim = (3 - (UIM)) * 32; 22528 DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM); 22529 putVSReg( XT, 22530 unop( Iop_Dup32x4, 22531 unop( Iop_V128to32, 22532 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 22533 break; 22534 } 22535 22536 default: 22537 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 22538 return False; 22539 } 22540 return True; 22541 } 22542 22543 /* 22544 AltiVec Load Instructions 22545 */ 22546 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) 22547 { 22548 /* X-Form */ 22549 UChar opc1 = ifieldOPC(theInstr); 22550 UChar vD_addr = ifieldRegDS(theInstr); 22551 UChar rA_addr = ifieldRegA(theInstr); 22552 UChar rB_addr = ifieldRegB(theInstr); 22553 UInt opc2 = ifieldOPClo10(theInstr); 22554 UChar b0 = ifieldBIT0(theInstr); 22555 22556 IRType ty = mode64 ? Ity_I64 : Ity_I32; 22557 IRTemp EA = newTemp(ty); 22558 IRTemp EA_align16 = newTemp(ty); 22559 22560 if (opc1 != 0x1F || b0 != 0) { 22561 vex_printf("dis_av_load(ppc)(instr)\n"); 22562 return False; 22563 } 22564 22565 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 22566 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 22567 22568 switch (opc2) { 22569 22570 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 22571 IRDirty* d; 22572 UInt vD_off = vectorGuestRegOffset(vD_addr); 22573 IRExpr** args_be = mkIRExprVec_5( 22574 IRExpr_GSPTR(), 22575 mkU32(vD_off), 22576 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 22577 mkU32(0xF)), 22578 mkU32(0)/*left*/, 22579 mkU32(1)/*Big Endian*/); 22580 IRExpr** args_le = mkIRExprVec_5( 22581 IRExpr_GSPTR(), 22582 mkU32(vD_off), 22583 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 22584 mkU32(0xF)), 22585 mkU32(0)/*left*/, 22586 mkU32(0)/*Little Endian*/); 22587 if (!mode64) { 22588 d = unsafeIRDirty_0_N ( 22589 0/*regparms*/, 22590 "ppc32g_dirtyhelper_LVS", 22591 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 22592 args_be ); 22593 } else { 22594 if (host_endness == VexEndnessBE) 22595 d = unsafeIRDirty_0_N ( 22596 0/*regparms*/, 22597 "ppc64g_dirtyhelper_LVS", 22598 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 22599 args_be ); 22600 else 22601 d = unsafeIRDirty_0_N ( 22602 0/*regparms*/, 22603 "ppc64g_dirtyhelper_LVS", 22604 fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ), 22605 args_le ); 22606 } 22607 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22608 /* declare guest state effects */ 22609 d->nFxState = 1; 22610 vex_bzero(&d->fxState, sizeof(d->fxState)); 22611 d->fxState[0].fx = Ifx_Write; 22612 d->fxState[0].offset = vD_off; 22613 d->fxState[0].size = sizeof(U128); 22614 22615 /* execute the dirty call, side-effecting guest state */ 22616 stmt( IRStmt_Dirty(d) ); 22617 break; 22618 } 22619 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 22620 IRDirty* d; 22621 UInt vD_off = vectorGuestRegOffset(vD_addr); 22622 IRExpr** args_be = mkIRExprVec_5( 22623 IRExpr_GSPTR(), 22624 mkU32(vD_off), 22625 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 22626 mkU32(0xF)), 22627 mkU32(1)/*right*/, 22628 mkU32(1)/*Big Endian*/); 22629 IRExpr** args_le = mkIRExprVec_5( 22630 IRExpr_GSPTR(), 22631 mkU32(vD_off), 22632 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 22633 mkU32(0xF)), 22634 mkU32(1)/*right*/, 22635 mkU32(0)/*Little Endian*/); 22636 22637 if (!mode64) { 22638 d = unsafeIRDirty_0_N ( 22639 0/*regparms*/, 22640 "ppc32g_dirtyhelper_LVS", 22641 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 22642 args_be ); 22643 } else { 22644 if (host_endness == VexEndnessBE) 22645 d = unsafeIRDirty_0_N ( 22646 0/*regparms*/, 22647 "ppc64g_dirtyhelper_LVS", 22648 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 22649 args_be ); 22650 else 22651 d = unsafeIRDirty_0_N ( 22652 0/*regparms*/, 22653 "ppc64g_dirtyhelper_LVS", 22654 fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ), 22655 args_le ); 22656 } 22657 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22658 /* declare guest state effects */ 22659 d->nFxState = 1; 22660 vex_bzero(&d->fxState, sizeof(d->fxState)); 22661 d->fxState[0].fx = Ifx_Write; 22662 d->fxState[0].offset = vD_off; 22663 d->fxState[0].size = sizeof(U128); 22664 22665 /* execute the dirty call, side-effecting guest state */ 22666 stmt( IRStmt_Dirty(d) ); 22667 break; 22668 } 22669 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 22670 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22671 /* loads addressed byte into vector[EA[0:3] 22672 since all other destination bytes are undefined, 22673 can simply load entire vector from 16-aligned EA */ 22674 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 22675 break; 22676 22677 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 22678 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22679 /* see note for lvebx */ 22680 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 22681 break; 22682 22683 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 22684 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22685 /* see note for lvebx */ 22686 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 22687 break; 22688 22689 case 0x067: // lvx (Load Vector Indexed, AV p127) 22690 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22691 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 22692 break; 22693 22694 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 22695 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 22696 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 22697 break; 22698 22699 default: 22700 vex_printf("dis_av_load(ppc)(opc2)\n"); 22701 return False; 22702 } 22703 return True; 22704 } 22705 22706 /* 22707 AltiVec Store Instructions 22708 */ 22709 static Bool dis_av_store ( UInt theInstr ) 22710 { 22711 /* X-Form */ 22712 UChar opc1 = ifieldOPC(theInstr); 22713 UChar vS_addr = ifieldRegDS(theInstr); 22714 UChar rA_addr = ifieldRegA(theInstr); 22715 UChar rB_addr = ifieldRegB(theInstr); 22716 UInt opc2 = ifieldOPClo10(theInstr); 22717 UChar b0 = ifieldBIT0(theInstr); 22718 22719 IRType ty = mode64 ? Ity_I64 : Ity_I32; 22720 IRTemp EA = newTemp(ty); 22721 IRTemp addr_aligned = newTemp(ty); 22722 IRTemp vS = newTemp(Ity_V128); 22723 IRTemp eb = newTemp(Ity_I8); 22724 IRTemp idx = newTemp(Ity_I8); 22725 22726 if (opc1 != 0x1F || b0 != 0) { 22727 vex_printf("dis_av_store(ppc)(instr)\n"); 22728 return False; 22729 } 22730 22731 assign( vS, getVReg(vS_addr)); 22732 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 22733 22734 switch (opc2) { 22735 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 22736 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 22737 assign( eb, binop(Iop_And8, mkU8(0xF), 22738 unop(Iop_32to8, 22739 mkNarrowTo32(ty, mkexpr(EA)) )) ); 22740 if (host_endness == VexEndnessLE) { 22741 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 22742 } else { 22743 assign( idx, binop(Iop_Shl8, 22744 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 22745 mkU8(3)) ); 22746 } 22747 store( mkexpr(EA), 22748 unop( Iop_32to8, unop(Iop_V128to32, 22749 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 22750 break; 22751 } 22752 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 22753 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 22754 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 22755 assign( eb, binop(Iop_And8, mkU8(0xF), 22756 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 22757 if (host_endness == VexEndnessLE) { 22758 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 22759 } else { 22760 assign( idx, binop(Iop_Shl8, 22761 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 22762 mkU8(3)) ); 22763 } 22764 store( mkexpr(addr_aligned), 22765 unop( Iop_32to16, unop(Iop_V128to32, 22766 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 22767 break; 22768 } 22769 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 22770 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 22771 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 22772 assign( eb, binop(Iop_And8, mkU8(0xF), 22773 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 22774 if (host_endness == VexEndnessLE) { 22775 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 22776 } else { 22777 assign( idx, binop(Iop_Shl8, 22778 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 22779 mkU8(3)) ); 22780 } 22781 store( mkexpr( addr_aligned), 22782 unop( Iop_V128to32, 22783 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 22784 break; 22785 } 22786 22787 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 22788 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 22789 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 22790 break; 22791 22792 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 22793 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 22794 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 22795 break; 22796 22797 default: 22798 vex_printf("dis_av_store(ppc)(opc2)\n"); 22799 return False; 22800 } 22801 return True; 22802 } 22803 22804 /* 22805 AltiVec Arithmetic Instructions 22806 */ 22807 static Bool dis_av_arith ( UInt theInstr ) 22808 { 22809 /* VX-Form */ 22810 UChar opc1 = ifieldOPC(theInstr); 22811 UChar vD_addr = ifieldRegDS(theInstr); 22812 UChar vA_addr = ifieldRegA(theInstr); 22813 UChar vB_addr = ifieldRegB(theInstr); 22814 UInt opc2 = IFIELD( theInstr, 0, 11 ); 22815 22816 IRTemp vA = newTemp(Ity_V128); 22817 IRTemp vB = newTemp(Ity_V128); 22818 IRTemp z3 = newTemp(Ity_I64); 22819 IRTemp z2 = newTemp(Ity_I64); 22820 IRTemp z1 = newTemp(Ity_I64); 22821 IRTemp z0 = newTemp(Ity_I64); 22822 IRTemp aEvn, aOdd; 22823 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 22824 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 22825 IRTemp b3, b2, b1, b0; 22826 22827 aEvn = aOdd = IRTemp_INVALID; 22828 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 22829 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 22830 b3 = b2 = b1 = b0 = IRTemp_INVALID; 22831 22832 assign( vA, getVReg( vA_addr ) ); 22833 assign( vB, getVReg( vB_addr ) ); 22834 22835 if (opc1 != 0x4) { 22836 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 22837 return False; 22838 } 22839 22840 switch (opc2) { 22841 /* Add */ 22842 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 22843 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22844 /* unsigned_ov(x+y) = (y >u not(x)) */ 22845 putVReg( vD_addr, binop( Iop_ShrN32x4, 22846 binop( Iop_CmpGT32Ux4, mkexpr( vB ), 22847 unop( Iop_NotV128, mkexpr( vA ) ) ), 22848 mkU8( 31 ) ) ); 22849 break; 22850 } 22851 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 22852 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22853 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 22854 break; 22855 22856 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 22857 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22858 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 22859 break; 22860 22861 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 22862 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22863 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 22864 break; 22865 22866 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo) 22867 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22868 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) ); 22869 break; 22870 22871 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 22872 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22873 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 22874 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 22875 break; 22876 22877 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 22878 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22879 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 22880 // TODO: set VSCR[SAT] 22881 break; 22882 22883 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 22884 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22885 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 22886 // TODO: set VSCR[SAT] 22887 break; 22888 22889 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 22890 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22891 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 22892 // TODO: set VSCR[SAT] 22893 break; 22894 22895 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 22896 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22897 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 22898 // TODO: set VSCR[SAT] 22899 break; 22900 22901 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 22902 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22903 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 22904 // TODO: set VSCR[SAT] 22905 break; 22906 22907 22908 /* Subtract */ 22909 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 22910 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22911 /* unsigned_ov(x-y) = (y >u x) */ 22912 putVReg( vD_addr, binop(Iop_ShrN32x4, 22913 unop(Iop_NotV128, 22914 binop(Iop_CmpGT32Ux4, mkexpr(vB), 22915 mkexpr(vA))), 22916 mkU8(31)) ); 22917 break; 22918 } 22919 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 22920 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22921 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 22922 break; 22923 22924 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 22925 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22926 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 22927 break; 22928 22929 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 22930 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22931 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 22932 break; 22933 22934 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo) 22935 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22936 putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) ); 22937 break; 22938 22939 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 22940 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22941 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 22942 // TODO: set VSCR[SAT] 22943 break; 22944 22945 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 22946 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22947 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 22948 // TODO: set VSCR[SAT] 22949 break; 22950 22951 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 22952 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22953 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 22954 // TODO: set VSCR[SAT] 22955 break; 22956 22957 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 22958 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22959 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 22960 // TODO: set VSCR[SAT] 22961 break; 22962 22963 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 22964 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22965 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 22966 // TODO: set VSCR[SAT] 22967 break; 22968 22969 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 22970 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22971 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 22972 // TODO: set VSCR[SAT] 22973 break; 22974 22975 22976 /* Maximum */ 22977 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 22978 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22979 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 22980 break; 22981 22982 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 22983 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22984 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 22985 break; 22986 22987 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 22988 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22989 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 22990 break; 22991 22992 case 0x0C2: // vmaxud (Maximum Unsigned Double word) 22993 DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22994 putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) ); 22995 break; 22996 22997 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 22998 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 22999 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 23000 break; 23001 23002 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 23003 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23004 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 23005 break; 23006 23007 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 23008 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23009 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 23010 break; 23011 23012 case 0x1C2: // vmaxsd (Maximum Signed Double word) 23013 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23014 putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) ); 23015 break; 23016 23017 /* Minimum */ 23018 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 23019 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23020 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 23021 break; 23022 23023 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 23024 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23025 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 23026 break; 23027 23028 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 23029 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23030 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 23031 break; 23032 23033 case 0x2C2: // vminud (Minimum Unsigned Double Word) 23034 DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23035 putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) ); 23036 break; 23037 23038 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 23039 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23040 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 23041 break; 23042 23043 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 23044 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23045 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 23046 break; 23047 23048 case 0x382: // vminsw (Minimum Signed Word, AV p190) 23049 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23050 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 23051 break; 23052 23053 case 0x3C2: // vminsd (Minimum Signed Double Word) 23054 DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23055 putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) ); 23056 break; 23057 23058 23059 /* Average */ 23060 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 23061 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23062 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 23063 break; 23064 23065 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 23066 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23067 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 23068 break; 23069 23070 case 0x482: // vavguw (Average Unsigned Word, AV p154) 23071 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23072 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 23073 break; 23074 23075 case 0x502: // vavgsb (Average Signed Byte, AV p149) 23076 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23077 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 23078 break; 23079 23080 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 23081 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23082 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 23083 break; 23084 23085 case 0x582: // vavgsw (Average Signed Word, AV p151) 23086 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23087 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 23088 break; 23089 23090 23091 /* Multiply */ 23092 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 23093 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23094 putVReg( vD_addr, 23095 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 23096 break; 23097 23098 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 23099 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23100 putVReg( vD_addr, 23101 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 23102 break; 23103 23104 case 0x088: // vmulouw (Multiply Odd Unsigned Word) 23105 DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23106 putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) ); 23107 break; 23108 23109 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo) 23110 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23111 putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) ); 23112 break; 23113 23114 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 23115 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23116 putVReg( vD_addr, 23117 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 23118 break; 23119 23120 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 23121 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23122 putVReg( vD_addr, 23123 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 23124 break; 23125 23126 case 0x188: // vmulosw (Multiply Odd Signed Word) 23127 DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23128 putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) ); 23129 break; 23130 23131 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 23132 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23133 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 23134 break; 23135 23136 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 23137 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23138 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 23139 break; 23140 23141 case 0x288: // vmuleuw (Multiply Even Unsigned Word) 23142 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23143 putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) ); 23144 break; 23145 23146 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 23147 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23148 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 23149 break; 23150 23151 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 23152 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23153 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 23154 break; 23155 23156 case 0x388: // vmulesw (Multiply Even Signed Word) 23157 DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23158 putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) ); 23159 break; 23160 23161 /* Sum Across Partial */ 23162 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 23163 IRTemp aEE, aEO, aOE, aOO; 23164 aEE = aEO = aOE = aOO = IRTemp_INVALID; 23165 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23166 23167 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 23168 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 23169 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 23170 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 23171 23172 /* break V128 to 4xI32's, zero-extending to I64's */ 23173 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 23174 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 23175 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 23176 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 23177 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 23178 23179 /* add lanes */ 23180 assign( z3, binop(Iop_Add64, mkexpr(b3), 23181 binop(Iop_Add64, 23182 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 23183 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 23184 assign( z2, binop(Iop_Add64, mkexpr(b2), 23185 binop(Iop_Add64, 23186 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 23187 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 23188 assign( z1, binop(Iop_Add64, mkexpr(b1), 23189 binop(Iop_Add64, 23190 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 23191 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 23192 assign( z0, binop(Iop_Add64, mkexpr(b0), 23193 binop(Iop_Add64, 23194 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 23195 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 23196 23197 /* saturate-narrow to 32bit, and combine to V128 */ 23198 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 23199 mkexpr(z1), mkexpr(z0)) ); 23200 break; 23201 } 23202 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 23203 IRTemp aEE, aEO, aOE, aOO; 23204 aEE = aEO = aOE = aOO = IRTemp_INVALID; 23205 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23206 23207 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 23208 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 23209 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 23210 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 23211 23212 /* break V128 to 4xI32's, sign-extending to I64's */ 23213 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 23214 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 23215 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 23216 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 23217 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 23218 23219 /* add lanes */ 23220 assign( z3, binop(Iop_Add64, mkexpr(b3), 23221 binop(Iop_Add64, 23222 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 23223 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 23224 assign( z2, binop(Iop_Add64, mkexpr(b2), 23225 binop(Iop_Add64, 23226 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 23227 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 23228 assign( z1, binop(Iop_Add64, mkexpr(b1), 23229 binop(Iop_Add64, 23230 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 23231 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 23232 assign( z0, binop(Iop_Add64, mkexpr(b0), 23233 binop(Iop_Add64, 23234 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 23235 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 23236 23237 /* saturate-narrow to 32bit, and combine to V128 */ 23238 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 23239 mkexpr(z1), mkexpr(z0)) ); 23240 break; 23241 } 23242 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 23243 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23244 23245 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 23246 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 23247 23248 /* break V128 to 4xI32's, sign-extending to I64's */ 23249 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 23250 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 23251 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 23252 23253 /* add lanes */ 23254 assign( z3, binop(Iop_Add64, mkexpr(b3), 23255 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 23256 assign( z2, binop(Iop_Add64, mkexpr(b2), 23257 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 23258 assign( z1, binop(Iop_Add64, mkexpr(b1), 23259 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 23260 assign( z0, binop(Iop_Add64, mkexpr(b0), 23261 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 23262 23263 /* saturate-narrow to 32bit, and combine to V128 */ 23264 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 23265 mkexpr(z1), mkexpr(z0)) ); 23266 break; 23267 } 23268 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 23269 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23270 23271 /* break V128 to 4xI32's, sign-extending to I64's */ 23272 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 23273 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 23274 23275 /* add lanes */ 23276 assign( z2, binop(Iop_Add64, mkexpr(b2), 23277 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 23278 assign( z0, binop(Iop_Add64, mkexpr(b0), 23279 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 23280 23281 /* saturate-narrow to 32bit, and combine to V128 */ 23282 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 23283 mkU64(0), mkexpr(z0)) ); 23284 break; 23285 } 23286 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 23287 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23288 23289 /* break V128 to 4xI32's, sign-extending to I64's */ 23290 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 23291 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 23292 23293 /* add lanes */ 23294 assign( z0, binop(Iop_Add64, mkexpr(b0), 23295 binop(Iop_Add64, 23296 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 23297 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 23298 23299 /* saturate-narrow to 32bit, and combine to V128 */ 23300 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 23301 mkU64(0), mkexpr(z0)) ); 23302 break; 23303 } 23304 default: 23305 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 23306 return False; 23307 } 23308 return True; 23309 } 23310 23311 /* 23312 AltiVec Logic Instructions 23313 */ 23314 static Bool dis_av_logic ( UInt theInstr ) 23315 { 23316 /* VX-Form */ 23317 UChar opc1 = ifieldOPC(theInstr); 23318 UChar vD_addr = ifieldRegDS(theInstr); 23319 UChar vA_addr = ifieldRegA(theInstr); 23320 UChar vB_addr = ifieldRegB(theInstr); 23321 UInt opc2 = IFIELD( theInstr, 0, 11 ); 23322 23323 IRTemp vA = newTemp(Ity_V128); 23324 IRTemp vB = newTemp(Ity_V128); 23325 assign( vA, getVReg(vA_addr)); 23326 assign( vB, getVReg(vB_addr)); 23327 23328 if (opc1 != 0x4) { 23329 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 23330 return False; 23331 } 23332 23333 switch (opc2) { 23334 case 0x404: // vand (And, AV p147) 23335 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23336 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 23337 break; 23338 23339 case 0x444: // vandc (And, AV p148) 23340 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23341 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 23342 unop(Iop_NotV128, mkexpr(vB))) ); 23343 break; 23344 23345 case 0x484: // vor (Or, AV p217) 23346 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23347 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 23348 break; 23349 23350 case 0x4C4: // vxor (Xor, AV p282) 23351 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23352 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 23353 break; 23354 23355 case 0x504: // vnor (Nor, AV p216) 23356 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23357 putVReg( vD_addr, 23358 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 23359 break; 23360 23361 case 0x544: // vorc (vA Or'd with complement of vb) 23362 DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23363 putVReg( vD_addr, binop( Iop_OrV128, 23364 mkexpr( vA ), 23365 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 23366 break; 23367 23368 case 0x584: // vnand (Nand) 23369 DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23370 putVReg( vD_addr, unop( Iop_NotV128, 23371 binop(Iop_AndV128, mkexpr( vA ), 23372 mkexpr( vB ) ) ) ); 23373 break; 23374 23375 case 0x684: // veqv (complemented XOr) 23376 DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23377 putVReg( vD_addr, unop( Iop_NotV128, 23378 binop( Iop_XorV128, mkexpr( vA ), 23379 mkexpr( vB ) ) ) ); 23380 break; 23381 23382 default: 23383 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 23384 return False; 23385 } 23386 return True; 23387 } 23388 23389 /* 23390 AltiVec Compare Instructions 23391 */ 23392 static Bool dis_av_cmp ( UInt theInstr ) 23393 { 23394 /* VXR-Form */ 23395 UChar opc1 = ifieldOPC(theInstr); 23396 UChar vD_addr = ifieldRegDS(theInstr); 23397 UChar vA_addr = ifieldRegA(theInstr); 23398 UChar vB_addr = ifieldRegB(theInstr); 23399 UChar flag_rC = ifieldBIT10(theInstr); 23400 UInt opc2 = IFIELD( theInstr, 0, 10 ); 23401 23402 IRTemp vA = newTemp(Ity_V128); 23403 IRTemp vB = newTemp(Ity_V128); 23404 IRTemp vD = newTemp(Ity_V128); 23405 assign( vA, getVReg(vA_addr)); 23406 assign( vB, getVReg(vB_addr)); 23407 23408 if (opc1 != 0x4) { 23409 vex_printf("dis_av_cmp(ppc)(instr)\n"); 23410 return False; 23411 } 23412 23413 switch (opc2) { 23414 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 23415 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23416 vD_addr, vA_addr, vB_addr); 23417 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 23418 break; 23419 23420 case 0x007: // vcmpneb (Compare Not Equal byte) 23421 DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23422 vD_addr, vA_addr, vB_addr); 23423 assign( vD, unop( Iop_NotV128, 23424 binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( vB ) ) ) ); 23425 break; 23426 23427 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 23428 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23429 vD_addr, vA_addr, vB_addr); 23430 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 23431 break; 23432 23433 case 0x047: // vcmpneh (Compare Not Equal-to Halfword) 23434 DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23435 vD_addr, vA_addr, vB_addr); 23436 assign( vD, unop( Iop_NotV128, 23437 binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( vB ) ) ) ); 23438 break; 23439 23440 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 23441 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23442 vD_addr, vA_addr, vB_addr); 23443 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 23444 break; 23445 23446 case 0x087: // vcmpnew (Compare Not Equal-to Word) 23447 DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23448 vD_addr, vA_addr, vB_addr); 23449 assign( vD, unop( Iop_NotV128, 23450 binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( vB ) ) ) ); 23451 break; 23452 23453 case 0x107: // vcmpnezb (Compare Not Equal or Zero byte) 23454 { 23455 IRTemp vAeqvB = newTemp( Ity_V128 ); 23456 IRTemp vAeq0 = newTemp( Ity_V128 ); 23457 IRTemp vBeq0 = newTemp( Ity_V128 ); 23458 IRTemp zero = newTemp( Ity_V128 ); 23459 23460 DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23461 vD_addr, vA_addr, vB_addr); 23462 23463 assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) ); 23464 assign( vAeq0, binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( zero ) ) ); 23465 assign( vBeq0, binop( Iop_CmpEQ8x16, mkexpr( vB ), mkexpr( zero ) ) ); 23466 assign( vAeqvB, unop( Iop_NotV128, 23467 binop( Iop_CmpEQ8x16, mkexpr( vA ), 23468 mkexpr( vB ) ) ) ); 23469 23470 assign( vD, mkOr3_V128( vAeqvB, vAeq0, vBeq0 ) ); 23471 } 23472 break; 23473 23474 case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword) 23475 { 23476 IRTemp vAeqvB = newTemp( Ity_V128 ); 23477 IRTemp vAeq0 = newTemp( Ity_V128 ); 23478 IRTemp vBeq0 = newTemp( Ity_V128 ); 23479 IRTemp zero = newTemp( Ity_V128 ); 23480 23481 DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23482 vD_addr, vA_addr, vB_addr); 23483 23484 assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) ); 23485 assign( vAeq0, binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( zero ) ) ); 23486 assign( vBeq0, binop( Iop_CmpEQ16x8, mkexpr( vB ), mkexpr( zero ) ) ); 23487 assign( vAeqvB, unop( Iop_NotV128, 23488 binop(Iop_CmpEQ16x8, mkexpr( vA ), 23489 mkexpr( vB ) ) ) ); 23490 23491 assign( vD, binop( Iop_OrV128, 23492 binop( Iop_OrV128, 23493 mkexpr( vAeq0 ), 23494 mkexpr( vBeq0 ) ), 23495 mkexpr( vAeqvB ) ) ); 23496 } 23497 break; 23498 23499 case 0x187: // vcmpnezw (Compare Not Equal or Zero Word) 23500 { 23501 IRTemp vAeqvB = newTemp( Ity_V128 ); 23502 IRTemp vAeq0 = newTemp( Ity_V128 ); 23503 IRTemp vBeq0 = newTemp( Ity_V128 ); 23504 IRTemp zero = newTemp( Ity_V128 ); 23505 23506 DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23507 vD_addr, vA_addr, vB_addr); 23508 23509 assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) ); 23510 assign( vAeq0, binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( zero ) ) ); 23511 assign( vBeq0, binop( Iop_CmpEQ32x4, mkexpr( vB ), mkexpr( zero ) ) ); 23512 assign( vAeqvB, unop( Iop_NotV128, 23513 binop(Iop_CmpEQ32x4, mkexpr( vA ), 23514 mkexpr( vB ) ) ) ); 23515 23516 assign( vD, binop( Iop_OrV128, 23517 binop( Iop_OrV128, 23518 mkexpr( vAeq0 ), 23519 mkexpr( vBeq0 ) ), 23520 mkexpr( vAeqvB ) ) ); 23521 } 23522 break; 23523 23524 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword) 23525 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23526 vD_addr, vA_addr, vB_addr); 23527 assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) ); 23528 break; 23529 23530 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 23531 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23532 vD_addr, vA_addr, vB_addr); 23533 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 23534 break; 23535 23536 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 23537 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23538 vD_addr, vA_addr, vB_addr); 23539 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 23540 break; 23541 23542 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 23543 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23544 vD_addr, vA_addr, vB_addr); 23545 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 23546 break; 23547 23548 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double) 23549 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23550 vD_addr, vA_addr, vB_addr); 23551 assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) ); 23552 break; 23553 23554 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 23555 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23556 vD_addr, vA_addr, vB_addr); 23557 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 23558 break; 23559 23560 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 23561 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23562 vD_addr, vA_addr, vB_addr); 23563 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 23564 break; 23565 23566 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 23567 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23568 vD_addr, vA_addr, vB_addr); 23569 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 23570 break; 23571 23572 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double) 23573 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 23574 vD_addr, vA_addr, vB_addr); 23575 assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) ); 23576 break; 23577 23578 default: 23579 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 23580 return False; 23581 } 23582 23583 putVReg( vD_addr, mkexpr(vD) ); 23584 23585 if (flag_rC) { 23586 set_AV_CR6( mkexpr(vD), True ); 23587 } 23588 return True; 23589 } 23590 23591 /* 23592 AltiVec Multiply-Sum Instructions 23593 */ 23594 static Bool dis_av_multarith ( UInt theInstr ) 23595 { 23596 /* VA-Form */ 23597 UChar opc1 = ifieldOPC(theInstr); 23598 UChar vD_addr = ifieldRegDS(theInstr); 23599 UChar vA_addr = ifieldRegA(theInstr); 23600 UChar vB_addr = ifieldRegB(theInstr); 23601 UChar vC_addr = ifieldRegC(theInstr); 23602 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 23603 23604 IRTemp vA = newTemp(Ity_V128); 23605 IRTemp vB = newTemp(Ity_V128); 23606 IRTemp vC = newTemp(Ity_V128); 23607 IRTemp zeros = newTemp(Ity_V128); 23608 IRTemp aLo = newTemp(Ity_V128); 23609 IRTemp bLo = newTemp(Ity_V128); 23610 IRTemp cLo = newTemp(Ity_V128); 23611 IRTemp zLo = newTemp(Ity_V128); 23612 IRTemp aHi = newTemp(Ity_V128); 23613 IRTemp bHi = newTemp(Ity_V128); 23614 IRTemp cHi = newTemp(Ity_V128); 23615 IRTemp zHi = newTemp(Ity_V128); 23616 IRTemp abEvn = newTemp(Ity_V128); 23617 IRTemp abOdd = newTemp(Ity_V128); 23618 IRTemp z3 = newTemp(Ity_I64); 23619 IRTemp z2 = newTemp(Ity_I64); 23620 IRTemp z1 = newTemp(Ity_I64); 23621 IRTemp z0 = newTemp(Ity_I64); 23622 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 23623 IRTemp c3, c2, c1, c0; 23624 23625 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 23626 c3 = c2 = c1 = c0 = IRTemp_INVALID; 23627 23628 assign( vA, getVReg(vA_addr)); 23629 assign( vB, getVReg(vB_addr)); 23630 assign( vC, getVReg(vC_addr)); 23631 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 23632 23633 if (opc1 != 0x4) { 23634 vex_printf("dis_av_multarith(ppc)(instr)\n"); 23635 return False; 23636 } 23637 23638 switch (opc2) { 23639 /* Multiply-Add */ 23640 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 23641 IRTemp cSigns = newTemp(Ity_V128); 23642 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 23643 vD_addr, vA_addr, vB_addr, vC_addr); 23644 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 23645 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 23646 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 23647 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 23648 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 23649 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 23650 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 23651 23652 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 23653 binop(Iop_SarN32x4, 23654 binop(Iop_MullEven16Sx8, 23655 mkexpr(aLo), mkexpr(bLo)), 23656 mkU8(15))) ); 23657 23658 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 23659 binop(Iop_SarN32x4, 23660 binop(Iop_MullEven16Sx8, 23661 mkexpr(aHi), mkexpr(bHi)), 23662 mkU8(15))) ); 23663 23664 putVReg( vD_addr, 23665 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 23666 break; 23667 } 23668 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 23669 IRTemp zKonst = newTemp(Ity_V128); 23670 IRTemp cSigns = newTemp(Ity_V128); 23671 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 23672 vD_addr, vA_addr, vB_addr, vC_addr); 23673 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 23674 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 23675 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 23676 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 23677 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 23678 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 23679 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 23680 23681 /* shifting our const avoids store/load version of Dup */ 23682 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 23683 mkU8(14)) ); 23684 23685 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 23686 binop(Iop_SarN32x4, 23687 binop(Iop_Add32x4, mkexpr(zKonst), 23688 binop(Iop_MullEven16Sx8, 23689 mkexpr(aLo), mkexpr(bLo))), 23690 mkU8(15))) ); 23691 23692 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 23693 binop(Iop_SarN32x4, 23694 binop(Iop_Add32x4, mkexpr(zKonst), 23695 binop(Iop_MullEven16Sx8, 23696 mkexpr(aHi), mkexpr(bHi))), 23697 mkU8(15))) ); 23698 23699 putVReg( vD_addr, 23700 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 23701 break; 23702 } 23703 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 23704 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 23705 vD_addr, vA_addr, vB_addr, vC_addr); 23706 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 23707 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 23708 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 23709 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 23710 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 23711 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 23712 assign(zLo, binop(Iop_Add32x4, 23713 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 23714 mkexpr(cLo)) ); 23715 assign(zHi, binop(Iop_Add32x4, 23716 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 23717 mkexpr(cHi))); 23718 putVReg( vD_addr, 23719 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 23720 break; 23721 } 23722 23723 case 0x23: { // vmsumudm 23724 DIP("vmsumudm v%d,v%d,v%d,v%d\n", 23725 vD_addr, vA_addr, vB_addr, vC_addr); 23726 /* This instruction takes input vectors VA, VB consisting of 2 usigned 23727 64-bit integer elements and a 128 bit unsigned input U128_C. The 23728 instruction performs the following operation: 23729 23730 VA[0] * VB[0] -> U128_mul_result0; 23731 VA[1] * VB[1] -> U128_mul_result1; 23732 U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum; 23733 carry out and overflow is discarded. 23734 */ 23735 23736 /* The Iop_MulI128low assumes the upper 64-bits in the two input operands 23737 are zero. */ 23738 IRTemp mul_result0 = newTemp( Ity_I128 ); 23739 IRTemp mul_result1 = newTemp( Ity_I128 ); 23740 IRTemp partial_sum_hi = newTemp( Ity_I64 ); 23741 IRTemp partial_sum_low = newTemp( Ity_I64 ); 23742 IRTemp result_hi = newTemp( Ity_I64 ); 23743 IRTemp result_low = newTemp( Ity_I64 ); 23744 IRExpr *ca_sum, *ca_result; 23745 23746 23747 /* Do multiplications */ 23748 assign ( mul_result0, binop( Iop_MullU64, 23749 unop( Iop_V128to64, mkexpr( vA ) ), 23750 unop( Iop_V128to64, mkexpr( vB) ) ) ); 23751 23752 assign ( mul_result1, binop( Iop_MullU64, 23753 unop( Iop_V128HIto64, mkexpr( vA ) ), 23754 unop( Iop_V128HIto64, mkexpr( vB) ) ) ); 23755 23756 /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry 23757 from low 64-bits add into sum of upper 64-bits. Throw away carry out 23758 of the upper 64-bit sum. */ 23759 assign ( partial_sum_low, binop( Iop_Add64, 23760 unop( Iop_128to64, mkexpr( mul_result0 ) ), 23761 unop( Iop_128to64, mkexpr( mul_result1 ) ) 23762 ) ); 23763 23764 /* ca_sum is type U32 */ 23765 ca_sum = calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD, 23766 mkexpr(partial_sum_low ), 23767 unop( Iop_128to64, mkexpr( mul_result0 ) ), 23768 unop( Iop_128to64, mkexpr( mul_result1 ) ), 23769 mkU64( 0 ) ); 23770 23771 assign ( partial_sum_hi, 23772 binop( Iop_Add64, 23773 binop( Iop_Add64, 23774 unop( Iop_128HIto64, mkexpr( mul_result0 ) ), 23775 unop( Iop_128HIto64, mkexpr( mul_result1 ) ) ), 23776 binop( Iop_32HLto64, mkU32( 0 ), ca_sum ) ) ); 23777 23778 /* Now add in the value of C */ 23779 assign ( result_low, binop( Iop_Add64, 23780 mkexpr( partial_sum_low ), 23781 unop( Iop_V128to64, mkexpr( vC ) ) ) ); 23782 23783 /* ca_result is type U32 */ 23784 ca_result = calculate_XER_CA_64( PPCG_FLAG_OP_ADD, 23785 mkexpr( result_low ), 23786 mkexpr( partial_sum_low ), 23787 unop( Iop_V128to64, 23788 mkexpr( vC ) ), 23789 mkU64( 0 ) ); 23790 23791 assign ( result_hi, 23792 binop( Iop_Add64, 23793 binop( Iop_Add64, 23794 mkexpr( partial_sum_hi ), 23795 unop( Iop_V128HIto64, mkexpr( vC ) ) ), 23796 binop( Iop_32HLto64, mkU32( 0 ), ca_result ) ) ); 23797 23798 putVReg( vD_addr, binop( Iop_64HLtoV128, 23799 mkexpr( result_hi ), mkexpr ( result_low ) ) ); 23800 break; 23801 } 23802 23803 /* Multiply-Sum */ 23804 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 23805 IRTemp abEE, abEO, abOE, abOO; 23806 abEE = abEO = abOE = abOO = IRTemp_INVALID; 23807 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 23808 vD_addr, vA_addr, vB_addr, vC_addr); 23809 23810 /* multiply vA,vB (unsigned, widening) */ 23811 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 23812 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 23813 23814 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 23815 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 23816 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 23817 23818 putVReg( vD_addr, 23819 binop(Iop_Add32x4, mkexpr(vC), 23820 binop(Iop_Add32x4, 23821 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 23822 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 23823 break; 23824 } 23825 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 23826 IRTemp aEvn, aOdd, bEvn, bOdd; 23827 IRTemp abEE = newTemp(Ity_V128); 23828 IRTemp abEO = newTemp(Ity_V128); 23829 IRTemp abOE = newTemp(Ity_V128); 23830 IRTemp abOO = newTemp(Ity_V128); 23831 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 23832 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 23833 vD_addr, vA_addr, vB_addr, vC_addr); 23834 23835 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 23836 (separating out adjacent lanes to different vectors) */ 23837 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 23838 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 23839 23840 /* multiply vA, vB, again separating adjacent lanes */ 23841 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 23842 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 23843 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 23844 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 23845 23846 /* add results together, + vC */ 23847 putVReg( vD_addr, 23848 binop(Iop_QAdd32Sx4, mkexpr(vC), 23849 binop(Iop_QAdd32Sx4, 23850 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 23851 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 23852 break; 23853 } 23854 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 23855 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 23856 vD_addr, vA_addr, vB_addr, vC_addr); 23857 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 23858 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 23859 putVReg( vD_addr, 23860 binop(Iop_Add32x4, mkexpr(vC), 23861 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 23862 break; 23863 } 23864 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 23865 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 23866 vD_addr, vA_addr, vB_addr, vC_addr); 23867 /* widening multiply, separating lanes */ 23868 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 23869 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 23870 23871 /* break V128 to 4xI32's, zero-extending to I64's */ 23872 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 23873 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 23874 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 23875 23876 /* add lanes */ 23877 assign( z3, binop(Iop_Add64, mkexpr(c3), 23878 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 23879 assign( z2, binop(Iop_Add64, mkexpr(c2), 23880 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 23881 assign( z1, binop(Iop_Add64, mkexpr(c1), 23882 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 23883 assign( z0, binop(Iop_Add64, mkexpr(c0), 23884 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 23885 23886 /* saturate-narrow to 32bit, and combine to V128 */ 23887 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 23888 mkexpr(z1), mkexpr(z0)) ); 23889 23890 break; 23891 } 23892 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 23893 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 23894 vD_addr, vA_addr, vB_addr, vC_addr); 23895 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 23896 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 23897 putVReg( vD_addr, 23898 binop(Iop_Add32x4, mkexpr(vC), 23899 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 23900 break; 23901 } 23902 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 23903 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 23904 vD_addr, vA_addr, vB_addr, vC_addr); 23905 /* widening multiply, separating lanes */ 23906 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 23907 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 23908 23909 /* break V128 to 4xI32's, sign-extending to I64's */ 23910 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 23911 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 23912 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 23913 23914 /* add lanes */ 23915 assign( z3, binop(Iop_Add64, mkexpr(c3), 23916 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 23917 assign( z2, binop(Iop_Add64, mkexpr(c2), 23918 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 23919 assign( z1, binop(Iop_Add64, mkexpr(c1), 23920 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 23921 assign( z0, binop(Iop_Add64, mkexpr(c0), 23922 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 23923 23924 /* saturate-narrow to 32bit, and combine to V128 */ 23925 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 23926 mkexpr(z1), mkexpr(z0)) ); 23927 break; 23928 } 23929 default: 23930 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 23931 return False; 23932 } 23933 return True; 23934 } 23935 23936 /* 23937 AltiVec Polynomial Multiply-Sum Instructions 23938 */ 23939 static Bool dis_av_polymultarith ( UInt theInstr ) 23940 { 23941 /* VA-Form */ 23942 UChar opc1 = ifieldOPC(theInstr); 23943 UChar vD_addr = ifieldRegDS(theInstr); 23944 UChar vA_addr = ifieldRegA(theInstr); 23945 UChar vB_addr = ifieldRegB(theInstr); 23946 UChar vC_addr = ifieldRegC(theInstr); 23947 UInt opc2 = IFIELD(theInstr, 0, 11); 23948 IRTemp vA = newTemp(Ity_V128); 23949 IRTemp vB = newTemp(Ity_V128); 23950 IRTemp vC = newTemp(Ity_V128); 23951 23952 assign( vA, getVReg(vA_addr)); 23953 assign( vB, getVReg(vB_addr)); 23954 assign( vC, getVReg(vC_addr)); 23955 23956 if (opc1 != 0x4) { 23957 vex_printf("dis_av_polymultarith(ppc)(instr)\n"); 23958 return False; 23959 } 23960 23961 switch (opc2) { 23962 /* Polynomial Multiply-Add */ 23963 case 0x408: // vpmsumb Vector Polynomial Multiply-sum Byte 23964 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23965 putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16, 23966 mkexpr(vA), mkexpr(vB)) ); 23967 break; 23968 case 0x448: // vpmsumd Vector Polynomial Multiply-sum Double Word 23969 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23970 putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2, 23971 mkexpr(vA), mkexpr(vB)) ); 23972 break; 23973 case 0x488: // vpmsumw Vector Polynomial Multiply-sum Word 23974 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23975 putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4, 23976 mkexpr(vA), mkexpr(vB)) ); 23977 break; 23978 case 0x4C8: // vpmsumh Vector Polynomial Multiply-sum Half Word 23979 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 23980 putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8, 23981 mkexpr(vA), mkexpr(vB)) ); 23982 break; 23983 default: 23984 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2); 23985 return False; 23986 } 23987 return True; 23988 } 23989 23990 /* 23991 AltiVec Shift/Rotate Instructions 23992 */ 23993 static Bool dis_av_shift ( UInt theInstr ) 23994 { 23995 /* VX-Form */ 23996 UChar opc1 = ifieldOPC(theInstr); 23997 UChar vD_addr = ifieldRegDS(theInstr); 23998 UChar vA_addr = ifieldRegA(theInstr); 23999 UChar vB_addr = ifieldRegB(theInstr); 24000 UInt opc2 = IFIELD( theInstr, 0, 11 ); 24001 24002 IRTemp vA = newTemp(Ity_V128); 24003 IRTemp vB = newTemp(Ity_V128); 24004 assign( vA, getVReg(vA_addr)); 24005 assign( vB, getVReg(vB_addr)); 24006 24007 if (opc1 != 0x4){ 24008 vex_printf("dis_av_shift(ppc)(instr)\n"); 24009 return False; 24010 } 24011 24012 switch (opc2) { 24013 /* Rotate */ 24014 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 24015 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24016 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 24017 break; 24018 24019 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 24020 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24021 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 24022 break; 24023 24024 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 24025 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24026 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 24027 break; 24028 24029 case 0x0C4: // vrld (Rotate Left Integer Double Word) 24030 DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24031 putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) ); 24032 break; 24033 24034 24035 /* Shift Left */ 24036 case 0x104: // vslb (Shift Left Integer B, AV p240) 24037 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24038 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 24039 break; 24040 24041 case 0x144: // vslh (Shift Left Integer HW, AV p242) 24042 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24043 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 24044 break; 24045 24046 case 0x184: // vslw (Shift Left Integer W, AV p244) 24047 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24048 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 24049 break; 24050 24051 case 0x5C4: // vsld (Shift Left Integer Double Word) 24052 DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24053 putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) ); 24054 break; 24055 24056 case 0x1C4: { // vsl (Shift Left, AV p239) 24057 IRTemp sh = newTemp(Ity_I8); 24058 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24059 assign( sh, binop(Iop_And8, mkU8(0x7), 24060 unop(Iop_32to8, 24061 unop(Iop_V128to32, mkexpr(vB)))) ); 24062 putVReg( vD_addr, 24063 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 24064 break; 24065 } 24066 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 24067 IRTemp sh = newTemp(Ity_I8); 24068 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24069 assign( sh, binop(Iop_And8, mkU8(0x78), 24070 unop(Iop_32to8, 24071 unop(Iop_V128to32, mkexpr(vB)))) ); 24072 putVReg( vD_addr, 24073 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 24074 break; 24075 } 24076 24077 24078 /* Shift Right */ 24079 case 0x204: // vsrb (Shift Right B, AV p256) 24080 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24081 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 24082 break; 24083 24084 case 0x244: // vsrh (Shift Right HW, AV p257) 24085 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24086 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 24087 break; 24088 24089 case 0x284: // vsrw (Shift Right W, AV p259) 24090 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24091 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 24092 break; 24093 24094 case 0x2C4: { // vsr (Shift Right, AV p251) 24095 IRTemp sh = newTemp(Ity_I8); 24096 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24097 assign( sh, binop(Iop_And8, mkU8(0x7), 24098 unop(Iop_32to8, 24099 unop(Iop_V128to32, mkexpr(vB)))) ); 24100 putVReg( vD_addr, 24101 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 24102 break; 24103 } 24104 case 0x304: // vsrab (Shift Right Alg B, AV p253) 24105 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24106 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 24107 break; 24108 24109 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 24110 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24111 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 24112 break; 24113 24114 case 0x384: // vsraw (Shift Right Alg W, AV p255) 24115 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24116 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 24117 break; 24118 24119 case 0x3C4: // vsrad (Shift Right Alg Double Word) 24120 DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24121 putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) ); 24122 break; 24123 24124 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 24125 IRTemp sh = newTemp(Ity_I8); 24126 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24127 assign( sh, binop(Iop_And8, mkU8(0x78), 24128 unop(Iop_32to8, 24129 unop(Iop_V128to32, mkexpr(vB)))) ); 24130 putVReg( vD_addr, 24131 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 24132 break; 24133 } 24134 24135 case 0x6C4: // vsrd (Shift Right Double Word) 24136 DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24137 putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) ); 24138 break; 24139 24140 24141 default: 24142 vex_printf("dis_av_shift(ppc)(opc2)\n"); 24143 return False; 24144 } 24145 return True; 24146 } 24147 24148 /* 24149 AltiVec Permute Instructions 24150 */ 24151 static Bool dis_av_permute ( UInt theInstr ) 24152 { 24153 /* VA-Form, VX-Form */ 24154 UChar opc1 = ifieldOPC(theInstr); 24155 UChar vD_addr = ifieldRegDS(theInstr); 24156 UChar vA_addr = ifieldRegA(theInstr); 24157 UChar UIMM_5 = vA_addr; 24158 UChar vB_addr = ifieldRegB(theInstr); 24159 UChar vC_addr = ifieldRegC(theInstr); 24160 UChar b10 = ifieldBIT10(theInstr); 24161 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 24162 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 24163 24164 UChar SIMM_8 = extend_s_5to8(UIMM_5); 24165 24166 IRTemp vA = newTemp(Ity_V128); 24167 IRTemp vB = newTemp(Ity_V128); 24168 IRTemp vC = newTemp(Ity_V128); 24169 assign( vA, getVReg(vA_addr)); 24170 assign( vB, getVReg(vB_addr)); 24171 assign( vC, getVReg(vC_addr)); 24172 24173 if (opc1 != 0x4) { 24174 vex_printf("dis_av_permute(ppc)(instr)\n"); 24175 return False; 24176 } 24177 24178 switch (opc2) { 24179 case 0x2A: // vsel (Conditional Select, AV p238) 24180 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 24181 /* vD = (vA & ~vC) | (vB & vC) */ 24182 putVReg( vD_addr, binop(Iop_OrV128, 24183 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 24184 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 24185 return True; 24186 24187 case 0x2B: { // vperm (Permute, AV p218) 24188 /* limited to two args for IR, so have to play games... */ 24189 IRTemp a_perm = newTemp(Ity_V128); 24190 IRTemp b_perm = newTemp(Ity_V128); 24191 IRTemp mask = newTemp(Ity_V128); 24192 IRTemp vC_andF = newTemp(Ity_V128); 24193 DIP("vperm v%d,v%d,v%d,v%d\n", 24194 vD_addr, vA_addr, vB_addr, vC_addr); 24195 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 24196 IR specifies, and also to hide irrelevant bits from 24197 memcheck */ 24198 assign( vC_andF, 24199 binop(Iop_AndV128, mkexpr(vC), 24200 unop(Iop_Dup8x16, mkU8(0xF))) ); 24201 assign( a_perm, 24202 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 24203 assign( b_perm, 24204 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 24205 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 24206 assign( mask, binop(Iop_SarN8x16, 24207 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 24208 mkU8(7)) ); 24209 // dst = (a & ~mask) | (b & mask) 24210 putVReg( vD_addr, binop(Iop_OrV128, 24211 binop(Iop_AndV128, mkexpr(a_perm), 24212 unop(Iop_NotV128, mkexpr(mask))), 24213 binop(Iop_AndV128, mkexpr(b_perm), 24214 mkexpr(mask))) ); 24215 return True; 24216 } 24217 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 24218 if (b10 != 0) { 24219 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 24220 return False; 24221 } 24222 DIP("vsldoi v%d,v%d,v%d,%d\n", 24223 vD_addr, vA_addr, vB_addr, SHB_uimm4); 24224 if (SHB_uimm4 == 0) 24225 putVReg( vD_addr, mkexpr(vA) ); 24226 else 24227 putVReg( vD_addr, 24228 binop(Iop_OrV128, 24229 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 24230 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 24231 return True; 24232 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR) 24233 IRTemp a_perm = newTemp(Ity_V128); 24234 IRTemp b_perm = newTemp(Ity_V128); 24235 IRTemp vrc_a = newTemp(Ity_V128); 24236 IRTemp vrc_b = newTemp(Ity_V128); 24237 24238 DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 24239 24240 /* IBM index is 0:7, Change index value to index 7:0 */ 24241 assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ), 24242 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) ); 24243 assign( vrc_a, binop( Iop_ShrV128, 24244 binop( Iop_AndV128, mkexpr( vC ), 24245 unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ), 24246 mkU8 ( 4 ) ) ); 24247 assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) ); 24248 assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) ); 24249 putVReg( vD_addr, binop( Iop_XorV128, 24250 mkexpr( a_perm ), mkexpr( b_perm) ) ); 24251 return True; 24252 } 24253 24254 case 0x3B: { // vpermr (Vector Permute Right-indexed) 24255 int i; 24256 IRTemp new_Vt[17]; 24257 IRTemp tmp[16]; 24258 IRTemp index[16]; 24259 IRTemp index_gt16[16]; 24260 IRTemp mask[16]; 24261 24262 DIP("vpermr v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 24263 24264 new_Vt[0] = newTemp( Ity_V128 ); 24265 assign( new_Vt[0], binop( Iop_64HLtoV128, 24266 mkU64( 0x0 ), 24267 mkU64( 0x0 ) ) ); 24268 24269 for ( i = 0; i < 16; i++ ) { 24270 index_gt16[i] = newTemp( Ity_V128 ); 24271 mask[i] = newTemp( Ity_V128 ); 24272 index[i] = newTemp( Ity_I32 ); 24273 tmp[i] = newTemp( Ity_V128 ); 24274 new_Vt[i+1] = newTemp( Ity_V128 ); 24275 24276 assign( index[i], 24277 binop( Iop_Sub32, 24278 mkU32( 31 ), 24279 unop( Iop_64to32, 24280 unop( Iop_V128to64, 24281 binop( Iop_ShrV128, 24282 binop( Iop_AndV128, 24283 binop( Iop_ShlV128, 24284 binop( Iop_64HLtoV128, 24285 mkU64( 0x0 ), 24286 mkU64( 0x3F ) ), 24287 mkU8( (15 - i) * 8 ) ), 24288 mkexpr( vC ) ), 24289 mkU8( (15 - i) * 8 ) ) ) ) ) ); 24290 24291 /* Determine if index < 16, src byte is vA[index], otherwise 24292 * vB[31-index]. Check if msb of index is 1 or not. 24293 */ 24294 assign( index_gt16[i], 24295 binop( Iop_64HLtoV128, 24296 unop( Iop_1Sto64, 24297 unop( Iop_32to1, 24298 binop( Iop_Shr32, 24299 mkexpr( index[i] ), 24300 mkU8( 4 ) ) ) ), 24301 unop( Iop_1Sto64, 24302 unop( Iop_32to1, 24303 binop( Iop_Shr32, 24304 mkexpr( index[i] ), 24305 mkU8( 4 ) ) ) ) ) ); 24306 assign( mask[i], 24307 binop( Iop_ShlV128, 24308 binop( Iop_64HLtoV128, 24309 mkU64( 0x0 ), 24310 mkU64( 0xFF ) ), 24311 unop( Iop_32to8, 24312 binop( Iop_Mul32, 24313 binop( Iop_Sub32, 24314 mkU32( 15 ), 24315 binop( Iop_And32, 24316 mkexpr( index[i] ), 24317 mkU32( 0xF ) ) ), 24318 mkU32( 8 ) ) ) ) ); 24319 24320 /* Extract the indexed byte from vA and vB using the lower 4-bits 24321 * of the index. Then use the index_gt16 mask to select vA if the 24322 * index < 16 or vB if index > 15. Put the selected byte in the 24323 * least significant byte. 24324 */ 24325 assign( tmp[i], 24326 binop( Iop_ShrV128, 24327 binop( Iop_OrV128, 24328 binop( Iop_AndV128, 24329 binop( Iop_AndV128, 24330 mkexpr( mask[i] ), 24331 mkexpr( vA ) ), 24332 unop( Iop_NotV128, 24333 mkexpr( index_gt16[i] ) ) ), 24334 binop( Iop_AndV128, 24335 binop( Iop_AndV128, 24336 mkexpr( mask[i] ), 24337 mkexpr( vB ) ), 24338 mkexpr( index_gt16[i] ) ) ), 24339 unop( Iop_32to8, 24340 binop( Iop_Mul32, 24341 binop( Iop_Sub32, 24342 mkU32( 15 ), 24343 binop( Iop_And32, 24344 mkexpr( index[i] ), 24345 mkU32( 0xF ) ) ), 24346 mkU32( 8 ) ) ) ) ); 24347 24348 /* Move the selected byte to the position to store in the result */ 24349 assign( new_Vt[i+1], binop( Iop_OrV128, 24350 binop( Iop_ShlV128, 24351 mkexpr( tmp[i] ), 24352 mkU8( (15 - i) * 8 ) ), 24353 mkexpr( new_Vt[i] ) ) ); 24354 } 24355 putVReg( vD_addr, mkexpr( new_Vt[16] ) ); 24356 return True; 24357 } 24358 24359 default: 24360 break; // Fall through... 24361 } 24362 24363 opc2 = IFIELD( theInstr, 0, 11 ); 24364 switch (opc2) { 24365 24366 /* Merge */ 24367 case 0x00C: // vmrghb (Merge High B, AV p195) 24368 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24369 putVReg( vD_addr, 24370 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 24371 break; 24372 24373 case 0x04C: // vmrghh (Merge High HW, AV p196) 24374 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24375 putVReg( vD_addr, 24376 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 24377 break; 24378 24379 case 0x08C: // vmrghw (Merge High W, AV p197) 24380 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24381 putVReg( vD_addr, 24382 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 24383 break; 24384 24385 case 0x10C: // vmrglb (Merge Low B, AV p198) 24386 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24387 putVReg( vD_addr, 24388 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 24389 break; 24390 24391 case 0x14C: // vmrglh (Merge Low HW, AV p199) 24392 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24393 putVReg( vD_addr, 24394 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 24395 break; 24396 24397 case 0x18C: // vmrglw (Merge Low W, AV p200) 24398 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24399 putVReg( vD_addr, 24400 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 24401 break; 24402 24403 /* Extract instructions */ 24404 case 0x20D: // vextractub (Vector Extract Unsigned Byte) 24405 { 24406 UChar uim = IFIELD( theInstr, 16, 4 ); 24407 24408 DIP("vextractub v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24409 24410 putVReg( vD_addr, binop( Iop_ShlV128, 24411 binop( Iop_AndV128, 24412 binop( Iop_ShrV128, 24413 mkexpr( vB ), 24414 unop( Iop_32to8, 24415 binop( Iop_Mul32, 24416 mkU32( 8 ), 24417 mkU32( 31 - uim ) ) ) ), 24418 binop( Iop_64HLtoV128, 24419 mkU64( 0x0ULL ), 24420 mkU64( 0xFFULL ) ) ), 24421 mkU8( 64 ) ) ); 24422 } 24423 break; 24424 24425 case 0x24D: // vextractuh (Vector Extract Unsigned Halfword) 24426 { 24427 UChar uim = IFIELD( theInstr, 16, 4 ); 24428 24429 DIP("vextractuh v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24430 24431 putVReg( vD_addr, binop( Iop_ShlV128, 24432 binop( Iop_AndV128, 24433 binop( Iop_ShrV128, 24434 mkexpr( vB ), 24435 unop( Iop_32to8, 24436 binop( Iop_Mul32, 24437 mkU32( 8 ), 24438 mkU32( 30 - uim ) ) ) ), 24439 binop( Iop_64HLtoV128, 24440 mkU64( 0x0ULL ), 24441 mkU64( 0xFFFFULL ) ) ), 24442 mkU8( 64 ) ) ); 24443 } 24444 break; 24445 24446 case 0x28D: // vextractuw (Vector Extract Unsigned Word) 24447 { 24448 UChar uim = IFIELD( theInstr, 16, 4 ); 24449 24450 DIP("vextractuw v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24451 24452 putVReg( vD_addr, 24453 binop( Iop_ShlV128, 24454 binop( Iop_AndV128, 24455 binop( Iop_ShrV128, 24456 mkexpr( vB ), 24457 unop( Iop_32to8, 24458 binop( Iop_Mul32, 24459 mkU32( 8 ), 24460 mkU32( 28 - uim ) ) ) ), 24461 binop( Iop_64HLtoV128, 24462 mkU64( 0x0ULL ), 24463 mkU64( 0xFFFFFFFFULL ) ) ), 24464 mkU8( 64 ) ) ); 24465 } 24466 break; 24467 24468 case 0x2CD: // vextractd (Vector Extract Double Word) 24469 { 24470 UChar uim = IFIELD( theInstr, 16, 4 ); 24471 24472 DIP("vextractd v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24473 24474 putVReg( vD_addr, 24475 binop( Iop_ShlV128, 24476 binop( Iop_AndV128, 24477 binop( Iop_ShrV128, 24478 mkexpr( vB ), 24479 unop( Iop_32to8, 24480 binop( Iop_Mul32, 24481 mkU32( 8 ), 24482 mkU32( 24 - uim ) ) ) ), 24483 binop( Iop_64HLtoV128, 24484 mkU64( 0x0ULL ), 24485 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ), 24486 mkU8( 64 ) ) ); 24487 } 24488 break; 24489 24490 /* Insert instructions */ 24491 case 0x30D: // vinsertb (Vector insert Unsigned Byte) 24492 { 24493 UChar uim = IFIELD( theInstr, 16, 4 ); 24494 IRTemp shift = newTemp( Ity_I8 ); 24495 IRTemp vD = newTemp( Ity_V128 ); 24496 24497 DIP("vinsertb v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24498 24499 assign( vD, getVReg( vD_addr ) ); 24500 24501 assign( shift, unop( Iop_32to8, 24502 binop( Iop_Mul32, 24503 mkU32( 8 ), 24504 mkU32( 15 - ( uim + 0 ) ) ) ) ); 24505 24506 putVReg( vD_addr, 24507 binop( Iop_OrV128, 24508 binop( Iop_ShlV128, 24509 binop( Iop_AndV128, 24510 binop( Iop_ShrV128, 24511 mkexpr( vB ), 24512 mkU8( ( 15 - 7 )*8 ) ), 24513 binop( Iop_64HLtoV128, 24514 mkU64( 0x0ULL ), 24515 mkU64( 0xFFULL ) ) ), 24516 mkexpr( shift ) ), 24517 binop( Iop_AndV128, 24518 unop( Iop_NotV128, 24519 binop( Iop_ShlV128, 24520 binop( Iop_64HLtoV128, 24521 mkU64( 0x0ULL ), 24522 mkU64( 0xFFULL ) ), 24523 mkexpr( shift ) ) ), 24524 mkexpr( vD ) ) ) ); 24525 } 24526 break; 24527 24528 case 0x34D: // vinserth (Vector insert Halfword) 24529 { 24530 UChar uim = IFIELD( theInstr, 16, 4 ); 24531 IRTemp shift = newTemp( Ity_I8 ); 24532 IRTemp vD = newTemp( Ity_V128 ); 24533 24534 DIP("vinserth v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24535 24536 assign( vD, getVReg( vD_addr ) ); 24537 24538 assign( shift, unop( Iop_32to8, 24539 binop( Iop_Mul32, 24540 mkU32( 8 ), 24541 mkU32( 15 - ( uim + 1 ) ) ) ) ); 24542 24543 putVReg( vD_addr, 24544 binop( Iop_OrV128, 24545 binop( Iop_ShlV128, 24546 binop( Iop_AndV128, 24547 binop( Iop_ShrV128, 24548 mkexpr( vB ), 24549 mkU8( (7 - 3)*16 ) ), 24550 binop( Iop_64HLtoV128, 24551 mkU64( 0x0ULL ), 24552 mkU64( 0xFFFFULL ) ) ), 24553 mkexpr( shift ) ), 24554 binop( Iop_AndV128, 24555 unop( Iop_NotV128, 24556 binop( Iop_ShlV128, 24557 binop( Iop_64HLtoV128, 24558 mkU64( 0x0ULL ), 24559 mkU64( 0xFFFFULL ) ), 24560 mkexpr( shift ) ) ), 24561 mkexpr( vD ) ) ) ); 24562 } 24563 break; 24564 24565 case 0x38D: // vinsertw (Vector insert Word) 24566 { 24567 UChar uim = IFIELD( theInstr, 16, 4 ); 24568 IRTemp shift = newTemp( Ity_I8 ); 24569 IRTemp vD = newTemp( Ity_V128 ); 24570 24571 DIP("vinsertw v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24572 24573 assign( vD, getVReg( vD_addr ) ); 24574 24575 assign( shift, unop( Iop_32to8, 24576 binop( Iop_Mul32, 24577 mkU32( 8 ), 24578 mkU32( 15 - ( uim + 3 ) ) ) ) ); 24579 24580 putVReg( vD_addr, 24581 binop( Iop_OrV128, 24582 binop( Iop_ShlV128, 24583 binop( Iop_AndV128, 24584 binop( Iop_ShrV128, 24585 mkexpr( vB ), 24586 mkU8( (3 - 1) * 32 ) ), 24587 binop( Iop_64HLtoV128, 24588 mkU64( 0x0ULL ), 24589 mkU64( 0xFFFFFFFFULL ) ) ), 24590 mkexpr( shift ) ), 24591 binop( Iop_AndV128, 24592 unop( Iop_NotV128, 24593 binop( Iop_ShlV128, 24594 binop( Iop_64HLtoV128, 24595 mkU64( 0x0ULL ), 24596 mkU64( 0xFFFFFFFFULL ) ), 24597 mkexpr( shift ) ) ), 24598 mkexpr( vD ) ) ) ); 24599 } 24600 break; 24601 24602 case 0x3CD: // vinsertd (Vector insert Doubleword) 24603 { 24604 UChar uim = IFIELD( theInstr, 16, 4 ); 24605 IRTemp shift = newTemp( Ity_I8 ); 24606 IRTemp vD = newTemp( Ity_V128 ); 24607 24608 DIP("vinsertd v%d,v%d,%d\n", vD_addr, vB_addr, uim); 24609 24610 assign( vD, getVReg( vD_addr ) ); 24611 24612 assign( shift, unop( Iop_32to8, 24613 binop( Iop_Mul32, 24614 mkU32( 8 ), 24615 mkU32( 15 - ( uim + 7 ) ) ) ) ); 24616 24617 putVReg( vD_addr, 24618 binop( Iop_OrV128, 24619 binop( Iop_ShlV128, 24620 binop( Iop_AndV128, 24621 binop( Iop_ShrV128, 24622 mkexpr( vB ), 24623 mkU8( ( 1 - 0 ) * 64 ) ), 24624 binop( Iop_64HLtoV128, 24625 mkU64( 0x0ULL ), 24626 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ), 24627 mkexpr( shift ) ), 24628 binop( Iop_AndV128, 24629 unop( Iop_NotV128, 24630 binop( Iop_ShlV128, 24631 binop( Iop_64HLtoV128, 24632 mkU64( 0x0ULL ), 24633 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ), 24634 mkexpr( shift ) ) ), 24635 mkexpr( vD ) ) ) ); 24636 } 24637 break; 24638 24639 /* Splat */ 24640 case 0x20C: { // vspltb (Splat Byte, AV p245) 24641 /* vD = Dup8x16( vB[UIMM_5] ) */ 24642 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 24643 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 24644 putVReg( vD_addr, unop(Iop_Dup8x16, 24645 unop(Iop_32to8, unop(Iop_V128to32, 24646 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 24647 break; 24648 } 24649 case 0x24C: { // vsplth (Splat Half Word, AV p246) 24650 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 24651 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 24652 putVReg( vD_addr, unop(Iop_Dup16x8, 24653 unop(Iop_32to16, unop(Iop_V128to32, 24654 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 24655 break; 24656 } 24657 case 0x28C: { // vspltw (Splat Word, AV p250) 24658 /* vD = Dup32x4( vB[UIMM_5] ) */ 24659 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 24660 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 24661 putVReg( vD_addr, unop(Iop_Dup32x4, 24662 unop(Iop_V128to32, 24663 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 24664 break; 24665 } 24666 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 24667 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 24668 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 24669 break; 24670 24671 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 24672 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 24673 putVReg( vD_addr, 24674 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 24675 break; 24676 24677 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 24678 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 24679 putVReg( vD_addr, 24680 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 24681 break; 24682 24683 case 0x68C: // vmrgow (Merge Odd Word) 24684 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24685 /* VD[0] <- VA[1] 24686 VD[1] <- VB[1] 24687 VD[2] <- VA[3] 24688 VD[3] <- VB[3] 24689 */ 24690 putVReg( vD_addr, 24691 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 24692 break; 24693 24694 case 0x78C: // vmrgew (Merge Even Word) 24695 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24696 /* VD[0] <- VA[0] 24697 VD[1] <- VB[0] 24698 VD[2] <- VA[2] 24699 VD[3] <- VB[2] 24700 */ 24701 putVReg( vD_addr, 24702 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 24703 break; 24704 24705 default: 24706 vex_printf("dis_av_permute(ppc)(opc2)\n"); 24707 return False; 24708 } 24709 return True; 24710 } 24711 24712 /* 24713 Vector Integer Absolute Difference 24714 */ 24715 static Bool dis_abs_diff ( UInt theInstr ) 24716 { 24717 /* VX-Form */ 24718 UChar opc1 = ifieldOPC( theInstr ); 24719 UChar vT_addr = ifieldRegDS( theInstr ); 24720 UChar vA_addr = ifieldRegA( theInstr ); 24721 UChar vB_addr = ifieldRegB( theInstr ); 24722 UInt opc2 = IFIELD( theInstr, 0, 11 ); 24723 24724 IRTemp vA = newTemp( Ity_V128 ); 24725 IRTemp vB = newTemp( Ity_V128 ); 24726 IRTemp vT = newTemp( Ity_V128 ); 24727 24728 IRTemp vAminusB = newTemp( Ity_V128 ); 24729 IRTemp vBminusA = newTemp( Ity_V128 ); 24730 IRTemp vMask = newTemp( Ity_V128 ); 24731 24732 assign( vA, getVReg( vA_addr ) ); 24733 assign( vB, getVReg( vB_addr ) ); 24734 24735 if ( opc1 != 0x4 ) { 24736 vex_printf("dis_abs_diff(ppc)(instr)\n"); 24737 return False; 24738 } 24739 24740 switch ( opc2 ) { 24741 case 0x403: // vabsdub Vector absolute difference Unsigned Byte 24742 { 24743 DIP("vabsdub v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 24744 24745 /* Determine which of the corresponding bytes is larger, 24746 * create mask with 1's in byte positions where vA[i] > vB[i] 24747 */ 24748 assign( vMask, binop( Iop_CmpGT8Ux16, mkexpr( vA ), mkexpr( vB ) ) ); 24749 24750 assign( vAminusB, 24751 binop( Iop_AndV128, 24752 binop( Iop_Sub8x16, mkexpr( vA ), mkexpr( vB ) ), 24753 mkexpr( vMask ) ) ); 24754 24755 assign( vBminusA, 24756 binop( Iop_AndV128, 24757 binop( Iop_Sub8x16, mkexpr( vB ), mkexpr( vA ) ), 24758 unop ( Iop_NotV128, mkexpr( vMask ) ) ) ); 24759 24760 assign( vT, binop( Iop_OrV128, 24761 mkexpr( vAminusB ), 24762 mkexpr( vBminusA ) ) ); 24763 } 24764 break; 24765 24766 case 0x443: // vabsduh Vector absolute difference Unsigned Halfword 24767 { 24768 DIP("vabsduh v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 24769 24770 /* Determine which of the corresponding halfwords is larger, 24771 * create mask with 1's in halfword positions where vA[i] > vB[i] 24772 */ 24773 assign( vMask, binop( Iop_CmpGT16Ux8, mkexpr( vA ), mkexpr( vB ) ) ); 24774 24775 assign( vAminusB, 24776 binop( Iop_AndV128, 24777 binop( Iop_Sub16x8, mkexpr( vA ), mkexpr( vB ) ), 24778 mkexpr( vMask ) ) ); 24779 24780 assign( vBminusA, 24781 binop( Iop_AndV128, 24782 binop( Iop_Sub16x8, mkexpr( vB ), mkexpr( vA ) ), 24783 unop ( Iop_NotV128, mkexpr( vMask ) ) ) ); 24784 24785 assign( vT, binop( Iop_OrV128, 24786 mkexpr( vAminusB ), 24787 mkexpr( vBminusA ) ) ); 24788 } 24789 break; 24790 24791 case 0x483: // vabsduw Vector absolute difference Unsigned Word 24792 { 24793 DIP("vabsduw v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 24794 24795 /* Determine which of the corresponding words is larger, 24796 * create mask with 1's in word positions where vA[i] > vB[i] 24797 */ 24798 assign( vMask, binop( Iop_CmpGT32Ux4, mkexpr( vA ), mkexpr( vB ) ) ); 24799 24800 assign( vAminusB, 24801 binop( Iop_AndV128, 24802 binop( Iop_Sub32x4, mkexpr( vA ), mkexpr( vB ) ), 24803 mkexpr( vMask ) ) ); 24804 24805 assign( vBminusA, 24806 binop( Iop_AndV128, 24807 binop( Iop_Sub32x4, mkexpr( vB ), mkexpr( vA ) ), 24808 unop ( Iop_NotV128, mkexpr( vMask ) ) ) ); 24809 24810 assign( vT, binop( Iop_OrV128, 24811 mkexpr( vAminusB ), 24812 mkexpr( vBminusA ) ) ); 24813 } 24814 break; 24815 24816 default: 24817 return False; 24818 } 24819 24820 putVReg( vT_addr, mkexpr( vT ) ); 24821 24822 return True; 24823 } 24824 24825 /* 24826 AltiVec 128 bit integer multiply by 10 Instructions 24827 */ 24828 static Bool dis_av_mult10 ( UInt theInstr ) 24829 { 24830 /* VX-Form */ 24831 UChar opc1 = ifieldOPC(theInstr); 24832 UChar vT_addr = ifieldRegDS(theInstr); 24833 UChar vA_addr = ifieldRegA(theInstr); 24834 UChar vB_addr = ifieldRegB(theInstr); 24835 UInt opc2 = IFIELD( theInstr, 0, 11 ); 24836 24837 IRTemp vA = newTemp(Ity_V128); 24838 assign( vA, getVReg(vA_addr)); 24839 24840 if (opc1 != 0x4) { 24841 vex_printf("dis_av_mult10(ppc)(instr)\n"); 24842 return False; 24843 } 24844 switch (opc2) { 24845 case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry 24846 DIP("vmul10cuq v%d,v%d\n", vT_addr, vA_addr); 24847 putVReg( vT_addr, 24848 unop( Iop_MulI128by10Carry, mkexpr( vA ) ) ); 24849 break; 24850 } 24851 case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry 24852 // Unsigned Quadword VX form) 24853 IRTemp vB = newTemp(Ity_V128); 24854 assign( vB, getVReg(vB_addr)); 24855 DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 24856 putVReg( vT_addr, 24857 binop( Iop_MulI128by10ECarry, mkexpr( vA ), mkexpr( vB ) ) ); 24858 break; 24859 } 24860 case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form) 24861 DIP("vmul10uq v%d,v%d\n", vT_addr, vA_addr); 24862 putVReg( vT_addr, 24863 unop( Iop_MulI128by10, mkexpr( vA ) ) ); 24864 break; 24865 } 24866 case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended 24867 // Unsigned Quadword VX form) 24868 IRTemp vB = newTemp(Ity_V128); 24869 assign( vB, getVReg(vB_addr)); 24870 DIP("vmul10euq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr); 24871 putVReg( vT_addr, 24872 binop( Iop_MulI128by10E, mkexpr( vA ), mkexpr( vB ) ) ); 24873 break; 24874 } 24875 default: 24876 vex_printf("dis_av_mult10(ppc)(opc2)\n"); 24877 return False; 24878 } 24879 return True; 24880 } 24881 24882 /* 24883 AltiVec Pack/Unpack Instructions 24884 */ 24885 static Bool dis_av_pack ( UInt theInstr ) 24886 { 24887 /* VX-Form */ 24888 UChar opc1 = ifieldOPC(theInstr); 24889 UChar vD_addr = ifieldRegDS(theInstr); 24890 UChar vA_addr = ifieldRegA(theInstr); 24891 UChar vB_addr = ifieldRegB(theInstr); 24892 UInt opc2 = IFIELD( theInstr, 0, 11 ); 24893 24894 IRTemp signs = IRTemp_INVALID; 24895 IRTemp zeros = IRTemp_INVALID; 24896 IRTemp vA = newTemp(Ity_V128); 24897 IRTemp vB = newTemp(Ity_V128); 24898 assign( vA, getVReg(vA_addr)); 24899 assign( vB, getVReg(vB_addr)); 24900 24901 if (opc1 != 0x4) { 24902 vex_printf("dis_av_pack(ppc)(instr)\n"); 24903 return False; 24904 } 24905 switch (opc2) { 24906 /* Packing */ 24907 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 24908 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24909 putVReg( vD_addr, 24910 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 24911 return True; 24912 24913 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 24914 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24915 putVReg( vD_addr, 24916 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 24917 return True; 24918 24919 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 24920 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24921 putVReg( vD_addr, 24922 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 24923 // TODO: set VSCR[SAT] 24924 return True; 24925 24926 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 24927 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24928 putVReg( vD_addr, 24929 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 24930 // TODO: set VSCR[SAT] 24931 return True; 24932 24933 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 24934 // This insn does a signed->unsigned saturating conversion. 24935 // Conversion done here, then uses unsigned->unsigned vpk insn: 24936 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 24937 IRTemp vA_tmp = newTemp(Ity_V128); 24938 IRTemp vB_tmp = newTemp(Ity_V128); 24939 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24940 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 24941 unop(Iop_NotV128, 24942 binop(Iop_SarN16x8, 24943 mkexpr(vA), mkU8(15)))) ); 24944 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 24945 unop(Iop_NotV128, 24946 binop(Iop_SarN16x8, 24947 mkexpr(vB), mkU8(15)))) ); 24948 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 24949 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 24950 // TODO: set VSCR[SAT] 24951 return True; 24952 } 24953 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 24954 // This insn does a signed->unsigned saturating conversion. 24955 // Conversion done here, then uses unsigned->unsigned vpk insn: 24956 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 24957 IRTemp vA_tmp = newTemp(Ity_V128); 24958 IRTemp vB_tmp = newTemp(Ity_V128); 24959 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24960 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 24961 unop(Iop_NotV128, 24962 binop(Iop_SarN32x4, 24963 mkexpr(vA), mkU8(31)))) ); 24964 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 24965 unop(Iop_NotV128, 24966 binop(Iop_SarN32x4, 24967 mkexpr(vB), mkU8(31)))) ); 24968 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 24969 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 24970 // TODO: set VSCR[SAT] 24971 return True; 24972 } 24973 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 24974 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24975 putVReg( vD_addr, 24976 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 24977 // TODO: set VSCR[SAT] 24978 return True; 24979 24980 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 24981 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24982 putVReg( vD_addr, 24983 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 24984 // TODO: set VSCR[SAT] 24985 return True; 24986 24987 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 24988 /* CAB: Worth a new primop? */ 24989 /* Using shifts to compact pixel elements, then packing them */ 24990 IRTemp a1 = newTemp(Ity_V128); 24991 IRTemp a2 = newTemp(Ity_V128); 24992 IRTemp a3 = newTemp(Ity_V128); 24993 IRTemp a_tmp = newTemp(Ity_V128); 24994 IRTemp b1 = newTemp(Ity_V128); 24995 IRTemp b2 = newTemp(Ity_V128); 24996 IRTemp b3 = newTemp(Ity_V128); 24997 IRTemp b_tmp = newTemp(Ity_V128); 24998 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 24999 assign( a1, binop(Iop_ShlN16x8, 25000 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 25001 mkU8(10)) ); 25002 assign( a2, binop(Iop_ShlN16x8, 25003 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 25004 mkU8(5)) ); 25005 assign( a3, binop(Iop_ShrN16x8, 25006 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 25007 mkU8(11)) ); 25008 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 25009 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 25010 25011 assign( b1, binop(Iop_ShlN16x8, 25012 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 25013 mkU8(10)) ); 25014 assign( b2, binop(Iop_ShlN16x8, 25015 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 25016 mkU8(5)) ); 25017 assign( b3, binop(Iop_ShrN16x8, 25018 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 25019 mkU8(11)) ); 25020 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 25021 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 25022 25023 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 25024 mkexpr(a_tmp), mkexpr(b_tmp)) ); 25025 return True; 25026 } 25027 25028 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo) 25029 DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25030 putVReg( vD_addr, 25031 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) ); 25032 return True; 25033 25034 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate) 25035 DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25036 putVReg( vD_addr, 25037 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) ); 25038 // TODO: set VSCR[SAT] 25039 return True; 25040 25041 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate) 25042 // This insn does a doubled signed->double unsigned saturating conversion 25043 // Conversion done here, then uses unsigned->unsigned vpk insn: 25044 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 25045 // This is similar to the technique used for vpkswus, except done 25046 // with double word integers versus word integers. 25047 IRTemp vA_tmp = newTemp(Ity_V128); 25048 IRTemp vB_tmp = newTemp(Ity_V128); 25049 DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25050 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 25051 unop(Iop_NotV128, 25052 binop(Iop_SarN64x2, 25053 mkexpr(vA), mkU8(63)))) ); 25054 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 25055 unop(Iop_NotV128, 25056 binop(Iop_SarN64x2, 25057 mkexpr(vB), mkU8(63)))) ); 25058 putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4, 25059 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 25060 // TODO: set VSCR[SAT] 25061 return True; 25062 } 25063 25064 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate) 25065 DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25066 putVReg( vD_addr, 25067 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) ); 25068 // TODO: set VSCR[SAT] 25069 return True; 25070 default: 25071 break; // Fall through... 25072 } 25073 25074 25075 if (vA_addr != 0) { 25076 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 25077 return False; 25078 } 25079 25080 signs = newTemp(Ity_V128); 25081 zeros = newTemp(Ity_V128); 25082 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 25083 25084 switch (opc2) { 25085 /* Unpacking */ 25086 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 25087 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 25088 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 25089 putVReg( vD_addr, 25090 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 25091 break; 25092 } 25093 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 25094 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 25095 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 25096 putVReg( vD_addr, 25097 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 25098 break; 25099 } 25100 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 25101 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 25102 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 25103 putVReg( vD_addr, 25104 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 25105 break; 25106 } 25107 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 25108 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 25109 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 25110 putVReg( vD_addr, 25111 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 25112 break; 25113 } 25114 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 25115 /* CAB: Worth a new primop? */ 25116 /* Using shifts to isolate pixel elements, then expanding them */ 25117 IRTemp z0 = newTemp(Ity_V128); 25118 IRTemp z1 = newTemp(Ity_V128); 25119 IRTemp z01 = newTemp(Ity_V128); 25120 IRTemp z2 = newTemp(Ity_V128); 25121 IRTemp z3 = newTemp(Ity_V128); 25122 IRTemp z23 = newTemp(Ity_V128); 25123 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 25124 assign( z0, binop(Iop_ShlN16x8, 25125 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 25126 mkU8(8)) ); 25127 assign( z1, binop(Iop_ShrN16x8, 25128 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 25129 mkU8(11)) ); 25130 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 25131 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 25132 assign( z2, binop(Iop_ShrN16x8, 25133 binop(Iop_ShlN16x8, 25134 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 25135 mkU8(11)), 25136 mkU8(3)) ); 25137 assign( z3, binop(Iop_ShrN16x8, 25138 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 25139 mkU8(11)) ); 25140 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 25141 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 25142 putVReg( vD_addr, 25143 binop(Iop_OrV128, 25144 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 25145 mkexpr(z23)) ); 25146 break; 25147 } 25148 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 25149 /* identical to vupkhpx, except interleaving LO */ 25150 IRTemp z0 = newTemp(Ity_V128); 25151 IRTemp z1 = newTemp(Ity_V128); 25152 IRTemp z01 = newTemp(Ity_V128); 25153 IRTemp z2 = newTemp(Ity_V128); 25154 IRTemp z3 = newTemp(Ity_V128); 25155 IRTemp z23 = newTemp(Ity_V128); 25156 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 25157 assign( z0, binop(Iop_ShlN16x8, 25158 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 25159 mkU8(8)) ); 25160 assign( z1, binop(Iop_ShrN16x8, 25161 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 25162 mkU8(11)) ); 25163 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 25164 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 25165 assign( z2, binop(Iop_ShrN16x8, 25166 binop(Iop_ShlN16x8, 25167 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 25168 mkU8(11)), 25169 mkU8(3)) ); 25170 assign( z3, binop(Iop_ShrN16x8, 25171 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 25172 mkU8(11)) ); 25173 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 25174 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 25175 putVReg( vD_addr, 25176 binop(Iop_OrV128, 25177 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 25178 mkexpr(z23)) ); 25179 break; 25180 } 25181 case 0x64E: { // vupkhsw (Unpack High Signed Word) 25182 DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr); 25183 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 25184 putVReg( vD_addr, 25185 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) ); 25186 break; 25187 } 25188 case 0x6CE: { // vupklsw (Unpack Low Signed Word) 25189 DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr); 25190 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 25191 putVReg( vD_addr, 25192 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) ); 25193 break; 25194 } 25195 default: 25196 vex_printf("dis_av_pack(ppc)(opc2)\n"); 25197 return False; 25198 } 25199 return True; 25200 } 25201 25202 /* 25203 AltiVec Cipher Instructions 25204 */ 25205 static Bool dis_av_cipher ( UInt theInstr ) 25206 { 25207 /* VX-Form */ 25208 UChar opc1 = ifieldOPC(theInstr); 25209 UChar vD_addr = ifieldRegDS(theInstr); 25210 UChar vA_addr = ifieldRegA(theInstr); 25211 UChar vB_addr = ifieldRegB(theInstr); 25212 UInt opc2 = IFIELD( theInstr, 0, 11 ); 25213 25214 IRTemp vA = newTemp(Ity_V128); 25215 IRTemp vB = newTemp(Ity_V128); 25216 assign( vA, getVReg(vA_addr)); 25217 assign( vB, getVReg(vB_addr)); 25218 25219 if (opc1 != 0x4) { 25220 vex_printf("dis_av_cipher(ppc)(instr)\n"); 25221 return False; 25222 } 25223 switch (opc2) { 25224 case 0x508: // vcipher (Vector Inverser Cipher) 25225 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25226 putVReg( vD_addr, 25227 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) ); 25228 return True; 25229 25230 case 0x509: // vcipherlast (Vector Inverser Cipher Last) 25231 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25232 putVReg( vD_addr, 25233 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) ); 25234 return True; 25235 25236 case 0x548: // vncipher (Vector Inverser Cipher) 25237 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25238 putVReg( vD_addr, 25239 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) ); 25240 return True; 25241 25242 case 0x549: // vncipherlast (Vector Inverser Cipher Last) 25243 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 25244 putVReg( vD_addr, 25245 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) ); 25246 return True; 25247 25248 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher 25249 * subBytes transform) 25250 */ 25251 DIP("vsbox v%d,v%d\n", vD_addr, vA_addr); 25252 putVReg( vD_addr, 25253 unop(Iop_CipherSV128, mkexpr(vA) ) ); 25254 return True; 25255 25256 default: 25257 vex_printf("dis_av_cipher(ppc)(opc2)\n"); 25258 return False; 25259 } 25260 return True; 25261 } 25262 25263 /* 25264 AltiVec Secure Hash Instructions 25265 */ 25266 static Bool dis_av_hash ( UInt theInstr ) 25267 { 25268 /* VX-Form */ 25269 UChar opc1 = ifieldOPC(theInstr); 25270 UChar vRT_addr = ifieldRegDS(theInstr); 25271 UChar vRA_addr = ifieldRegA(theInstr); 25272 UChar s_field = IFIELD( theInstr, 11, 5 ); // st and six field 25273 UChar st = IFIELD( theInstr, 15, 1 ); // st 25274 UChar six = IFIELD( theInstr, 11, 4 ); // six field 25275 UInt opc2 = IFIELD( theInstr, 0, 11 ); 25276 25277 IRTemp vA = newTemp(Ity_V128); 25278 IRTemp dst = newTemp(Ity_V128); 25279 assign( vA, getVReg(vRA_addr)); 25280 25281 if (opc1 != 0x4) { 25282 vex_printf("dis_av_hash(ppc)(instr)\n"); 25283 return False; 25284 } 25285 25286 switch (opc2) { 25287 case 0x682: // vshasigmaw 25288 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 25289 assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) ); 25290 putVReg( vRT_addr, mkexpr(dst)); 25291 return True; 25292 25293 case 0x6C2: // vshasigmad, 25294 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 25295 putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) ); 25296 return True; 25297 25298 default: 25299 vex_printf("dis_av_hash(ppc)(opc2)\n"); 25300 return False; 25301 } 25302 return True; 25303 } 25304 25305 /* 25306 * This function is used by the Vector add/subtract [extended] modulo/carry 25307 * instructions. 25308 * - For the non-extended add instructions, the cin arg is set to zero. 25309 * - For the extended add instructions, cin is the integer value of 25310 * src3.bit[127]. 25311 * - For the non-extended subtract instructions, src1 is added to the one's 25312 * complement of src2 + 1. We re-use the cin argument to hold the '1' 25313 * value for this operation. 25314 * - For the extended subtract instructions, cin is the integer value of src3.bit[127]. 25315 */ 25316 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB, 25317 IRExpr * cin, Bool modulo) 25318 { 25319 IRTemp _vecA_32 = IRTemp_INVALID; 25320 IRTemp _vecB_32 = IRTemp_INVALID; 25321 IRTemp res_32 = IRTemp_INVALID; 25322 IRTemp res_64 = IRTemp_INVALID; 25323 IRTemp result = IRTemp_INVALID; 25324 IRTemp tmp_result = IRTemp_INVALID; 25325 IRTemp carry = IRTemp_INVALID; 25326 Int i; 25327 IRExpr * _vecA_low64 = unop( Iop_V128to64, vecA ); 25328 IRExpr * _vecB_low64 = unop( Iop_V128to64, vecB ); 25329 IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA ); 25330 IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB ); 25331 25332 carry = newTemp(Ity_I32); 25333 assign( carry, cin ); 25334 25335 for (i = 0; i < 4; i++) { 25336 _vecA_32 = newTemp(Ity_I32); 25337 _vecB_32 = newTemp(Ity_I32); 25338 res_32 = newTemp(Ity_I32); 25339 res_64 = newTemp(Ity_I64); 25340 25341 switch (i) { 25342 case 0: 25343 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) ); 25344 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) ); 25345 break; 25346 case 1: 25347 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) ); 25348 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) ); 25349 break; 25350 case 2: 25351 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) ); 25352 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) ); 25353 break; 25354 case 3: 25355 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) ); 25356 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) ); 25357 break; 25358 } 25359 25360 assign( res_64, binop( Iop_Add64, 25361 binop ( Iop_Add64, 25362 binop( Iop_32HLto64, 25363 mkU32( 0 ), 25364 mkexpr(_vecA_32) ), 25365 binop( Iop_32HLto64, 25366 mkU32( 0 ), 25367 mkexpr(_vecB_32) ) ), 25368 binop( Iop_32HLto64, 25369 mkU32( 0 ), 25370 mkexpr( carry ) ) ) ); 25371 25372 /* Calculate the carry to the next higher 32 bits. */ 25373 carry = newTemp(Ity_I32); 25374 assign(carry, unop( Iop_64HIto32, mkexpr( res_64 ) ) ); 25375 25376 /* result is the lower 32-bits */ 25377 assign(res_32, unop( Iop_64to32, mkexpr( res_64 ) ) ); 25378 25379 if (modulo) { 25380 result = newTemp(Ity_V128); 25381 assign(result, binop( Iop_OrV128, 25382 (i == 0) ? binop( Iop_64HLtoV128, 25383 mkU64(0), 25384 mkU64(0) ) : mkexpr(tmp_result), 25385 binop( Iop_ShlV128, 25386 binop( Iop_64HLtoV128, 25387 mkU64(0), 25388 binop( Iop_32HLto64, 25389 mkU32(0), 25390 mkexpr(res_32) ) ), 25391 mkU8(i * 32) ) ) ); 25392 tmp_result = newTemp(Ity_V128); 25393 assign(tmp_result, mkexpr(result)); 25394 } 25395 } 25396 if (modulo) 25397 return result; 25398 else 25399 return carry; 25400 } 25401 25402 25403 static Bool dis_av_quad ( UInt theInstr ) 25404 { 25405 /* VX-Form */ 25406 UChar opc1 = ifieldOPC(theInstr); 25407 UChar vRT_addr = ifieldRegDS(theInstr); 25408 UChar vRA_addr = ifieldRegA(theInstr); 25409 UChar vRB_addr = ifieldRegB(theInstr); 25410 UChar vRC_addr; 25411 UInt opc2 = IFIELD( theInstr, 0, 11 ); 25412 25413 IRTemp vA = newTemp(Ity_V128); 25414 IRTemp vB = newTemp(Ity_V128); 25415 IRTemp vC = IRTemp_INVALID; 25416 IRTemp cin = IRTemp_INVALID; 25417 assign( vA, getVReg(vRA_addr)); 25418 assign( vB, getVReg(vRB_addr)); 25419 25420 if (opc1 != 0x4) { 25421 vex_printf("dis_av_quad(ppc)(instr)\n"); 25422 return False; 25423 } 25424 25425 switch (opc2) { 25426 case 0x140: // vaddcuq 25427 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25428 putVReg( vRT_addr, unop( Iop_32UtoV128, 25429 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25430 mkexpr(vB), 25431 mkU32(0), False) ) ) ); 25432 return True; 25433 case 0x100: // vadduqm 25434 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25435 putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25436 mkexpr(vB), mkU32(0), True) ) ); 25437 return True; 25438 case 0x540: // vsubcuq 25439 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25440 putVReg( vRT_addr, 25441 unop( Iop_32UtoV128, 25442 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25443 unop( Iop_NotV128, 25444 mkexpr(vB) ), 25445 mkU32(1), False) ) ) ); 25446 return True; 25447 case 0x500: // vsubuqm 25448 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25449 putVReg( vRT_addr, 25450 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25451 unop( Iop_NotV128, mkexpr(vB) ), 25452 mkU32(1), True) ) ); 25453 return True; 25454 case 0x054C: // vbpermq 25455 { 25456 #define BPERMD_IDX_MASK 0x00000000000000FFULL 25457 #define BPERMD_BIT_MASK 0x8000000000000000ULL 25458 int i; 25459 IRExpr * vB_expr = mkexpr(vB); 25460 IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0)); 25461 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25462 for (i = 0; i < 16; i++) { 25463 IRTemp idx_tmp = newTemp( Ity_V128 ); 25464 IRTemp perm_bit = newTemp( Ity_V128 ); 25465 IRTemp idx = newTemp( Ity_I8 ); 25466 IRTemp idx_LT127 = newTemp( Ity_I1 ); 25467 IRTemp idx_LT127_ity128 = newTemp( Ity_V128 ); 25468 25469 assign( idx_tmp, 25470 binop( Iop_AndV128, 25471 binop( Iop_64HLtoV128, 25472 mkU64(0), 25473 mkU64(BPERMD_IDX_MASK) ), 25474 vB_expr ) ); 25475 assign( idx_LT127, 25476 binop( Iop_CmpEQ32, 25477 unop ( Iop_64to32, 25478 unop( Iop_V128to64, binop( Iop_ShrV128, 25479 mkexpr(idx_tmp), 25480 mkU8(7) ) ) ), 25481 mkU32(0) ) ); 25482 25483 /* Below, we set idx to determine which bit of vA to use for the 25484 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'. 25485 */ 25486 assign( idx, 25487 binop( Iop_And8, 25488 unop( Iop_1Sto8, 25489 mkexpr(idx_LT127) ), 25490 unop( Iop_32to8, 25491 unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) ); 25492 25493 assign( idx_LT127_ity128, 25494 binop( Iop_64HLtoV128, 25495 mkU64(0), 25496 unop( Iop_32Uto64, 25497 unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) ); 25498 assign( perm_bit, 25499 binop( Iop_AndV128, 25500 mkexpr( idx_LT127_ity128 ), 25501 binop( Iop_ShrV128, 25502 binop( Iop_AndV128, 25503 binop (Iop_64HLtoV128, 25504 mkU64( BPERMD_BIT_MASK ), 25505 mkU64(0)), 25506 binop( Iop_ShlV128, 25507 mkexpr( vA ), 25508 mkexpr( idx ) ) ), 25509 mkU8( 127 ) ) ) ); 25510 res = binop( Iop_OrV128, 25511 res, 25512 binop( Iop_ShlV128, 25513 mkexpr( perm_bit ), 25514 mkU8( i + 64 ) ) ); 25515 vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) ); 25516 } 25517 putVReg( vRT_addr, res); 25518 return True; 25519 #undef BPERMD_IDX_MASK 25520 #undef BPERMD_BIT_MASK 25521 } 25522 25523 default: 25524 break; // fall through 25525 } 25526 25527 opc2 = IFIELD( theInstr, 0, 6 ); 25528 vRC_addr = ifieldRegC(theInstr); 25529 vC = newTemp(Ity_V128); 25530 cin = newTemp(Ity_I32); 25531 switch (opc2) { 25532 case 0x3D: // vaddecuq 25533 assign( vC, getVReg(vRC_addr)); 25534 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 25535 vRC_addr); 25536 assign(cin, binop( Iop_And32, 25537 unop( Iop_64to32, 25538 unop( Iop_V128to64, mkexpr(vC) ) ), 25539 mkU32(1) ) ); 25540 putVReg( vRT_addr, 25541 unop( Iop_32UtoV128, 25542 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 25543 mkexpr(cin), 25544 False) ) ) ); 25545 return True; 25546 case 0x3C: // vaddeuqm 25547 assign( vC, getVReg(vRC_addr)); 25548 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 25549 vRC_addr); 25550 assign(cin, binop( Iop_And32, 25551 unop( Iop_64to32, 25552 unop( Iop_V128to64, mkexpr(vC) ) ), 25553 mkU32(1) ) ); 25554 putVReg( vRT_addr, 25555 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 25556 mkexpr(cin), 25557 True) ) ); 25558 return True; 25559 case 0x3F: // vsubecuq 25560 assign( vC, getVReg(vRC_addr)); 25561 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 25562 vRC_addr); 25563 assign(cin, binop( Iop_And32, 25564 unop( Iop_64to32, 25565 unop( Iop_V128to64, mkexpr(vC) ) ), 25566 mkU32(1) ) ); 25567 putVReg( vRT_addr, 25568 unop( Iop_32UtoV128, 25569 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25570 unop( Iop_NotV128, 25571 mkexpr(vB) ), 25572 mkexpr(cin), 25573 False) ) ) ); 25574 return True; 25575 case 0x3E: // vsubeuqm 25576 assign( vC, getVReg(vRC_addr)); 25577 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 25578 vRC_addr); 25579 assign(cin, binop( Iop_And32, 25580 unop( Iop_64to32, 25581 unop( Iop_V128to64, mkexpr(vC) ) ), 25582 mkU32(1) ) ); 25583 putVReg( vRT_addr, 25584 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 25585 unop( Iop_NotV128, mkexpr(vB) ), 25586 mkexpr(cin), 25587 True) ) ); 25588 return True; 25589 default: 25590 vex_printf("dis_av_quad(ppc)(opc2.2)\n"); 25591 return False; 25592 } 25593 25594 return True; 25595 } 25596 25597 static IRExpr * bcd_sign_code_adjust( UInt ps, IRExpr * tmp) 25598 { 25599 /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC 25600 * instruction being issued with ps = 0. If ps = 1, the sign code, which 25601 * is in the least significant four bits of the result, needs to be updated 25602 * per the ISA: 25603 * 25604 * If PS=0, the sign code of the result is set to 0b1100. 25605 * If PS=1, the sign code of the result is set to 0b1111. 25606 * 25607 * Note, the ps value is NOT being passed down to the instruction issue 25608 * because passing a constant via triop() breaks the vbit-test test. The 25609 * vbit-tester assumes it can set non-zero shadow bits for the triop() 25610 * arguments. Thus they have to be expressions not a constant. 25611 * Use 32-bit compare instructiions as 64-bit compares are not supported 25612 * in 32-bit mode. 25613 */ 25614 IRTemp mask = newTemp(Ity_I64); 25615 IRExpr *rtn; 25616 25617 if ( ps == 0 ) { 25618 /* sign code is correct, just return it. */ 25619 rtn = tmp; 25620 25621 } else { 25622 /* Check if lower four bits are 0b1100, if so, change to 0b1111 */ 25623 /* Make this work in 32-bit mode using only 32-bit compares */ 25624 assign( mask, unop( Iop_1Sto64, 25625 binop( Iop_CmpEQ32, mkU32( 0xC ), 25626 binop( Iop_And32, mkU32( 0xF ), 25627 unop( Iop_64to32, 25628 unop( Iop_V128to64, tmp ) 25629 ) ) ) ) ); 25630 rtn = binop( Iop_64HLtoV128, 25631 unop( Iop_V128HIto64, tmp ), 25632 binop( Iop_Or64, 25633 binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ), 25634 unop( Iop_V128to64, tmp ) ) ); 25635 } 25636 25637 return rtn; 25638 } 25639 25640 /* 25641 AltiVec BCD Arithmetic instructions. 25642 These instructions modify CR6 for various conditions in the result, 25643 including when an overflow occurs. We could easily detect all conditions 25644 except when an overflow occurs. But since we can't be 100% accurate 25645 in our emulation of CR6, it seems best to just not support it all. 25646 */ 25647 static Bool dis_av_bcd_misc ( UInt theInstr, const VexAbiInfo* vbi ) 25648 { 25649 UChar opc1 = ifieldOPC(theInstr); 25650 UChar vRT_addr = ifieldRegDS(theInstr); 25651 UChar vRA_addr = ifieldRegA(theInstr); 25652 UChar vRB_addr = ifieldRegB(theInstr); 25653 IRTemp vA = newTemp(Ity_V128); 25654 IRTemp vB = newTemp(Ity_V128); 25655 UInt opc2 = IFIELD( theInstr, 0, 11 ); 25656 IRExpr *pos, *neg, *valid, *zero, *sign; 25657 IRTemp eq_lt_gt = newTemp( Ity_I32 ); 25658 25659 assign( vA, getVReg(vRA_addr)); 25660 assign( vB, getVReg(vRB_addr)); 25661 25662 if (opc1 != 0x4) { 25663 vex_printf("dis_av_bcd_misc(ppc)(instr)\n"); 25664 return False; 25665 } 25666 25667 switch (opc2) { 25668 case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form 25669 { 25670 IRExpr *sign_vb, *value_va; 25671 DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 25672 25673 zero = 25674 BCDstring_zero( binop( Iop_AndV128, 25675 binop( Iop_64HLtoV128, 25676 mkU64( 0xFFFFFFFFFFFFFFFF ), 25677 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 25678 mkexpr( vA ) ) ); 25679 25680 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 25681 * codes 0xB and 0xD are negative. 25682 */ 25683 sign = binop( Iop_And64, mkU64( 0xF ), 25684 unop( Iop_V128to64, mkexpr( vB ) ) ); 25685 25686 neg = mkOR1( binop( Iop_CmpEQ64, 25687 sign, 25688 mkU64 ( 0xB ) ), 25689 binop( Iop_CmpEQ64, 25690 sign, 25691 mkU64 ( 0xD ) ) ); 25692 25693 pos = mkNOT1( neg ); 25694 25695 /* invalid if vA or vB is not valid */ 25696 valid = 25697 unop( Iop_64to32, 25698 binop( Iop_And64, 25699 is_BCDstring128( vbi, 25700 /*Signed*/True, mkexpr( vA ) ), 25701 is_BCDstring128( vbi, 25702 /*Signed*/True, mkexpr( vB ) ) ) ); 25703 25704 sign_vb = binop( Iop_AndV128, 25705 binop( Iop_64HLtoV128, 25706 mkU64( 0 ), 25707 mkU64( 0xF ) ), 25708 mkexpr( vB ) ); 25709 25710 value_va = binop( Iop_AndV128, 25711 binop( Iop_64HLtoV128, 25712 mkU64( 0xFFFFFFFFFFFFFFFF ), 25713 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 25714 mkexpr( vA ) ); 25715 putVReg( vRT_addr, binop( Iop_OrV128, sign_vb, value_va ) ); 25716 } 25717 break; 25718 25719 default: 25720 vex_printf("dis_av_bcd_misc(ppc)(opc2)\n"); 25721 return False; 25722 } 25723 25724 /* set CR field 6 to: 25725 * 0b1000 if vB less then 0, i.e. vB is neg and not zero, 25726 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero, 25727 * 0b1000 if vB equals 0, 25728 * 0b0001 if vB is invalid over rules lt, gt, eq 25729 */ 25730 assign( eq_lt_gt, 25731 binop( Iop_Or32, 25732 binop( Iop_Shl32, 25733 unop( Iop_1Uto32, 25734 mkAND1( neg, 25735 mkNOT1( zero ) ) ), 25736 mkU8( 3 ) ), 25737 binop( Iop_Or32, 25738 binop( Iop_Shl32, 25739 unop( Iop_1Uto32, 25740 mkAND1( pos, 25741 mkNOT1( zero ) ) ), 25742 mkU8( 2 ) ), 25743 binop( Iop_Shl32, 25744 unop( Iop_1Uto32, zero ), 25745 mkU8( 1 ) ) ) ) ); 25746 25747 IRTemp valid_mask = newTemp( Ity_I32 ); 25748 25749 assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) ); 25750 25751 putGST_field( PPC_GST_CR, 25752 binop( Iop_Or32, 25753 binop( Iop_And32, 25754 mkexpr( valid_mask ), 25755 mkexpr( eq_lt_gt ) ), 25756 binop( Iop_And32, 25757 unop( Iop_Not32, mkexpr( valid_mask ) ), 25758 mkU32( 1 ) ) ), 25759 6 ); 25760 return True; 25761 } 25762 25763 static Bool dis_av_bcd ( UInt theInstr, const VexAbiInfo* vbi ) 25764 { 25765 /* VX-Form */ 25766 UChar opc1 = ifieldOPC(theInstr); 25767 UChar vRT_addr = ifieldRegDS(theInstr); 25768 UChar vRA_addr = ifieldRegA(theInstr); 25769 UChar vRB_addr = ifieldRegB(theInstr); 25770 UChar ps = IFIELD( theInstr, 9, 1 ); 25771 UInt opc2 = IFIELD( theInstr, 0, 9 ); 25772 IRTemp vA = newTemp(Ity_V128); 25773 IRTemp vB = newTemp(Ity_V128); 25774 IRTemp dst = newTemp(Ity_V128); 25775 IRExpr *pos, *neg, *valid, *zero, *sign_digit, *in_range; 25776 IRTemp eq_lt_gt = newTemp( Ity_I32 ); 25777 IRExpr *overflow, *value; 25778 25779 assign( vA, getVReg(vRA_addr)); 25780 assign( vB, getVReg(vRB_addr)); 25781 25782 if (opc1 != 0x4) { 25783 vex_printf("dis_av_bcd(ppc)(instr)\n"); 25784 return False; 25785 } 25786 25787 switch (opc2) { 25788 case 0x1: // bcdadd. 25789 case 0x41: // bcdsub. 25790 { 25791 /* NOTE 64 bit compares are not supported in 32-bit mode. Use 25792 * 32-bit compares only. 25793 */ 25794 25795 IRExpr *sign, *res_smaller; 25796 IRExpr *signA, *signB, *sign_digitA, *sign_digitB; 25797 IRExpr *zeroA, *zeroB, *posA, *posB, *negA, *negB; 25798 25799 if ( opc2 == 0x1 ) { 25800 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 25801 assign( dst, bcd_sign_code_adjust( ps, 25802 binop( Iop_BCDAdd, 25803 mkexpr( vA ), 25804 mkexpr( vB ) ) ) ); 25805 } else { 25806 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 25807 assign( dst, bcd_sign_code_adjust( ps, 25808 binop( Iop_BCDSub, 25809 mkexpr( vA ), 25810 mkexpr( vB ) ) ) ); 25811 } 25812 25813 putVReg( vRT_addr, mkexpr( dst ) ); 25814 /* set CR field 6 */ 25815 /* result */ 25816 zero = BCDstring_zero( binop( Iop_AndV128, 25817 binop( Iop_64HLtoV128, 25818 mkU64( 0xFFFFFFFFFFFFFFFF ), 25819 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 25820 mkexpr(dst) ) ); // ignore sign 25821 25822 sign_digit = binop( Iop_And32, mkU32( 0xF ), 25823 unop( Iop_64to32, 25824 unop( Iop_V128to64, mkexpr( dst ) ) ) ); 25825 25826 sign = mkOR1( binop( Iop_CmpEQ32, 25827 sign_digit, 25828 mkU32 ( 0xB ) ), 25829 binop( Iop_CmpEQ32, 25830 sign_digit, 25831 mkU32 ( 0xD ) ) ); 25832 neg = mkAND1( sign, mkNOT1( zero ) ); 25833 25834 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */ 25835 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 25836 valid = unop( Iop_64to32, 25837 binop( Iop_And64, 25838 is_BCDstring128( vbi, 25839 /*Signed*/True, mkexpr( vA ) ), 25840 is_BCDstring128( vbi, 25841 /*Signed*/True, mkexpr( vB ) ) 25842 ) ); 25843 25844 /* src A */ 25845 zeroA = BCDstring_zero( binop( Iop_AndV128, 25846 binop( Iop_64HLtoV128, 25847 mkU64( 0xFFFFFFFFFFFFFFFF ), 25848 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 25849 mkexpr( vA ) ) ); // ignore sign 25850 sign_digitA = binop( Iop_And32, mkU32( 0xF ), 25851 unop( Iop_64to32, 25852 unop( Iop_V128to64, mkexpr( vA ) ) ) ); 25853 25854 signA = mkOR1( binop( Iop_CmpEQ32, 25855 sign_digitA, 25856 mkU32 ( 0xB ) ), 25857 binop( Iop_CmpEQ32, 25858 sign_digitA, 25859 mkU32 ( 0xD ) ) ); 25860 negA = mkAND1( signA, mkNOT1( zeroA ) ); 25861 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */ 25862 posA = mkAND1( mkNOT1( signA ), mkNOT1( zeroA ) ); 25863 25864 /* src B */ 25865 zeroB = BCDstring_zero( binop( Iop_AndV128, 25866 binop( Iop_64HLtoV128, 25867 mkU64( 0xFFFFFFFFFFFFFFFF ), 25868 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 25869 mkexpr( vB ) ) ); // ignore sign 25870 sign_digitB = binop( Iop_And32, mkU32( 0xF ), 25871 unop( Iop_64to32, 25872 unop( Iop_V128to64, mkexpr( vB ) ) ) ); 25873 25874 signB = mkOR1( binop( Iop_CmpEQ32, 25875 sign_digitB, 25876 mkU32 ( 0xB ) ), 25877 binop( Iop_CmpEQ32, 25878 sign_digitB, 25879 mkU32 ( 0xD ) ) ); 25880 negB = mkAND1( signB, mkNOT1( zeroB ) ); 25881 25882 25883 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */ 25884 posB = mkAND1( mkNOT1( signB ), mkNOT1( zeroB ) ); 25885 25886 25887 if (mode64) { 25888 res_smaller = mkAND1( CmpGT128U( mkexpr( vA ), mkexpr( dst ) ), 25889 CmpGT128U( mkexpr( vB ), mkexpr( dst ) ) ); 25890 25891 } else { 25892 /* Have to do this with 32-bit compares, expensive */ 25893 res_smaller = mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA ), 25894 mkexpr( dst ) ), 25895 UNSIGNED_CMP_GT_V128( mkexpr( vB ), 25896 mkexpr( dst ) ) ); 25897 } 25898 25899 if ( opc2 == 0x1) { 25900 /* Overflow for Add can only occur if the signs of the operands 25901 * are the same and the two operands are non-zero. On overflow, 25902 * the PPC hardware produces a result consisting of just the lower 25903 * digits of the result. So, if the result is less then both 25904 * operands and the sign of the operands are the same overflow 25905 * occured. 25906 */ 25907 overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, negB ) ), 25908 mkAND1( res_smaller, mkAND1( posA, posB ) ) ); 25909 } else { 25910 /* Overflow for Add can only occur if the signs of the operands 25911 * are the different and the two operands are non-zero. On overflow, 25912 * the PPC hardware produces a result consisting of just the lower 25913 * digits of the result. So, if the result is less then both 25914 * operands and the sign of the operands are different overflow 25915 * occured. 25916 */ 25917 overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, posB ) ), 25918 mkAND1( res_smaller, mkAND1( posA, negB ) ) ); 25919 } 25920 } 25921 break; 25922 25923 case 0x081: // bcdus. Decimal Unsigned Shift VX-form 25924 case 0x0C1: // bcds. Decimal Shift VX-form 25925 case 0x1C1: // bcdsr. Decimal Shift and Round VX-form 25926 { 25927 IRExpr *shift_dir; 25928 IRExpr *shift_mask, *result, *new_sign_val, *sign; 25929 IRExpr *not_excess_shift, *not_excess_shift_mask; 25930 IRTemp shift_dir_mask = newTemp( Ity_I64 ); 25931 IRTemp shift_by = newTemp( Ity_I64 ); 25932 IRTemp shift_field = newTemp( Ity_I64 ); 25933 IRTemp shifted_out = newTemp( Ity_V128 ); 25934 IRTemp value_shl = newTemp( Ity_V128 ); 25935 IRTemp value_shr = newTemp( Ity_V128 ); 25936 IRTemp round = newTemp( Ity_I32); 25937 25938 ULong value_mask_low = 0; 25939 UInt max_shift = 0; 25940 25941 if (opc2 == 0x0C1) { 25942 DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps); 25943 value_mask_low = 0xFFFFFFFFFFFFFFF0; 25944 max_shift = 30 * 4; /* maximum without shifting all digits out */ 25945 25946 } else if (opc2 == 0x1C1) { 25947 DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps); 25948 25949 value_mask_low = 0xFFFFFFFFFFFFFFF0; 25950 max_shift = 30 * 4; /* maximum without shifting all digits out */ 25951 25952 } else { 25953 DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, 25954 vRB_addr, ps); 25955 value_mask_low = 0xFFFFFFFFFFFFFFFF; 25956 max_shift = 31 * 4; /* maximum without shifting all digits out */ 25957 } 25958 25959 value = binop( Iop_AndV128, 25960 binop( Iop_64HLtoV128, 25961 mkU64( 0xFFFFFFFFFFFFFFFF ), 25962 mkU64( value_mask_low ) ), 25963 mkexpr( vB ) ); 25964 25965 zero = BCDstring_zero( value ); 25966 25967 /* Shift field is 2's complement value */ 25968 assign( shift_field, unop( Iop_V128to64, 25969 binop( Iop_ShrV128, 25970 binop( Iop_AndV128, 25971 binop( Iop_64HLtoV128, 25972 mkU64( 0xFF ), 25973 mkU64( 0x0) ), 25974 mkexpr( vA ) ), 25975 mkU8( 64 ) ) ) ); 25976 25977 /* if shift_dir = 0 shift left, otherwise shift right */ 25978 shift_dir = binop( Iop_CmpEQ64, 25979 binop( Iop_Shr64, 25980 mkexpr( shift_field ), 25981 mkU8( 7 ) ), 25982 mkU64( 1 ) ); 25983 25984 assign( shift_dir_mask, unop( Iop_1Sto64, shift_dir ) ); 25985 25986 /* Shift field is stored in 2's complement form */ 25987 assign(shift_by, 25988 binop( Iop_Mul64, 25989 binop( Iop_Or64, 25990 binop( Iop_And64, 25991 unop( Iop_Not64, 25992 mkexpr( shift_dir_mask ) ), 25993 mkexpr( shift_field ) ), 25994 binop( Iop_And64, 25995 mkexpr( shift_dir_mask ), 25996 binop( Iop_And64, 25997 binop( Iop_Add64, 25998 mkU64( 1 ), 25999 unop( Iop_Not64, 26000 mkexpr( shift_field ) ) ), 26001 mkU64( 0xFF ) ) ) ), 26002 mkU64( 4 ) ) ); 26003 26004 /* If the shift exceeds 128 bits, we need to force the result 26005 * to zero because Valgrind shift amount is only 7-bits. Otherwise, 26006 * we get a shift amount of mod(shift_by, 127) 26007 */ 26008 not_excess_shift = unop( Iop_1Sto64, 26009 binop( Iop_CmpLE64U, 26010 mkexpr( shift_by ), 26011 mkU64( max_shift ) ) ); 26012 26013 not_excess_shift_mask = binop( Iop_64HLtoV128, 26014 not_excess_shift, 26015 not_excess_shift ); 26016 26017 assign( value_shl, 26018 binop( Iop_ShlV128, value, unop( Iop_64to8, 26019 mkexpr( shift_by) ) ) ); 26020 assign( value_shr, 26021 binop( Iop_AndV128, 26022 binop( Iop_64HLtoV128, 26023 mkU64( 0xFFFFFFFFFFFFFFFF ), 26024 mkU64( value_mask_low) ), 26025 binop( Iop_ShrV128, 26026 value, 26027 unop( Iop_64to8, 26028 mkexpr( shift_by ) ) ) ) ); 26029 26030 /* Overflow occurs if the shift amount is greater than zero, the 26031 * operation is a left shift and any non-zero digits are left 26032 * shifted out. 26033 */ 26034 assign( shifted_out, 26035 binop( Iop_OrV128, 26036 binop( Iop_ShrV128, 26037 value, 26038 unop( Iop_64to8, 26039 binop( Iop_Sub64, 26040 mkU64( 32*4 ), 26041 mkexpr( shift_by ) ) ) ), 26042 binop( Iop_AndV128, 26043 unop( Iop_NotV128, 26044 not_excess_shift_mask ), 26045 value ) ) ); 26046 26047 overflow = mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out ) ) ), 26048 mkAND1( mkNOT1( shift_dir ), 26049 binop( Iop_CmpNE64, 26050 mkexpr( shift_by ), 26051 mkU64( 0 ) ) ) ); 26052 26053 if ((opc2 == 0xC1) || (opc2 == 0x1C1)) { 26054 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 26055 * codes 0xB and 0xD are negative. 26056 */ 26057 sign_digit = binop( Iop_And64, mkU64( 0xF ), 26058 unop( Iop_V128to64, mkexpr( vB ) ) ); 26059 26060 sign = mkOR1( binop( Iop_CmpEQ64, 26061 sign_digit, 26062 mkU64 ( 0xB ) ), 26063 binop( Iop_CmpEQ64, 26064 sign_digit, 26065 mkU64 ( 0xD ) ) ); 26066 neg = mkAND1( sign, mkNOT1( zero ) ); 26067 26068 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */ 26069 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26070 26071 valid = 26072 unop( Iop_64to32, 26073 is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) ); 26074 26075 } else { 26076 /* string is an unsigned BCD value */ 26077 pos = mkU1( 1 ); 26078 neg = mkU1( 0 ); 26079 sign = mkU1( 0 ); 26080 26081 valid = 26082 unop( Iop_64to32, 26083 is_BCDstring128( vbi, /* Unsigned */False, 26084 mkexpr( vB ) ) ); 26085 } 26086 26087 /* if PS = 0 26088 vB positive, sign is C 26089 vB negative, sign is D 26090 if PS = 1 26091 vB positive, sign is F 26092 vB negative, sign is D 26093 Note can't use pos or neg here since they are ANDed with zero, 26094 use sign instead. 26095 */ 26096 if (ps == 0) { 26097 new_sign_val = binop( Iop_Or64, 26098 unop( Iop_1Uto64, sign ), 26099 mkU64( 0xC ) ); 26100 26101 } else { 26102 new_sign_val = binop( Iop_Xor64, 26103 binop( Iop_Shl64, 26104 unop( Iop_1Uto64, sign ), 26105 mkU8( 1 ) ), 26106 mkU64( 0xF ) ); 26107 } 26108 26109 shift_mask = binop( Iop_64HLtoV128, 26110 unop( Iop_1Sto64, shift_dir ), 26111 unop( Iop_1Sto64, shift_dir ) ); 26112 26113 result = binop( Iop_OrV128, 26114 binop( Iop_AndV128, mkexpr( value_shr ), shift_mask ), 26115 binop( Iop_AndV128, 26116 mkexpr( value_shl ), 26117 unop( Iop_NotV128, shift_mask ) ) ); 26118 26119 if (opc2 == 0xC1) { // bcds. 26120 putVReg( vRT_addr, binop( Iop_OrV128, 26121 binop( Iop_64HLtoV128, 26122 mkU64( 0 ), 26123 new_sign_val ), 26124 binop( Iop_AndV128, 26125 not_excess_shift_mask, 26126 result ) ) ); 26127 } else if (opc2 == 0x1C1) { //bcdsr. 26128 /* If shifting right, need to round up if needed */ 26129 assign( round, unop( Iop_1Uto32, 26130 mkAND1( shift_dir, 26131 check_BCD_round( value, 26132 shift_by ) ) ) ); 26133 26134 putVReg( vRT_addr, 26135 binop( Iop_OrV128, 26136 binop( Iop_64HLtoV128, 26137 mkU64( 0 ), 26138 new_sign_val ), 26139 binop( Iop_AndV128, 26140 not_excess_shift_mask, 26141 mkexpr( increment_BCDstring( vbi, result, 26142 mkexpr( round) 26143 ) ) ) ) ); 26144 } else { // bcdus. 26145 putVReg( vRT_addr, binop( Iop_AndV128, 26146 not_excess_shift_mask, 26147 result ) ); 26148 } 26149 } 26150 break; 26151 26152 case 0x101: // bcdtrunc. Decimal Truncate VX-form 26153 case 0x141: // bcdutrunc. Decimal Unsigned Truncate VX-form 26154 { 26155 IRTemp length = newTemp( Ity_I64 ); 26156 IRTemp masked_out = newTemp( Ity_V128 ); 26157 IRExpr *new_sign_val, *result, *shift; 26158 IRExpr *length_neq_128, *sign; 26159 ULong value_mask_low; 26160 Int max_digits; 26161 26162 if ( opc2 == 0x101) { // bcdtrunc. 26163 value_mask_low = 0xFFFFFFFFFFFFFFF0; 26164 max_digits = 31; 26165 } else { 26166 value_mask_low = 0xFFFFFFFFFFFFFFFF; 26167 max_digits = 32; 26168 } 26169 26170 assign( length, binop( Iop_And64, 26171 unop( Iop_V128HIto64, 26172 mkexpr( vA ) ), 26173 mkU64( 0xFFFF ) ) ); 26174 shift = unop( Iop_64to8, 26175 binop( Iop_Mul64, 26176 binop( Iop_Sub64, 26177 mkU64( max_digits ), 26178 mkexpr( length ) ), 26179 mkU64( 4 ) ) ); 26180 26181 /* Note ShrV128 gets masked by 127 so a shift of 128 results in 26182 * the value not being shifted. A shift of 128 sets the register 26183 * zero. So if length+1 = 128, just set the value to 0. 26184 */ 26185 length_neq_128 = mkNOT1( binop( Iop_CmpEQ64, 26186 mkexpr( length), 26187 mkU64( 0x1F ) ) ); 26188 26189 assign( masked_out, 26190 binop( Iop_AndV128, 26191 binop( Iop_64HLtoV128, 26192 unop( Iop_1Sto64, length_neq_128 ), 26193 unop( Iop_1Sto64, length_neq_128 ) ), 26194 binop( Iop_ShrV128, 26195 mkexpr( vB ), 26196 unop( Iop_64to8, 26197 binop( Iop_Mul64, 26198 mkU64( 4 ), 26199 binop( Iop_Add64, 26200 mkU64( 1 ), 26201 mkexpr( length ) ) ) ) ) 26202 ) ); 26203 26204 /* Overflow occurs if any of the left most 31-length digits of vB 26205 * are non-zero. 26206 */ 26207 overflow = mkNOT1( BCDstring_zero( mkexpr( masked_out ) ) ); 26208 26209 value = binop( Iop_AndV128, 26210 binop( Iop_64HLtoV128, 26211 mkU64( 0xFFFFFFFFFFFFFFFF ), 26212 mkU64( value_mask_low ) ), 26213 mkexpr( vB ) ); 26214 26215 26216 if ( opc2 == 0x101 ) { // bcdtrunc. 26217 /* Check if all of the non-sign digits are zero */ 26218 zero = BCDstring_zero( binop( Iop_AndV128, 26219 binop( Iop_64HLtoV128, 26220 mkU64( 0xFFFFFFFFFFFFFFFF ), 26221 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 26222 value ) ); 26223 26224 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 26225 * codes 0xB and 0xD are negative. 26226 */ 26227 sign_digit = binop( Iop_And64, mkU64( 0xF ), 26228 unop( Iop_V128to64, mkexpr( vB ) ) ); 26229 26230 sign = mkOR1( binop( Iop_CmpEQ64, 26231 sign_digit, 26232 mkU64 ( 0xB ) ), 26233 binop( Iop_CmpEQ64, 26234 sign_digit, 26235 mkU64 ( 0xD ) ) ); 26236 neg = mkAND1( sign, mkNOT1( zero ) ); 26237 26238 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */ 26239 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26240 26241 /* Note can't use pos or neg here since they are ANDed with zero, 26242 use sign instead. 26243 */ 26244 if (ps == 0) { 26245 new_sign_val = binop( Iop_Or64, 26246 unop( Iop_1Uto64, sign ), 26247 mkU64( 0xC ) ); 26248 } else { 26249 new_sign_val = binop( Iop_Xor64, 26250 binop( Iop_Shl64, 26251 unop( Iop_1Uto64, sign ), 26252 mkU8 ( 1 ) ), 26253 mkU64( 0xF ) ); 26254 } 26255 valid = 26256 unop( Iop_64to32, 26257 is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) ); 26258 26259 } else { // bcdutrunc. 26260 /* Check if all of the digits are zero */ 26261 zero = BCDstring_zero( value ); 26262 26263 /* unsigned value, need to make CC code happy */ 26264 neg = mkU1( 0 ); 26265 26266 /* Pos position AKA gt = 1 if (not eq zero) */ 26267 pos = mkNOT1( zero ); 26268 valid = 26269 unop( Iop_64to32, 26270 is_BCDstring128( vbi, /* Unsigned */False, 26271 mkexpr( vB ) ) ); 26272 } 26273 26274 /* If vB is not valid, the result is undefined, but we need to 26275 * match the hardware so the output of the test suite will match. 26276 * Hardware sets result to 0x0. 26277 */ 26278 result = binop( Iop_AndV128, 26279 mkV128( 0xFFFF ), 26280 binop( Iop_ShrV128, 26281 binop( Iop_ShlV128, value, shift ), 26282 shift ) ); 26283 26284 if ( opc2 == 0x101) { // bcdtrunc. 26285 putVReg( vRT_addr, binop( Iop_OrV128, 26286 binop( Iop_64HLtoV128, 26287 mkU64( 0 ), 26288 new_sign_val ), 26289 result ) ); 26290 } else { 26291 putVReg( vRT_addr, result ); 26292 } 26293 } 26294 break; 26295 26296 case 0x181: // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn., 26297 // bcdcfsq., bcdctsq. 26298 { 26299 UInt inst_select = IFIELD( theInstr, 16, 5); 26300 26301 switch (inst_select) { 26302 case 0: // bcdctsq. (Decimal Convert to Signed Quadword VX-form) 26303 { 26304 IRExpr *sign; 26305 26306 /* The instruction takes a 32-bit integer in a vector source 26307 * register and returns the signed packed decimal number 26308 * in a vector register. The source integer needs to be moved 26309 * from the V128 to an I32 for the Iop. 26310 */ 26311 26312 DIP("bcdctsq v%d, v%d\n", vRT_addr, vRB_addr); 26313 26314 putVReg( vRT_addr, unop( Iop_BCD128toI128S, mkexpr( vB ) ) ); 26315 26316 sign = binop( Iop_And64, 26317 unop( Iop_V128to64, mkexpr( vB ) ), 26318 mkU64( 0xF ) ); 26319 zero = mkAND1( binop( Iop_CmpEQ64, 26320 unop( Iop_V128HIto64, mkexpr( vB ) ), 26321 mkU64( 0x0 ) ), 26322 binop( Iop_CmpEQ64, 26323 binop( Iop_And64, 26324 unop( Iop_V128to64, mkexpr( vB ) ), 26325 mkU64( 0xFFFFFFF0 ) ), 26326 mkU64( 0x0 ) ) ); 26327 pos = mkAND1( mkNOT1( zero ), 26328 mkOR1( mkOR1( binop( Iop_CmpEQ64, 26329 sign, mkU64( 0xA ) ), 26330 binop( Iop_CmpEQ64, 26331 sign, mkU64( 0xC ) ) ), 26332 mkOR1( binop( Iop_CmpEQ64, 26333 sign, mkU64( 0xE ) ), 26334 binop( Iop_CmpEQ64, 26335 sign, mkU64( 0xF ) ) ) ) ); 26336 neg = mkAND1( mkNOT1( zero ), 26337 mkOR1( binop( Iop_CmpEQ64, sign, mkU64( 0xB ) ), 26338 binop( Iop_CmpEQ64, sign, mkU64( 0xD ) ) ) ); 26339 26340 /* Check each of the nibbles for a valid digit 0 to 9 */ 26341 valid = 26342 unop( Iop_64to32, 26343 is_BCDstring128( vbi, /* Signed */True, 26344 mkexpr( vB ) ) ); 26345 overflow = mkU1( 0 ); // not used 26346 } 26347 break; 26348 26349 case 2: // bcdcfsq. (Decimal Convert from Signed Quadword VX-form) 26350 { 26351 IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt; 26352 IRExpr *neg_upper_lt, *neg_upper_eq, *neg_lower_lt; 26353 26354 DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr, vRB_addr, ps); 26355 26356 /* The instruction takes a signed packed decimal number and 26357 * returns the integer value in the vector register. The Iop 26358 * returns an I32 which needs to be moved to the destination 26359 * vector register. 26360 */ 26361 putVReg( vRT_addr, 26362 binop( Iop_I128StoBCD128, mkexpr( vB ), mkU8( ps ) ) ); 26363 26364 zero = mkAND1( binop( Iop_CmpEQ64, mkU64( 0 ), 26365 unop( Iop_V128to64, mkexpr( vB ) ) ), 26366 binop( Iop_CmpEQ64, mkU64( 0 ), 26367 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 26368 pos = mkAND1( mkNOT1 ( zero ), 26369 binop( Iop_CmpEQ64, mkU64( 0 ), 26370 binop( Iop_And64, 26371 unop( Iop_V128HIto64, 26372 mkexpr( vB ) ), 26373 mkU64( 0x8000000000000000UL ) ) ) ); 26374 neg = mkAND1( mkNOT1 ( zero ), 26375 binop( Iop_CmpEQ64, mkU64( 0x8000000000000000UL ), 26376 binop( Iop_And64, 26377 unop( Iop_V128HIto64, 26378 mkexpr( vB ) ), 26379 mkU64( 0x8000000000000000UL ) ) ) ); 26380 26381 /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1 26382 * do not have a 128 bit compare. Will have to compare the 26383 * upper 64 bit and athe lower 64 bits. If the upper 64-bits 26384 * are equal then overflow if the lower 64 bits of vB is greater 26385 * otherwise if the upper bits of vB is greater then the max 26386 * for the upper 64-bits then overflow 26387 * 26388 * 10^31-1 = 0x7E37BE2022C0914B267FFFFFFF 26389 */ 26390 pos_upper_gt = binop( Iop_CmpLT64U, 26391 mkU64( 0x7E37BE2022 ), 26392 unop( Iop_V128HIto64, mkexpr( vB ) ) ); 26393 pos_upper_eq = binop( Iop_CmpEQ64, 26394 unop( Iop_V128HIto64, mkexpr( vB ) ), 26395 mkU64( 0x7E37BE2022 ) ); 26396 pos_lower_gt = binop( Iop_CmpLT64U, 26397 mkU64( 0x0914B267FFFFFFF ), 26398 unop( Iop_V128to64, mkexpr( vB ) ) ); 26399 /* -10^31-1 = 0X81C841DFDD3F6EB4D97FFFFFFF */ 26400 neg_upper_lt = binop( Iop_CmpLT64U, 26401 mkU64( 0X81C841DFDD ), 26402 unop( Iop_V128HIto64, mkexpr( vB ) ) ); 26403 neg_upper_eq = binop( Iop_CmpEQ64, 26404 unop( Iop_V128HIto64, mkexpr( vB ) ), 26405 mkU64( 0X81C841DFDD ) ); 26406 neg_lower_lt = binop( Iop_CmpLT64U, 26407 mkU64( 0x3F6EB4D97FFFFFFF ), 26408 unop( Iop_V128to64, mkexpr( vB ) ) ); 26409 26410 /* calculate overflow, masking for positive and negative */ 26411 overflow = mkOR1( mkAND1( pos, 26412 mkOR1( pos_upper_gt, 26413 mkAND1( pos_upper_eq, 26414 pos_lower_gt ) ) ), 26415 mkAND1( neg, 26416 mkOR1( neg_upper_lt, 26417 mkAND1( neg_upper_eq, 26418 neg_lower_lt ) 26419 ) ) ); 26420 valid = mkU32( 1 ); 26421 } 26422 break; 26423 26424 case 4: // bcdctz. (Decimal Convert to Zoned VX-form) 26425 { 26426 IRExpr *ox_flag, *sign, *vrb_nibble30; 26427 int neg_bit_shift; 26428 unsigned int upper_byte, sign_byte; 26429 IRTemp tmp = newTemp( Ity_V128 ); 26430 26431 DIP("bcdctz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps); 26432 26433 if (ps == 0) { 26434 upper_byte = 0x30; 26435 sign_byte = 0x30; 26436 neg_bit_shift = 4+2; /* sign byte is in bits [7:4] */ 26437 } else { 26438 upper_byte = 0xF0; 26439 sign_byte = 0xC0; 26440 neg_bit_shift = 4+0; 26441 } 26442 26443 /* Grab vB bits[7:4]. It goes into bits [3:0] of the 26444 * result. 26445 */ 26446 vrb_nibble30 = binop( Iop_Shr64, 26447 binop( Iop_And64, 26448 unop( Iop_V128to64, mkexpr( vB ) ), 26449 mkU64( 0xF0 ) ), 26450 mkU8( 4 ) ); 26451 26452 /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23], 26453 * must be zero for the value to be zero. This goes 26454 * in the overflow position of the condition code register. 26455 */ 26456 ox_flag = binop( Iop_CmpEQ64, 26457 binop( Iop_And64, 26458 unop( Iop_V128to64, mkexpr( vB ) ), 26459 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 26460 mkU64( 0 ) ); 26461 26462 /* zero is the same as eq_flag */ 26463 zero = mkAND1( binop( Iop_CmpEQ64, 26464 binop( Iop_And64, 26465 unop( Iop_V128HIto64, mkexpr( vB ) ), 26466 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 26467 mkU64( 0 ) ), 26468 binop( Iop_CmpEQ64, 26469 binop( Iop_And64, 26470 unop( Iop_V128to64, mkexpr( vB ) ), 26471 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 26472 mkU64( 0 ) ) ); 26473 26474 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 26475 * codes 0xB and 0xD are negative. 26476 */ 26477 sign_digit = binop( Iop_And64, mkU64( 0xF ), 26478 unop( Iop_V128to64, mkexpr( vB ) ) ); 26479 26480 /* The negative value goes in the LT bit position of the 26481 * condition code register. Set neg if the sign of vB 26482 * is negative and zero is true. 26483 */ 26484 sign = mkOR1( binop( Iop_CmpEQ64, 26485 sign_digit, 26486 mkU64 ( 0xB ) ), 26487 binop( Iop_CmpEQ64, 26488 sign_digit, 26489 mkU64 ( 0xD ) ) ); 26490 neg = mkAND1( sign, mkNOT1( zero ) ); 26491 26492 /* The positive value goes in the LT bit position of the 26493 * condition code register. Set positive if the sign of the 26494 * value is not negative. 26495 */ 26496 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26497 26498 assign( tmp, 26499 convert_to_zoned( vbi, mkexpr( vB ), 26500 mkU64( upper_byte ) ) ); 26501 26502 /* Insert the sign based on ps and sign of vB 26503 * in the lower byte. 26504 */ 26505 putVReg( vRT_addr, 26506 binop( Iop_OrV128, 26507 binop( Iop_64HLtoV128, 26508 mkU64( 0 ), 26509 vrb_nibble30 ), 26510 binop( Iop_OrV128, 26511 mkexpr( tmp ), 26512 binop( Iop_64HLtoV128, 26513 mkU64( 0 ), 26514 binop( Iop_Or64, 26515 mkU64( sign_byte ), 26516 binop( Iop_Shl64, 26517 unop( Iop_1Uto64, 26518 sign ), 26519 mkU8( neg_bit_shift) 26520 ) ) ) ) ) ); 26521 26522 /* A valid number must have a value that is less then or 26523 * equal to 10^16 - 1. This is checked by making sure 26524 * bytes [31:16] of vB are zero. 26525 */ 26526 in_range = binop( Iop_CmpEQ64, 26527 binop( Iop_And64, 26528 mkU64( 0xFFFFFFFFFFFFFFF0 ), 26529 unop( Iop_V128HIto64, mkexpr( vB ) ) ), 26530 mkU64( 0 ) ); 26531 26532 /* overflow is set if ox_flag or not in_inrange. Setting is 26533 * ORed with the other condition code values. 26534 */ 26535 overflow = mkOR1( ox_flag, mkNOT1( in_range ) ); 26536 26537 /* The sign code must be between 0xA and 0xF and all digits are 26538 * between 0x0 and 0x9. The vB must be in range to be valid. 26539 * If not valid, condition code set to 0x0001. 26540 */ 26541 valid = 26542 unop( Iop_64to32, 26543 is_BCDstring128( vbi, /* Signed */True, 26544 mkexpr( vB ) ) ); 26545 } 26546 break; 26547 26548 case 5: // bcdctn. (Decimal Convert to National VX-form) 26549 { 26550 IRExpr *ox_flag, *sign; 26551 IRTemp tmp = newTemp( Ity_V128 );; 26552 26553 DIP("bcdctn. v%d,v%d\n", vRT_addr, vRB_addr); 26554 26555 value = binop( Iop_And64, 26556 mkU64( 0xFFFFFFFF ), 26557 unop( Iop_V128to64, mkexpr( vB ) ) ); 26558 26559 /* A valid number must have a value that is less then or 26560 * equal to 10^7 - 1. This is checked by making sure 26561 * bytes [31:8] of vB are zero. 26562 */ 26563 in_range = mkAND1( binop( Iop_CmpEQ64, 26564 unop( Iop_V128HIto64, mkexpr( vB ) ), 26565 mkU64( 0 ) ), 26566 binop( Iop_CmpEQ64, 26567 binop( Iop_Shr64, 26568 unop( Iop_V128to64, 26569 mkexpr( vB ) ), 26570 mkU8( 32 ) ), 26571 mkU64( 0 ) ) ); 26572 26573 /* The sign code must be between 0xA and 0xF and all digits are 26574 * between 0x0 and 0x9. 26575 */ 26576 valid = 26577 unop( Iop_64to32, 26578 is_BCDstring128( vbi, /* Signed */True, 26579 mkexpr( vB ) ) ); 26580 26581 /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23], 26582 * must be zero for the ox_flag to be zero. This goes 26583 * in the LSB position (variable overflow) of the 26584 * condition code register. 26585 */ 26586 ox_flag = 26587 mkNOT1( mkAND1( binop( Iop_CmpEQ64, 26588 binop( Iop_And64, 26589 unop( Iop_V128HIto64, 26590 mkexpr( vB ) ), 26591 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 26592 mkU64( 0 ) ), 26593 binop( Iop_CmpEQ64, 26594 binop( Iop_And64, 26595 unop( Iop_V128to64, 26596 mkexpr( vB ) ), 26597 mkU64( 0xFFFFFFFF00000000 ) ), 26598 mkU64( 0 ) ) ) ); 26599 26600 /* Set zero to 1 if all of the bytes in vB are zero. This is 26601 * used when setting the lt_flag (variable neg) and the gt_flag 26602 * (variable pos). 26603 */ 26604 zero = mkAND1( binop( Iop_CmpEQ64, 26605 binop( Iop_And64, 26606 unop( Iop_V128HIto64, 26607 mkexpr( vB ) ), 26608 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 26609 mkU64( 0 ) ), 26610 binop( Iop_CmpEQ64, 26611 binop( Iop_And64, 26612 unop( Iop_V128to64, mkexpr( vB ) ), 26613 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 26614 mkU64( 0 ) ) ); 26615 26616 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 26617 * codes 0xB and 0xD are negative. 26618 */ 26619 sign_digit = binop( Iop_And64, mkU64( 0xF ), value ); 26620 26621 /* The negative value goes in the LT bit position of the 26622 * condition code register. Set neg if the sign of the 26623 * value is negative and the value is zero. 26624 */ 26625 sign = mkOR1( binop( Iop_CmpEQ64, 26626 sign_digit, 26627 mkU64 ( 0xB ) ), 26628 binop( Iop_CmpEQ64, 26629 sign_digit, 26630 mkU64 ( 0xD ) ) ); 26631 neg = mkAND1( sign, mkNOT1( zero ) ); 26632 26633 /* The positive value goes in the LT bit position of the 26634 * condition code register. Set neg if the sign of the 26635 * value is not negative and the value is zero. 26636 */ 26637 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26638 26639 assign( tmp, 26640 convert_to_national( vbi, mkexpr( vB ) ) ); 26641 26642 /* If vB is positive insert sign value 0x002B, otherwise 26643 * insert 0x002D for negative. Have to use sign not neg 26644 * because neg has been ANDed with zero. This is 0x29 26645 * OR'd with (sign << 1 | NOT sign) << 1. 26646 * sign = 1 if vB is negative. 26647 */ 26648 putVReg( vRT_addr, 26649 binop( Iop_OrV128, 26650 mkexpr( tmp ), 26651 binop( Iop_64HLtoV128, 26652 mkU64( 0 ), 26653 binop( Iop_Or64, 26654 mkU64( 0x29 ), 26655 binop( Iop_Or64, 26656 binop( Iop_Shl64, 26657 unop( Iop_1Uto64, 26658 sign ), 26659 mkU8( 2 ) ), 26660 binop( Iop_Shl64, 26661 unop( Iop_1Uto64, 26662 mkNOT1(sign)), 26663 mkU8( 1 ) ) 26664 ) ) ) ) ); 26665 26666 26667 /* The sign code must be between 0xA and 0xF and all digits are 26668 * between 0x0 and 0x9. The vB must be in range to be valid. 26669 */ 26670 valid = 26671 unop( Iop_64to32, 26672 is_BCDstring128( vbi, /* Signed */True, 26673 mkexpr( vB ) ) ); 26674 26675 overflow = ox_flag; 26676 } 26677 break; 26678 26679 case 6: // bcdcfz. (Decimal Convert From Zoned VX-form) 26680 { 26681 IRExpr *sign; 26682 IRTemp tmp = newTemp( Ity_V128 );; 26683 26684 DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps); 26685 26686 valid = unop( Iop_1Uto32, is_Zoned_decimal( vB, ps ) ); 26687 26688 assign( tmp, 26689 convert_from_zoned( vbi, mkexpr( vB ) ) ); 26690 26691 /* If the result of checking the lower 4 bits of each 8-bit 26692 * value is zero, then the "number" was zero. 26693 */ 26694 zero = 26695 binop( Iop_CmpEQ64, 26696 binop( Iop_Or64, 26697 binop( Iop_And64, 26698 unop( Iop_V128to64, mkexpr( vB ) ), 26699 mkU64( 0x0F0F0F0F0F0F0F0FULL ) ), 26700 binop( Iop_And64, 26701 unop( Iop_V128to64, mkexpr( vB ) ), 26702 mkU64( 0x0F0F0F0F0F0F0F0FULL ) ) ), 26703 mkU64( 0 ) ); 26704 26705 /* Sign bit is in bit 6 of vB. */ 26706 sign_digit = binop( Iop_And64, mkU64( 0xF0 ), 26707 unop( Iop_V128to64, mkexpr( vB ) ) ); 26708 26709 if ( ps == 0 ) { 26710 /* sign will be equal to 0 for positive number */ 26711 sign = binop( Iop_CmpEQ64, 26712 binop( Iop_And64, 26713 sign_digit, 26714 mkU64( 0x40 ) ), 26715 mkU64( 0x40 ) ); 26716 } else { 26717 sign = mkOR1( 26718 binop( Iop_CmpEQ64, sign_digit, mkU64( 0xB0 ) ), 26719 binop( Iop_CmpEQ64, sign_digit, mkU64( 0xD0 ) ) ); 26720 } 26721 26722 /* The negative value goes in the LT bit position of the 26723 * condition code register. Set neg if the sign of the 26724 * value is negative and the value is zero. 26725 */ 26726 neg = mkAND1( sign, mkNOT1( zero ) ); 26727 26728 /* The positive value goes in the GT bit position of the 26729 * condition code register. Set neg if the sign of the 26730 * value is not negative and the value is zero. 26731 */ 26732 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26733 26734 /* sign of the result is 0xC for positive, 0xD for negative */ 26735 putVReg( vRT_addr, 26736 binop( Iop_OrV128, 26737 mkexpr( tmp ), 26738 binop( Iop_64HLtoV128, 26739 mkU64( 0 ), 26740 binop( Iop_Or64, 26741 mkU64( 0xC ), 26742 unop( Iop_1Uto64, sign ) 26743 ) ) ) ); 26744 /* For this instructions the LSB position in the CC 26745 * field, the overflow position in the other instructions, 26746 * is given by 0. There is nothing to or with LT, EQ or GT. 26747 */ 26748 overflow = mkU1( 0 ); 26749 } 26750 break; 26751 26752 case 7: // bcdcfn. (Decimal Convert From National VX-form) 26753 { 26754 IRTemp hword_7 = newTemp( Ity_I64 ); 26755 IRExpr *sign; 26756 IRTemp tmp = newTemp( Ity_I64 );; 26757 26758 DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps); 26759 26760 /* check that the value is valid */ 26761 valid = unop( Iop_1Uto32, is_National_decimal( vB ) ); 26762 26763 assign( hword_7, binop( Iop_And64, 26764 unop( Iop_V128to64, mkexpr( vB ) ), 26765 mkU64( 0xFFF ) ) ); 26766 /* sign = 1 if vB is negative */ 26767 sign = binop( Iop_CmpEQ64, mkexpr( hword_7 ), mkU64( 0x002D ) ); 26768 26769 assign( tmp, convert_from_national( vbi, mkexpr( vB ) ) ); 26770 26771 /* If the result of checking the lower 4 bits of each 16-bit 26772 * value is zero, then the "number" was zero. 26773 */ 26774 zero = 26775 binop( Iop_CmpEQ64, 26776 binop( Iop_Or64, 26777 binop( Iop_And64, 26778 unop( Iop_V128HIto64, mkexpr( vB ) ), 26779 mkU64( 0x000F000F000F000FULL ) ), 26780 binop( Iop_And64, 26781 unop( Iop_V128to64, mkexpr( vB ) ), 26782 mkU64( 0x000F000F000F0000ULL ) ) ), 26783 mkU64( 0 ) ); 26784 26785 26786 /* The negative value goes in the LT bit position of the 26787 * condition code register. Set neg if the sign of the 26788 * value is negative and the value is zero. 26789 */ 26790 neg = mkAND1( sign, mkNOT1( zero ) ); 26791 26792 /* The positive value goes in the GT bit position of the 26793 * condition code register. Set neg if the sign of the 26794 * value is not negative and the value is zero. 26795 */ 26796 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26797 26798 /* For this instructions the LSB position in the CC 26799 * field, the overflow position in the other instructions, 26800 * is given by invalid. There is nothing to OR with the valid 26801 * flag. 26802 */ 26803 overflow = mkU1( 0 ); 26804 26805 /* sign of the result is: 26806 ( 0b1100 OR neg) OR (ps OR (ps AND pos) << 1 ) 26807 */ 26808 26809 putVReg( vRT_addr, 26810 binop( Iop_64HLtoV128, 26811 mkU64( 0 ), 26812 binop( Iop_Or64, 26813 binop( Iop_Or64, 26814 binop( Iop_Shl64, 26815 binop( Iop_And64, 26816 mkU64( ps ), 26817 unop( Iop_1Uto64, 26818 mkNOT1(sign))), 26819 mkU8( 1 ) ), 26820 mkU64( ps ) ), 26821 binop( Iop_Or64, 26822 binop( Iop_Or64, 26823 mkU64( 0xC ), 26824 unop( Iop_1Uto64, sign ) ), 26825 mkexpr( tmp ) ) ) ) ); 26826 26827 } 26828 break; 26829 26830 case 31: // bcdsetsgn. (BCD set sign) 26831 { 26832 IRExpr *new_sign_val, *sign; 26833 26834 DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps); 26835 26836 value = binop( Iop_AndV128, 26837 binop( Iop_64HLtoV128, 26838 mkU64( 0xFFFFFFFFFFFFFFFF ), 26839 mkU64( 0xFFFFFFFFFFFFFFF0 ) ), 26840 mkexpr( vB ) ); 26841 zero = BCDstring_zero( value ); 26842 26843 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign 26844 * codes 0xB and 0xD are negative. 26845 */ 26846 sign_digit = binop( Iop_And64, mkU64( 0xF ), 26847 unop( Iop_V128to64, mkexpr( vB ) ) ); 26848 26849 sign = mkOR1( binop( Iop_CmpEQ64, 26850 sign_digit, 26851 mkU64 ( 0xB ) ), 26852 binop( Iop_CmpEQ64, 26853 sign_digit, 26854 mkU64 ( 0xD ) ) ); 26855 neg = mkAND1( sign, mkNOT1( zero ) ); 26856 26857 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) ); 26858 26859 valid = 26860 unop( Iop_64to32, 26861 is_BCDstring128( vbi, /* Signed */True, 26862 mkexpr( vB ) ) ); 26863 26864 /* if PS = 0 26865 vB positive, sign is C 26866 vB negative, sign is D 26867 if PS = 1 26868 vB positive, sign is F 26869 vB negative, sign is D 26870 Note can't use pos or neg here since they are ANDed with 26871 zero, use sign instead. 26872 */ 26873 if (ps == 0) { 26874 new_sign_val = binop( Iop_Or64, 26875 unop( Iop_1Uto64, sign ), 26876 mkU64( 0xC ) ); 26877 26878 } else { 26879 new_sign_val = binop( Iop_Xor64, 26880 binop( Iop_Shl64, 26881 unop( Iop_1Uto64, sign ), 26882 mkU8( 1 ) ), 26883 mkU64( 0xF ) ); 26884 } 26885 26886 putVReg( vRT_addr, binop( Iop_OrV128, 26887 binop( Iop_64HLtoV128, 26888 mkU64( 0 ), 26889 new_sign_val ), 26890 value ) ); 26891 /* For this instructions the LSB position in the CC 26892 * field, the overflow position in the other instructions, 26893 * is given by invalid. 26894 */ 26895 overflow = unop( Iop_32to1, unop( Iop_Not32, valid ) ); 26896 } 26897 break; 26898 26899 default: 26900 vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n"); 26901 return False; 26902 } 26903 } 26904 break; 26905 26906 default: 26907 vex_printf("dis_av_bcd(ppc)(opc2)\n"); 26908 return False; 26909 } 26910 26911 IRTemp valid_mask = newTemp( Ity_I32 ); 26912 26913 assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) ); 26914 26915 /* set CR field 6 to: 26916 * 0b1000 if vB less then 0, i.e. vB is neg and not zero, 26917 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero, 26918 * 0b0010 if vB equals 0, 26919 * 0b0001 if vB is invalid over rules lt, gt, eq 26920 */ 26921 assign( eq_lt_gt, 26922 binop( Iop_Or32, 26923 binop( Iop_Shl32, 26924 unop( Iop_1Uto32, neg ), 26925 mkU8( 3 ) ), 26926 binop( Iop_Or32, 26927 binop( Iop_Shl32, 26928 unop( Iop_1Uto32, pos ), 26929 mkU8( 2 ) ), 26930 binop( Iop_Shl32, 26931 unop( Iop_1Uto32, zero ), 26932 mkU8( 1 ) ) ) ) ); 26933 /* valid is 1 if it is a valid number, complement and put in the 26934 * invalid bit location, overriding ls, eq, gt, overflow. 26935 */ 26936 putGST_field( PPC_GST_CR, 26937 binop( Iop_Or32, 26938 binop( Iop_And32, 26939 mkexpr( valid_mask ), 26940 binop( Iop_Or32, 26941 mkexpr( eq_lt_gt ), 26942 unop( Iop_1Uto32, overflow ) ) ), 26943 binop( Iop_And32, 26944 unop( Iop_Not32, mkexpr( valid_mask ) ), 26945 mkU32( 1 ) ) ), 26946 6 ); 26947 return True; 26948 } 26949 26950 /* 26951 AltiVec Floating Point Arithmetic Instructions 26952 */ 26953 static Bool dis_av_fp_arith ( UInt theInstr ) 26954 { 26955 /* VA-Form */ 26956 UChar opc1 = ifieldOPC(theInstr); 26957 UChar vD_addr = ifieldRegDS(theInstr); 26958 UChar vA_addr = ifieldRegA(theInstr); 26959 UChar vB_addr = ifieldRegB(theInstr); 26960 UChar vC_addr = ifieldRegC(theInstr); 26961 UInt opc2=0; 26962 26963 IRTemp vA = newTemp(Ity_V128); 26964 IRTemp vB = newTemp(Ity_V128); 26965 IRTemp vC = newTemp(Ity_V128); 26966 assign( vA, getVReg(vA_addr)); 26967 assign( vB, getVReg(vB_addr)); 26968 assign( vC, getVReg(vC_addr)); 26969 26970 if (opc1 != 0x4) { 26971 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 26972 return False; 26973 } 26974 26975 IRTemp rm = newTemp(Ity_I32); 26976 assign(rm, get_IR_roundingmode()); 26977 26978 opc2 = IFIELD( theInstr, 0, 6 ); 26979 switch (opc2) { 26980 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 26981 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 26982 vD_addr, vA_addr, vC_addr, vB_addr); 26983 putVReg( vD_addr, 26984 triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST), 26985 mkexpr(vB), 26986 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 26987 mkexpr(vA), mkexpr(vC))) ); 26988 return True; 26989 26990 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 26991 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 26992 vD_addr, vA_addr, vC_addr, vB_addr); 26993 putVReg( vD_addr, 26994 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 26995 mkexpr(vB), 26996 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 26997 mkexpr(vA), mkexpr(vC))) ); 26998 return True; 26999 } 27000 27001 default: 27002 break; // Fall through... 27003 } 27004 27005 opc2 = IFIELD( theInstr, 0, 11 ); 27006 switch (opc2) { 27007 case 0x00A: // vaddfp (Add FP, AV p137) 27008 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 27009 putVReg( vD_addr, triop(Iop_Add32Fx4, 27010 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 27011 return True; 27012 27013 case 0x04A: // vsubfp (Subtract FP, AV p261) 27014 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 27015 putVReg( vD_addr, triop(Iop_Sub32Fx4, 27016 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 27017 return True; 27018 27019 case 0x40A: // vmaxfp (Maximum FP, AV p178) 27020 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 27021 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 27022 return True; 27023 27024 case 0x44A: // vminfp (Minimum FP, AV p187) 27025 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 27026 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 27027 return True; 27028 27029 default: 27030 break; // Fall through... 27031 } 27032 27033 27034 if (vA_addr != 0) { 27035 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 27036 return False; 27037 } 27038 27039 switch (opc2) { 27040 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 27041 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 27042 putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) ); 27043 return True; 27044 27045 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 27046 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 27047 putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) ); 27048 return True; 27049 27050 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 27051 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 27052 DIP(" => not implemented\n"); 27053 return False; 27054 27055 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 27056 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 27057 DIP(" => not implemented\n"); 27058 return False; 27059 27060 default: 27061 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 27062 return False; 27063 } 27064 return True; 27065 } 27066 27067 /* 27068 AltiVec Floating Point Compare Instructions 27069 */ 27070 static Bool dis_av_fp_cmp ( UInt theInstr ) 27071 { 27072 /* VXR-Form */ 27073 UChar opc1 = ifieldOPC(theInstr); 27074 UChar vD_addr = ifieldRegDS(theInstr); 27075 UChar vA_addr = ifieldRegA(theInstr); 27076 UChar vB_addr = ifieldRegB(theInstr); 27077 UChar flag_rC = ifieldBIT10(theInstr); 27078 UInt opc2 = IFIELD( theInstr, 0, 10 ); 27079 27080 Bool cmp_bounds = False; 27081 27082 IRTemp vA = newTemp(Ity_V128); 27083 IRTemp vB = newTemp(Ity_V128); 27084 IRTemp vD = newTemp(Ity_V128); 27085 assign( vA, getVReg(vA_addr)); 27086 assign( vB, getVReg(vB_addr)); 27087 27088 if (opc1 != 0x4) { 27089 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 27090 return False; 27091 } 27092 27093 switch (opc2) { 27094 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 27095 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 27096 vD_addr, vA_addr, vB_addr); 27097 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 27098 break; 27099 27100 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 27101 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 27102 vD_addr, vA_addr, vB_addr); 27103 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 27104 break; 27105 27106 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 27107 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 27108 vD_addr, vA_addr, vB_addr); 27109 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 27110 break; 27111 27112 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 27113 IRTemp gt = newTemp(Ity_V128); 27114 IRTemp lt = newTemp(Ity_V128); 27115 IRTemp zeros = newTemp(Ity_V128); 27116 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 27117 vD_addr, vA_addr, vB_addr); 27118 cmp_bounds = True; 27119 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 27120 27121 /* Note: making use of fact that the ppc backend for compare insns 27122 return zero'd lanes if either of the corresponding arg lanes is 27123 a nan. 27124 27125 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 27126 need this for the other compares too (vcmpeqfp etc)... 27127 Better still, tighten down the spec for compare irops. 27128 */ 27129 assign( gt, unop(Iop_NotV128, 27130 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 27131 assign( lt, unop(Iop_NotV128, 27132 binop(Iop_CmpGE32Fx4, mkexpr(vA), 27133 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 27134 mkexpr(zeros), 27135 mkexpr(vB)))) ); 27136 27137 // finally, just shift gt,lt to correct position 27138 assign( vD, binop(Iop_ShlN32x4, 27139 binop(Iop_OrV128, 27140 binop(Iop_AndV128, mkexpr(gt), 27141 unop(Iop_Dup32x4, mkU32(0x2))), 27142 binop(Iop_AndV128, mkexpr(lt), 27143 unop(Iop_Dup32x4, mkU32(0x1)))), 27144 mkU8(30)) ); 27145 break; 27146 } 27147 27148 default: 27149 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 27150 return False; 27151 } 27152 27153 putVReg( vD_addr, mkexpr(vD) ); 27154 27155 if (flag_rC) { 27156 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 27157 } 27158 return True; 27159 } 27160 27161 /* 27162 AltiVec Floating Point Convert/Round Instructions 27163 */ 27164 static Bool dis_av_fp_convert ( UInt theInstr ) 27165 { 27166 /* VX-Form */ 27167 UChar opc1 = ifieldOPC(theInstr); 27168 UChar vD_addr = ifieldRegDS(theInstr); 27169 UChar UIMM_5 = ifieldRegA(theInstr); 27170 UChar vB_addr = ifieldRegB(theInstr); 27171 UInt opc2 = IFIELD( theInstr, 0, 11 ); 27172 27173 IRTemp vB = newTemp(Ity_V128); 27174 IRTemp vScale = newTemp(Ity_V128); 27175 IRTemp vInvScale = newTemp(Ity_V128); 27176 27177 float scale, inv_scale; 27178 27179 assign( vB, getVReg(vB_addr)); 27180 27181 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 27182 scale = (float)( (unsigned int) 1<<UIMM_5 ); 27183 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 27184 inv_scale = 1/scale; 27185 assign( vInvScale, 27186 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 27187 27188 if (opc1 != 0x4) { 27189 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 27190 return False; 27191 } 27192 27193 switch (opc2) { 27194 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 27195 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 27196 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 27197 unop(Iop_I32UtoFx4, mkexpr(vB)), 27198 mkexpr(vInvScale)) ); 27199 return True; 27200 27201 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 27202 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 27203 27204 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 27205 unop(Iop_I32StoFx4, mkexpr(vB)), 27206 mkexpr(vInvScale)) ); 27207 return True; 27208 27209 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 27210 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 27211 putVReg( vD_addr, 27212 unop(Iop_QFtoI32Ux4_RZ, 27213 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 27214 mkexpr(vB), mkexpr(vScale))) ); 27215 return True; 27216 27217 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 27218 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 27219 putVReg( vD_addr, 27220 unop(Iop_QFtoI32Sx4_RZ, 27221 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 27222 mkexpr(vB), mkexpr(vScale))) ); 27223 return True; 27224 27225 default: 27226 break; // Fall through... 27227 } 27228 27229 if (UIMM_5 != 0) { 27230 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 27231 return False; 27232 } 27233 27234 switch (opc2) { 27235 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 27236 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 27237 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 27238 break; 27239 27240 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 27241 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 27242 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 27243 break; 27244 27245 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 27246 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 27247 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 27248 break; 27249 27250 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 27251 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 27252 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 27253 break; 27254 27255 default: 27256 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 27257 return False; 27258 } 27259 return True; 27260 } 27261 27262 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr, 27263 const VexAbiInfo* vbi, 27264 /*OUT*/DisResult* dres, 27265 Bool (*resteerOkFn)(void*,Addr), 27266 void* callback_opaque ) 27267 { 27268 UInt opc2 = IFIELD( theInstr, 1, 10 ); 27269 27270 switch (opc2) { 27271 case 0x28E: { //tbegin. 27272 /* The current implementation is to just fail the tbegin and execute 27273 * the failure path. The failure path is assumed to be functionaly 27274 * equivalent to the transactional path with the needed data locking 27275 * to ensure correctness. The tend is just a noop and shouldn't 27276 * actually get executed. 27277 * 1) set cr0 to 0x2 27278 * 2) Initialize TFHAR to CIA+4 27279 * 3) Initialize TEXASR 27280 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.) 27281 * 5) Continue executing at the next instruction. 27282 */ 27283 UInt R = IFIELD( theInstr, 21, 1 ); 27284 27285 ULong tm_reason; 27286 UInt failure_code = 0; /* Forcing failure, will not be due to tabort 27287 * or treclaim. 27288 */ 27289 UInt persistant = 1; /* set persistant since we are always failing 27290 * the tbegin. 27291 */ 27292 UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this 27293 as the reason for failing the trasaction */ 27294 UInt tm_exact = 1; /* have exact address for failure */ 27295 27296 DIP("tbegin. %u\n", R); 27297 27298 /* Set the CR0 field to indicate the tbegin failed. Then let 27299 * the code do the branch to the failure path. 27300 * 27301 * 000 || 0 Transaction initiation successful, 27302 * unnested (Transaction state of 27303 * Non-transactional prior to tbegin.) 27304 * 010 || 0 Transaction initiation successful, nested 27305 * (Transaction state of Transactional 27306 * prior to tbegin.) 27307 * 001 || 0 Transaction initiation unsuccessful, 27308 * (Transaction state of Suspended prior 27309 * to tbegin.) 27310 */ 27311 putCR321( 0, mkU8( 0x2 ) ); 27312 27313 tm_reason = generate_TMreason( failure_code, persistant, 27314 nest_overflow, tm_exact ); 27315 27316 storeTMfailure( guest_CIA_curr_instr, tm_reason, 27317 guest_CIA_curr_instr+4 ); 27318 27319 return True; 27320 27321 break; 27322 } 27323 27324 case 0x2AE: { //tend. 27325 /* The tend. is just a noop. Do nothing */ 27326 UInt A = IFIELD( theInstr, 25, 1 ); 27327 27328 DIP("tend. %u\n", A); 27329 break; 27330 } 27331 27332 case 0x2EE: { //tsr. 27333 /* The tsr. is just a noop. Do nothing */ 27334 UInt L = IFIELD( theInstr, 21, 1 ); 27335 27336 DIP("tsr. %u\n", L); 27337 break; 27338 } 27339 27340 case 0x2CE: { //tcheck. 27341 /* The tcheck. is just a noop. Do nothing */ 27342 UInt BF = IFIELD( theInstr, 25, 1 ); 27343 27344 DIP("tcheck. %u\n", BF); 27345 break; 27346 } 27347 27348 case 0x30E: { //tbortwc. 27349 /* The tabortwc. is just a noop. Do nothing */ 27350 UInt TO = IFIELD( theInstr, 25, 1 ); 27351 UInt RA = IFIELD( theInstr, 16, 5 ); 27352 UInt RB = IFIELD( theInstr, 11, 5 ); 27353 27354 DIP("tabortwc. %u,%u,%u\n", TO, RA, RB); 27355 break; 27356 } 27357 27358 case 0x32E: { //tbortdc. 27359 /* The tabortdc. is just a noop. Do nothing */ 27360 UInt TO = IFIELD( theInstr, 25, 1 ); 27361 UInt RA = IFIELD( theInstr, 16, 5 ); 27362 UInt RB = IFIELD( theInstr, 11, 5 ); 27363 27364 DIP("tabortdc. %u,%u,%u\n", TO, RA, RB); 27365 break; 27366 } 27367 27368 case 0x34E: { //tbortwci. 27369 /* The tabortwci. is just a noop. Do nothing */ 27370 UInt TO = IFIELD( theInstr, 25, 1 ); 27371 UInt RA = IFIELD( theInstr, 16, 5 ); 27372 UInt SI = IFIELD( theInstr, 11, 5 ); 27373 27374 DIP("tabortwci. %u,%u,%u\n", TO, RA, SI); 27375 break; 27376 } 27377 27378 case 0x36E: { //tbortdci. 27379 /* The tabortdci. is just a noop. Do nothing */ 27380 UInt TO = IFIELD( theInstr, 25, 1 ); 27381 UInt RA = IFIELD( theInstr, 16, 5 ); 27382 UInt SI = IFIELD( theInstr, 11, 5 ); 27383 27384 DIP("tabortdci. %u,%u,%u\n", TO, RA, SI); 27385 break; 27386 } 27387 27388 case 0x38E: { //tbort. 27389 /* The tabort. is just a noop. Do nothing */ 27390 UInt RA = IFIELD( theInstr, 16, 5 ); 27391 27392 DIP("tabort. %u\n", RA); 27393 break; 27394 } 27395 27396 case 0x3AE: { //treclaim. 27397 /* The treclaim. is just a noop. Do nothing */ 27398 UInt RA = IFIELD( theInstr, 16, 5 ); 27399 27400 DIP("treclaim. %u\n", RA); 27401 break; 27402 } 27403 27404 case 0x3EE: { //trechkpt. 27405 /* The trechkpt. is just a noop. Do nothing */ 27406 DIP("trechkpt.\n"); 27407 break; 27408 } 27409 27410 default: 27411 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n"); 27412 return False; 27413 } 27414 27415 return True; 27416 } 27417 27418 27419 /* The 0x3C primary opcode (VSX category) uses several different forms of 27420 * extended opcodes: 27421 * o XX2-form: 27422 * - [10:2] (IBM notation [21:29]) 27423 * o XX3-form variants: 27424 * - variant 1: [10:3] (IBM notation [21:28]) 27425 * - variant 2: [9:3] (IBM notation [22:28]) 27426 * - variant 3: [7:3] (IBM notation [24:28]) 27427 * o XX-4 form: 27428 * - [10:6] (IBM notation [21:25]) 27429 * 27430 * The XX2-form needs bit 0 masked from the standard extended opcode 27431 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 27432 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 27433 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 27434 * front end since their encoding does not begin at bit 21 like the standard 27435 * format. 27436 * 27437 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 27438 * secondary opcode for such VSX instructions. 27439 * 27440 */ 27441 27442 27443 struct vsx_insn { 27444 UInt opcode; 27445 const HChar * name; 27446 }; 27447 27448 // ATTENTION: Keep this array sorted on the opcocde!!! 27449 static struct vsx_insn vsx_xx2[] = { 27450 { 0x14, "xsrsqrtesp" }, 27451 { 0x16, "xssqrtsp" }, 27452 { 0x18, "xxsel" }, 27453 { 0x34, "xsresp" }, 27454 { 0x90, "xscvdpuxws" }, 27455 { 0x92, "xsrdpi" }, 27456 { 0x94, "xsrsqrtedp" }, 27457 { 0x96, "xssqrtdp" }, 27458 { 0xb0, "xscvdpsxws" }, 27459 { 0xb2, "xsrdpiz" }, 27460 { 0xb4, "xsredp" }, 27461 { 0xd2, "xsrdpip" }, 27462 { 0xd4, "xstsqrtdp" }, 27463 { 0xd6, "xsrdpic" }, 27464 { 0xf2, "xsrdpim" }, 27465 { 0x112, "xvrspi" }, 27466 { 0x116, "xvsqrtsp" }, 27467 { 0x130, "xvcvspsxws" }, 27468 { 0x132, "xvrspiz" }, 27469 { 0x134, "xvresp" }, 27470 { 0x148, "xxspltw" }, 27471 { 0x14A, "xxextractuw" }, 27472 { 0x150, "xvcvuxwsp" }, 27473 { 0x152, "xvrspip" }, 27474 { 0x154, "xvtsqrtsp" }, 27475 { 0x156, "xvrspic" }, 27476 { 0x16A, "xxinsertw" }, 27477 { 0x170, "xvcvsxwsp" }, 27478 { 0x172, "xvrspim" }, 27479 { 0x190, "xvcvdpuxws" }, 27480 { 0x192, "xvrdpi" }, 27481 { 0x194, "xvrsqrtedp" }, 27482 { 0x196, "xvsqrtdp" }, 27483 { 0x1b0, "xvcvdpsxws" }, 27484 { 0x1b2, "xvrdpiz" }, 27485 { 0x1b4, "xvredp" }, 27486 { 0x1d0, "xvcvuxwdp" }, 27487 { 0x1d2, "xvrdpip" }, 27488 { 0x1d4, "xvtsqrtdp" }, 27489 { 0x1d6, "xvrdpic" }, 27490 { 0x1f0, "xvcvsxwdp" }, 27491 { 0x1f2, "xvrdpim" }, 27492 { 0x212, "xscvdpsp" }, 27493 { 0x216, "xscvdpspn" }, 27494 { 0x232, "xxrsp" }, 27495 { 0x250, "xscvuxdsp" }, 27496 { 0x254, "xststdcsp" }, 27497 { 0x270, "xscvsxdsp" }, 27498 { 0x290, "xscvdpuxds" }, 27499 { 0x292, "xscvspdp" }, 27500 { 0x296, "xscvspdpn" }, 27501 { 0x2b0, "xscvdpsxds" }, 27502 { 0x2b2, "xsabsdp" }, 27503 { 0x2b6, "xsxexpdp_xsxigdp" }, 27504 { 0x2d0, "xscvuxddp" }, 27505 { 0x2d2, "xsnabsdp" }, 27506 { 0x2d4, "xststdcdp" }, 27507 { 0x2e4, "xsnmsubmdp" }, 27508 { 0x2f0, "xscvsxddp" }, 27509 { 0x2f2, "xsnegdp" }, 27510 { 0x310, "xvcvspuxds" }, 27511 { 0x312, "xvcvdpsp" }, 27512 { 0x330, "xvcvspsxds" }, 27513 { 0x332, "xvabssp" }, 27514 { 0x350, "xvcvuxdsp" }, 27515 { 0x352, "xvnabssp" }, 27516 { 0x370, "xvcvsxdsp" }, 27517 { 0x372, "xvnegsp" }, 27518 { 0x390, "xvcvdpuxds" }, 27519 { 0x392, "xvcvspdp" }, 27520 { 0x3b0, "xvcvdpsxds" }, 27521 { 0x3b2, "xvabsdp" }, 27522 { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp" }, 27523 { 0x3d0, "xvcvuxddp" }, 27524 { 0x3d2, "xvnabsdp" }, 27525 { 0x3f2, "xvnegdp" } 27526 }; 27527 #define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2) 27528 27529 // ATTENTION: Keep this array sorted on the opcocde!!! 27530 static struct vsx_insn vsx_xx3[] = { 27531 { 0x0, "xsaddsp" }, 27532 { 0x4, "xsmaddasp" }, 27533 { 0x9, "xsmaddmsp" }, 27534 { 0x20, "xssubsp" }, 27535 { 0x24, "xsmaddmsp" }, 27536 { 0x3A, "xxpermr" }, 27537 { 0x40, "xsmulsp" }, 27538 { 0x44, "xsmsubasp" }, 27539 { 0x48, "xxmrghw" }, 27540 { 0x60, "xsdivsp" }, 27541 { 0x64, "xsmsubmsp" }, 27542 { 0x68, "xxperm" }, 27543 { 0x80, "xsadddp" }, 27544 { 0x84, "xsmaddadp" }, 27545 { 0x8c, "xscmpudp" }, 27546 { 0xa0, "xssubdp" }, 27547 { 0xa4, "xsmaddmdp" }, 27548 { 0xac, "xscmpodp" }, 27549 { 0xc0, "xsmuldp" }, 27550 { 0xc4, "xsmsubadp" }, 27551 { 0xc8, "xxmrglw" }, 27552 { 0xd4, "xstsqrtdp" }, 27553 { 0xe0, "xsdivdp" }, 27554 { 0xe4, "xsmsubmdp" }, 27555 { 0xe8, "xxpermr" }, 27556 { 0xeC, "xscmpexpdp" }, 27557 { 0xf4, "xstdivdp" }, 27558 { 0x100, "xvaddsp" }, 27559 { 0x104, "xvmaddasp" }, 27560 { 0x10C, "xvcmpeqsp" }, 27561 { 0x110, "xvcvspuxws" }, 27562 { 0x114, "xvrsqrtesp" }, 27563 { 0x120, "xvsubsp" }, 27564 { 0x124, "xvmaddmsp" }, 27565 { 0x130, "xvcvspsxws" }, 27566 { 0x140, "xvmulsp" }, 27567 { 0x144, "xvmsubasp" }, 27568 { 0x14C, "xvcmpgesp", }, 27569 { 0x160, "xvdivsp" }, 27570 { 0x164, "xvmsubmsp" }, 27571 { 0x174, "xvtdivsp" }, 27572 { 0x180, "xvadddp" }, 27573 { 0x184, "xvmaddadp" }, 27574 { 0x18C, "xvcmpeqdp" }, 27575 { 0x1a0, "xvsubdp" }, 27576 { 0x1a4, "xvmaddmdp" }, 27577 { 0x1aC, "xvcmpgtdp" }, 27578 { 0x1c0, "xvmuldp" }, 27579 { 0x1c4, "xvmsubadp" }, 27580 { 0x1cc, "xvcmpgedp" }, 27581 { 0x1e0, "xvdivdp" }, 27582 { 0x1e4, "xvmsubmdp" }, 27583 { 0x1f4, "xvtdivdp" }, 27584 { 0x204, "xsnmaddasp" }, 27585 { 0x208, "xxland" }, 27586 { 0x224, "xsnmaddmsp" }, 27587 { 0x228, "xxlandc" }, 27588 { 0x244, "xsnmsubasp" }, 27589 { 0x248, "xxlor" }, 27590 { 0x264, "xsnmsubmsp" }, 27591 { 0x268, "xxlxor" }, 27592 { 0x280, "xsmaxdp" }, 27593 { 0x284, "xsnmaddadp" }, 27594 { 0x288, "xxlnor" }, 27595 { 0x2a0, "xsmindp" }, 27596 { 0x2a4, "xsnmaddmdp" }, 27597 { 0x2a8, "xxlorc" }, 27598 { 0x2c0, "xscpsgndp" }, 27599 { 0x2c4, "xsnmsubadp" }, 27600 { 0x2c8, "xxlnand" }, 27601 { 0x2e4, "xsnmsubmdp" }, 27602 { 0x2e8, "xxleqv" }, 27603 { 0x300, "xvmaxsp" }, 27604 { 0x304, "xvnmaddasp" }, 27605 { 0x320, "xvminsp" }, 27606 { 0x324, "xvnmaddmsp" }, 27607 { 0x340, "xvcpsgnsp" }, 27608 { 0x344, "xvnmsubasp" }, 27609 { 0x360, "xviexpsp" }, 27610 { 0x364, "xvnmsubmsp" }, 27611 { 0x380, "xvmaxdp" }, 27612 { 0x384, "xvnmaddadp" }, 27613 { 0x3a0, "xvmindp" }, 27614 { 0x3a4, "xvnmaddmdp" }, 27615 { 0x3c0, "xvcpsgndp" }, 27616 { 0x3c4, "xvnmsubadp" }, 27617 { 0x3e0, "xviexpdp" }, 27618 { 0x3e4, "xvnmsubmdp" }, 27619 { 0x3f0, "xvcvsxddp" }, 27620 }; 27621 #define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3) 27622 27623 27624 /* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays 27625 * are sorted. 27626 */ 27627 static Int findVSXextOpCode_xx2(UInt opcode) 27628 { 27629 Int low, mid, high; 27630 low = 0; 27631 high = VSX_XX2_LEN - 1; 27632 while (low <= high) { 27633 mid = (low + high)/2; 27634 if (opcode < vsx_xx2[mid].opcode) 27635 high = mid - 1; 27636 else if (opcode > vsx_xx2[mid].opcode) 27637 low = mid + 1; 27638 else 27639 return mid; 27640 } 27641 return -1; 27642 } 27643 27644 static Int findVSXextOpCode_xx3(UInt opcode) 27645 { 27646 Int low, mid, high; 27647 low = 0; 27648 high = VSX_XX3_LEN - 1; 27649 while (low <= high) { 27650 mid = (low + high)/2; 27651 if (opcode < vsx_xx3[mid].opcode) 27652 high = mid - 1; 27653 else if (opcode > vsx_xx3[mid].opcode) 27654 low = mid + 1; 27655 else 27656 return mid; 27657 } 27658 return -1; 27659 } 27660 27661 27662 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 27663 * passed, and we then try to match it up with one of the VSX forms 27664 * below. 27665 */ 27666 static UInt get_VSX60_opc2(UInt opc2_full, UInt theInstr) 27667 { 27668 #define XX2_1_MASK 0x000003FF // xsiexpdp specific 27669 #define XX2_2_MASK 0x000003FE 27670 #define XX3_1_MASK 0x000003FC 27671 #define XX3_2_MASK 0x000001FC 27672 #define XX3_4_MASK 0x0000027C 27673 #define XX3_5_MASK 0x000003DC 27674 #define XX4_MASK 0x00000018 27675 27676 Int ret; 27677 UInt vsxExtOpcode = 0; 27678 27679 if (( ret = findVSXextOpCode_xx2(opc2_full & XX2_2_MASK)) >= 0) 27680 return vsx_xx2[ret].opcode; 27681 else if ((opc2_full & XX2_1_MASK) == 0x396 ) // xsiexpdp 27682 return 0x396; 27683 else if (( ret = findVSXextOpCode_xx3(opc2_full & XX3_1_MASK)) >= 0) 27684 return vsx_xx3[ret].opcode; 27685 else { 27686 27687 /* There are only a few codes in each of these cases it is 27688 * probably faster to check for the codes then do the array lookups. 27689 */ 27690 vsxExtOpcode = opc2_full & XX3_2_MASK; 27691 27692 switch (vsxExtOpcode) { 27693 case 0x10C: return vsxExtOpcode; // xvcmpeqsp 27694 case 0x12C: return vsxExtOpcode; // xvcmpgtsp, xvcmpgtsp. 27695 case 0x14C: return vsxExtOpcode; // xvcmpgesp, xvcmpgesp. 27696 case 0x18C: return vsxExtOpcode; // xvcmpeqdp, xvcmpeqdp. 27697 case 0x1AC: return vsxExtOpcode; // xvcmpgtdp, xvcmpgtdp. 27698 case 0x1CC: return vsxExtOpcode; // xvcmpgedp, xvcmpgedp. 27699 default: break; 27700 } 27701 27702 vsxExtOpcode = opc2_full & XX3_4_MASK; 27703 27704 switch (vsxExtOpcode) { 27705 case 0x8: return vsxExtOpcode; // xxsldwi 27706 case 0x28: return vsxExtOpcode; // xxpermdi 27707 default: break; 27708 } 27709 27710 vsxExtOpcode = opc2_full & XX3_5_MASK; 27711 27712 switch (vsxExtOpcode) { 27713 case 0x354: return vsxExtOpcode; // xvtstdcsp 27714 case 0x3D4: return vsxExtOpcode; // xvtstdcdp 27715 default: break; 27716 } 27717 27718 if (( opc2_full & XX4_MASK ) == XX4_MASK ) { // xxsel 27719 vsxExtOpcode = 0x18; 27720 return vsxExtOpcode; 27721 } 27722 } 27723 27724 vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n", 27725 opc2_full, theInstr ); 27726 vpanic( "ERROR: get_VSX60_opc2()\n" ); 27727 return 0; 27728 } 27729 27730 /*------------------------------------------------------------*/ 27731 /*--- Disassemble a single instruction ---*/ 27732 /*------------------------------------------------------------*/ 27733 27734 /* Disassemble a single instruction into IR. The instruction 27735 is located in host memory at &guest_code[delta]. */ 27736 27737 static 27738 DisResult disInstr_PPC_WRK ( 27739 Bool (*resteerOkFn) ( /*opaque*/void*, Addr ), 27740 Bool resteerCisOk, 27741 void* callback_opaque, 27742 Long delta64, 27743 const VexArchInfo* archinfo, 27744 const VexAbiInfo* abiinfo, 27745 Bool sigill_diag 27746 ) 27747 { 27748 UChar opc1; 27749 UInt opc2; 27750 DisResult dres; 27751 UInt theInstr; 27752 IRType ty = mode64 ? Ity_I64 : Ity_I32; 27753 UInt hwcaps = archinfo->hwcaps; 27754 Long delta; 27755 Bool allow_F = False; 27756 Bool allow_V = False; 27757 Bool allow_FX = False; 27758 Bool allow_GX = False; 27759 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 27760 Bool allow_DFP = False; 27761 Bool allow_isa_2_07 = False; 27762 Bool allow_isa_3_0 = False; 27763 27764 /* What insn variants are we supporting today? */ 27765 if (mode64) { 27766 allow_F = True; 27767 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 27768 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 27769 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 27770 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 27771 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); 27772 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07)); 27773 allow_isa_3_0 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_0)); 27774 } else { 27775 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 27776 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 27777 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 27778 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 27779 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 27780 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); 27781 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07)); 27782 allow_isa_3_0 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_0)); 27783 } 27784 27785 /* Enable writting the OV32 and CA32 bits added with ISA3.0 */ 27786 OV32_CA32_supported = allow_isa_3_0; 27787 27788 /* The running delta */ 27789 delta = (Long)mkSzAddr(ty, (ULong)delta64); 27790 27791 /* Set result defaults. */ 27792 dres.whatNext = Dis_Continue; 27793 dres.len = 0; 27794 dres.continueAt = 0; 27795 dres.jk_StopHere = Ijk_INVALID; 27796 dres.hint = Dis_HintNone; 27797 27798 /* At least this is simple on PPC32: insns are all 4 bytes long, and 27799 4-aligned. So just fish the whole thing out of memory right now 27800 and have done. */ 27801 theInstr = getUIntPPCendianly( &guest_code[delta] ); 27802 27803 if (0) vex_printf("insn: 0x%x\n", theInstr); 27804 27805 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 27806 27807 /* Spot "Special" instructions (see comment at top of file). */ 27808 { 27809 const UChar* code = guest_code + delta; 27810 /* Spot the 16-byte preamble: 27811 32-bit mode: 27812 5400183E rlwinm 0,0,3,0,31 27813 5400683E rlwinm 0,0,13,0,31 27814 5400E83E rlwinm 0,0,29,0,31 27815 5400983E rlwinm 0,0,19,0,31 27816 64-bit mode: 27817 78001800 rotldi 0,0,3 27818 78006800 rotldi 0,0,13 27819 7800E802 rotldi 0,0,61 27820 78009802 rotldi 0,0,51 27821 */ 27822 UInt word1 = mode64 ? 0x78001800 : 0x5400183E; 27823 UInt word2 = mode64 ? 0x78006800 : 0x5400683E; 27824 UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; 27825 UInt word4 = mode64 ? 0x78009802 : 0x5400983E; 27826 Bool is_special_preamble = False; 27827 if (getUIntPPCendianly(code+ 0) == word1 && 27828 getUIntPPCendianly(code+ 4) == word2 && 27829 getUIntPPCendianly(code+ 8) == word3 && 27830 getUIntPPCendianly(code+12) == word4) { 27831 is_special_preamble = True; 27832 } else if (! mode64 && 27833 getUIntPPCendianly(code+ 0) == 0x54001800 && 27834 getUIntPPCendianly(code+ 4) == 0x54006800 && 27835 getUIntPPCendianly(code+ 8) == 0x5400E800 && 27836 getUIntPPCendianly(code+12) == 0x54009800) { 27837 static Bool reported = False; 27838 if (!reported) { 27839 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n"); 27840 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n"); 27841 reported = True; 27842 } 27843 is_special_preamble = True; 27844 } 27845 if (is_special_preamble) { 27846 /* Got a "Special" instruction preamble. Which one is it? */ 27847 if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 27848 /* %R3 = client_request ( %R4 ) */ 27849 DIP("r3 = client_request ( %%r4 )\n"); 27850 delta += 20; 27851 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 27852 dres.jk_StopHere = Ijk_ClientReq; 27853 dres.whatNext = Dis_StopHere; 27854 goto decode_success; 27855 } 27856 else 27857 if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 27858 /* %R3 = guest_NRADDR */ 27859 DIP("r3 = guest_NRADDR\n"); 27860 delta += 20; 27861 dres.len = 20; 27862 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 27863 goto decode_success; 27864 } 27865 else 27866 if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 27867 delta += 20; 27868 if (host_endness == VexEndnessLE) { 27869 /* branch-and-link-to-noredir %R12 */ 27870 DIP("branch-and-link-to-noredir r12\n"); 27871 putGST( PPC_GST_LR, 27872 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 27873 putGST( PPC_GST_CIA, getIReg(12)); 27874 } else { 27875 /* branch-and-link-to-noredir %R11 */ 27876 DIP("branch-and-link-to-noredir r11\n"); 27877 putGST( PPC_GST_LR, 27878 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 27879 putGST( PPC_GST_CIA, getIReg(11)); 27880 } 27881 dres.jk_StopHere = Ijk_NoRedir; 27882 dres.whatNext = Dis_StopHere; 27883 goto decode_success; 27884 } 27885 else 27886 if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 27887 /* %R3 = guest_NRADDR_GPR2 */ 27888 DIP("r3 = guest_NRADDR_GPR2\n"); 27889 delta += 20; 27890 dres.len = 20; 27891 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 27892 goto decode_success; 27893 } 27894 else 27895 if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { 27896 DIP("IR injection\n"); 27897 if (host_endness == VexEndnessBE) 27898 vex_inject_ir(irsb, Iend_BE); 27899 else 27900 vex_inject_ir(irsb, Iend_LE); 27901 27902 delta += 20; 27903 dres.len = 20; 27904 27905 // Invalidate the current insn. The reason is that the IRop we're 27906 // injecting here can change. In which case the translation has to 27907 // be redone. For ease of handling, we simply invalidate all the 27908 // time. 27909 27910 stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr))); 27911 stmt(IRStmt_Put(OFFB_CMLEN, mkSzImm(ty, 20))); 27912 27913 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 27914 dres.whatNext = Dis_StopHere; 27915 dres.jk_StopHere = Ijk_InvalICache; 27916 goto decode_success; 27917 } 27918 /* We don't know what it is. Set opc1/opc2 so decode_failure 27919 can print the insn following the Special-insn preamble. */ 27920 theInstr = getUIntPPCendianly(code+16); 27921 opc1 = ifieldOPC(theInstr); 27922 opc2 = ifieldOPClo10(theInstr); 27923 goto decode_failure; 27924 /*NOTREACHED*/ 27925 } 27926 } 27927 27928 opc1 = ifieldOPC(theInstr); 27929 opc2 = ifieldOPClo10(theInstr); 27930 27931 // Note: all 'reserved' bits must be cleared, else invalid 27932 switch (opc1) { 27933 27934 /* Integer Arithmetic Instructions */ 27935 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 27936 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 27937 if (dis_int_arith( theInstr )) goto decode_success; 27938 goto decode_failure; 27939 27940 /* Integer Compare Instructions */ 27941 case 0x0B: case 0x0A: // cmpi, cmpli 27942 if (dis_int_cmp( theInstr )) goto decode_success; 27943 goto decode_failure; 27944 27945 /* Integer Logical Instructions */ 27946 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 27947 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 27948 if (dis_int_logic( theInstr )) goto decode_success; 27949 goto decode_failure; 27950 27951 /* Integer Rotate Instructions */ 27952 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 27953 if (dis_int_rot( theInstr )) goto decode_success; 27954 goto decode_failure; 27955 27956 /* 64bit Integer Rotate Instructions */ 27957 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 27958 if (!mode64) goto decode_failure; 27959 if (dis_int_rot( theInstr )) goto decode_success; 27960 goto decode_failure; 27961 27962 /* Integer Load Instructions */ 27963 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 27964 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 27965 case 0x20: case 0x21: // lwz, lwzu 27966 if (dis_int_load( theInstr )) goto decode_success; 27967 goto decode_failure; 27968 27969 /* Integer Store Instructions */ 27970 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 27971 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 27972 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 27973 goto decode_failure; 27974 27975 /* Integer Load and Store Multiple Instructions */ 27976 case 0x2E: case 0x2F: // lmw, stmw 27977 if (dis_int_ldst_mult( theInstr )) goto decode_success; 27978 goto decode_failure; 27979 27980 /* Branch Instructions */ 27981 case 0x12: case 0x10: // b, bc 27982 if (dis_branch(theInstr, abiinfo, &dres, 27983 resteerOkFn, callback_opaque)) 27984 goto decode_success; 27985 goto decode_failure; 27986 27987 /* System Linkage Instructions */ 27988 case 0x11: // sc 27989 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 27990 goto decode_failure; 27991 27992 /* Trap Instructions */ 27993 case 0x02: // tdi 27994 if (!mode64) goto decode_failure; 27995 if (dis_trapi(theInstr, &dres)) goto decode_success; 27996 goto decode_failure; 27997 27998 case 0x03: // twi 27999 if (dis_trapi(theInstr, &dres)) goto decode_success; 28000 goto decode_failure; 28001 28002 /* Floating Point Load Instructions */ 28003 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 28004 case 0x33: // lfdu 28005 if (!allow_F) goto decode_noF; 28006 if (dis_fp_load( theInstr )) goto decode_success; 28007 goto decode_failure; 28008 28009 /* Floating Point Store Instructions */ 28010 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 28011 case 0x37: // stfdux 28012 if (!allow_F) goto decode_noF; 28013 if (dis_fp_store( theInstr )) goto decode_success; 28014 goto decode_failure; 28015 28016 /* Floating Point Load Double Pair Instructions */ 28017 case 0x39: case 0x3D: // lfdp, lxsd, lxssp, lxv 28018 // stfdp, stxsd, stxssp, stxv 28019 if (!allow_F) goto decode_noF; 28020 if (dis_fp_pair( theInstr )) goto decode_success; 28021 goto decode_failure; 28022 28023 /* 128-bit Integer Load */ 28024 case 0x38: // lq 28025 if (dis_int_load( theInstr )) goto decode_success; 28026 goto decode_failure; 28027 28028 /* 64bit Integer Loads */ 28029 case 0x3A: // ld, ldu, lwa 28030 if (!mode64) goto decode_failure; 28031 if (dis_int_load( theInstr )) goto decode_success; 28032 goto decode_failure; 28033 28034 case 0x3B: 28035 if (!allow_F) goto decode_noF; 28036 opc2 = ifieldOPClo10(theInstr); 28037 28038 switch (opc2) { 28039 case 0x2: // dadd - DFP Add 28040 case 0x202: // dsub - DFP Subtract 28041 case 0x22: // dmul - DFP Mult 28042 case 0x222: // ddiv - DFP Divide 28043 if (!allow_DFP) goto decode_noDFP; 28044 if (dis_dfp_arith( theInstr )) 28045 goto decode_success; 28046 case 0x82: // dcmpo, DFP comparison ordered instruction 28047 case 0x282: // dcmpu, DFP comparison unordered instruction 28048 if (!allow_DFP) goto decode_noDFP; 28049 if (dis_dfp_compare( theInstr ) ) 28050 goto decode_success; 28051 goto decode_failure; 28052 case 0x102: // dctdp - DFP convert to DFP long 28053 case 0x302: // drsp - DFP round to dfp short 28054 case 0x122: // dctfix - DFP convert to fixed 28055 if (!allow_DFP) goto decode_noDFP; 28056 if (dis_dfp_fmt_conv( theInstr )) 28057 goto decode_success; 28058 goto decode_failure; 28059 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed 28060 if (!allow_VX) 28061 goto decode_failure; 28062 if (!allow_DFP) goto decode_noDFP; 28063 if (dis_dfp_fmt_conv( theInstr )) 28064 goto decode_success; 28065 goto decode_failure; 28066 case 0x2A2: // dtstsf - DFP number of significant digits 28067 case 0x2A3: // dtstsfi - DFP number of significant digits Immediate 28068 if (!allow_DFP) goto decode_noDFP; 28069 if (dis_dfp_significant_digits(theInstr)) 28070 goto decode_success; 28071 goto decode_failure; 28072 case 0x142: // ddedpd DFP Decode DPD to BCD 28073 case 0x342: // denbcd DFP Encode BCD to DPD 28074 if (!allow_DFP) goto decode_noDFP; 28075 if (dis_dfp_bcd(theInstr)) 28076 goto decode_success; 28077 goto decode_failure; 28078 case 0x162: // dxex - Extract exponent 28079 case 0x362: // diex - Insert exponent 28080 if (!allow_DFP) goto decode_noDFP; 28081 if (dis_dfp_extract_insert( theInstr ) ) 28082 goto decode_success; 28083 goto decode_failure; 28084 case 0x3CE: // fcfidus (implemented as native insn) 28085 if (!allow_VX) 28086 goto decode_noVX; 28087 if (dis_fp_round( theInstr )) 28088 goto decode_success; 28089 goto decode_failure; 28090 case 0x34E: // fcfids 28091 if (dis_fp_round( theInstr )) 28092 goto decode_success; 28093 goto decode_failure; 28094 } 28095 28096 opc2 = ifieldOPClo9( theInstr ); 28097 switch (opc2) { 28098 case 0x42: // dscli, DFP shift left 28099 case 0x62: // dscri, DFP shift right 28100 if (!allow_DFP) goto decode_noDFP; 28101 if (dis_dfp_shift( theInstr )) 28102 goto decode_success; 28103 goto decode_failure; 28104 case 0xc2: // dtstdc, DFP test data class 28105 case 0xe2: // dtstdg, DFP test data group 28106 if (!allow_DFP) goto decode_noDFP; 28107 if (dis_dfp_class_test( theInstr )) 28108 goto decode_success; 28109 goto decode_failure; 28110 } 28111 28112 opc2 = ifieldOPClo8( theInstr ); 28113 switch (opc2) { 28114 case 0x3: // dqua - DFP Quantize 28115 case 0x23: // drrnd - DFP Reround 28116 case 0x43: // dquai - DFP Quantize immediate 28117 if (!allow_DFP) goto decode_noDFP; 28118 if (dis_dfp_quantize_sig_rrnd( theInstr ) ) 28119 goto decode_success; 28120 goto decode_failure; 28121 case 0xA2: // dtstex - DFP Test exponent 28122 if (!allow_DFP) goto decode_noDFP; 28123 if (dis_dfp_exponent_test( theInstr ) ) 28124 goto decode_success; 28125 goto decode_failure; 28126 case 0x63: // drintx - Round to an integer value 28127 case 0xE3: // drintn - Round to an integer value 28128 if (!allow_DFP) goto decode_noDFP; 28129 if (dis_dfp_round( theInstr ) ) { 28130 goto decode_success; 28131 } 28132 goto decode_failure; 28133 default: 28134 break; /* fall through to next opc2 check */ 28135 } 28136 28137 opc2 = IFIELD(theInstr, 1, 5); 28138 switch (opc2) { 28139 /* Floating Point Arith Instructions */ 28140 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 28141 case 0x19: // fmuls 28142 if (dis_fp_arith(theInstr)) goto decode_success; 28143 goto decode_failure; 28144 case 0x16: // fsqrts 28145 if (!allow_FX) goto decode_noFX; 28146 if (dis_fp_arith(theInstr)) goto decode_success; 28147 goto decode_failure; 28148 case 0x18: // fres 28149 if (!allow_GX) goto decode_noGX; 28150 if (dis_fp_arith(theInstr)) goto decode_success; 28151 goto decode_failure; 28152 28153 /* Floating Point Mult-Add Instructions */ 28154 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 28155 case 0x1F: // fnmadds 28156 if (dis_fp_multadd(theInstr)) goto decode_success; 28157 goto decode_failure; 28158 28159 case 0x1A: // frsqrtes 28160 if (!allow_GX) goto decode_noGX; 28161 if (dis_fp_arith(theInstr)) goto decode_success; 28162 goto decode_failure; 28163 28164 default: 28165 goto decode_failure; 28166 } 28167 break; 28168 28169 case 0x3C: // VSX instructions (except load/store) 28170 { 28171 // All of these VSX instructions use some VMX facilities, so 28172 // if allow_V is not set, we'll skip trying to decode. 28173 if (!allow_V) goto decode_noVX; 28174 /* The xvtstdcdp and xvtstdcsp instructions do not have a 28175 contiguous opc2 field. The following vsxOpc2 = get_VSX60_opc2() 28176 doesn't correctly match these instructions for dc != 0. So, 28177 we will explicitly look for the two instructions. */ 28178 opc2 = ifieldOPClo10(theInstr); 28179 UInt opc2hi = IFIELD(theInstr, 7, 4); 28180 UInt opc2lo = IFIELD(theInstr, 3, 3); 28181 UInt vsxOpc2; 28182 28183 if (( opc2hi == 13 ) && ( opc2lo == 5)) { //xvtstdcsp 28184 if (dis_vxs_misc(theInstr, 0x354, allow_isa_3_0)) 28185 goto decode_success; 28186 goto decode_failure; 28187 } 28188 28189 if (( opc2hi == 15 ) && ( opc2lo == 5)) { //xvtstdcdp 28190 if (dis_vxs_misc(theInstr, 0x3D4, allow_isa_3_0)) 28191 goto decode_success; 28192 goto decode_failure; 28193 } 28194 28195 /* The vsxOpc2 returned is the "normalized" value, representing the 28196 * instructions secondary opcode as taken from the standard secondary 28197 * opcode field [21:30] (IBM notatition), even if the actual field 28198 * is non-standard. These normalized values are given in the opcode 28199 * appendices of the ISA 2.06 document. 28200 */ 28201 if ( ( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )// xxspltib 28202 { 28203 /* This is a special case of the XX1 form where the RA, RB 28204 * fields hold an immediate value. 28205 */ 28206 if (dis_vxs_misc(theInstr, opc2, allow_isa_3_0)) goto decode_success; 28207 goto decode_failure; 28208 } 28209 28210 vsxOpc2 = get_VSX60_opc2(opc2, theInstr); 28211 28212 switch (vsxOpc2) { 28213 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 28214 case 0x068: case 0xE8: // xxperm, xxpermr 28215 case 0x018: case 0x148: // xxsel, xxspltw 28216 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 28217 goto decode_failure; 28218 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor, 28219 case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc 28220 case 0x2C8: case 0x2E8: // xxlnand, xxleqv 28221 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 28222 goto decode_failure; 28223 case 0x0ec: // xscmpexpdp 28224 case 0x14A: case 0x16A: // xxextractuw, xxinsertw 28225 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 28226 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 28227 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 28228 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 28229 case 0x034: case 0x014: // xsresp, xsrsqrtesp 28230 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 28231 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 28232 case 0x092: case 0x232: // xsrdpi, xsrsp 28233 case 0x3B6: // xxbrh, xvxexpdp, xvxexpsp, xvxsigdp 28234 // xvxsigsp, xvcvhpsp 28235 case 0x2b6: // xsxexpdp, xsxsigdp 28236 case 0x254: case 0x2d4: // xststdcsp, xststdcdp 28237 case 0x354: // xvtstdcsp 28238 case 0x360:case 0x396: // xviexpsp, xsiexpdp 28239 case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp 28240 if (dis_vxs_misc(theInstr, vsxOpc2, allow_isa_3_0)) 28241 goto decode_success; 28242 goto decode_failure; 28243 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 28244 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 28245 goto decode_failure; 28246 case 0x0: case 0x020: // xsaddsp, xssubsp 28247 case 0x080: // xsadddp 28248 case 0x060: case 0x0E0: // xsdivsp, xsdivdp 28249 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp 28250 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 28251 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp 28252 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 28253 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp 28254 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 28255 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp 28256 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 28257 case 0x040: case 0x0C0: // xsmulsp, xsmuldp 28258 case 0x0A0: // xssubdp 28259 case 0x016: case 0x096: // xssqrtsp,xssqrtdp 28260 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp 28261 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 28262 goto decode_failure; 28263 case 0x180: // xvadddp 28264 case 0x1E0: // xvdivdp 28265 case 0x1C0: // xvmuldp 28266 case 0x1A0: // xvsubdp 28267 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 28268 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 28269 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 28270 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 28271 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 28272 case 0x196: // xvsqrtdp 28273 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 28274 goto decode_failure; 28275 case 0x100: // xvaddsp 28276 case 0x160: // xvdivsp 28277 case 0x140: // xvmulsp 28278 case 0x120: // xvsubsp 28279 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 28280 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 28281 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 28282 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 28283 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 28284 case 0x116: // xvsqrtsp 28285 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 28286 goto decode_failure; 28287 28288 case 0x250: // xscvuxdsp 28289 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp 28290 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp 28291 case 0x090: // xscvdpuxws 28292 // The above VSX conversion instructions employ some ISA 2.06 28293 // floating point conversion instructions under the covers, 28294 // so if allow_VX (which means "supports ISA 2.06") is not set, 28295 // we'll skip the decode. 28296 if (!allow_VX) goto decode_noVX; 28297 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 28298 goto decode_failure; 28299 28300 case 0x2B0: // xscvdpsxds 28301 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp 28302 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 28303 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 28304 case 0x212: case 0x216: // xscvdpsp, xscvdpspn 28305 case 0x292: case 0x296: // xscvspdp, xscvspdpn 28306 case 0x312: // xvcvdpsp 28307 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 28308 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 28309 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 28310 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 28311 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 28312 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 28313 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 28314 goto decode_failure; 28315 28316 case 0x18C: // xvcmpeqdp[.] 28317 case 0x10C: // xvcmpeqsp[.] 28318 case 0x14C: // xvcmpgesp[.] 28319 case 0x12C: // xvcmpgtsp[.] 28320 case 0x1CC: // xvcmpgedp[.] 28321 case 0x1AC: // xvcmpgtdp[.] 28322 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 28323 goto decode_failure; 28324 28325 case 0x134: // xvresp 28326 case 0x1B4: // xvredp 28327 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 28328 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 28329 case 0x300: case 0x320: // xvmaxsp, xvminsp 28330 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 28331 case 0x3B2: case 0x332: // xvabsdp, xvabssp 28332 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 28333 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 28334 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 28335 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 28336 case 0x112: case 0x156: // xvrspi, xvrspic 28337 case 0x172: case 0x152: // xvrspim, xvrspip 28338 case 0x132: // xvrspiz 28339 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 28340 goto decode_failure; 28341 28342 default: 28343 goto decode_failure; 28344 } 28345 break; 28346 } 28347 28348 /* 64bit Integer Stores */ 28349 case 0x3E: // std, stdu, stq 28350 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 28351 goto decode_failure; 28352 28353 case 0x3F: 28354 if (!allow_F) goto decode_noF; 28355 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 28356 so we can simply fall through the first switch statement */ 28357 28358 opc2 = IFIELD(theInstr, 1, 5); 28359 switch (opc2) { 28360 /* Floating Point Arith Instructions */ 28361 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 28362 case 0x19: // fmul 28363 if (dis_fp_arith(theInstr)) goto decode_success; 28364 goto decode_failure; 28365 case 0x16: // fsqrt 28366 if (!allow_FX) goto decode_noFX; 28367 if (dis_fp_arith(theInstr)) goto decode_success; 28368 goto decode_failure; 28369 case 0x17: case 0x1A: // fsel, frsqrte 28370 if (!allow_GX) goto decode_noGX; 28371 if (dis_fp_arith(theInstr)) goto decode_success; 28372 goto decode_failure; 28373 28374 /* Floating Point Mult-Add Instructions */ 28375 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 28376 case 0x1F: // fnmadd 28377 if (dis_fp_multadd(theInstr)) goto decode_success; 28378 goto decode_failure; 28379 28380 case 0x18: // fre 28381 if (!allow_GX) goto decode_noGX; 28382 if (dis_fp_arith(theInstr)) goto decode_success; 28383 goto decode_failure; 28384 28385 default: 28386 break; // Fall through 28387 } 28388 28389 opc2 = IFIELD(theInstr, 1, 8); 28390 switch (opc2) { 28391 case 0x5: // xsrqpi, xsrqpix 28392 case 0x25: // xsrqpxp 28393 if ( !mode64 || !allow_isa_3_0 ) goto decode_failure; 28394 if ( dis_vx_Scalar_Round_to_quad_integer( theInstr ) ) 28395 goto decode_success; 28396 goto decode_failure; 28397 default: 28398 break; // Fall through 28399 } 28400 28401 opc2 = IFIELD(theInstr, 1, 10); 28402 UInt inst_select = IFIELD( theInstr, 16, 5 ); 28403 28404 switch (opc2) { 28405 /* 128-bit DFP instructions */ 28406 case 0x2: // daddq - DFP Add 28407 case 0x202: // dsubq - DFP Subtract 28408 case 0x22: // dmulq - DFP Mult 28409 case 0x222: // ddivq - DFP Divide 28410 if (!allow_DFP) goto decode_noDFP; 28411 if (dis_dfp_arithq( theInstr )) 28412 goto decode_success; 28413 goto decode_failure; 28414 case 0x162: // dxexq - DFP Extract exponent 28415 case 0x362: // diexq - DFP Insert exponent 28416 if (!allow_DFP) goto decode_noDFP; 28417 if (dis_dfp_extract_insertq( theInstr )) 28418 goto decode_success; 28419 goto decode_failure; 28420 28421 case 0x82: // dcmpoq, DFP comparison ordered instruction 28422 case 0x282: // dcmpuq, DFP comparison unordered instruction 28423 if (!allow_DFP) goto decode_noDFP; 28424 if (dis_dfp_compare( theInstr ) ) 28425 goto decode_success; 28426 goto decode_failure; 28427 28428 case 0x102: // dctqpq - DFP convert to DFP extended 28429 case 0x302: // drdpq - DFP round to dfp Long 28430 case 0x122: // dctfixq - DFP convert to fixed quad 28431 case 0x322: // dcffixq - DFP convert from fixed quad 28432 if (!allow_DFP) goto decode_noDFP; 28433 if (dis_dfp_fmt_convq( theInstr )) 28434 goto decode_success; 28435 goto decode_failure; 28436 28437 case 0x2A2: // dtstsfq - DFP number of significant digits 28438 case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate 28439 if (!allow_DFP) goto decode_noDFP; 28440 if (dis_dfp_significant_digits(theInstr)) 28441 goto decode_success; 28442 goto decode_failure; 28443 28444 case 0x142: // ddedpdq DFP Decode DPD to BCD 28445 case 0x342: // denbcdq DFP Encode BCD to DPD 28446 if (!allow_DFP) goto decode_noDFP; 28447 if (dis_dfp_bcdq(theInstr)) 28448 goto decode_success; 28449 goto decode_failure; 28450 28451 /* Floating Point Compare Instructions */ 28452 case 0x000: // fcmpu 28453 case 0x020: // fcmpo 28454 if (dis_fp_cmp(theInstr)) goto decode_success; 28455 goto decode_failure; 28456 28457 case 0x080: // ftdiv 28458 case 0x0A0: // ftsqrt 28459 if (dis_fp_tests(theInstr)) goto decode_success; 28460 goto decode_failure; 28461 28462 /* Floating Point Rounding/Conversion Instructions */ 28463 case 0x00C: // frsp 28464 case 0x00E: // fctiw 28465 case 0x00F: // fctiwz 28466 case 0x32E: // fctid 28467 case 0x32F: // fctidz 28468 case 0x34E: // fcfid 28469 if (dis_fp_round(theInstr)) goto decode_success; 28470 goto decode_failure; 28471 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 28472 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 28473 if (!allow_VX) goto decode_noVX; 28474 if (dis_fp_round(theInstr)) goto decode_success; 28475 goto decode_failure; 28476 28477 /* Power6 rounding stuff */ 28478 case 0x1E8: // frim 28479 case 0x1C8: // frip 28480 case 0x188: // frin 28481 case 0x1A8: // friz 28482 /* A hack to check for P6 capability . . . */ 28483 if ((allow_F && allow_V && allow_FX && allow_GX) && 28484 (dis_fp_round(theInstr))) 28485 goto decode_success; 28486 goto decode_failure; 28487 28488 /* Floating Point Move Instructions */ 28489 case 0x008: // fcpsgn 28490 case 0x028: // fneg 28491 case 0x048: // fmr 28492 case 0x088: // fnabs 28493 case 0x108: // fabs 28494 if (dis_fp_move( theInstr )) goto decode_success; 28495 goto decode_failure; 28496 28497 case 0x3c6: case 0x346: // fmrgew, fmrgow 28498 if (dis_fp_merge( theInstr )) goto decode_success; 28499 goto decode_failure; 28500 28501 /* Floating Point Status/Control Register Instructions */ 28502 case 0x026: // mtfsb1 28503 case 0x040: // mcrfs 28504 case 0x046: // mtfsb0 28505 case 0x086: // mtfsfi 28506 case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni, 28507 // mffscrn, mffscrn, mffscri, mffsl 28508 case 0x2C7: // mtfsf 28509 // Some of the above instructions need to know more about the 28510 // ISA level supported by the host. 28511 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success; 28512 goto decode_failure; 28513 28514 case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp 28515 if ( inst_select == 27 ) { // xssqrtqp 28516 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) ) 28517 goto decode_success; 28518 } 28519 28520 /* Instructions implemented with Pre ISA 3.0 Iops */ 28521 /* VSX Scalar Quad-Precision instructions */ 28522 case 0x064: // xscpsgnqp 28523 case 0x0A4: // xscmpexpqp 28524 case 0x084: // xscmpoqp 28525 case 0x284: // xscmpuqp 28526 case 0x2C4: // xststdcqp 28527 case 0x364: // xsiexpqp 28528 if (dis_vx_scalar_quad_precision( theInstr )) goto decode_success; 28529 goto decode_failure; 28530 28531 /* Instructions implemented using ISA 3.0 instructions */ 28532 // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD] 28533 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision [using RN mode] 28534 // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD] 28535 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision [using RN mode] 28536 // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD] 28537 case 0x184: // xsmaddqp (VSX Scalar Multiply Add Quad-Precision [using RN mode] 28538 // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD] 28539 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Sub Quad-Precision [using RN mode] 28540 // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD] 28541 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode] 28542 // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD] 28543 case 0x1E4: // xsnmsubqp (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode] 28544 // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD] 28545 case 0x204: // xssubqp (VSX Scalar Subrtact Quad-Precision [using RN mode] 28546 // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD] 28547 case 0x224: // xsdivqp (VSX Scalar Divde Quad-Precision [using RN mode] 28548 case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp 28549 // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz 28550 if ( !mode64 || !allow_isa_3_0 ) goto decode_failure; 28551 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) ) 28552 goto decode_success; 28553 goto decode_failure; 28554 28555 default: 28556 break; // Fall through... 28557 } 28558 28559 opc2 = ifieldOPClo9( theInstr ); 28560 switch (opc2) { 28561 case 0x42: // dscli, DFP shift left 28562 case 0x62: // dscri, DFP shift right 28563 if (!allow_DFP) goto decode_noDFP; 28564 if (dis_dfp_shiftq( theInstr )) 28565 goto decode_success; 28566 goto decode_failure; 28567 case 0xc2: // dtstdc, DFP test data class 28568 case 0xe2: // dtstdg, DFP test data group 28569 if (!allow_DFP) goto decode_noDFP; 28570 if (dis_dfp_class_test( theInstr )) 28571 goto decode_success; 28572 goto decode_failure; 28573 default: 28574 break; 28575 } 28576 28577 opc2 = ifieldOPClo8( theInstr ); 28578 switch (opc2) { 28579 case 0x3: // dquaq - DFP Quantize Quad 28580 case 0x23: // drrndq - DFP Reround Quad 28581 case 0x43: // dquaiq - DFP Quantize immediate Quad 28582 if (!allow_DFP) goto decode_noDFP; 28583 if (dis_dfp_quantize_sig_rrndq( theInstr )) 28584 goto decode_success; 28585 goto decode_failure; 28586 case 0xA2: // dtstexq - DFP Test exponent Quad 28587 if (!allow_DFP) goto decode_noDFP; 28588 if (dis_dfp_exponent_test( theInstr ) ) 28589 goto decode_success; 28590 goto decode_failure; 28591 case 0x63: // drintxq - DFP Round to an integer value 28592 case 0xE3: // drintnq - DFP Round to an integer value 28593 if (!allow_DFP) goto decode_noDFP; 28594 if (dis_dfp_roundq( theInstr )) 28595 goto decode_success; 28596 goto decode_failure; 28597 28598 default: 28599 goto decode_failure; 28600 } 28601 break; 28602 28603 case 0x13: 28604 28605 opc2 = ifieldOPClo5(theInstr); 28606 switch (opc2) { 28607 28608 /* PC relative load/store */ 28609 case 0x002: // addpcis 28610 if (dis_pc_relative(theInstr)) goto decode_success; 28611 goto decode_failure; 28612 28613 /* fall through to the next opc2 field size */ 28614 } 28615 28616 opc2 = ifieldOPClo10(theInstr); 28617 switch (opc2) { 28618 28619 /* Condition Register Logical Instructions */ 28620 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 28621 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 28622 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 28623 if (dis_cond_logic( theInstr )) goto decode_success; 28624 goto decode_failure; 28625 28626 /* Branch Instructions */ 28627 case 0x210: case 0x010: // bcctr, bclr 28628 if (dis_branch(theInstr, abiinfo, &dres, 28629 resteerOkFn, callback_opaque)) 28630 goto decode_success; 28631 goto decode_failure; 28632 28633 /* Memory Synchronization Instructions */ 28634 case 0x096: // isync 28635 if (dis_memsync( theInstr )) goto decode_success; 28636 goto decode_failure; 28637 28638 default: 28639 goto decode_failure; 28640 } 28641 break; 28642 28643 28644 case 0x1F: 28645 28646 /* For arith instns, bit10 is the OE flag (overflow enable) */ 28647 28648 opc2 = IFIELD(theInstr, 1, 9); 28649 switch (opc2) { 28650 /* Integer Arithmetic Instructions */ 28651 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 28652 case 0x0AA: // addex 28653 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 28654 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 28655 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 28656 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 28657 case 0x0C8: // subfze 28658 if (dis_int_arith( theInstr )) goto decode_success; 28659 goto decode_failure; 28660 28661 case 0x18B: // divweu (implemented as native insn) 28662 case 0x1AB: // divwe (implemented as native insn) 28663 if (!allow_VX) goto decode_noVX; 28664 if (dis_int_arith( theInstr )) goto decode_success; 28665 goto decode_failure; 28666 28667 /* 64bit Integer Arithmetic */ 28668 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 28669 case 0x1C9: case 0x1E9: // divdu, divd 28670 if (!mode64) goto decode_failure; 28671 if (dis_int_arith( theInstr )) goto decode_success; 28672 goto decode_failure; 28673 28674 case 0x1A9: // divde (implemented as native insn) 28675 case 0x189: // divdeuo (implemented as native insn) 28676 if (!allow_VX) goto decode_noVX; 28677 if (!mode64) goto decode_failure; 28678 if (dis_int_arith( theInstr )) goto decode_success; 28679 goto decode_failure; 28680 28681 case 0x1FC: // cmpb 28682 if (dis_int_logic( theInstr )) goto decode_success; 28683 goto decode_failure; 28684 28685 default: 28686 break; // Fall through... 28687 } 28688 28689 /* All remaining opcodes use full 10 bits. */ 28690 28691 opc2 = IFIELD(theInstr, 1, 10); 28692 switch (opc2) { 28693 28694 /* Integer miscellaneous instructions */ 28695 case 0x01E: // wait RFC 2500 28696 if (dis_int_misc( theInstr )) goto decode_success; 28697 goto decode_failure; 28698 28699 28700 /* Integer Compare Instructions */ 28701 case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb 28702 if (dis_int_cmp( theInstr )) goto decode_success; 28703 goto decode_failure; 28704 28705 case 0x0C0: case 0x0E0: // cmprb, cmpeqb 28706 if (dis_byte_cmp( theInstr )) goto decode_success; 28707 goto decode_failure; 28708 28709 case 0x10B: case 0x30B: // moduw, modsw 28710 case 0x109: case 0x309: // modsd, modud 28711 case 0x21A: case 0x23A: // cnttzw, cnttzd 28712 if (dis_modulo_int( theInstr )) goto decode_success; 28713 goto decode_failure; 28714 28715 /* Integer Logical Instructions */ 28716 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 28717 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 28718 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 28719 case 0x19C: case 0x13C: // orc, xor 28720 case 0x2DF: case 0x25F: // mftgpr, mffgpr 28721 if (dis_int_logic( theInstr )) goto decode_success; 28722 goto decode_failure; 28723 28724 case 0x28E: case 0x2AE: // tbegin., tend. 28725 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc. 28726 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. 28727 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt. 28728 if (dis_transactional_memory( theInstr, 28729 getUIntPPCendianly( &guest_code[delta + 4]), 28730 abiinfo, &dres, 28731 resteerOkFn, callback_opaque)) 28732 goto decode_success; 28733 goto decode_failure; 28734 28735 /* 64bit Integer Logical Instructions */ 28736 case 0x3DA: case 0x03A: // extsw, cntlzd 28737 if (!mode64) goto decode_failure; 28738 if (dis_int_logic( theInstr )) goto decode_success; 28739 goto decode_failure; 28740 28741 /* 64bit Integer Parity Instructions */ 28742 case 0xba: // prtyd 28743 if (!mode64) goto decode_failure; 28744 if (dis_int_parity( theInstr )) goto decode_success; 28745 goto decode_failure; 28746 28747 case 0x9a: // prtyw 28748 if (dis_int_parity( theInstr )) goto decode_success; 28749 goto decode_failure; 28750 28751 /* Integer Shift Instructions */ 28752 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 28753 case 0x218: // srw 28754 if (dis_int_shift( theInstr )) goto decode_success; 28755 goto decode_failure; 28756 28757 /* 64bit Integer Shift Instructions */ 28758 case 0x01B: case 0x31A: // sld, srad 28759 case 0x33A: case 0x33B: // sradi 28760 case 0x21B: // srd 28761 if (!mode64) goto decode_failure; 28762 if (dis_int_shift( theInstr )) goto decode_success; 28763 goto decode_failure; 28764 28765 /* Integer Load Instructions */ 28766 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 28767 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 28768 case 0x017: case 0x037: // lwzx, lwzux 28769 if (dis_int_load( theInstr )) goto decode_success; 28770 goto decode_failure; 28771 28772 /* 64bit Integer Load Instructions */ 28773 case 0x035: case 0x015: // ldux, ldx 28774 case 0x175: case 0x155: // lwaux, lwax 28775 if (!mode64) goto decode_failure; 28776 if (dis_int_load( theInstr )) goto decode_success; 28777 goto decode_failure; 28778 28779 /* Integer Store Instructions */ 28780 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 28781 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 28782 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 28783 goto decode_failure; 28784 28785 /* 64bit Integer Store Instructions */ 28786 case 0x0B5: case 0x095: // stdux, stdx 28787 if (!mode64) goto decode_failure; 28788 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 28789 goto decode_failure; 28790 28791 /* Integer Load and Store with Byte Reverse Instructions */ 28792 case 0x214: case 0x294: // ldbrx, stdbrx 28793 if (!mode64) goto decode_failure; 28794 if (dis_int_ldst_rev( theInstr )) goto decode_success; 28795 goto decode_failure; 28796 28797 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx 28798 case 0x396: // sthbrx 28799 if (dis_int_ldst_rev( theInstr )) goto decode_success; 28800 goto decode_failure; 28801 28802 /* Integer Load and Store String Instructions */ 28803 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 28804 case 0x295: { // stswx 28805 Bool stopHere = False; 28806 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 28807 if (!ok) goto decode_failure; 28808 if (stopHere) { 28809 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) ); 28810 dres.jk_StopHere = Ijk_Boring; 28811 dres.whatNext = Dis_StopHere; 28812 } 28813 goto decode_success; 28814 } 28815 28816 /* Memory Synchronization Instructions */ 28817 case 0x034: case 0x074: // lbarx, lharx 28818 case 0x2B6: case 0x2D6: // stbcx, sthcx 28819 if (!allow_isa_2_07) goto decode_noP8; 28820 if (dis_memsync( theInstr )) goto decode_success; 28821 goto decode_failure; 28822 28823 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 28824 case 0x256: // sync 28825 if (dis_memsync( theInstr )) goto decode_success; 28826 goto decode_failure; 28827 28828 /* 64bit Memory Synchronization Instructions */ 28829 case 0x054: case 0x0D6: // ldarx, stdcx. 28830 if (!mode64) goto decode_failure; 28831 if (dis_memsync( theInstr )) goto decode_success; 28832 goto decode_failure; 28833 28834 case 0x114: case 0x0B6: // lqarx, stqcx. 28835 if (dis_memsync( theInstr )) goto decode_success; 28836 goto decode_failure; 28837 28838 /* Processor Control Instructions */ 28839 case 0x33: case 0x73: // mfvsrd, mfvsrwz 28840 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz 28841 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 28842 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 28843 case 0x220: // mcrxrt 28844 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 28845 goto decode_failure; 28846 28847 /* Cache Management Instructions */ 28848 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 28849 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 28850 case 0x3D6: // icbi 28851 if (dis_cache_manage( theInstr, &dres, archinfo )) 28852 goto decode_success; 28853 goto decode_failure; 28854 28855 //zz /* External Control Instructions */ 28856 //zz case 0x136: case 0x1B6: // eciwx, ecowx 28857 //zz DIP("external control op => not implemented\n"); 28858 //zz goto decode_failure; 28859 28860 /* Trap Instructions */ 28861 case 0x004: // tw 28862 if (dis_trap(theInstr, &dres)) goto decode_success; 28863 goto decode_failure; 28864 28865 case 0x044: // td 28866 if (!mode64) goto decode_failure; 28867 if (dis_trap(theInstr, &dres)) goto decode_success; 28868 goto decode_failure; 28869 28870 /* Floating Point Load Instructions */ 28871 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 28872 case 0x277: // lfdux 28873 if (!allow_F) goto decode_noF; 28874 if (dis_fp_load( theInstr )) goto decode_success; 28875 goto decode_failure; 28876 28877 /* Floating Point Store Instructions */ 28878 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 28879 case 0x2F7: // stfdu, stfiwx 28880 if (!allow_F) goto decode_noF; 28881 if (dis_fp_store( theInstr )) goto decode_success; 28882 goto decode_failure; 28883 case 0x3D7: // stfiwx 28884 if (!allow_F) goto decode_noF; 28885 if (!allow_GX) goto decode_noGX; 28886 if (dis_fp_store( theInstr )) goto decode_success; 28887 goto decode_failure; 28888 28889 /* Floating Point Double Pair Indexed Instructions */ 28890 case 0x317: // lfdpx (Power6) 28891 case 0x397: // stfdpx (Power6) 28892 if (!allow_F) goto decode_noF; 28893 if (dis_fp_pair(theInstr)) goto decode_success; 28894 goto decode_failure; 28895 28896 case 0x357: // lfiwax 28897 if (!allow_F) goto decode_noF; 28898 if (dis_fp_load( theInstr )) goto decode_success; 28899 goto decode_failure; 28900 28901 case 0x377: // lfiwzx 28902 if (!allow_F) goto decode_noF; 28903 if (dis_fp_load( theInstr )) goto decode_success; 28904 goto decode_failure; 28905 28906 /* AltiVec instructions */ 28907 28908 /* AV Cache Control - Data streams */ 28909 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 28910 if (!allow_V) goto decode_noV; 28911 if (dis_av_datastream( theInstr )) goto decode_success; 28912 goto decode_failure; 28913 28914 /* AV Load */ 28915 case 0x006: case 0x026: // lvsl, lvsr 28916 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 28917 case 0x067: case 0x167: // lvx, lvxl 28918 if (!allow_V) goto decode_noV; 28919 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 28920 goto decode_failure; 28921 28922 /* AV Store */ 28923 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 28924 case 0x0E7: case 0x1E7: // stvx, stvxl 28925 if (!allow_V) goto decode_noV; 28926 if (dis_av_store( theInstr )) goto decode_success; 28927 goto decode_failure; 28928 28929 /* VSX Load */ 28930 case 0x00C: // lxsiwzx 28931 case 0x04C: // lxsiwax 28932 case 0x10C: // lxvx 28933 case 0x10D: // lxvl 28934 case 0x12D: // lxvll 28935 case 0x16C: // lxvwsx 28936 case 0x20C: // lxsspx 28937 case 0x24C: // lxsdx 28938 case 0x32C: // lxvh8x 28939 case 0x30D: // lxsibzx 28940 case 0x32D: // lxsihzx 28941 case 0x34C: // lxvd2x 28942 case 0x36C: // lxvb16x 28943 case 0x14C: // lxvdsx 28944 case 0x30C: // lxvw4x 28945 // All of these VSX load instructions use some VMX facilities, so 28946 // if allow_V is not set, we'll skip trying to decode. 28947 if (!allow_V) goto decode_noV; 28948 28949 if (dis_vx_load( theInstr )) goto decode_success; 28950 goto decode_failure; 28951 28952 /* VSX Store */ 28953 case 0x08C: // stxsiwx 28954 case 0x18C: // stxvx 28955 case 0x18D: // stxvl 28956 case 0x1AD: // stxvll 28957 case 0x28C: // stxsspx 28958 case 0x2CC: // stxsdx 28959 case 0x38C: // stxvw4x 28960 case 0x3CC: // stxvd2x 28961 case 0x38D: // stxsibx 28962 case 0x3AD: // stxsihx 28963 case 0x3AC: // stxvh8x 28964 case 0x3EC: // stxvb16x 28965 // All of these VSX store instructions use some VMX facilities, so 28966 // if allow_V is not set, we'll skip trying to decode. 28967 if (!allow_V) goto decode_noV; 28968 28969 if (dis_vx_store( theInstr )) goto decode_success; 28970 goto decode_failure; 28971 28972 case 0x133: case 0x193: case 0x1B3: // mfvsrld, mfvsrdd, mtvsrws 28973 // The move from/to VSX instructions use some VMX facilities, so 28974 // if allow_V is not set, we'll skip trying to decode. 28975 if (!allow_V) goto decode_noV; 28976 if (dis_vx_move( theInstr )) goto decode_success; 28977 goto decode_failure; 28978 28979 /* Miscellaneous ISA 2.06 instructions */ 28980 case 0x1FA: // popcntd 28981 case 0x17A: // popcntw 28982 case 0x7A: // popcntb 28983 if (dis_int_logic( theInstr )) goto decode_success; 28984 goto decode_failure; 28985 28986 case 0x0FC: // bpermd 28987 if (!mode64) goto decode_failure; 28988 if (dis_int_logic( theInstr )) goto decode_success; 28989 goto decode_failure; 28990 28991 default: 28992 /* Deal with some other cases that we would otherwise have 28993 punted on. */ 28994 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 28995 /* only decode this insn when reserved bit 0 (31 in IBM's 28996 notation) is zero */ 28997 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 28998 UInt rT = ifieldRegDS( theInstr ); 28999 UInt rA = ifieldRegA( theInstr ); 29000 UInt rB = ifieldRegB( theInstr ); 29001 UInt bi = ifieldRegC( theInstr ); 29002 putIReg( 29003 rT, 29004 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)), 29005 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 29006 : getIReg(rA), 29007 getIReg(rB)) 29008 29009 ); 29010 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 29011 goto decode_success; 29012 } 29013 } 29014 29015 opc2 = IFIELD(theInstr, 2, 9); 29016 switch (opc2) { 29017 case 0x1BD: 29018 if (!mode64) goto decode_failure; 29019 if (dis_int_logic( theInstr )) goto decode_success; 29020 goto decode_failure; 29021 29022 default: 29023 goto decode_failure; 29024 } 29025 break; 29026 29027 29028 case 0x04: 29029 /* AltiVec instructions */ 29030 29031 opc2 = IFIELD(theInstr, 0, 6); 29032 switch (opc2) { 29033 /* AV Mult-Add, Mult-Sum */ 29034 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 29035 case 0x23: // vmsumudm 29036 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 29037 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 29038 if (!allow_V) goto decode_noV; 29039 if (dis_av_multarith( theInstr )) goto decode_success; 29040 goto decode_failure; 29041 29042 case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld 29043 if (!mode64) goto decode_failure; 29044 if (dis_int_mult_add( theInstr )) goto decode_success; 29045 goto decode_failure; 29046 29047 /* AV Permutations */ 29048 case 0x2A: // vsel 29049 case 0x2B: // vperm 29050 case 0x2C: // vsldoi 29051 if (!allow_V) goto decode_noV; 29052 if (dis_av_permute( theInstr )) goto decode_success; 29053 goto decode_failure; 29054 29055 case 0x2D: // vpermxor 29056 case 0x3B: // vpermr 29057 if (!allow_isa_2_07) goto decode_noP8; 29058 if (dis_av_permute( theInstr )) goto decode_success; 29059 goto decode_failure; 29060 29061 /* AV Floating Point Mult-Add/Sub */ 29062 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 29063 if (!allow_V) goto decode_noV; 29064 if (dis_av_fp_arith( theInstr )) goto decode_success; 29065 goto decode_failure; 29066 29067 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm 29068 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm 29069 if (!allow_V) goto decode_noV; 29070 if (dis_av_quad( theInstr)) goto decode_success; 29071 goto decode_failure; 29072 29073 default: 29074 break; // Fall through... 29075 } 29076 29077 opc2 = IFIELD(theInstr, 0, 9); 29078 if (IFIELD(theInstr, 10, 1) == 1) { 29079 /* The following instructions have bit 21 set and a PS bit (bit 22) 29080 * Bit 21 distinquishes them from instructions with an 11 bit opc2 29081 * field. 29082 */ 29083 switch (opc2) { 29084 /* BCD arithmetic */ 29085 case 0x001: case 0x041: // bcdadd, bcdsub 29086 case 0x101: case 0x141: // bcdtrunc., bcdutrunc. 29087 case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr. 29088 case 0x181: // bcdcfn., bcdcfz. 29089 // bcdctz., bcdcfsq., bcdctsq. 29090 if (!allow_isa_2_07) goto decode_noP8; 29091 if (dis_av_bcd( theInstr, abiinfo )) goto decode_success; 29092 goto decode_failure; 29093 default: 29094 break; // Fall through... 29095 } 29096 } 29097 29098 opc2 = IFIELD(theInstr, 0, 11); 29099 switch (opc2) { 29100 /* BCD manipulation */ 29101 case 0x341: // bcdcpsgn 29102 29103 if (!allow_isa_2_07) goto decode_noP8; 29104 if (dis_av_bcd_misc( theInstr, abiinfo )) goto decode_success; 29105 goto decode_failure; 29106 29107 29108 /* AV Arithmetic */ 29109 case 0x180: // vaddcuw 29110 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 29111 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 29112 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 29113 case 0x580: // vsubcuw 29114 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 29115 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 29116 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 29117 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 29118 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 29119 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 29120 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 29121 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 29122 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 29123 case 0x008: case 0x048: // vmuloub, vmulouh 29124 case 0x108: case 0x148: // vmulosb, vmulosh 29125 case 0x208: case 0x248: // vmuleub, vmuleuh 29126 case 0x308: case 0x348: // vmulesb, vmulesh 29127 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 29128 case 0x688: case 0x788: // vsum2sws, vsumsws 29129 if (!allow_V) goto decode_noV; 29130 if (dis_av_arith( theInstr )) goto decode_success; 29131 goto decode_failure; 29132 29133 case 0x088: case 0x089: // vmulouw, vmuluwm 29134 case 0x0C0: case 0x0C2: // vaddudm, vmaxud 29135 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd 29136 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw 29137 case 0x4C0: // vsubudm 29138 if (!allow_isa_2_07) goto decode_noP8; 29139 if (dis_av_arith( theInstr )) goto decode_success; 29140 goto decode_failure; 29141 29142 /* AV Polynomial Vector Multiply Add */ 29143 case 0x408: case 0x448: // vpmsumb, vpmsumd 29144 case 0x488: case 0x4C8: // vpmsumw, vpmsumh 29145 if (!allow_isa_2_07) goto decode_noP8; 29146 if (dis_av_polymultarith( theInstr )) goto decode_success; 29147 goto decode_failure; 29148 29149 /* AV Rotate, Shift */ 29150 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 29151 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 29152 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 29153 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 29154 case 0x1C4: case 0x2C4: // vsl, vsr 29155 case 0x40C: case 0x44C: // vslo, vsro 29156 if (!allow_V) goto decode_noV; 29157 if (dis_av_shift( theInstr )) goto decode_success; 29158 goto decode_failure; 29159 29160 case 0x0C4: // vrld 29161 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd 29162 if (!allow_isa_2_07) goto decode_noP8; 29163 if (dis_av_shift( theInstr )) goto decode_success; 29164 goto decode_failure; 29165 29166 /* AV Logic */ 29167 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 29168 case 0x4C4: case 0x504: // vxor, vnor 29169 if (!allow_V) goto decode_noV; 29170 if (dis_av_logic( theInstr )) goto decode_success; 29171 goto decode_failure; 29172 29173 case 0x544: // vorc 29174 case 0x584: case 0x684: // vnand, veqv 29175 if (!allow_isa_2_07) goto decode_noP8; 29176 if (dis_av_logic( theInstr )) goto decode_success; 29177 goto decode_failure; 29178 29179 /* AV Rotate */ 29180 case 0x085: case 0x185: // vrlwmi, vrlwnm 29181 case 0x0C5: case 0x1C5: // vrldmi, vrldnm 29182 if (!allow_V) goto decode_noV; 29183 if (dis_av_rotate( theInstr )) goto decode_success; 29184 goto decode_failure; 29185 29186 /* AV Processor Control */ 29187 case 0x604: case 0x644: // mfvscr, mtvscr 29188 if (!allow_V) goto decode_noV; 29189 if (dis_av_procctl( theInstr )) goto decode_success; 29190 goto decode_failure; 29191 29192 /* AV Vector Extract Element instructions */ 29193 case 0x60D: case 0x64D: case 0x68D: // vextublx, vextuhlx, vextuwlx 29194 case 0x70D: case 0x74D: case 0x78D: // vextubrx, vextuhrx, vextuwrx 29195 if (!allow_V) goto decode_noV; 29196 if (dis_av_extract_element( theInstr )) goto decode_success; 29197 goto decode_failure; 29198 29199 29200 /* AV Floating Point Arithmetic */ 29201 case 0x00A: case 0x04A: // vaddfp, vsubfp 29202 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 29203 case 0x1CA: // vlogefp 29204 case 0x40A: case 0x44A: // vmaxfp, vminfp 29205 if (!allow_V) goto decode_noV; 29206 if (dis_av_fp_arith( theInstr )) goto decode_success; 29207 goto decode_failure; 29208 29209 /* AV Floating Point Round/Convert */ 29210 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 29211 case 0x2CA: // vrfim 29212 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 29213 case 0x3CA: // vctsxs 29214 if (!allow_V) goto decode_noV; 29215 if (dis_av_fp_convert( theInstr )) goto decode_success; 29216 goto decode_failure; 29217 29218 /* AV Merge, Splat, Extract, Insert */ 29219 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 29220 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 29221 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 29222 case 0x20D: case 0x24D: // vextractub, vextractuh, 29223 case 0x28D: case 0x2CD: // vextractuw, vextractd, 29224 case 0x30D: case 0x34D: // vinsertb, vinserth 29225 case 0x38D: case 0x3CD: // vinsertw, vinsertd 29226 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 29227 if (!allow_V) goto decode_noV; 29228 if (dis_av_permute( theInstr )) goto decode_success; 29229 goto decode_failure; 29230 29231 case 0x68C: case 0x78C: // vmrgow, vmrgew 29232 if (!allow_isa_2_07) goto decode_noP8; 29233 if (dis_av_permute( theInstr )) goto decode_success; 29234 goto decode_failure; 29235 29236 /* AltiVec 128 bit integer multiply by 10 Instructions */ 29237 case 0x201: case 0x001: //vmul10uq, vmul10cuq 29238 case 0x241: case 0x041: //vmul10euq, vmul10ceuq 29239 if (!allow_V) goto decode_noV; 29240 if (!allow_isa_3_0) goto decode_noP9; 29241 if (dis_av_mult10( theInstr )) goto decode_success; 29242 goto decode_failure; 29243 29244 /* AV Pack, Unpack */ 29245 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 29246 case 0x0CE: // vpkuwus 29247 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 29248 case 0x1CE: // vpkswss 29249 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 29250 case 0x2CE: // vupklsh 29251 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 29252 if (!allow_V) goto decode_noV; 29253 if (dis_av_pack( theInstr )) goto decode_success; 29254 goto decode_failure; 29255 29256 case 0x403: case 0x443: case 0x483: // vabsdub, vabsduh, vabsduw 29257 if (!allow_V) goto decode_noV; 29258 if (dis_abs_diff( theInstr )) goto decode_success; 29259 goto decode_failure; 29260 29261 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus 29262 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw 29263 if (!allow_isa_2_07) goto decode_noP8; 29264 if (dis_av_pack( theInstr )) goto decode_success; 29265 goto decode_failure; 29266 29267 case 0x508: case 0x509: // vcipher, vcipherlast 29268 case 0x548: case 0x549: // vncipher, vncipherlast 29269 case 0x5C8: // vsbox 29270 if (!allow_isa_2_07) goto decode_noP8; 29271 if (dis_av_cipher( theInstr )) goto decode_success; 29272 goto decode_failure; 29273 29274 /* AV Vector Extend Sign Instructions and 29275 * Vector Count Leading/Trailing zero Least-Significant bits Byte. 29276 * Vector Integer Negate Instructions 29277 */ 29278 case 0x602: // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d 29279 // vclzlsbb and vctzlsbb 29280 // vnegw, vnegd 29281 // vprtybw, vprtybd, vprtybq 29282 // vctzb, vctzh, vctzw, vctzd 29283 if (!allow_V) goto decode_noV; 29284 if (dis_av_extend_sign_count_zero( theInstr, allow_isa_3_0 )) 29285 goto decode_success; 29286 goto decode_failure; 29287 29288 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad 29289 if (!allow_isa_2_07) goto decode_noP8; 29290 if (dis_av_hash( theInstr )) goto decode_success; 29291 goto decode_failure; 29292 29293 case 0x702: case 0x742: // vclzb, vclzh 29294 case 0x782: case 0x7c2: // vclzw, vclzd 29295 if (!allow_isa_2_07) goto decode_noP8; 29296 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 29297 goto decode_failure; 29298 29299 case 0x703: case 0x743: // vpopcntb, vpopcnth 29300 case 0x783: case 0x7c3: // vpopcntw, vpopcntd 29301 if (!allow_isa_2_07) goto decode_noP8; 29302 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 29303 goto decode_failure; 29304 29305 case 0x50c: // vgbbd 29306 case 0x5cc: // vbpermd 29307 if (!allow_isa_2_07) goto decode_noP8; 29308 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 29309 goto decode_failure; 29310 29311 case 0x140: case 0x100: // vaddcuq, vadduqm 29312 case 0x540: case 0x500: // vsubcuq, vsubuqm 29313 case 0x54C: // vbpermq 29314 if (!allow_V) goto decode_noV; 29315 if (dis_av_quad( theInstr)) goto decode_success; 29316 goto decode_failure; 29317 29318 default: 29319 break; // Fall through... 29320 } 29321 29322 opc2 = IFIELD(theInstr, 0, 10); 29323 switch (opc2) { 29324 29325 /* AV Compare */ 29326 case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb 29327 case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh 29328 case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw 29329 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 29330 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 29331 if (!allow_V) goto decode_noV; 29332 if (dis_av_cmp( theInstr )) goto decode_success; 29333 goto decode_failure; 29334 29335 case 0x0C7: // vcmpequd 29336 case 0x2C7: // vcmpgtud 29337 case 0x3C7: // vcmpgtsd 29338 if (!allow_isa_2_07) goto decode_noP8; 29339 if (dis_av_cmp( theInstr )) goto decode_success; 29340 goto decode_failure; 29341 29342 /* AV Floating Point Compare */ 29343 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 29344 case 0x3C6: // vcmpbfp 29345 if (!allow_V) goto decode_noV; 29346 if (dis_av_fp_cmp( theInstr )) goto decode_success; 29347 goto decode_failure; 29348 29349 default: 29350 goto decode_failure; 29351 } 29352 break; 29353 29354 default: 29355 goto decode_failure; 29356 29357 decode_noF: 29358 vassert(!allow_F); 29359 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n" 29360 "can't be handled by Valgrind on this host. This instruction\n" 29361 "requires a host that supports Floating Point instructions.\n", 29362 theInstr); 29363 goto not_supported; 29364 decode_noV: 29365 vassert(!allow_V); 29366 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n" 29367 "that can't be handled by Valgrind. If this instruction is an\n" 29368 "Altivec instruction, Valgrind must be run on a host that supports" 29369 "AltiVec instructions. If the application was compiled for e500, then\n" 29370 "unfortunately Valgrind does not yet support e500 instructions.\n", 29371 theInstr); 29372 goto not_supported; 29373 decode_noVX: 29374 vassert(!allow_VX); 29375 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n" 29376 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n" 29377 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n", 29378 theInstr); 29379 goto not_supported; 29380 decode_noFX: 29381 vassert(!allow_FX); 29382 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n" 29383 "that can't be handled by Valgrind on this host. This instruction\n" 29384 "requires a host that supports the General Purpose-Optional instructions.\n", 29385 theInstr); 29386 goto not_supported; 29387 decode_noGX: 29388 vassert(!allow_GX); 29389 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n" 29390 "that can't be handled by Valgrind on this host. This instruction\n" 29391 "requires a host that supports the Graphic-Optional instructions.\n", 29392 theInstr); 29393 goto not_supported; 29394 decode_noDFP: 29395 vassert(!allow_DFP); 29396 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n" 29397 "that can't be handled by Valgrind on this host. This instruction\n" 29398 "requires a host that supports DFP instructions.\n", 29399 theInstr); 29400 goto not_supported; 29401 decode_noP8: 29402 vassert(!allow_isa_2_07); 29403 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n" 29404 "by Valgrind on this host. This instruction requires a host that\n" 29405 "supports Power 8 instructions.\n", 29406 theInstr); 29407 goto not_supported; 29408 29409 decode_noP9: 29410 vassert(!allow_isa_3_0); 29411 vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n" 29412 "by Valgrind on this host. This instruction requires a host that\n" 29413 "supports Power 9 instructions.\n", 29414 theInstr); 29415 goto not_supported; 29416 29417 decode_failure: 29418 /* All decode failures end up here. */ 29419 opc2 = (theInstr) & 0x7FF; 29420 if (sigill_diag) { 29421 vex_printf("disInstr(ppc): unhandled instruction: " 29422 "0x%x\n", theInstr); 29423 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 29424 opc1, opc1, opc2, opc2); 29425 } 29426 29427 not_supported: 29428 /* Tell the dispatcher that this insn cannot be decoded, and so has 29429 not been executed, and (is currently) the next to be executed. 29430 CIA should be up-to-date since it made so at the start of each 29431 insn, but nevertheless be paranoid and update it again right 29432 now. */ 29433 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 29434 dres.len = 0; 29435 dres.whatNext = Dis_StopHere; 29436 dres.jk_StopHere = Ijk_NoDecode; 29437 dres.continueAt = 0; 29438 return dres; 29439 } /* switch (opc) for the main (primary) opcode switch. */ 29440 29441 decode_success: 29442 /* All decode successes end up here. */ 29443 switch (dres.whatNext) { 29444 case Dis_Continue: 29445 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4)); 29446 break; 29447 case Dis_ResteerU: 29448 case Dis_ResteerC: 29449 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt)); 29450 break; 29451 case Dis_StopHere: 29452 break; 29453 default: 29454 vassert(0); 29455 } 29456 DIP("\n"); 29457 29458 if (dres.len == 0) { 29459 dres.len = 4; 29460 } else { 29461 vassert(dres.len == 20); 29462 } 29463 return dres; 29464 } 29465 29466 #undef DIP 29467 #undef DIS 29468 29469 29470 /*------------------------------------------------------------*/ 29471 /*--- Top-level fn ---*/ 29472 /*------------------------------------------------------------*/ 29473 29474 /* Disassemble a single instruction into IR. The instruction 29475 is located in host memory at &guest_code[delta]. */ 29476 29477 DisResult disInstr_PPC ( IRSB* irsb_IN, 29478 Bool (*resteerOkFn) ( void*, Addr ), 29479 Bool resteerCisOk, 29480 void* callback_opaque, 29481 const UChar* guest_code_IN, 29482 Long delta, 29483 Addr guest_IP, 29484 VexArch guest_arch, 29485 const VexArchInfo* archinfo, 29486 const VexAbiInfo* abiinfo, 29487 VexEndness host_endness_IN, 29488 Bool sigill_diag_IN ) 29489 { 29490 IRType ty; 29491 DisResult dres; 29492 UInt mask32, mask64; 29493 UInt hwcaps_guest = archinfo->hwcaps; 29494 29495 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 29496 29497 /* global -- ick */ 29498 mode64 = guest_arch == VexArchPPC64; 29499 ty = mode64 ? Ity_I64 : Ity_I32; 29500 if (!mode64 && (host_endness_IN == VexEndnessLE)) { 29501 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n"); 29502 dres.len = 0; 29503 dres.whatNext = Dis_StopHere; 29504 dres.jk_StopHere = Ijk_NoDecode; 29505 dres.continueAt = 0; 29506 dres.hint = Dis_HintNone; 29507 return dres; 29508 } 29509 29510 /* do some sanity checks */ 29511 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 29512 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX 29513 | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07; 29514 29515 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 29516 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP 29517 | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0; 29518 29519 if (mode64) { 29520 vassert((hwcaps_guest & mask32) == 0); 29521 } else { 29522 vassert((hwcaps_guest & mask64) == 0); 29523 } 29524 29525 /* Set globals (see top of this file) */ 29526 guest_code = guest_code_IN; 29527 irsb = irsb_IN; 29528 host_endness = host_endness_IN; 29529 29530 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 29531 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 29532 29533 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque, 29534 delta, archinfo, abiinfo, sigill_diag_IN); 29535 29536 return dres; 29537 } 29538 29539 29540 /*------------------------------------------------------------*/ 29541 /*--- Unused stuff ---*/ 29542 /*------------------------------------------------------------*/ 29543 29544 ///* A potentially more memcheck-friendly implementation of Clz32, with 29545 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 29546 // 29547 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 29548 //{ 29549 // /* Welcome ... to SSA R Us. */ 29550 // IRTemp n1 = newTemp(Ity_I32); 29551 // IRTemp n2 = newTemp(Ity_I32); 29552 // IRTemp n3 = newTemp(Ity_I32); 29553 // IRTemp n4 = newTemp(Ity_I32); 29554 // IRTemp n5 = newTemp(Ity_I32); 29555 // IRTemp n6 = newTemp(Ity_I32); 29556 // IRTemp n7 = newTemp(Ity_I32); 29557 // IRTemp n8 = newTemp(Ity_I32); 29558 // IRTemp n9 = newTemp(Ity_I32); 29559 // IRTemp n10 = newTemp(Ity_I32); 29560 // IRTemp n11 = newTemp(Ity_I32); 29561 // IRTemp n12 = newTemp(Ity_I32); 29562 // 29563 // /* First, propagate the most significant 1-bit into all lower 29564 // positions in the word. */ 29565 // /* unsigned int clz ( unsigned int n ) 29566 // { 29567 // n |= (n >> 1); 29568 // n |= (n >> 2); 29569 // n |= (n >> 4); 29570 // n |= (n >> 8); 29571 // n |= (n >> 16); 29572 // return bitcount(~n); 29573 // } 29574 // */ 29575 // assign(n1, mkexpr(arg)); 29576 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 29577 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 29578 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 29579 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 29580 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 29581 // /* This gives a word of the form 0---01---1. Now invert it, giving 29582 // a word of the form 1---10---0, then do a population-count idiom 29583 // (to count the 1s, which is the number of leading zeroes, or 32 29584 // if the original word was 0. */ 29585 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 29586 // 29587 // /* unsigned int bitcount ( unsigned int n ) 29588 // { 29589 // n = n - ((n >> 1) & 0x55555555); 29590 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 29591 // n = (n + (n >> 4)) & 0x0F0F0F0F; 29592 // n = n + (n >> 8); 29593 // n = (n + (n >> 16)) & 0x3F; 29594 // return n; 29595 // } 29596 // */ 29597 // assign(n8, 29598 // binop(Iop_Sub32, 29599 // mkexpr(n7), 29600 // binop(Iop_And32, 29601 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 29602 // mkU32(0x55555555)))); 29603 // assign(n9, 29604 // binop(Iop_Add32, 29605 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 29606 // binop(Iop_And32, 29607 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 29608 // mkU32(0x33333333)))); 29609 // assign(n10, 29610 // binop(Iop_And32, 29611 // binop(Iop_Add32, 29612 // mkexpr(n9), 29613 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 29614 // mkU32(0x0F0F0F0F))); 29615 // assign(n11, 29616 // binop(Iop_Add32, 29617 // mkexpr(n10), 29618 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 29619 // assign(n12, 29620 // binop(Iop_Add32, 29621 // mkexpr(n11), 29622 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 29623 // return 29624 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 29625 //} 29626 29627 /*--------------------------------------------------------------------*/ 29628 /*--- end guest_ppc_toIR.c ---*/ 29629 /*--------------------------------------------------------------------*/ 29630