1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_ppc_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2013 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 /* TODO 18/Nov/05: 37 38 Spot rld... cases which are simply left/right shifts and emit 39 Shl64/Shr64 accordingly. 40 41 Altivec 42 - datastream insns 43 - lvxl,stvxl: load/store with 'least recently used' hint 44 - vexptefp, vlogefp 45 46 LIMITATIONS: 47 48 Various, including: 49 50 - Some invalid forms of lswi and lswx are accepted when they should 51 not be. 52 53 - Floating Point: 54 - All exceptions disabled in FPSCR 55 - condition codes not set in FPSCR 56 57 - Altivec floating point: 58 - vmaddfp, vnmsubfp 59 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the 60 system default of Non-Java mode, we get some small errors 61 (lowest bit only). 62 This is because Non-Java mode brutally hacks denormalised results 63 to zero, whereas we keep maximum accuracy. However, using 64 Non-Java mode would give us more inaccuracy, as our intermediate 65 results would then be zeroed, too. 66 67 - AbiHints for the stack red zone are only emitted for 68 unconditional calls and returns (bl, blr). They should also be 69 emitted for conditional calls and returns, but we don't have a 70 way to express that right now. Ah well. 71 72 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c) 73 ignores the rounding mode, and generates code that assumes 74 round-to-nearest. This means V will compute incorrect results 75 for uses of these IROps when the rounding mode (first) arg is 76 not mkU32(Irrm_NEAREST). 77 */ 78 79 /* "Special" instructions. 80 81 This instruction decoder can decode four special instructions 82 which mean nothing natively (are no-ops as far as regs/mem are 83 concerned) but have meaning for supporting Valgrind. A special 84 instruction is flagged by a 16-byte preamble: 85 86 32-bit mode: 5400183E 5400683E 5400E83E 5400983E 87 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31; 88 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31) 89 90 64-bit mode: 78001800 78006800 7800E802 78009802 91 (rotldi 0,0,3; rotldi 0,0,13; 92 rotldi 0,0,61; rotldi 0,0,51) 93 94 Following that, one of the following 3 are allowed 95 (standard interpretation in parentheses): 96 97 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 98 7C421378 (or 2,2,2) %R3 = guest_NRADDR 99 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian 100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian 101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 102 7CA52B78 (or 5,5,5) IR injection 103 104 Any other bytes following the 16-byte preamble are illegal and 105 constitute a failure in instruction decoding. This all assumes 106 that the preamble will never occur except in specific code 107 fragments designed for Valgrind to catch. 108 */ 109 110 /* Little Endian notes */ 111 /* 112 * Vector operations in little Endian mode behave in non-obvious ways at times. 113 * Below is an attempt at explaining this. 114 * 115 * LE/BE vector example 116 * With a vector of unsigned ints declared as follows: 117 * vector unsigned int vec_inA = 118 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; 119 * The '0x11111111' word is word zero in both LE and BE format. But the 120 * loaded vector register will have word zero on the far left in BE mode and 121 * on the far right in LE mode. The lvx and stvx instructions work naturally 122 * for whatever endianness is in effect. For example, in LE mode, the stvx 123 * stores word zero (far right word) of the vector at the lowest memory 124 * address of the EA; in BE mode, stvx still stores word zero at the lowest 125 * memory address, but with word zero interpreted as the one at the far left 126 * of the register. 127 * 128 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode. 129 * When the compiler generates an lxvd2x instruction to load the 130 * above-declared vector of unsigned integers, it loads the vector as two 131 * double words, but they are in BE word-wise format. To put the vector in 132 * the right order for LE, the compiler also generates an xxswapd after the 133 * load, which puts it in proper LE format. Similarly, the stxvd2x 134 * instruction has a BE bias, storing the vector in BE word-wise format. But 135 * the compiler also generates an xxswapd prior to the store, thus ensuring 136 * the vector is stored in memory in the correct LE order. 137 * 138 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts 139 * of a double words and words within a vector. Because of the reverse order 140 * of numbering for LE as described above, the high part refers to word 1 in 141 * LE format. When input data is saved to a guest state vector register 142 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the 143 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction. 144 * The saving of the data to memory must be done in proper LE order. For the 145 * inverse operation of extracting data from a vector register (e.g., 146 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting 147 * in stvx), and then integer registers are loaded from the memory location 148 * from where the vector register was saved. Again, this must be done in 149 * proper LE order. So for these various vector Iops, we have LE-specific 150 * code in host_ppc_isel.c 151 * 152 * Another unique behavior of vectors in LE mode is with the vector scalar 153 * (VSX) operations that operate on "double word 0" of the source register, 154 * storing the result in "double word 0" of the output vector register. For 155 * these operations, "double word 0" is interpreted as "high half of the 156 * register" (i.e, the part on the left side). 157 * 158 */ 159 /* Translates PPC32/64 code to IR. */ 160 161 /* References 162 163 #define PPC32 164 "PowerPC Microprocessor Family: 165 The Programming Environments Manual for 32-Bit Microprocessors" 166 02/21/2000 167 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 168 169 #define PPC64 170 "PowerPC Microprocessor Family: 171 Programming Environments Manual for 64-Bit Microprocessors" 172 06/10/2003 173 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 174 175 #define AV 176 "PowerPC Microprocessor Family: 177 AltiVec(TM) Technology Programming Environments Manual" 178 07/10/2003 179 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 180 */ 181 182 #include "libvex_basictypes.h" 183 #include "libvex_ir.h" 184 #include "libvex.h" 185 #include "libvex_emnote.h" 186 #include "libvex_guest_ppc32.h" 187 #include "libvex_guest_ppc64.h" 188 189 #include "main_util.h" 190 #include "main_globals.h" 191 #include "guest_generic_bb_to_IR.h" 192 #include "guest_ppc_defs.h" 193 194 /*------------------------------------------------------------*/ 195 /*--- Globals ---*/ 196 /*------------------------------------------------------------*/ 197 198 /* These are set at the start of the translation of an insn, right 199 down in disInstr_PPC, so that we don't have to pass them around 200 endlessly. They are all constant during the translation of any 201 given insn. */ 202 203 /* We need to know this to do sub-register accesses correctly. */ 204 static VexEndness host_endness; 205 206 /* Pointer to the guest code area. */ 207 static const UChar* guest_code; 208 209 /* The guest address corresponding to guest_code[0]. */ 210 static Addr64 guest_CIA_bbstart; 211 212 /* The guest address for the instruction currently being 213 translated. */ 214 static Addr64 guest_CIA_curr_instr; 215 216 /* The IRSB* into which we're generating code. */ 217 static IRSB* irsb; 218 219 /* Is our guest binary 32 or 64bit? Set at each call to 220 disInstr_PPC below. */ 221 static Bool mode64 = False; 222 223 // Given a pointer to a function as obtained by "& functionname" in C, 224 // produce a pointer to the actual entry point for the function. For 225 // most platforms it's the identity function. Unfortunately, on 226 // ppc64-linux it isn't (sigh) 227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f ) 228 { 229 if (vbi->host_ppc_calls_use_fndescrs) { 230 /* f is a pointer to a 3-word function descriptor, of which the 231 first word is the entry address. */ 232 /* note, this is correct even with cross-jitting, since this is 233 purely a host issue, not a guest one. */ 234 HWord* fdescr = (HWord*)f; 235 return (void*)(fdescr[0]); 236 } else { 237 /* Simple; "& f" points directly at the code for f. */ 238 return f; 239 } 240 } 241 242 #define SIGN_BIT 0x8000000000000000ULL 243 #define SIGN_MASK 0x7fffffffffffffffULL 244 #define SIGN_BIT32 0x80000000 245 #define SIGN_MASK32 0x7fffffff 246 247 248 /*------------------------------------------------------------*/ 249 /*--- Debugging output ---*/ 250 /*------------------------------------------------------------*/ 251 252 #define DIP(format, args...) \ 253 if (vex_traceflags & VEX_TRACE_FE) \ 254 vex_printf(format, ## args) 255 256 #define DIS(buf, format, args...) \ 257 if (vex_traceflags & VEX_TRACE_FE) \ 258 vex_sprintf(buf, format, ## args) 259 260 261 /*------------------------------------------------------------*/ 262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 263 /*------------------------------------------------------------*/ 264 265 #define offsetofPPCGuestState(_x) \ 266 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 267 offsetof(VexGuestPPC32State, _x)) 268 269 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 271 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 272 #define OFFB_LR offsetofPPCGuestState(guest_LR) 273 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 274 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 275 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 276 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 277 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 278 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 279 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 280 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 281 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 282 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 283 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 284 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 285 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 287 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 288 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 289 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU) 290 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 291 292 293 /*------------------------------------------------------------*/ 294 /*--- Extract instruction fields --- */ 295 /*------------------------------------------------------------*/ 296 297 /* Extract field from insn, given idx (zero = lsb) and field length */ 298 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 299 300 /* Extract primary opcode, instr[31:26] */ 301 static UChar ifieldOPC( UInt instr ) { 302 return toUChar( IFIELD( instr, 26, 6 ) ); 303 } 304 305 /* Extract 10-bit secondary opcode, instr[10:1] */ 306 static UInt ifieldOPClo10 ( UInt instr) { 307 return IFIELD( instr, 1, 10 ); 308 } 309 310 /* Extract 9-bit secondary opcode, instr[9:1] */ 311 static UInt ifieldOPClo9 ( UInt instr) { 312 return IFIELD( instr, 1, 9 ); 313 } 314 315 /* Extract 8-bit secondary opcode, instr[8:1] */ 316 static UInt ifieldOPClo8 ( UInt instr) { 317 return IFIELD( instr, 1, 8 ); 318 } 319 320 /* Extract 5-bit secondary opcode, instr[5:1] */ 321 static UInt ifieldOPClo5 ( UInt instr) { 322 return IFIELD( instr, 1, 5 ); 323 } 324 325 /* Extract RD (destination register) field, instr[25:21] */ 326 static UChar ifieldRegDS( UInt instr ) { 327 return toUChar( IFIELD( instr, 21, 5 ) ); 328 } 329 330 /* Extract XT (destination register) field, instr[0,25:21] */ 331 static UChar ifieldRegXT ( UInt instr ) 332 { 333 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 334 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 335 return (upper_bit << 5) | lower_bits; 336 } 337 338 /* Extract XS (store source register) field, instr[0,25:21] */ 339 static inline UChar ifieldRegXS ( UInt instr ) 340 { 341 return ifieldRegXT ( instr ); 342 } 343 344 /* Extract RA (1st source register) field, instr[20:16] */ 345 static UChar ifieldRegA ( UInt instr ) { 346 return toUChar( IFIELD( instr, 16, 5 ) ); 347 } 348 349 /* Extract XA (1st source register) field, instr[2,20:16] */ 350 static UChar ifieldRegXA ( UInt instr ) 351 { 352 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 353 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 354 return (upper_bit << 5) | lower_bits; 355 } 356 357 /* Extract RB (2nd source register) field, instr[15:11] */ 358 static UChar ifieldRegB ( UInt instr ) { 359 return toUChar( IFIELD( instr, 11, 5 ) ); 360 } 361 362 /* Extract XB (2nd source register) field, instr[1,15:11] */ 363 static UChar ifieldRegXB ( UInt instr ) 364 { 365 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 366 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 367 return (upper_bit << 5) | lower_bits; 368 } 369 370 /* Extract RC (3rd source register) field, instr[10:6] */ 371 static UChar ifieldRegC ( UInt instr ) { 372 return toUChar( IFIELD( instr, 6, 5 ) ); 373 } 374 375 /* Extract XC (3rd source register) field, instr[3,10:6] */ 376 static UChar ifieldRegXC ( UInt instr ) 377 { 378 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 379 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 380 return (upper_bit << 5) | lower_bits; 381 } 382 383 /* Extract bit 10, instr[10] */ 384 static UChar ifieldBIT10 ( UInt instr ) { 385 return toUChar( IFIELD( instr, 10, 1 ) ); 386 } 387 388 /* Extract 2nd lowest bit, instr[1] */ 389 static UChar ifieldBIT1 ( UInt instr ) { 390 return toUChar( IFIELD( instr, 1, 1 ) ); 391 } 392 393 /* Extract lowest bit, instr[0] */ 394 static UChar ifieldBIT0 ( UInt instr ) { 395 return toUChar( instr & 0x1 ); 396 } 397 398 /* Extract unsigned bottom half, instr[15:0] */ 399 static UInt ifieldUIMM16 ( UInt instr ) { 400 return instr & 0xFFFF; 401 } 402 403 /* Extract unsigned bottom 26 bits, instr[25:0] */ 404 static UInt ifieldUIMM26 ( UInt instr ) { 405 return instr & 0x3FFFFFF; 406 } 407 408 /* Extract DM field, instr[9:8] */ 409 static UChar ifieldDM ( UInt instr ) { 410 return toUChar( IFIELD( instr, 8, 2 ) ); 411 } 412 413 /* Extract SHW field, instr[9:8] */ 414 static inline UChar ifieldSHW ( UInt instr ) 415 { 416 return ifieldDM ( instr ); 417 } 418 419 /*------------------------------------------------------------*/ 420 /*--- Guest-state identifiers ---*/ 421 /*------------------------------------------------------------*/ 422 423 typedef enum { 424 PPC_GST_CIA, // Current Instruction Address 425 PPC_GST_LR, // Link Register 426 PPC_GST_CTR, // Count Register 427 PPC_GST_XER, // Overflow, carry flags, byte count 428 PPC_GST_CR, // Condition Register 429 PPC_GST_FPSCR, // Floating Point Status/Control Register 430 PPC_GST_VRSAVE, // Vector Save/Restore Register 431 PPC_GST_VSCR, // Vector Status and Control Register 432 PPC_GST_EMWARN, // Emulation warnings 433 PPC_GST_CMSTART,// For icbi: start of area to invalidate 434 PPC_GST_CMLEN, // For icbi: length of area to invalidate 435 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 436 PPC_GST_SPRG3_RO, // SPRG3 437 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 438 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 439 PPC_GST_TEXASR, // Transactional EXception And Summary Register 440 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 441 PPC_GST_MAX 442 } PPC_GST; 443 444 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 445 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 446 #define MASK_VSCR_VALID 0x00010001 447 448 449 /*------------------------------------------------------------*/ 450 /*--- FP Helpers ---*/ 451 /*------------------------------------------------------------*/ 452 453 /* Produce the 32-bit pattern corresponding to the supplied 454 float. */ 455 static UInt float_to_bits ( Float f ) 456 { 457 union { UInt i; Float f; } u; 458 vassert(4 == sizeof(UInt)); 459 vassert(4 == sizeof(Float)); 460 vassert(4 == sizeof(u)); 461 u.f = f; 462 return u.i; 463 } 464 465 466 /*------------------------------------------------------------*/ 467 /*--- Misc Helpers ---*/ 468 /*------------------------------------------------------------*/ 469 470 /* Generate mask with 1's from 'begin' through 'end', 471 wrapping if begin > end. 472 begin->end works from right to left, 0=lsb 473 */ 474 static UInt MASK32( UInt begin, UInt end ) 475 { 476 UInt m1, m2, mask; 477 vassert(begin < 32); 478 vassert(end < 32); 479 m1 = ((UInt)(-1)) << begin; 480 m2 = ((UInt)(-1)) << end << 1; 481 mask = m1 ^ m2; 482 if (begin > end) mask = ~mask; // wrap mask 483 return mask; 484 } 485 486 static ULong MASK64( UInt begin, UInt end ) 487 { 488 ULong m1, m2, mask; 489 vassert(begin < 64); 490 vassert(end < 64); 491 m1 = ((ULong)(-1)) << begin; 492 m2 = ((ULong)(-1)) << end << 1; 493 mask = m1 ^ m2; 494 if (begin > end) mask = ~mask; // wrap mask 495 return mask; 496 } 497 498 static Addr64 nextInsnAddr( void ) 499 { 500 return guest_CIA_curr_instr + 4; 501 } 502 503 504 /*------------------------------------------------------------*/ 505 /*--- Helper bits and pieces for deconstructing the ---*/ 506 /*--- ppc32/64 insn stream. ---*/ 507 /*------------------------------------------------------------*/ 508 509 /* Add a statement to the list held by "irsb". */ 510 static void stmt ( IRStmt* st ) 511 { 512 addStmtToIRSB( irsb, st ); 513 } 514 515 /* Generate a new temporary of the given type. */ 516 static IRTemp newTemp ( IRType ty ) 517 { 518 vassert(isPlausibleIRType(ty)); 519 return newIRTemp( irsb->tyenv, ty ); 520 } 521 522 /* Various simple conversions */ 523 524 static UChar extend_s_5to8 ( UChar x ) 525 { 526 return toUChar((((Int)x) << 27) >> 27); 527 } 528 529 static UInt extend_s_8to32( UChar x ) 530 { 531 return (UInt)((((Int)x) << 24) >> 24); 532 } 533 534 static UInt extend_s_16to32 ( UInt x ) 535 { 536 return (UInt)((((Int)x) << 16) >> 16); 537 } 538 539 static ULong extend_s_16to64 ( UInt x ) 540 { 541 return (ULong)((((Long)x) << 48) >> 48); 542 } 543 544 static ULong extend_s_26to64 ( UInt x ) 545 { 546 return (ULong)((((Long)x) << 38) >> 38); 547 } 548 549 static ULong extend_s_32to64 ( UInt x ) 550 { 551 return (ULong)((((Long)x) << 32) >> 32); 552 } 553 554 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 555 of the underlying host. */ 556 static UInt getUIntPPCendianly ( const UChar* p ) 557 { 558 UInt w = 0; 559 if (host_endness == VexEndnessBE) { 560 w = (w << 8) | p[0]; 561 w = (w << 8) | p[1]; 562 w = (w << 8) | p[2]; 563 w = (w << 8) | p[3]; 564 } else { 565 w = (w << 8) | p[3]; 566 w = (w << 8) | p[2]; 567 w = (w << 8) | p[1]; 568 w = (w << 8) | p[0]; 569 } 570 return w; 571 } 572 573 574 /*------------------------------------------------------------*/ 575 /*--- Helpers for constructing IR. ---*/ 576 /*------------------------------------------------------------*/ 577 578 static void assign ( IRTemp dst, IRExpr* e ) 579 { 580 stmt( IRStmt_WrTmp(dst, e) ); 581 } 582 583 /* This generates a normal (non store-conditional) store. */ 584 static void store ( IRExpr* addr, IRExpr* data ) 585 { 586 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 587 vassert(tyA == Ity_I32 || tyA == Ity_I64); 588 589 if (host_endness == VexEndnessBE) 590 stmt( IRStmt_Store(Iend_BE, addr, data) ); 591 else 592 stmt( IRStmt_Store(Iend_LE, addr, data) ); 593 } 594 595 static IRExpr* unop ( IROp op, IRExpr* a ) 596 { 597 return IRExpr_Unop(op, a); 598 } 599 600 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 601 { 602 return IRExpr_Binop(op, a1, a2); 603 } 604 605 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 606 { 607 return IRExpr_Triop(op, a1, a2, a3); 608 } 609 610 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 611 IRExpr* a3, IRExpr* a4 ) 612 { 613 return IRExpr_Qop(op, a1, a2, a3, a4); 614 } 615 616 static IRExpr* mkexpr ( IRTemp tmp ) 617 { 618 return IRExpr_RdTmp(tmp); 619 } 620 621 static IRExpr* mkU8 ( UChar i ) 622 { 623 return IRExpr_Const(IRConst_U8(i)); 624 } 625 626 static IRExpr* mkU16 ( UInt i ) 627 { 628 return IRExpr_Const(IRConst_U16(i)); 629 } 630 631 static IRExpr* mkU32 ( UInt i ) 632 { 633 return IRExpr_Const(IRConst_U32(i)); 634 } 635 636 static IRExpr* mkU64 ( ULong i ) 637 { 638 return IRExpr_Const(IRConst_U64(i)); 639 } 640 641 static IRExpr* mkV128 ( UShort i ) 642 { 643 vassert(i == 0 || i == 0xffff); 644 return IRExpr_Const(IRConst_V128(i)); 645 } 646 647 /* This generates a normal (non load-linked) load. */ 648 static IRExpr* load ( IRType ty, IRExpr* addr ) 649 { 650 if (host_endness == VexEndnessBE) 651 return IRExpr_Load(Iend_BE, ty, addr); 652 else 653 return IRExpr_Load(Iend_LE, ty, addr); 654 } 655 656 static IRStmt* stmt_load ( IRTemp result, 657 IRExpr* addr, IRExpr* storedata ) 658 { 659 if (host_endness == VexEndnessBE) 660 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 661 else 662 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 663 } 664 665 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 666 { 667 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 668 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 669 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 670 unop(Iop_1Uto32, arg2))); 671 } 672 673 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 674 { 675 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 676 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 677 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 678 unop(Iop_1Uto32, arg2))); 679 } 680 681 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 682 static void expand8Ux16( IRExpr* vIn, 683 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 684 { 685 IRTemp ones8x16 = newTemp(Ity_V128); 686 687 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 688 vassert(vEvn && *vEvn == IRTemp_INVALID); 689 vassert(vOdd && *vOdd == IRTemp_INVALID); 690 *vEvn = newTemp(Ity_V128); 691 *vOdd = newTemp(Ity_V128); 692 693 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 694 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 695 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 696 binop(Iop_ShrV128, vIn, mkU8(8))) ); 697 } 698 699 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 700 static void expand8Sx16( IRExpr* vIn, 701 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 702 { 703 IRTemp ones8x16 = newTemp(Ity_V128); 704 705 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 706 vassert(vEvn && *vEvn == IRTemp_INVALID); 707 vassert(vOdd && *vOdd == IRTemp_INVALID); 708 *vEvn = newTemp(Ity_V128); 709 *vOdd = newTemp(Ity_V128); 710 711 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 712 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 713 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 714 binop(Iop_ShrV128, vIn, mkU8(8))) ); 715 } 716 717 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 718 static void expand16Ux8( IRExpr* vIn, 719 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 720 { 721 IRTemp ones16x8 = newTemp(Ity_V128); 722 723 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 724 vassert(vEvn && *vEvn == IRTemp_INVALID); 725 vassert(vOdd && *vOdd == IRTemp_INVALID); 726 *vEvn = newTemp(Ity_V128); 727 *vOdd = newTemp(Ity_V128); 728 729 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 730 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 731 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 732 binop(Iop_ShrV128, vIn, mkU8(16))) ); 733 } 734 735 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 736 static void expand16Sx8( IRExpr* vIn, 737 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 738 { 739 IRTemp ones16x8 = newTemp(Ity_V128); 740 741 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 742 vassert(vEvn && *vEvn == IRTemp_INVALID); 743 vassert(vOdd && *vOdd == IRTemp_INVALID); 744 *vEvn = newTemp(Ity_V128); 745 *vOdd = newTemp(Ity_V128); 746 747 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 748 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 749 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 750 binop(Iop_ShrV128, vIn, mkU8(16))) ); 751 } 752 753 /* break V128 to 4xF64's*/ 754 static void breakV128to4xF64( IRExpr* t128, 755 /*OUTs*/ 756 IRTemp* t3, IRTemp* t2, 757 IRTemp* t1, IRTemp* t0 ) 758 { 759 IRTemp hi64 = newTemp(Ity_I64); 760 IRTemp lo64 = newTemp(Ity_I64); 761 762 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 763 vassert(t0 && *t0 == IRTemp_INVALID); 764 vassert(t1 && *t1 == IRTemp_INVALID); 765 vassert(t2 && *t2 == IRTemp_INVALID); 766 vassert(t3 && *t3 == IRTemp_INVALID); 767 *t0 = newTemp(Ity_F64); 768 *t1 = newTemp(Ity_F64); 769 *t2 = newTemp(Ity_F64); 770 *t3 = newTemp(Ity_F64); 771 772 assign( hi64, unop(Iop_V128HIto64, t128) ); 773 assign( lo64, unop(Iop_V128to64, t128) ); 774 assign( *t3, 775 unop( Iop_F32toF64, 776 unop( Iop_ReinterpI32asF32, 777 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 778 assign( *t2, 779 unop( Iop_F32toF64, 780 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 781 assign( *t1, 782 unop( Iop_F32toF64, 783 unop( Iop_ReinterpI32asF32, 784 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 785 assign( *t0, 786 unop( Iop_F32toF64, 787 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 788 } 789 790 791 /* break V128 to 4xI32's, then sign-extend to I64's */ 792 static void breakV128to4x64S( IRExpr* t128, 793 /*OUTs*/ 794 IRTemp* t3, IRTemp* t2, 795 IRTemp* t1, IRTemp* t0 ) 796 { 797 IRTemp hi64 = newTemp(Ity_I64); 798 IRTemp lo64 = newTemp(Ity_I64); 799 800 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 801 vassert(t0 && *t0 == IRTemp_INVALID); 802 vassert(t1 && *t1 == IRTemp_INVALID); 803 vassert(t2 && *t2 == IRTemp_INVALID); 804 vassert(t3 && *t3 == IRTemp_INVALID); 805 *t0 = newTemp(Ity_I64); 806 *t1 = newTemp(Ity_I64); 807 *t2 = newTemp(Ity_I64); 808 *t3 = newTemp(Ity_I64); 809 810 assign( hi64, unop(Iop_V128HIto64, t128) ); 811 assign( lo64, unop(Iop_V128to64, t128) ); 812 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 813 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 814 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 815 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 816 } 817 818 /* break V128 to 4xI32's, then zero-extend to I64's */ 819 static void breakV128to4x64U ( IRExpr* t128, 820 /*OUTs*/ 821 IRTemp* t3, IRTemp* t2, 822 IRTemp* t1, IRTemp* t0 ) 823 { 824 IRTemp hi64 = newTemp(Ity_I64); 825 IRTemp lo64 = newTemp(Ity_I64); 826 827 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 828 vassert(t0 && *t0 == IRTemp_INVALID); 829 vassert(t1 && *t1 == IRTemp_INVALID); 830 vassert(t2 && *t2 == IRTemp_INVALID); 831 vassert(t3 && *t3 == IRTemp_INVALID); 832 *t0 = newTemp(Ity_I64); 833 *t1 = newTemp(Ity_I64); 834 *t2 = newTemp(Ity_I64); 835 *t3 = newTemp(Ity_I64); 836 837 assign( hi64, unop(Iop_V128HIto64, t128) ); 838 assign( lo64, unop(Iop_V128to64, t128) ); 839 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 840 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 841 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 842 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 843 } 844 845 static void breakV128to4x32( IRExpr* t128, 846 /*OUTs*/ 847 IRTemp* t3, IRTemp* t2, 848 IRTemp* t1, IRTemp* t0 ) 849 { 850 IRTemp hi64 = newTemp(Ity_I64); 851 IRTemp lo64 = newTemp(Ity_I64); 852 853 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 854 vassert(t0 && *t0 == IRTemp_INVALID); 855 vassert(t1 && *t1 == IRTemp_INVALID); 856 vassert(t2 && *t2 == IRTemp_INVALID); 857 vassert(t3 && *t3 == IRTemp_INVALID); 858 *t0 = newTemp(Ity_I32); 859 *t1 = newTemp(Ity_I32); 860 *t2 = newTemp(Ity_I32); 861 *t3 = newTemp(Ity_I32); 862 863 assign( hi64, unop(Iop_V128HIto64, t128) ); 864 assign( lo64, unop(Iop_V128to64, t128) ); 865 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 866 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 867 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 868 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 869 } 870 871 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 872 IRTemp t1, IRTemp t0 ) 873 { 874 return 875 binop( Iop_64HLtoV128, 876 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 877 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 878 ); 879 } 880 881 882 /* Signed saturating narrow 64S to 32 */ 883 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 884 { 885 IRTemp hi32 = newTemp(Ity_I32); 886 IRTemp lo32 = newTemp(Ity_I32); 887 888 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 889 890 assign( hi32, unop(Iop_64HIto32, t64)); 891 assign( lo32, unop(Iop_64to32, t64)); 892 893 return IRExpr_ITE( 894 /* if (hi32 == (lo32 >>s 31)) */ 895 binop(Iop_CmpEQ32, mkexpr(hi32), 896 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 897 /* then: within signed-32 range: lo half good enough */ 898 mkexpr(lo32), 899 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 900 binop(Iop_Add32, mkU32(0x7FFFFFFF), 901 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 902 } 903 904 /* Unsigned saturating narrow 64S to 32 */ 905 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 906 { 907 IRTemp hi32 = newTemp(Ity_I32); 908 IRTemp lo32 = newTemp(Ity_I32); 909 910 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 911 912 assign( hi32, unop(Iop_64HIto32, t64)); 913 assign( lo32, unop(Iop_64to32, t64)); 914 915 return IRExpr_ITE( 916 /* if (top 32 bits of t64 are 0) */ 917 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 918 /* then: within unsigned-32 range: lo half good enough */ 919 mkexpr(lo32), 920 /* else: positive saturate -> 0xFFFFFFFF */ 921 mkU32(0xFFFFFFFF)); 922 } 923 924 /* Signed saturate narrow 64->32, combining to V128 */ 925 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 926 IRExpr* t1, IRExpr* t0 ) 927 { 928 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 929 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 930 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 931 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 932 return binop(Iop_64HLtoV128, 933 binop(Iop_32HLto64, 934 mkQNarrow64Sto32( t3 ), 935 mkQNarrow64Sto32( t2 )), 936 binop(Iop_32HLto64, 937 mkQNarrow64Sto32( t1 ), 938 mkQNarrow64Sto32( t0 ))); 939 } 940 941 /* Unsigned saturate narrow 64->32, combining to V128 */ 942 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 943 IRExpr* t1, IRExpr* t0 ) 944 { 945 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 946 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 947 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 948 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 949 return binop(Iop_64HLtoV128, 950 binop(Iop_32HLto64, 951 mkQNarrow64Uto32( t3 ), 952 mkQNarrow64Uto32( t2 )), 953 binop(Iop_32HLto64, 954 mkQNarrow64Uto32( t1 ), 955 mkQNarrow64Uto32( t0 ))); 956 } 957 958 /* Simulate irops Iop_MullOdd*, since we don't have them */ 959 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 960 binop(Iop_MullEven8Ux16, \ 961 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 962 binop(Iop_ShrV128, expr_vB, mkU8(8))) 963 964 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 965 binop(Iop_MullEven8Sx16, \ 966 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 967 binop(Iop_ShrV128, expr_vB, mkU8(8))) 968 969 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 970 binop(Iop_MullEven16Ux8, \ 971 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 972 binop(Iop_ShrV128, expr_vB, mkU8(16))) 973 974 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 975 binop(Iop_MullEven32Ux4, \ 976 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 977 binop(Iop_ShrV128, expr_vB, mkU8(32))) 978 979 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 980 binop(Iop_MullEven16Sx8, \ 981 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 982 binop(Iop_ShrV128, expr_vB, mkU8(16))) 983 984 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 985 binop(Iop_MullEven32Sx4, \ 986 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 987 binop(Iop_ShrV128, expr_vB, mkU8(32))) 988 989 990 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 991 { 992 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 993 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 994 } 995 996 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 997 { 998 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 999 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1000 } 1001 1002 static IROp mkSzOp ( IRType ty, IROp op8 ) 1003 { 1004 Int adj; 1005 vassert(ty == Ity_I8 || ty == Ity_I16 || 1006 ty == Ity_I32 || ty == Ity_I64); 1007 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1008 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1009 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1010 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1011 op8 == Iop_Not8 ); 1012 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1013 return adj + op8; 1014 } 1015 1016 /* Make sure we get valid 32 and 64bit addresses */ 1017 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1018 { 1019 vassert(ty == Ity_I32 || ty == Ity_I64); 1020 return ( ty == Ity_I64 ? 1021 (Addr64)addr : 1022 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1023 } 1024 1025 /* sz, ULong -> IRExpr */ 1026 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1027 { 1028 vassert(ty == Ity_I32 || ty == Ity_I64); 1029 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1030 } 1031 1032 /* sz, ULong -> IRConst */ 1033 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1034 { 1035 vassert(ty == Ity_I32 || ty == Ity_I64); 1036 return ( ty == Ity_I64 ? 1037 IRConst_U64(imm64) : 1038 IRConst_U32((UInt)imm64) ); 1039 } 1040 1041 /* Sign extend imm16 -> IRExpr* */ 1042 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1043 { 1044 vassert(ty == Ity_I32 || ty == Ity_I64); 1045 return ( ty == Ity_I64 ? 1046 mkU64(extend_s_16to64(imm16)) : 1047 mkU32(extend_s_16to32(imm16)) ); 1048 } 1049 1050 /* Sign extend imm32 -> IRExpr* */ 1051 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1052 { 1053 vassert(ty == Ity_I32 || ty == Ity_I64); 1054 return ( ty == Ity_I64 ? 1055 mkU64(extend_s_32to64(imm32)) : 1056 mkU32(imm32) ); 1057 } 1058 1059 /* IR narrows I32/I64 -> I8/I16/I32 */ 1060 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1061 { 1062 vassert(ty == Ity_I32 || ty == Ity_I64); 1063 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1064 } 1065 1066 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1067 { 1068 vassert(ty == Ity_I32 || ty == Ity_I64); 1069 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1070 } 1071 1072 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1073 { 1074 vassert(ty == Ity_I32 || ty == Ity_I64); 1075 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1076 } 1077 1078 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1079 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1080 { 1081 IROp op; 1082 vassert(ty == Ity_I32 || ty == Ity_I64); 1083 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1084 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1085 return unop(op, src); 1086 } 1087 1088 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1089 { 1090 IROp op; 1091 vassert(ty == Ity_I32 || ty == Ity_I64); 1092 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1093 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1094 return unop(op, src); 1095 } 1096 1097 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1098 { 1099 vassert(ty == Ity_I32 || ty == Ity_I64); 1100 if (ty == Ity_I32) 1101 return src; 1102 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1103 } 1104 1105 1106 static Int integerGuestRegOffset ( UInt archreg ) 1107 { 1108 vassert(archreg < 32); 1109 1110 // jrs: probably not necessary; only matters if we reference sub-parts 1111 // of the ppc registers, but that isn't the case 1112 // later: this might affect Altivec though? 1113 1114 switch (archreg) { 1115 case 0: return offsetofPPCGuestState(guest_GPR0); 1116 case 1: return offsetofPPCGuestState(guest_GPR1); 1117 case 2: return offsetofPPCGuestState(guest_GPR2); 1118 case 3: return offsetofPPCGuestState(guest_GPR3); 1119 case 4: return offsetofPPCGuestState(guest_GPR4); 1120 case 5: return offsetofPPCGuestState(guest_GPR5); 1121 case 6: return offsetofPPCGuestState(guest_GPR6); 1122 case 7: return offsetofPPCGuestState(guest_GPR7); 1123 case 8: return offsetofPPCGuestState(guest_GPR8); 1124 case 9: return offsetofPPCGuestState(guest_GPR9); 1125 case 10: return offsetofPPCGuestState(guest_GPR10); 1126 case 11: return offsetofPPCGuestState(guest_GPR11); 1127 case 12: return offsetofPPCGuestState(guest_GPR12); 1128 case 13: return offsetofPPCGuestState(guest_GPR13); 1129 case 14: return offsetofPPCGuestState(guest_GPR14); 1130 case 15: return offsetofPPCGuestState(guest_GPR15); 1131 case 16: return offsetofPPCGuestState(guest_GPR16); 1132 case 17: return offsetofPPCGuestState(guest_GPR17); 1133 case 18: return offsetofPPCGuestState(guest_GPR18); 1134 case 19: return offsetofPPCGuestState(guest_GPR19); 1135 case 20: return offsetofPPCGuestState(guest_GPR20); 1136 case 21: return offsetofPPCGuestState(guest_GPR21); 1137 case 22: return offsetofPPCGuestState(guest_GPR22); 1138 case 23: return offsetofPPCGuestState(guest_GPR23); 1139 case 24: return offsetofPPCGuestState(guest_GPR24); 1140 case 25: return offsetofPPCGuestState(guest_GPR25); 1141 case 26: return offsetofPPCGuestState(guest_GPR26); 1142 case 27: return offsetofPPCGuestState(guest_GPR27); 1143 case 28: return offsetofPPCGuestState(guest_GPR28); 1144 case 29: return offsetofPPCGuestState(guest_GPR29); 1145 case 30: return offsetofPPCGuestState(guest_GPR30); 1146 case 31: return offsetofPPCGuestState(guest_GPR31); 1147 default: break; 1148 } 1149 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1150 } 1151 1152 static IRExpr* getIReg ( UInt archreg ) 1153 { 1154 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1155 vassert(archreg < 32); 1156 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1157 } 1158 1159 /* Ditto, but write to a reg instead. */ 1160 static void putIReg ( UInt archreg, IRExpr* e ) 1161 { 1162 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1163 vassert(archreg < 32); 1164 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1165 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1166 } 1167 1168 1169 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1170 static Int floatGuestRegOffset ( UInt archreg ) 1171 { 1172 vassert(archreg < 32); 1173 1174 if (host_endness == VexEndnessLE) { 1175 switch (archreg) { 1176 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1177 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1178 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1179 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1180 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1181 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1182 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1183 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1184 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1185 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1186 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1187 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1188 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1189 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1190 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1191 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1192 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1193 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1194 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1195 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1196 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1197 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1198 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1199 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1200 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1201 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1202 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1203 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1204 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1205 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1206 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1207 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1208 default: break; 1209 } 1210 } else { 1211 switch (archreg) { 1212 case 0: return offsetofPPCGuestState(guest_VSR0); 1213 case 1: return offsetofPPCGuestState(guest_VSR1); 1214 case 2: return offsetofPPCGuestState(guest_VSR2); 1215 case 3: return offsetofPPCGuestState(guest_VSR3); 1216 case 4: return offsetofPPCGuestState(guest_VSR4); 1217 case 5: return offsetofPPCGuestState(guest_VSR5); 1218 case 6: return offsetofPPCGuestState(guest_VSR6); 1219 case 7: return offsetofPPCGuestState(guest_VSR7); 1220 case 8: return offsetofPPCGuestState(guest_VSR8); 1221 case 9: return offsetofPPCGuestState(guest_VSR9); 1222 case 10: return offsetofPPCGuestState(guest_VSR10); 1223 case 11: return offsetofPPCGuestState(guest_VSR11); 1224 case 12: return offsetofPPCGuestState(guest_VSR12); 1225 case 13: return offsetofPPCGuestState(guest_VSR13); 1226 case 14: return offsetofPPCGuestState(guest_VSR14); 1227 case 15: return offsetofPPCGuestState(guest_VSR15); 1228 case 16: return offsetofPPCGuestState(guest_VSR16); 1229 case 17: return offsetofPPCGuestState(guest_VSR17); 1230 case 18: return offsetofPPCGuestState(guest_VSR18); 1231 case 19: return offsetofPPCGuestState(guest_VSR19); 1232 case 20: return offsetofPPCGuestState(guest_VSR20); 1233 case 21: return offsetofPPCGuestState(guest_VSR21); 1234 case 22: return offsetofPPCGuestState(guest_VSR22); 1235 case 23: return offsetofPPCGuestState(guest_VSR23); 1236 case 24: return offsetofPPCGuestState(guest_VSR24); 1237 case 25: return offsetofPPCGuestState(guest_VSR25); 1238 case 26: return offsetofPPCGuestState(guest_VSR26); 1239 case 27: return offsetofPPCGuestState(guest_VSR27); 1240 case 28: return offsetofPPCGuestState(guest_VSR28); 1241 case 29: return offsetofPPCGuestState(guest_VSR29); 1242 case 30: return offsetofPPCGuestState(guest_VSR30); 1243 case 31: return offsetofPPCGuestState(guest_VSR31); 1244 default: break; 1245 } 1246 } 1247 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1248 } 1249 1250 static IRExpr* getFReg ( UInt archreg ) 1251 { 1252 vassert(archreg < 32); 1253 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1254 } 1255 1256 /* Ditto, but write to a reg instead. */ 1257 static void putFReg ( UInt archreg, IRExpr* e ) 1258 { 1259 vassert(archreg < 32); 1260 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1261 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1262 } 1263 1264 /* get Decimal float value. Note, they share floating point register file. */ 1265 static IRExpr* getDReg(UInt archreg) { 1266 IRExpr *e; 1267 vassert( archreg < 32 ); 1268 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1269 return e; 1270 } 1271 static IRExpr* getDReg32(UInt archreg) { 1272 IRExpr *e; 1273 vassert( archreg < 32 ); 1274 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1275 return e; 1276 } 1277 1278 /* Read a floating point register pair and combine their contents into a 1279 128-bit value */ 1280 static IRExpr *getDReg_pair(UInt archreg) { 1281 IRExpr *high = getDReg( archreg ); 1282 IRExpr *low = getDReg( archreg + 1 ); 1283 1284 return binop( Iop_D64HLtoD128, high, low ); 1285 } 1286 1287 /* Ditto, but write to a reg instead. */ 1288 static void putDReg32(UInt archreg, IRExpr* e) { 1289 vassert( archreg < 32 ); 1290 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1291 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1292 } 1293 1294 static void putDReg(UInt archreg, IRExpr* e) { 1295 vassert( archreg < 32 ); 1296 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1297 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1298 } 1299 1300 /* Write a 128-bit floating point value into a register pair. */ 1301 static void putDReg_pair(UInt archreg, IRExpr *e) { 1302 IRTemp low = newTemp( Ity_D64 ); 1303 IRTemp high = newTemp( Ity_D64 ); 1304 1305 vassert( archreg < 32 ); 1306 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1307 1308 assign( low, unop( Iop_D128LOtoD64, e ) ); 1309 assign( high, unop( Iop_D128HItoD64, e ) ); 1310 1311 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1312 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1313 } 1314 1315 static Int vsxGuestRegOffset ( UInt archreg ) 1316 { 1317 vassert(archreg < 64); 1318 switch (archreg) { 1319 case 0: return offsetofPPCGuestState(guest_VSR0); 1320 case 1: return offsetofPPCGuestState(guest_VSR1); 1321 case 2: return offsetofPPCGuestState(guest_VSR2); 1322 case 3: return offsetofPPCGuestState(guest_VSR3); 1323 case 4: return offsetofPPCGuestState(guest_VSR4); 1324 case 5: return offsetofPPCGuestState(guest_VSR5); 1325 case 6: return offsetofPPCGuestState(guest_VSR6); 1326 case 7: return offsetofPPCGuestState(guest_VSR7); 1327 case 8: return offsetofPPCGuestState(guest_VSR8); 1328 case 9: return offsetofPPCGuestState(guest_VSR9); 1329 case 10: return offsetofPPCGuestState(guest_VSR10); 1330 case 11: return offsetofPPCGuestState(guest_VSR11); 1331 case 12: return offsetofPPCGuestState(guest_VSR12); 1332 case 13: return offsetofPPCGuestState(guest_VSR13); 1333 case 14: return offsetofPPCGuestState(guest_VSR14); 1334 case 15: return offsetofPPCGuestState(guest_VSR15); 1335 case 16: return offsetofPPCGuestState(guest_VSR16); 1336 case 17: return offsetofPPCGuestState(guest_VSR17); 1337 case 18: return offsetofPPCGuestState(guest_VSR18); 1338 case 19: return offsetofPPCGuestState(guest_VSR19); 1339 case 20: return offsetofPPCGuestState(guest_VSR20); 1340 case 21: return offsetofPPCGuestState(guest_VSR21); 1341 case 22: return offsetofPPCGuestState(guest_VSR22); 1342 case 23: return offsetofPPCGuestState(guest_VSR23); 1343 case 24: return offsetofPPCGuestState(guest_VSR24); 1344 case 25: return offsetofPPCGuestState(guest_VSR25); 1345 case 26: return offsetofPPCGuestState(guest_VSR26); 1346 case 27: return offsetofPPCGuestState(guest_VSR27); 1347 case 28: return offsetofPPCGuestState(guest_VSR28); 1348 case 29: return offsetofPPCGuestState(guest_VSR29); 1349 case 30: return offsetofPPCGuestState(guest_VSR30); 1350 case 31: return offsetofPPCGuestState(guest_VSR31); 1351 case 32: return offsetofPPCGuestState(guest_VSR32); 1352 case 33: return offsetofPPCGuestState(guest_VSR33); 1353 case 34: return offsetofPPCGuestState(guest_VSR34); 1354 case 35: return offsetofPPCGuestState(guest_VSR35); 1355 case 36: return offsetofPPCGuestState(guest_VSR36); 1356 case 37: return offsetofPPCGuestState(guest_VSR37); 1357 case 38: return offsetofPPCGuestState(guest_VSR38); 1358 case 39: return offsetofPPCGuestState(guest_VSR39); 1359 case 40: return offsetofPPCGuestState(guest_VSR40); 1360 case 41: return offsetofPPCGuestState(guest_VSR41); 1361 case 42: return offsetofPPCGuestState(guest_VSR42); 1362 case 43: return offsetofPPCGuestState(guest_VSR43); 1363 case 44: return offsetofPPCGuestState(guest_VSR44); 1364 case 45: return offsetofPPCGuestState(guest_VSR45); 1365 case 46: return offsetofPPCGuestState(guest_VSR46); 1366 case 47: return offsetofPPCGuestState(guest_VSR47); 1367 case 48: return offsetofPPCGuestState(guest_VSR48); 1368 case 49: return offsetofPPCGuestState(guest_VSR49); 1369 case 50: return offsetofPPCGuestState(guest_VSR50); 1370 case 51: return offsetofPPCGuestState(guest_VSR51); 1371 case 52: return offsetofPPCGuestState(guest_VSR52); 1372 case 53: return offsetofPPCGuestState(guest_VSR53); 1373 case 54: return offsetofPPCGuestState(guest_VSR54); 1374 case 55: return offsetofPPCGuestState(guest_VSR55); 1375 case 56: return offsetofPPCGuestState(guest_VSR56); 1376 case 57: return offsetofPPCGuestState(guest_VSR57); 1377 case 58: return offsetofPPCGuestState(guest_VSR58); 1378 case 59: return offsetofPPCGuestState(guest_VSR59); 1379 case 60: return offsetofPPCGuestState(guest_VSR60); 1380 case 61: return offsetofPPCGuestState(guest_VSR61); 1381 case 62: return offsetofPPCGuestState(guest_VSR62); 1382 case 63: return offsetofPPCGuestState(guest_VSR63); 1383 default: break; 1384 } 1385 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1386 } 1387 1388 /* Vector registers are mapped to VSX registers[32..63]. */ 1389 static Int vectorGuestRegOffset ( UInt archreg ) 1390 { 1391 vassert(archreg < 32); 1392 1393 switch (archreg) { 1394 case 0: return offsetofPPCGuestState(guest_VSR32); 1395 case 1: return offsetofPPCGuestState(guest_VSR33); 1396 case 2: return offsetofPPCGuestState(guest_VSR34); 1397 case 3: return offsetofPPCGuestState(guest_VSR35); 1398 case 4: return offsetofPPCGuestState(guest_VSR36); 1399 case 5: return offsetofPPCGuestState(guest_VSR37); 1400 case 6: return offsetofPPCGuestState(guest_VSR38); 1401 case 7: return offsetofPPCGuestState(guest_VSR39); 1402 case 8: return offsetofPPCGuestState(guest_VSR40); 1403 case 9: return offsetofPPCGuestState(guest_VSR41); 1404 case 10: return offsetofPPCGuestState(guest_VSR42); 1405 case 11: return offsetofPPCGuestState(guest_VSR43); 1406 case 12: return offsetofPPCGuestState(guest_VSR44); 1407 case 13: return offsetofPPCGuestState(guest_VSR45); 1408 case 14: return offsetofPPCGuestState(guest_VSR46); 1409 case 15: return offsetofPPCGuestState(guest_VSR47); 1410 case 16: return offsetofPPCGuestState(guest_VSR48); 1411 case 17: return offsetofPPCGuestState(guest_VSR49); 1412 case 18: return offsetofPPCGuestState(guest_VSR50); 1413 case 19: return offsetofPPCGuestState(guest_VSR51); 1414 case 20: return offsetofPPCGuestState(guest_VSR52); 1415 case 21: return offsetofPPCGuestState(guest_VSR53); 1416 case 22: return offsetofPPCGuestState(guest_VSR54); 1417 case 23: return offsetofPPCGuestState(guest_VSR55); 1418 case 24: return offsetofPPCGuestState(guest_VSR56); 1419 case 25: return offsetofPPCGuestState(guest_VSR57); 1420 case 26: return offsetofPPCGuestState(guest_VSR58); 1421 case 27: return offsetofPPCGuestState(guest_VSR59); 1422 case 28: return offsetofPPCGuestState(guest_VSR60); 1423 case 29: return offsetofPPCGuestState(guest_VSR61); 1424 case 30: return offsetofPPCGuestState(guest_VSR62); 1425 case 31: return offsetofPPCGuestState(guest_VSR63); 1426 default: break; 1427 } 1428 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1429 } 1430 1431 static IRExpr* getVReg ( UInt archreg ) 1432 { 1433 vassert(archreg < 32); 1434 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1435 } 1436 1437 /* Ditto, but write to a reg instead. */ 1438 static void putVReg ( UInt archreg, IRExpr* e ) 1439 { 1440 vassert(archreg < 32); 1441 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1442 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1443 } 1444 1445 /* Get contents of VSX guest register */ 1446 static IRExpr* getVSReg ( UInt archreg ) 1447 { 1448 vassert(archreg < 64); 1449 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1450 } 1451 1452 /* Ditto, but write to a VSX reg instead. */ 1453 static void putVSReg ( UInt archreg, IRExpr* e ) 1454 { 1455 vassert(archreg < 64); 1456 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1457 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1458 } 1459 1460 1461 static Int guestCR321offset ( UInt cr ) 1462 { 1463 switch (cr) { 1464 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1465 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1466 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1467 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1468 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1469 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1470 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1471 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1472 default: vpanic("guestCR321offset(ppc)"); 1473 } 1474 } 1475 1476 static Int guestCR0offset ( UInt cr ) 1477 { 1478 switch (cr) { 1479 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1480 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1481 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1482 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1483 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1484 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1485 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1486 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1487 default: vpanic("guestCR3offset(ppc)"); 1488 } 1489 } 1490 1491 typedef enum { 1492 _placeholder0, 1493 _placeholder1, 1494 _placeholder2, 1495 BYTE, 1496 HWORD, 1497 WORD, 1498 DWORD 1499 } _popcount_data_type; 1500 1501 /* Generate an IR sequence to do a popcount operation on the supplied 1502 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1503 Ity_I32 or Ity_I64 only. */ 1504 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1505 { 1506 /* Do count across 2^data_type bits, 1507 byte: data_type = 3 1508 half word: data_type = 4 1509 word: data_type = 5 1510 double word: data_type = 6 (not supported for 32-bit type) 1511 */ 1512 Int shift[6]; 1513 _popcount_data_type idx, i; 1514 IRTemp mask[6]; 1515 IRTemp old = IRTemp_INVALID; 1516 IRTemp nyu = IRTemp_INVALID; 1517 1518 vassert(ty == Ity_I64 || ty == Ity_I32); 1519 1520 if (ty == Ity_I32) { 1521 1522 for (idx = 0; idx < WORD; idx++) { 1523 mask[idx] = newTemp(ty); 1524 shift[idx] = 1 << idx; 1525 } 1526 assign(mask[0], mkU32(0x55555555)); 1527 assign(mask[1], mkU32(0x33333333)); 1528 assign(mask[2], mkU32(0x0F0F0F0F)); 1529 assign(mask[3], mkU32(0x00FF00FF)); 1530 assign(mask[4], mkU32(0x0000FFFF)); 1531 old = src; 1532 for (i = 0; i < data_type; i++) { 1533 nyu = newTemp(ty); 1534 assign(nyu, 1535 binop(Iop_Add32, 1536 binop(Iop_And32, 1537 mkexpr(old), 1538 mkexpr(mask[i])), 1539 binop(Iop_And32, 1540 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1541 mkexpr(mask[i])))); 1542 old = nyu; 1543 } 1544 return nyu; 1545 } 1546 1547 // else, ty == Ity_I64 1548 vassert(mode64); 1549 1550 for (i = 0; i < DWORD; i++) { 1551 mask[i] = newTemp( Ity_I64 ); 1552 shift[i] = 1 << i; 1553 } 1554 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1555 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1556 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1557 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1558 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1559 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1560 old = src; 1561 for (i = 0; i < data_type; i++) { 1562 nyu = newTemp( Ity_I64 ); 1563 assign( nyu, 1564 binop( Iop_Add64, 1565 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1566 binop( Iop_And64, 1567 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1568 mkexpr( mask[i] ) ) ) ); 1569 old = nyu; 1570 } 1571 return nyu; 1572 } 1573 1574 /* Special purpose population count function for 1575 * vpopcntd in 32-bit mode. 1576 */ 1577 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1578 { 1579 Int i, shift[6]; 1580 IRTemp mask[6]; 1581 IRTemp old = IRTemp_INVALID; 1582 IRTemp nyu1 = IRTemp_INVALID; 1583 IRTemp nyu2 = IRTemp_INVALID; 1584 IRTemp retval = newTemp(Ity_I64); 1585 1586 vassert(!mode64); 1587 1588 for (i = 0; i < WORD; i++) { 1589 mask[i] = newTemp(Ity_I32); 1590 shift[i] = 1 << i; 1591 } 1592 assign(mask[0], mkU32(0x55555555)); 1593 assign(mask[1], mkU32(0x33333333)); 1594 assign(mask[2], mkU32(0x0F0F0F0F)); 1595 assign(mask[3], mkU32(0x00FF00FF)); 1596 assign(mask[4], mkU32(0x0000FFFF)); 1597 old = src1; 1598 for (i = 0; i < WORD; i++) { 1599 nyu1 = newTemp(Ity_I32); 1600 assign(nyu1, 1601 binop(Iop_Add32, 1602 binop(Iop_And32, 1603 mkexpr(old), 1604 mkexpr(mask[i])), 1605 binop(Iop_And32, 1606 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1607 mkexpr(mask[i])))); 1608 old = nyu1; 1609 } 1610 1611 old = src2; 1612 for (i = 0; i < WORD; i++) { 1613 nyu2 = newTemp(Ity_I32); 1614 assign(nyu2, 1615 binop(Iop_Add32, 1616 binop(Iop_And32, 1617 mkexpr(old), 1618 mkexpr(mask[i])), 1619 binop(Iop_And32, 1620 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1621 mkexpr(mask[i])))); 1622 old = nyu2; 1623 } 1624 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1625 return retval; 1626 } 1627 1628 1629 // ROTL(src32/64, rot_amt5/6) 1630 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1631 IRExpr* rot_amt ) 1632 { 1633 IRExpr *mask, *rot; 1634 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1635 1636 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1637 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1638 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1639 rot = binop(Iop_Or64, 1640 binop(Iop_Shl64, src, mask), 1641 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1642 } else { 1643 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1644 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1645 rot = binop(Iop_Or32, 1646 binop(Iop_Shl32, src, mask), 1647 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1648 } 1649 /* Note: the ITE not merely an optimisation; it's needed 1650 because otherwise the Shr is a shift by the word size when 1651 mask denotes zero. For rotates by immediates, a lot of 1652 this junk gets folded out. */ 1653 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1654 /* non-zero rotate */ rot, 1655 /* zero rotate */ src); 1656 } 1657 1658 /* Standard effective address calc: (rA + rB) */ 1659 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1660 { 1661 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1662 vassert(rA < 32); 1663 vassert(rB < 32); 1664 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1665 } 1666 1667 /* Standard effective address calc: (rA + simm) */ 1668 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1669 { 1670 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1671 vassert(rA < 32); 1672 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1673 mkSzExtendS16(ty, simm16)); 1674 } 1675 1676 /* Standard effective address calc: (rA|0) */ 1677 static IRExpr* ea_rAor0 ( UInt rA ) 1678 { 1679 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1680 vassert(rA < 32); 1681 if (rA == 0) { 1682 return mkSzImm(ty, 0); 1683 } else { 1684 return getIReg(rA); 1685 } 1686 } 1687 1688 /* Standard effective address calc: (rA|0) + rB */ 1689 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1690 { 1691 vassert(rA < 32); 1692 vassert(rB < 32); 1693 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1694 } 1695 1696 /* Standard effective address calc: (rA|0) + simm16 */ 1697 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1698 { 1699 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1700 vassert(rA < 32); 1701 if (rA == 0) { 1702 return mkSzExtendS16(ty, simm16); 1703 } else { 1704 return ea_rA_simm( rA, simm16 ); 1705 } 1706 } 1707 1708 1709 /* Align effective address */ 1710 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1711 { 1712 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1713 Long mask; 1714 switch (align) { 1715 case 1: return addr; // byte aligned 1716 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1717 case 4: mask = ((Long)-1) << 2; break; // word aligned 1718 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1719 default: 1720 vex_printf("addr_align: align = %u\n", align); 1721 vpanic("addr_align(ppc)"); 1722 } 1723 1724 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1725 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1726 } 1727 1728 1729 /* Exit the trace if ADDR (intended to be a guest memory address) is 1730 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1731 restart of the current insn. */ 1732 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1733 { 1734 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1735 if (mode64) { 1736 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1737 stmt( 1738 IRStmt_Exit( 1739 binop(Iop_CmpNE64, 1740 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1741 mkU64(0)), 1742 Ijk_SigBUS, 1743 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1744 ) 1745 ); 1746 } else { 1747 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1748 stmt( 1749 IRStmt_Exit( 1750 binop(Iop_CmpNE32, 1751 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1752 mkU32(0)), 1753 Ijk_SigBUS, 1754 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1755 ) 1756 ); 1757 } 1758 } 1759 1760 1761 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1762 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1763 N) becomes undefined. That is at function calls and returns. ELF 1764 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1765 the address of the next instruction to be executed. 1766 */ 1767 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1768 IRTemp nia, const HChar* who ) 1769 { 1770 Int szB = vbi->guest_stack_redzone_size; 1771 if (0) vex_printf("AbiHint: %s\n", who); 1772 vassert(szB >= 0); 1773 if (szB > 0) { 1774 if (mode64) { 1775 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1776 stmt( IRStmt_AbiHint( 1777 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1778 szB, 1779 mkexpr(nia) 1780 )); 1781 } else { 1782 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1783 stmt( IRStmt_AbiHint( 1784 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1785 szB, 1786 mkexpr(nia) 1787 )); 1788 } 1789 } 1790 } 1791 1792 1793 /*------------------------------------------------------------*/ 1794 /*--- Helpers for condition codes. ---*/ 1795 /*------------------------------------------------------------*/ 1796 1797 /* Condition register layout. 1798 1799 In the hardware, CR is laid out like this. The leftmost end is the 1800 most significant bit in the register; however the IBM documentation 1801 numbers the bits backwards for some reason. 1802 1803 CR0 CR1 .......... CR6 CR7 1804 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1805 31 28 3 0 (normal bit numbering) 1806 1807 Each CR field is 4 bits: [<,>,==,SO] 1808 1809 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1810 1811 Indexing from BI to guest state: 1812 1813 let n = BI / 4 1814 off = BI % 4 1815 this references CR n: 1816 1817 off==0 -> guest_CRn_321 >> 3 1818 off==1 -> guest_CRn_321 >> 2 1819 off==2 -> guest_CRn_321 >> 1 1820 off==3 -> guest_CRn_SO 1821 1822 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1823 (normal notation) and in guest_CRn_321 the significant bits are 1824 3, 2 and 1 (normal notation). 1825 */ 1826 1827 static void putCR321 ( UInt cr, IRExpr* e ) 1828 { 1829 vassert(cr < 8); 1830 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1831 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1832 } 1833 1834 static void putCR0 ( UInt cr, IRExpr* e ) 1835 { 1836 vassert(cr < 8); 1837 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1838 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1839 } 1840 1841 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1842 { 1843 vassert(cr < 8); 1844 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1845 } 1846 1847 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1848 { 1849 vassert(cr < 8); 1850 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1851 } 1852 1853 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1854 return it at the bottom of an I32; the top 31 bits are guaranteed 1855 to be zero. */ 1856 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1857 { 1858 UInt n = bi / 4; 1859 UInt off = bi % 4; 1860 vassert(bi < 32); 1861 if (off == 3) { 1862 /* Fetch the SO bit for this CR field */ 1863 /* Note: And32 is redundant paranoia iff guest state only has 0 1864 or 1 in that slot. */ 1865 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1866 } else { 1867 /* Fetch the <, > or == bit for this CR field */ 1868 return binop( Iop_And32, 1869 binop( Iop_Shr32, 1870 unop(Iop_8Uto32, getCR321(n)), 1871 mkU8(toUChar(3-off)) ), 1872 mkU32(1) ); 1873 } 1874 } 1875 1876 /* Dually, write the least significant bit of BIT to the specified CR 1877 bit. Indexing as per getCRbit. */ 1878 static void putCRbit ( UInt bi, IRExpr* bit ) 1879 { 1880 UInt n, off; 1881 IRExpr* safe; 1882 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1883 safe = binop(Iop_And32, bit, mkU32(1)); 1884 n = bi / 4; 1885 off = bi % 4; 1886 vassert(bi < 32); 1887 if (off == 3) { 1888 /* This is the SO bit for this CR field */ 1889 putCR0(n, unop(Iop_32to8, safe)); 1890 } else { 1891 off = 3 - off; 1892 vassert(off == 1 || off == 2 || off == 3); 1893 putCR321( 1894 n, 1895 unop( Iop_32to8, 1896 binop( Iop_Or32, 1897 /* old value with field masked out */ 1898 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1899 mkU32(~(1 << off))), 1900 /* new value in the right place */ 1901 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1902 ) 1903 ) 1904 ); 1905 } 1906 } 1907 1908 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1909 return it somewhere in an I32; it does not matter where, but 1910 whichever bit it is, all other bits are guaranteed to be zero. In 1911 other words, the I32-typed expression will be zero if the bit is 1912 zero and nonzero if the bit is 1. Write into *where the index 1913 of where the bit will be. */ 1914 1915 static 1916 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1917 { 1918 UInt n = bi / 4; 1919 UInt off = bi % 4; 1920 vassert(bi < 32); 1921 if (off == 3) { 1922 /* Fetch the SO bit for this CR field */ 1923 /* Note: And32 is redundant paranoia iff guest state only has 0 1924 or 1 in that slot. */ 1925 *where = 0; 1926 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1927 } else { 1928 /* Fetch the <, > or == bit for this CR field */ 1929 *where = 3-off; 1930 return binop( Iop_And32, 1931 unop(Iop_8Uto32, getCR321(n)), 1932 mkU32(1 << (3-off)) ); 1933 } 1934 } 1935 1936 /* Set the CR0 flags following an arithmetic operation. 1937 (Condition Register CR0 Field Definition, PPC32 p60) 1938 */ 1939 static IRExpr* getXER_SO ( void ); 1940 static void set_CR0 ( IRExpr* result ) 1941 { 1942 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1943 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1944 if (mode64) { 1945 putCR321( 0, unop(Iop_64to8, 1946 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1947 } else { 1948 putCR321( 0, unop(Iop_32to8, 1949 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1950 } 1951 putCR0( 0, getXER_SO() ); 1952 } 1953 1954 1955 /* Set the CR6 flags following an AltiVec compare operation. 1956 * NOTE: This also works for VSX single-precision compares. 1957 * */ 1958 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1959 { 1960 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1961 all_ones = (v[0] && v[1] && v[2] && v[3]) 1962 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1963 */ 1964 IRTemp v0 = newTemp(Ity_V128); 1965 IRTemp v1 = newTemp(Ity_V128); 1966 IRTemp v2 = newTemp(Ity_V128); 1967 IRTemp v3 = newTemp(Ity_V128); 1968 IRTemp rOnes = newTemp(Ity_I8); 1969 IRTemp rZeros = newTemp(Ity_I8); 1970 1971 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1972 1973 assign( v0, result ); 1974 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1975 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1976 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1977 1978 assign( rZeros, unop(Iop_1Uto8, 1979 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1980 unop(Iop_Not32, 1981 unop(Iop_V128to32, 1982 binop(Iop_OrV128, 1983 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1984 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1985 ))) ); 1986 1987 if (test_all_ones) { 1988 assign( rOnes, unop(Iop_1Uto8, 1989 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1990 unop(Iop_V128to32, 1991 binop(Iop_AndV128, 1992 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1993 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1994 ))) ); 1995 putCR321( 6, binop(Iop_Or8, 1996 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1997 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1998 } else { 1999 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2000 } 2001 putCR0( 6, mkU8(0) ); 2002 } 2003 2004 2005 2006 /*------------------------------------------------------------*/ 2007 /*--- Helpers for XER flags. ---*/ 2008 /*------------------------------------------------------------*/ 2009 2010 static void putXER_SO ( IRExpr* e ) 2011 { 2012 IRExpr* so; 2013 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2014 so = binop(Iop_And8, e, mkU8(1)); 2015 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2016 } 2017 2018 static void putXER_OV ( IRExpr* e ) 2019 { 2020 IRExpr* ov; 2021 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2022 ov = binop(Iop_And8, e, mkU8(1)); 2023 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2024 } 2025 2026 static void putXER_CA ( IRExpr* e ) 2027 { 2028 IRExpr* ca; 2029 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2030 ca = binop(Iop_And8, e, mkU8(1)); 2031 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2032 } 2033 2034 static void putXER_BC ( IRExpr* e ) 2035 { 2036 IRExpr* bc; 2037 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2038 bc = binop(Iop_And8, e, mkU8(0x7F)); 2039 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2040 } 2041 2042 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2043 { 2044 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2045 } 2046 2047 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 2048 { 2049 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2050 } 2051 2052 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2053 { 2054 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2055 } 2056 2057 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 2058 { 2059 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2060 } 2061 2062 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 2063 { 2064 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2065 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2066 } 2067 2068 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2069 { 2070 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2071 } 2072 2073 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 2074 { 2075 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2076 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2077 } 2078 2079 2080 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2081 %XER.SO accordingly. */ 2082 2083 static void set_XER_OV_32( UInt op, IRExpr* res, 2084 IRExpr* argL, IRExpr* argR ) 2085 { 2086 IRTemp t64; 2087 IRExpr* xer_ov; 2088 vassert(op < PPCG_FLAG_OP_NUMBER); 2089 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2090 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2091 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2092 2093 # define INT32_MIN 0x80000000 2094 2095 # define XOR2(_aa,_bb) \ 2096 binop(Iop_Xor32,(_aa),(_bb)) 2097 2098 # define XOR3(_cc,_dd,_ee) \ 2099 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2100 2101 # define AND3(_ff,_gg,_hh) \ 2102 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2103 2104 #define NOT(_jj) \ 2105 unop(Iop_Not32, (_jj)) 2106 2107 switch (op) { 2108 case /* 0 */ PPCG_FLAG_OP_ADD: 2109 case /* 1 */ PPCG_FLAG_OP_ADDE: 2110 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2111 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2112 xer_ov 2113 = AND3( XOR3(argL,argR,mkU32(-1)), 2114 XOR2(argL,res), 2115 mkU32(INT32_MIN) ); 2116 /* xer_ov can only be 0 or 1<<31 */ 2117 xer_ov 2118 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2119 break; 2120 2121 case /* 2 */ PPCG_FLAG_OP_DIVW: 2122 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2123 xer_ov 2124 = mkOR1( 2125 mkAND1( 2126 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2127 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2128 ), 2129 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2130 ); 2131 xer_ov 2132 = unop(Iop_1Uto32, xer_ov); 2133 break; 2134 2135 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2136 /* argR == 0 */ 2137 xer_ov 2138 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2139 break; 2140 2141 case /* 4 */ PPCG_FLAG_OP_MULLW: 2142 /* OV true if result can't be represented in 32 bits 2143 i.e sHi != sign extension of sLo */ 2144 t64 = newTemp(Ity_I64); 2145 assign( t64, binop(Iop_MullS32, argL, argR) ); 2146 xer_ov 2147 = binop( Iop_CmpNE32, 2148 unop(Iop_64HIto32, mkexpr(t64)), 2149 binop( Iop_Sar32, 2150 unop(Iop_64to32, mkexpr(t64)), 2151 mkU8(31)) 2152 ); 2153 xer_ov 2154 = unop(Iop_1Uto32, xer_ov); 2155 break; 2156 2157 case /* 5 */ PPCG_FLAG_OP_NEG: 2158 /* argL == INT32_MIN */ 2159 xer_ov 2160 = unop( Iop_1Uto32, 2161 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2162 break; 2163 2164 case /* 6 */ PPCG_FLAG_OP_SUBF: 2165 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2166 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2167 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2168 xer_ov 2169 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2170 XOR2(NOT(argL),res), 2171 mkU32(INT32_MIN) ); 2172 /* xer_ov can only be 0 or 1<<31 */ 2173 xer_ov 2174 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2175 break; 2176 2177 case PPCG_FLAG_OP_DIVWEU: 2178 xer_ov 2179 = binop( Iop_Or32, 2180 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2181 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2182 break; 2183 2184 case PPCG_FLAG_OP_DIVWE: 2185 2186 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2187 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2188 * an overflow is implied. 2189 */ 2190 xer_ov = binop( Iop_Or32, 2191 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2192 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2193 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2194 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2195 break; 2196 2197 2198 2199 default: 2200 vex_printf("set_XER_OV: op = %u\n", op); 2201 vpanic("set_XER_OV(ppc)"); 2202 } 2203 2204 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2205 putXER_OV( unop(Iop_32to8, xer_ov) ); 2206 2207 /* Update the summary overflow */ 2208 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2209 2210 # undef INT32_MIN 2211 # undef AND3 2212 # undef XOR3 2213 # undef XOR2 2214 # undef NOT 2215 } 2216 2217 static void set_XER_OV_64( UInt op, IRExpr* res, 2218 IRExpr* argL, IRExpr* argR ) 2219 { 2220 IRExpr* xer_ov; 2221 vassert(op < PPCG_FLAG_OP_NUMBER); 2222 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2223 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2224 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2225 2226 # define INT64_MIN 0x8000000000000000ULL 2227 2228 # define XOR2(_aa,_bb) \ 2229 binop(Iop_Xor64,(_aa),(_bb)) 2230 2231 # define XOR3(_cc,_dd,_ee) \ 2232 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2233 2234 # define AND3(_ff,_gg,_hh) \ 2235 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2236 2237 #define NOT(_jj) \ 2238 unop(Iop_Not64, (_jj)) 2239 2240 switch (op) { 2241 case /* 0 */ PPCG_FLAG_OP_ADD: 2242 case /* 1 */ PPCG_FLAG_OP_ADDE: 2243 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2244 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2245 xer_ov 2246 = AND3( XOR3(argL,argR,mkU64(-1)), 2247 XOR2(argL,res), 2248 mkU64(INT64_MIN) ); 2249 /* xer_ov can only be 0 or 1<<63 */ 2250 xer_ov 2251 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2252 break; 2253 2254 case /* 2 */ PPCG_FLAG_OP_DIVW: 2255 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2256 xer_ov 2257 = mkOR1( 2258 mkAND1( 2259 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2260 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2261 ), 2262 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2263 ); 2264 break; 2265 2266 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2267 /* argR == 0 */ 2268 xer_ov 2269 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2270 break; 2271 2272 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2273 /* OV true if result can't be represented in 64 bits 2274 i.e sHi != sign extension of sLo */ 2275 xer_ov 2276 = binop( Iop_CmpNE32, 2277 unop(Iop_64HIto32, res), 2278 binop( Iop_Sar32, 2279 unop(Iop_64to32, res), 2280 mkU8(31)) 2281 ); 2282 break; 2283 } 2284 2285 case /* 5 */ PPCG_FLAG_OP_NEG: 2286 /* argL == INT64_MIN */ 2287 xer_ov 2288 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2289 break; 2290 2291 case /* 6 */ PPCG_FLAG_OP_SUBF: 2292 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2293 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2294 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2295 xer_ov 2296 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2297 XOR2(NOT(argL),res), 2298 mkU64(INT64_MIN) ); 2299 /* xer_ov can only be 0 or 1<<63 */ 2300 xer_ov 2301 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2302 break; 2303 2304 case PPCG_FLAG_OP_DIVDE: 2305 2306 /* If argR == 0, we must set the OV bit. But there's another condition 2307 * where we can get overflow set for divde . . . when the 2308 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2309 * both dividend and divisor are non-zero, it implies an overflow. 2310 */ 2311 xer_ov 2312 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2313 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2314 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2315 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2316 break; 2317 2318 case PPCG_FLAG_OP_DIVDEU: 2319 /* If argR == 0 or if argL >= argR, set OV. */ 2320 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2321 binop( Iop_CmpLE64U, argR, argL ) ); 2322 break; 2323 2324 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2325 IRTemp t128; 2326 /* OV true if result can't be represented in 64 bits 2327 i.e sHi != sign extension of sLo */ 2328 t128 = newTemp(Ity_I128); 2329 assign( t128, binop(Iop_MullS64, argL, argR) ); 2330 xer_ov 2331 = binop( Iop_CmpNE64, 2332 unop(Iop_128HIto64, mkexpr(t128)), 2333 binop( Iop_Sar64, 2334 unop(Iop_128to64, mkexpr(t128)), 2335 mkU8(63)) 2336 ); 2337 break; 2338 } 2339 2340 default: 2341 vex_printf("set_XER_OV: op = %u\n", op); 2342 vpanic("set_XER_OV(ppc64)"); 2343 } 2344 2345 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2346 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2347 2348 /* Update the summary overflow */ 2349 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2350 2351 # undef INT64_MIN 2352 # undef AND3 2353 # undef XOR3 2354 # undef XOR2 2355 # undef NOT 2356 } 2357 2358 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2359 IRExpr* argL, IRExpr* argR ) 2360 { 2361 if (ty == Ity_I32) 2362 set_XER_OV_32( op, res, argL, argR ); 2363 else 2364 set_XER_OV_64( op, res, argL, argR ); 2365 } 2366 2367 2368 2369 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2370 value being OLDCA. Set %XER.CA accordingly. */ 2371 2372 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2373 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2374 { 2375 IRExpr* xer_ca; 2376 vassert(op < PPCG_FLAG_OP_NUMBER); 2377 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2378 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2379 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2380 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2381 2382 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2383 seems reasonable given that it's always generated by 2384 getXER_CA32(), which masks it accordingly. In any case it being 2385 0 or 1 is an invariant of the ppc guest state representation; 2386 if it has any other value, that invariant has been violated. */ 2387 2388 switch (op) { 2389 case /* 0 */ PPCG_FLAG_OP_ADD: 2390 /* res <u argL */ 2391 xer_ca 2392 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2393 break; 2394 2395 case /* 1 */ PPCG_FLAG_OP_ADDE: 2396 /* res <u argL || (old_ca==1 && res==argL) */ 2397 xer_ca 2398 = mkOR1( 2399 binop(Iop_CmpLT32U, res, argL), 2400 mkAND1( 2401 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2402 binop(Iop_CmpEQ32, res, argL) 2403 ) 2404 ); 2405 xer_ca 2406 = unop(Iop_1Uto32, xer_ca); 2407 break; 2408 2409 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2410 /* res <u argR || (old_ca==1 && res==argR) */ 2411 xer_ca 2412 = mkOR1( 2413 binop(Iop_CmpLT32U, res, argR), 2414 mkAND1( 2415 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2416 binop(Iop_CmpEQ32, res, argR) 2417 ) 2418 ); 2419 xer_ca 2420 = unop(Iop_1Uto32, xer_ca); 2421 break; 2422 2423 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2424 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2425 /* res <=u argR */ 2426 xer_ca 2427 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2428 break; 2429 2430 case /* 10 */ PPCG_FLAG_OP_SRAW: 2431 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2432 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2433 bit of argL. */ 2434 /* This term valid for shift amount < 32 only */ 2435 xer_ca 2436 = binop( 2437 Iop_And32, 2438 binop(Iop_Sar32, argL, mkU8(31)), 2439 binop( Iop_And32, 2440 argL, 2441 binop( Iop_Sub32, 2442 binop(Iop_Shl32, mkU32(1), 2443 unop(Iop_32to8,argR)), 2444 mkU32(1) ) 2445 ) 2446 ); 2447 xer_ca 2448 = IRExpr_ITE( 2449 /* shift amt > 31 ? */ 2450 binop(Iop_CmpLT32U, mkU32(31), argR), 2451 /* yes -- get sign bit of argL */ 2452 binop(Iop_Shr32, argL, mkU8(31)), 2453 /* no -- be like srawi */ 2454 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2455 ); 2456 break; 2457 2458 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2459 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2460 0. Since the shift amount is known to be in the range 2461 0 .. 31 inclusive the following seems viable: 2462 xer.ca == 1 iff the following is nonzero: 2463 (argL >>s 31) -- either all 0s or all 1s 2464 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2465 xer_ca 2466 = binop( 2467 Iop_And32, 2468 binop(Iop_Sar32, argL, mkU8(31)), 2469 binop( Iop_And32, 2470 argL, 2471 binop( Iop_Sub32, 2472 binop(Iop_Shl32, mkU32(1), 2473 unop(Iop_32to8,argR)), 2474 mkU32(1) ) 2475 ) 2476 ); 2477 xer_ca 2478 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2479 break; 2480 2481 default: 2482 vex_printf("set_XER_CA: op = %u\n", op); 2483 vpanic("set_XER_CA(ppc)"); 2484 } 2485 2486 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2487 putXER_CA( unop(Iop_32to8, xer_ca) ); 2488 } 2489 2490 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2491 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2492 { 2493 IRExpr* xer_ca; 2494 vassert(op < PPCG_FLAG_OP_NUMBER); 2495 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2496 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2497 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2498 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2499 2500 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2501 seems reasonable given that it's always generated by 2502 getXER_CA32(), which masks it accordingly. In any case it being 2503 0 or 1 is an invariant of the ppc guest state representation; 2504 if it has any other value, that invariant has been violated. */ 2505 2506 switch (op) { 2507 case /* 0 */ PPCG_FLAG_OP_ADD: 2508 /* res <u argL */ 2509 xer_ca 2510 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2511 break; 2512 2513 case /* 1 */ PPCG_FLAG_OP_ADDE: 2514 /* res <u argL || (old_ca==1 && res==argL) */ 2515 xer_ca 2516 = mkOR1( 2517 binop(Iop_CmpLT64U, res, argL), 2518 mkAND1( 2519 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2520 binop(Iop_CmpEQ64, res, argL) 2521 ) 2522 ); 2523 xer_ca 2524 = unop(Iop_1Uto32, xer_ca); 2525 break; 2526 2527 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2528 /* res <u argR || (old_ca==1 && res==argR) */ 2529 xer_ca 2530 = mkOR1( 2531 binop(Iop_CmpLT64U, res, argR), 2532 mkAND1( 2533 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2534 binop(Iop_CmpEQ64, res, argR) 2535 ) 2536 ); 2537 xer_ca 2538 = unop(Iop_1Uto32, xer_ca); 2539 break; 2540 2541 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2542 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2543 /* res <=u argR */ 2544 xer_ca 2545 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2546 break; 2547 2548 2549 case /* 10 */ PPCG_FLAG_OP_SRAW: 2550 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2551 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2552 bit of argL. */ 2553 /* This term valid for shift amount < 31 only */ 2554 2555 xer_ca 2556 = binop( 2557 Iop_And64, 2558 binop(Iop_Sar64, argL, mkU8(31)), 2559 binop( Iop_And64, 2560 argL, 2561 binop( Iop_Sub64, 2562 binop(Iop_Shl64, mkU64(1), 2563 unop(Iop_64to8,argR)), 2564 mkU64(1) ) 2565 ) 2566 ); 2567 xer_ca 2568 = IRExpr_ITE( 2569 /* shift amt > 31 ? */ 2570 binop(Iop_CmpLT64U, mkU64(31), argR), 2571 /* yes -- get sign bit of argL */ 2572 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2573 /* no -- be like srawi */ 2574 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2575 ); 2576 break; 2577 2578 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2579 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2580 Since the shift amount is known to be in the range 0 .. 31 2581 inclusive the following seems viable: 2582 xer.ca == 1 iff the following is nonzero: 2583 (argL >>s 31) -- either all 0s or all 1s 2584 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2585 2586 xer_ca 2587 = binop( 2588 Iop_And64, 2589 binop(Iop_Sar64, argL, mkU8(31)), 2590 binop( Iop_And64, 2591 argL, 2592 binop( Iop_Sub64, 2593 binop(Iop_Shl64, mkU64(1), 2594 unop(Iop_64to8,argR)), 2595 mkU64(1) ) 2596 ) 2597 ); 2598 xer_ca 2599 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2600 break; 2601 2602 2603 case /* 12 */ PPCG_FLAG_OP_SRAD: 2604 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2605 If it is <= 63, behave like SRADI; else XER.CA is the sign 2606 bit of argL. */ 2607 /* This term valid for shift amount < 63 only */ 2608 2609 xer_ca 2610 = binop( 2611 Iop_And64, 2612 binop(Iop_Sar64, argL, mkU8(63)), 2613 binop( Iop_And64, 2614 argL, 2615 binop( Iop_Sub64, 2616 binop(Iop_Shl64, mkU64(1), 2617 unop(Iop_64to8,argR)), 2618 mkU64(1) ) 2619 ) 2620 ); 2621 xer_ca 2622 = IRExpr_ITE( 2623 /* shift amt > 63 ? */ 2624 binop(Iop_CmpLT64U, mkU64(63), argR), 2625 /* yes -- get sign bit of argL */ 2626 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2627 /* no -- be like sradi */ 2628 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2629 ); 2630 break; 2631 2632 2633 case /* 13 */ PPCG_FLAG_OP_SRADI: 2634 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2635 Since the shift amount is known to be in the range 0 .. 63 2636 inclusive, the following seems viable: 2637 xer.ca == 1 iff the following is nonzero: 2638 (argL >>s 63) -- either all 0s or all 1s 2639 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2640 2641 xer_ca 2642 = binop( 2643 Iop_And64, 2644 binop(Iop_Sar64, argL, mkU8(63)), 2645 binop( Iop_And64, 2646 argL, 2647 binop( Iop_Sub64, 2648 binop(Iop_Shl64, mkU64(1), 2649 unop(Iop_64to8,argR)), 2650 mkU64(1) ) 2651 ) 2652 ); 2653 xer_ca 2654 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2655 break; 2656 2657 default: 2658 vex_printf("set_XER_CA: op = %u\n", op); 2659 vpanic("set_XER_CA(ppc64)"); 2660 } 2661 2662 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2663 putXER_CA( unop(Iop_32to8, xer_ca) ); 2664 } 2665 2666 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2667 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2668 { 2669 if (ty == Ity_I32) 2670 set_XER_CA_32( op, res, argL, argR, oldca ); 2671 else 2672 set_XER_CA_64( op, res, argL, argR, oldca ); 2673 } 2674 2675 2676 2677 /*------------------------------------------------------------*/ 2678 /*--- Read/write to guest-state --- */ 2679 /*------------------------------------------------------------*/ 2680 2681 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2682 { 2683 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2684 switch (reg) { 2685 case PPC_GST_SPRG3_RO: 2686 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2687 2688 case PPC_GST_CIA: 2689 return IRExpr_Get( OFFB_CIA, ty ); 2690 2691 case PPC_GST_LR: 2692 return IRExpr_Get( OFFB_LR, ty ); 2693 2694 case PPC_GST_CTR: 2695 return IRExpr_Get( OFFB_CTR, ty ); 2696 2697 case PPC_GST_VRSAVE: 2698 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2699 2700 case PPC_GST_VSCR: 2701 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2702 mkU32(MASK_VSCR_VALID)); 2703 2704 case PPC_GST_CR: { 2705 /* Synthesise the entire CR into a single word. Expensive. */ 2706 # define FIELD(_n) \ 2707 binop(Iop_Shl32, \ 2708 unop(Iop_8Uto32, \ 2709 binop(Iop_Or8, \ 2710 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2711 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2712 ) \ 2713 ), \ 2714 mkU8(4 * (7-(_n))) \ 2715 ) 2716 return binop(Iop_Or32, 2717 binop(Iop_Or32, 2718 binop(Iop_Or32, FIELD(0), FIELD(1)), 2719 binop(Iop_Or32, FIELD(2), FIELD(3)) 2720 ), 2721 binop(Iop_Or32, 2722 binop(Iop_Or32, FIELD(4), FIELD(5)), 2723 binop(Iop_Or32, FIELD(6), FIELD(7)) 2724 ) 2725 ); 2726 # undef FIELD 2727 } 2728 2729 case PPC_GST_XER: 2730 return binop(Iop_Or32, 2731 binop(Iop_Or32, 2732 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2733 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2734 binop(Iop_Or32, 2735 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2736 getXER_BC32())); 2737 2738 case PPC_GST_TFHAR: 2739 return IRExpr_Get( OFFB_TFHAR, ty ); 2740 2741 case PPC_GST_TEXASR: 2742 return IRExpr_Get( OFFB_TEXASR, ty ); 2743 2744 case PPC_GST_TEXASRU: 2745 return IRExpr_Get( OFFB_TEXASRU, ty ); 2746 2747 case PPC_GST_TFIAR: 2748 return IRExpr_Get( OFFB_TFIAR, ty ); 2749 2750 default: 2751 vex_printf("getGST(ppc): reg = %u", reg); 2752 vpanic("getGST(ppc)"); 2753 } 2754 } 2755 2756 /* Get a masked word from the given reg */ 2757 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2758 { 2759 IRTemp val = newTemp(Ity_I32); 2760 vassert( reg < PPC_GST_MAX ); 2761 2762 switch (reg) { 2763 2764 case PPC_GST_FPSCR: { 2765 /* Vex-generated code expects the FPSCR to be set as follows: 2766 all exceptions masked, round-to-nearest. 2767 This corresponds to a FPSCR value of 0x0. */ 2768 2769 /* In the lower 32 bits of FPSCR, we're only keeping track of 2770 * the binary floating point rounding mode, so if the mask isn't 2771 * asking for this, just return 0x0. 2772 */ 2773 if (mask & MASK_FPSCR_RN) { 2774 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2775 } else { 2776 assign( val, mkU32(0x0) ); 2777 } 2778 break; 2779 } 2780 2781 default: 2782 vex_printf("getGST_masked(ppc): reg = %u", reg); 2783 vpanic("getGST_masked(ppc)"); 2784 } 2785 2786 if (mask != 0xFFFFFFFF) { 2787 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2788 } else { 2789 return mkexpr(val); 2790 } 2791 } 2792 2793 /* Get a masked word from the given reg */ 2794 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2795 IRExpr * val; 2796 vassert( reg < PPC_GST_MAX ); 2797 2798 switch (reg) { 2799 2800 case PPC_GST_FPSCR: { 2801 /* In the upper 32 bits of FPSCR, we're only keeping track 2802 * of the decimal floating point rounding mode, so if the mask 2803 * isn't asking for this, just return 0x0. 2804 */ 2805 if (mask & MASK_FPSCR_DRN) { 2806 val = binop( Iop_And32, 2807 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2808 unop( Iop_64HIto32, mkU64( mask ) ) ); 2809 } else { 2810 val = mkU32( 0x0ULL ); 2811 } 2812 break; 2813 } 2814 2815 default: 2816 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2817 vpanic( "getGST_masked_upper(ppc)" ); 2818 } 2819 return val; 2820 } 2821 2822 2823 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2824 and return it at the bottom of an I32; the top 27 bits are 2825 guaranteed to be zero. */ 2826 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2827 { 2828 UInt shft, mask; 2829 2830 vassert( fld < 8 ); 2831 vassert( reg < PPC_GST_MAX ); 2832 2833 shft = 4*(7-fld); 2834 mask = 0xF<<shft; 2835 2836 switch (reg) { 2837 case PPC_GST_XER: 2838 vassert(fld ==7); 2839 return binop(Iop_Or32, 2840 binop(Iop_Or32, 2841 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2842 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2843 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2844 break; 2845 2846 default: 2847 if (shft == 0) 2848 return getGST_masked( reg, mask ); 2849 else 2850 return binop(Iop_Shr32, 2851 getGST_masked( reg, mask ), 2852 mkU8(toUChar( shft ))); 2853 } 2854 } 2855 2856 static void putGST ( PPC_GST reg, IRExpr* src ) 2857 { 2858 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2859 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2860 vassert( reg < PPC_GST_MAX ); 2861 switch (reg) { 2862 case PPC_GST_IP_AT_SYSCALL: 2863 vassert( ty_src == ty ); 2864 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2865 break; 2866 case PPC_GST_CIA: 2867 vassert( ty_src == ty ); 2868 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2869 break; 2870 case PPC_GST_LR: 2871 vassert( ty_src == ty ); 2872 stmt( IRStmt_Put( OFFB_LR, src ) ); 2873 break; 2874 case PPC_GST_CTR: 2875 vassert( ty_src == ty ); 2876 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2877 break; 2878 case PPC_GST_VRSAVE: 2879 vassert( ty_src == Ity_I32 ); 2880 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2881 break; 2882 case PPC_GST_VSCR: 2883 vassert( ty_src == Ity_I32 ); 2884 stmt( IRStmt_Put( OFFB_VSCR, 2885 binop(Iop_And32, src, 2886 mkU32(MASK_VSCR_VALID)) ) ); 2887 break; 2888 case PPC_GST_XER: 2889 vassert( ty_src == Ity_I32 ); 2890 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2891 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2892 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2893 putXER_BC( unop(Iop_32to8, src) ); 2894 break; 2895 2896 case PPC_GST_EMWARN: 2897 vassert( ty_src == Ity_I32 ); 2898 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 2899 break; 2900 2901 case PPC_GST_CMSTART: 2902 vassert( ty_src == ty ); 2903 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 2904 break; 2905 2906 case PPC_GST_CMLEN: 2907 vassert( ty_src == ty ); 2908 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 2909 break; 2910 2911 case PPC_GST_TEXASR: 2912 vassert( ty_src == Ity_I64 ); 2913 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 2914 break; 2915 2916 case PPC_GST_TEXASRU: 2917 vassert( ty_src == Ity_I32 ); 2918 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 2919 break; 2920 2921 case PPC_GST_TFIAR: 2922 vassert( ty_src == Ity_I64 ); 2923 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 2924 break; 2925 case PPC_GST_TFHAR: 2926 vassert( ty_src == Ity_I64 ); 2927 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 2928 break; 2929 default: 2930 vex_printf("putGST(ppc): reg = %u", reg); 2931 vpanic("putGST(ppc)"); 2932 } 2933 } 2934 2935 /* Write masked src to the given reg */ 2936 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 2937 { 2938 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2939 vassert( reg < PPC_GST_MAX ); 2940 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 2941 2942 switch (reg) { 2943 case PPC_GST_FPSCR: { 2944 /* Allow writes to either binary or decimal floating point 2945 Rounding Mode. 2946 */ 2947 /* If any part of |mask| covers FPSCR.RN, update the bits of 2948 FPSCR.RN by copying in |src| for locations where the 2949 corresponding bit in |mask| is 1, and leaving it unchanged 2950 for corresponding |mask| zero bits. */ 2951 if (mask & MASK_FPSCR_RN) { 2952 stmt( 2953 IRStmt_Put( 2954 OFFB_FPROUND, 2955 unop( 2956 Iop_32to8, 2957 binop( 2958 Iop_Or32, 2959 binop( 2960 Iop_And32, 2961 unop(Iop_64to32, src), 2962 mkU32(MASK_FPSCR_RN & mask) 2963 ), 2964 binop( 2965 Iop_And32, 2966 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 2967 mkU32(MASK_FPSCR_RN & ~mask) 2968 ) 2969 ) 2970 ) 2971 ) 2972 ); 2973 } 2974 /* Similarly, update FPSCR.DRN if any bits of |mask| 2975 corresponding to FPSCR.DRN are set. */ 2976 if (mask & MASK_FPSCR_DRN) { 2977 stmt( 2978 IRStmt_Put( 2979 OFFB_DFPROUND, 2980 unop( 2981 Iop_32to8, 2982 binop( 2983 Iop_Or32, 2984 binop( 2985 Iop_And32, 2986 unop(Iop_64HIto32, src), 2987 mkU32((MASK_FPSCR_DRN & mask) >> 32) 2988 ), 2989 binop( 2990 Iop_And32, 2991 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 2992 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 2993 ) 2994 ) 2995 ) 2996 ) 2997 ); 2998 } 2999 3000 /* Give EmNote for attempted writes to: 3001 - Exception Controls 3002 - Non-IEEE Mode 3003 */ 3004 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3005 VexEmNote ew = EmWarn_PPCexns; 3006 3007 /* If any of the src::exception_control bits are actually set, 3008 side-exit to the next insn, reporting the warning, 3009 so that Valgrind's dispatcher sees the warning. */ 3010 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3011 stmt( 3012 IRStmt_Exit( 3013 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3014 Ijk_EmWarn, 3015 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3016 } 3017 3018 /* Ignore all other writes */ 3019 break; 3020 } 3021 3022 default: 3023 vex_printf("putGST_masked(ppc): reg = %u", reg); 3024 vpanic("putGST_masked(ppc)"); 3025 } 3026 } 3027 3028 /* Write the least significant nibble of src to the specified 3029 REG[FLD] (as per IBM/hardware notation). */ 3030 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3031 { 3032 UInt shft; 3033 ULong mask; 3034 3035 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3036 vassert( fld < 16 ); 3037 vassert( reg < PPC_GST_MAX ); 3038 3039 if (fld < 8) 3040 shft = 4*(7-fld); 3041 else 3042 shft = 4*(15-fld); 3043 mask = 0xF; 3044 mask = mask << shft; 3045 3046 switch (reg) { 3047 case PPC_GST_CR: 3048 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3049 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3050 break; 3051 3052 default: 3053 { 3054 IRExpr * src64 = unop( Iop_32Uto64, src ); 3055 3056 if (shft == 0) { 3057 putGST_masked( reg, src64, mask ); 3058 } else { 3059 putGST_masked( reg, 3060 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3061 mask ); 3062 } 3063 } 3064 } 3065 } 3066 3067 /*------------------------------------------------------------*/ 3068 /* Helpers for VSX instructions that do floating point 3069 * operations and need to determine if a src contains a 3070 * special FP value. 3071 * 3072 *------------------------------------------------------------*/ 3073 3074 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3075 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3076 mkexpr( x ), \ 3077 mkU64( NONZERO_FRAC_MASK ) ) 3078 3079 // Returns exponent part of a single precision floating point as I32 3080 static IRExpr * fp_exp_part_sp(IRTemp src) 3081 { 3082 return binop( Iop_And32, 3083 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3084 mkU32( 0xff ) ); 3085 } 3086 3087 // Returns exponent part of floating point as I32 3088 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 3089 { 3090 IRExpr * exp; 3091 if (sp) 3092 return fp_exp_part_sp(src); 3093 3094 if (!mode64) 3095 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 3096 mkexpr( src ) ), 3097 mkU8( 20 ) ), mkU32( 0x7ff ) ); 3098 else 3099 exp = unop( Iop_64to32, 3100 binop( Iop_And64, 3101 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 3102 mkU64( 0x7ff ) ) ); 3103 return exp; 3104 } 3105 3106 static IRExpr * is_Inf_sp(IRTemp src) 3107 { 3108 IRTemp frac_part = newTemp(Ity_I32); 3109 IRExpr * Inf_exp; 3110 3111 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 3112 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 3113 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 3114 } 3115 3116 3117 // Infinity: exp = 7ff and fraction is zero; s = 0/1 3118 static IRExpr * is_Inf(IRTemp src, Bool sp) 3119 { 3120 IRExpr * Inf_exp, * hi32, * low32; 3121 IRTemp frac_part; 3122 3123 if (sp) 3124 return is_Inf_sp(src); 3125 3126 frac_part = newTemp(Ity_I64); 3127 assign( frac_part, FP_FRAC_PART(src) ); 3128 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 3129 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3130 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3131 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3132 mkU32( 0 ) ) ); 3133 } 3134 3135 static IRExpr * is_Zero_sp(IRTemp src) 3136 { 3137 IRTemp sign_less_part = newTemp(Ity_I32); 3138 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 3139 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 3140 } 3141 3142 // Zero: exp is zero and fraction is zero; s = 0/1 3143 static IRExpr * is_Zero(IRTemp src, Bool sp) 3144 { 3145 IRExpr * hi32, * low32; 3146 IRTemp sign_less_part; 3147 if (sp) 3148 return is_Zero_sp(src); 3149 3150 sign_less_part = newTemp(Ity_I64); 3151 3152 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 3153 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 3154 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 3155 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3156 mkU32( 0 ) ); 3157 } 3158 3159 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 3160 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 3161 * This function returns an IRExpr value of '1' for any type of NaN. 3162 */ 3163 static IRExpr * is_NaN(IRTemp src) 3164 { 3165 IRExpr * NaN_exp, * hi32, * low32; 3166 IRTemp frac_part = newTemp(Ity_I64); 3167 3168 assign( frac_part, FP_FRAC_PART(src) ); 3169 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3170 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3171 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 3172 mkU32( 0x7ff ) ); 3173 3174 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 3175 mkU32( 0 ) ) ); 3176 } 3177 3178 /* This function returns an IRExpr value of '1' for any type of NaN. 3179 * The passed 'src' argument is assumed to be Ity_I32. 3180 */ 3181 static IRExpr * is_NaN_32(IRTemp src) 3182 { 3183 #define NONZERO_FRAC_MASK32 0x007fffffULL 3184 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3185 mkexpr( x ), \ 3186 mkU32( NONZERO_FRAC_MASK32 ) ) 3187 3188 IRExpr * frac_part = FP_FRAC_PART32(src); 3189 IRExpr * exp_part = binop( Iop_And32, 3190 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3191 mkU32( 0x0ff ) ); 3192 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 3193 3194 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 3195 } 3196 3197 /* This function takes an Ity_I32 input argument interpreted 3198 * as a single-precision floating point value. If src is a 3199 * SNaN, it is changed to a QNaN and returned; otherwise, 3200 * the original value is returned. 3201 */ 3202 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 3203 { 3204 #define SNAN_MASK32 0x00400000 3205 IRTemp tmp = newTemp(Ity_I32); 3206 IRTemp mask = newTemp(Ity_I32); 3207 IRTemp is_SNAN = newTemp(Ity_I1); 3208 3209 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 3210 assign(tmp, src); 3211 3212 /* check if input is SNaN, if it is convert to QNaN */ 3213 assign( is_SNAN, 3214 mkAND1( is_NaN_32( tmp ), 3215 binop( Iop_CmpEQ32, 3216 binop( Iop_And32, mkexpr( tmp ), 3217 mkU32( SNAN_MASK32 ) ), 3218 mkU32( 0 ) ) ) ); 3219 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 3220 assign ( mask, binop( Iop_And32, 3221 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 3222 mkU32( SNAN_MASK32 ) ) ); 3223 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 3224 } 3225 3226 3227 /* This helper function performs the negation part of operations of the form: 3228 * "Negate Multiply-<op>" 3229 * where "<op>" is either "Add" or "Sub". 3230 * 3231 * This function takes one argument -- the floating point intermediate result (converted to 3232 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 3233 * the operation described above. 3234 */ 3235 static IRTemp getNegatedResult(IRTemp intermediateResult) 3236 { 3237 ULong signbit_mask = 0x8000000000000000ULL; 3238 IRTemp signbit_32 = newTemp(Ity_I32); 3239 IRTemp resultantSignbit = newTemp(Ity_I1); 3240 IRTemp negatedResult = newTemp(Ity_I64); 3241 assign( signbit_32, binop( Iop_Shr32, 3242 unop( Iop_64HIto32, 3243 binop( Iop_And64, mkexpr( intermediateResult ), 3244 mkU64( signbit_mask ) ) ), 3245 mkU8( 31 ) ) ); 3246 /* We negate the signbit if and only if the intermediate result from the 3247 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3248 */ 3249 assign( resultantSignbit, 3250 unop( Iop_Not1, 3251 binop( Iop_CmpEQ32, 3252 binop( Iop_Xor32, 3253 mkexpr( signbit_32 ), 3254 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 3255 mkU32( 1 ) ) ) ); 3256 3257 assign( negatedResult, 3258 binop( Iop_Or64, 3259 binop( Iop_And64, 3260 mkexpr( intermediateResult ), 3261 mkU64( ~signbit_mask ) ), 3262 binop( Iop_32HLto64, 3263 binop( Iop_Shl32, 3264 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3265 mkU8( 31 ) ), 3266 mkU32( 0 ) ) ) ); 3267 3268 return negatedResult; 3269 } 3270 3271 /* This helper function performs the negation part of operations of the form: 3272 * "Negate Multiply-<op>" 3273 * where "<op>" is either "Add" or "Sub". 3274 * 3275 * This function takes one argument -- the floating point intermediate result (converted to 3276 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 3277 * the operation described above. 3278 */ 3279 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 3280 { 3281 UInt signbit_mask = 0x80000000; 3282 IRTemp signbit_32 = newTemp(Ity_I32); 3283 IRTemp resultantSignbit = newTemp(Ity_I1); 3284 IRTemp negatedResult = newTemp(Ity_I32); 3285 assign( signbit_32, binop( Iop_Shr32, 3286 binop( Iop_And32, mkexpr( intermediateResult ), 3287 mkU32( signbit_mask ) ), 3288 mkU8( 31 ) ) ); 3289 /* We negate the signbit if and only if the intermediate result from the 3290 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3291 */ 3292 assign( resultantSignbit, 3293 unop( Iop_Not1, 3294 binop( Iop_CmpEQ32, 3295 binop( Iop_Xor32, 3296 mkexpr( signbit_32 ), 3297 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 3298 mkU32( 1 ) ) ) ); 3299 3300 assign( negatedResult, 3301 binop( Iop_Or32, 3302 binop( Iop_And32, 3303 mkexpr( intermediateResult ), 3304 mkU32( ~signbit_mask ) ), 3305 binop( Iop_Shl32, 3306 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3307 mkU8( 31 ) ) ) ); 3308 3309 return negatedResult; 3310 } 3311 3312 /*------------------------------------------------------------*/ 3313 /* Transactional memory helpers 3314 * 3315 *------------------------------------------------------------*/ 3316 3317 static ULong generate_TMreason( UInt failure_code, 3318 UInt persistant, 3319 UInt nest_overflow, 3320 UInt tm_exact ) 3321 { 3322 ULong tm_err_code = 3323 ( (ULong) 0) << (63-6) /* Failure code */ 3324 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 3325 | ( (ULong) 0) << (63-8) /* Disallowed */ 3326 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 3327 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 3328 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 3329 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 3330 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 3331 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 3332 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 3333 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 3334 | ( (ULong) 0) << (63-30) /* Reserved */ 3335 | ( (ULong) 0) << (63-31) /* Abort */ 3336 | ( (ULong) 0) << (63-32) /* Suspend */ 3337 | ( (ULong) 0) << (63-33) /* Reserved */ 3338 | ( (ULong) 0) << (63-35) /* Privilege */ 3339 | ( (ULong) 0) << (63-36) /* Failure Summary */ 3340 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 3341 | ( (ULong) 0) << (63-38) /* ROT */ 3342 | ( (ULong) 0) << (63-51) /* Reserved */ 3343 | ( (ULong) 0) << (63-63); /* Transaction Level */ 3344 3345 return tm_err_code; 3346 } 3347 3348 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 3349 Addr64 handler_address ) 3350 { 3351 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 3352 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 3353 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 3354 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 3355 } 3356 3357 /*------------------------------------------------------------*/ 3358 /*--- Integer Instruction Translation --- */ 3359 /*------------------------------------------------------------*/ 3360 3361 /* 3362 Integer Arithmetic Instructions 3363 */ 3364 static Bool dis_int_arith ( UInt theInstr ) 3365 { 3366 /* D-Form, XO-Form */ 3367 UChar opc1 = ifieldOPC(theInstr); 3368 UChar rD_addr = ifieldRegDS(theInstr); 3369 UChar rA_addr = ifieldRegA(theInstr); 3370 UInt uimm16 = ifieldUIMM16(theInstr); 3371 UChar rB_addr = ifieldRegB(theInstr); 3372 UChar flag_OE = ifieldBIT10(theInstr); 3373 UInt opc2 = ifieldOPClo9(theInstr); 3374 UChar flag_rC = ifieldBIT0(theInstr); 3375 3376 Long simm16 = extend_s_16to64(uimm16); 3377 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3378 IRTemp rA = newTemp(ty); 3379 IRTemp rB = newTemp(ty); 3380 IRTemp rD = newTemp(ty); 3381 3382 Bool do_rc = False; 3383 3384 assign( rA, getIReg(rA_addr) ); 3385 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3386 3387 switch (opc1) { 3388 /* D-Form */ 3389 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3390 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3391 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3392 mkSzExtendS16(ty, uimm16) ) ); 3393 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3394 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3395 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3396 break; 3397 3398 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3399 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3400 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3401 mkSzExtendS16(ty, uimm16) ) ); 3402 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3403 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3404 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3405 do_rc = True; // Always record to CR 3406 flag_rC = 1; 3407 break; 3408 3409 case 0x0E: // addi (Add Immediate, PPC32 p350) 3410 // li rD,val == addi rD,0,val 3411 // la disp(rA) == addi rD,rA,disp 3412 if ( rA_addr == 0 ) { 3413 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3414 assign( rD, mkSzExtendS16(ty, uimm16) ); 3415 } else { 3416 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3417 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3418 mkSzExtendS16(ty, uimm16) ) ); 3419 } 3420 break; 3421 3422 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3423 // lis rD,val == addis rD,0,val 3424 if ( rA_addr == 0 ) { 3425 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3426 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3427 } else { 3428 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 3429 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3430 mkSzExtendS32(ty, uimm16 << 16) ) ); 3431 } 3432 break; 3433 3434 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3435 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3436 if (mode64) 3437 assign( rD, unop(Iop_128to64, 3438 binop(Iop_MullS64, mkexpr(rA), 3439 mkSzExtendS16(ty, uimm16))) ); 3440 else 3441 assign( rD, unop(Iop_64to32, 3442 binop(Iop_MullS32, mkexpr(rA), 3443 mkSzExtendS16(ty, uimm16))) ); 3444 break; 3445 3446 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3447 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3448 // rD = simm16 - rA 3449 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3450 mkSzExtendS16(ty, uimm16), 3451 mkexpr(rA)) ); 3452 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3453 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3454 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3455 break; 3456 3457 /* XO-Form */ 3458 case 0x1F: 3459 do_rc = True; // All below record to CR 3460 3461 switch (opc2) { 3462 case 0x10A: // add (Add, PPC32 p347) 3463 DIP("add%s%s r%u,r%u,r%u\n", 3464 flag_OE ? "o" : "", flag_rC ? ".":"", 3465 rD_addr, rA_addr, rB_addr); 3466 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3467 mkexpr(rA), mkexpr(rB) ) ); 3468 if (flag_OE) { 3469 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3470 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3471 } 3472 break; 3473 3474 case 0x00A: // addc (Add Carrying, PPC32 p348) 3475 DIP("addc%s%s r%u,r%u,r%u\n", 3476 flag_OE ? "o" : "", flag_rC ? ".":"", 3477 rD_addr, rA_addr, rB_addr); 3478 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3479 mkexpr(rA), mkexpr(rB)) ); 3480 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3481 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3482 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3483 if (flag_OE) { 3484 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3485 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3486 } 3487 break; 3488 3489 case 0x08A: { // adde (Add Extended, PPC32 p349) 3490 IRTemp old_xer_ca = newTemp(ty); 3491 DIP("adde%s%s r%u,r%u,r%u\n", 3492 flag_OE ? "o" : "", flag_rC ? ".":"", 3493 rD_addr, rA_addr, rB_addr); 3494 // rD = rA + rB + XER[CA] 3495 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3496 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3497 binop( mkSzOp(ty, Iop_Add8), 3498 mkexpr(rB), mkexpr(old_xer_ca))) ); 3499 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3500 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3501 mkexpr(old_xer_ca) ); 3502 if (flag_OE) { 3503 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3504 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3505 } 3506 break; 3507 } 3508 3509 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3510 IRTemp old_xer_ca = newTemp(ty); 3511 IRExpr *min_one; 3512 if (rB_addr != 0) { 3513 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3514 return False; 3515 } 3516 DIP("addme%s%s r%u,r%u,r%u\n", 3517 flag_OE ? "o" : "", flag_rC ? ".":"", 3518 rD_addr, rA_addr, rB_addr); 3519 // rD = rA + (-1) + XER[CA] 3520 // => Just another form of adde 3521 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3522 min_one = mkSzImm(ty, (Long)-1); 3523 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3524 binop( mkSzOp(ty, Iop_Add8), 3525 min_one, mkexpr(old_xer_ca)) )); 3526 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3527 mkexpr(rD), mkexpr(rA), min_one, 3528 mkexpr(old_xer_ca) ); 3529 if (flag_OE) { 3530 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3531 mkexpr(rD), mkexpr(rA), min_one ); 3532 } 3533 break; 3534 } 3535 3536 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3537 IRTemp old_xer_ca = newTemp(ty); 3538 if (rB_addr != 0) { 3539 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3540 return False; 3541 } 3542 DIP("addze%s%s r%u,r%u,r%u\n", 3543 flag_OE ? "o" : "", flag_rC ? ".":"", 3544 rD_addr, rA_addr, rB_addr); 3545 // rD = rA + (0) + XER[CA] 3546 // => Just another form of adde 3547 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3548 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3549 mkexpr(rA), mkexpr(old_xer_ca)) ); 3550 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3551 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3552 mkexpr(old_xer_ca) ); 3553 if (flag_OE) { 3554 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3555 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3556 } 3557 break; 3558 } 3559 3560 case 0x1EB: // divw (Divide Word, PPC32 p388) 3561 DIP("divw%s%s r%u,r%u,r%u\n", 3562 flag_OE ? "o" : "", flag_rC ? ".":"", 3563 rD_addr, rA_addr, rB_addr); 3564 if (mode64) { 3565 /* Note: 3566 XER settings are mode independent, and reflect the 3567 overflow of the low-order 32bit result 3568 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3569 */ 3570 /* rD[hi32] are undefined: setting them to sign of lo32 3571 - makes set_CR0 happy */ 3572 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3573 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3574 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3575 divisor) ) ); 3576 if (flag_OE) { 3577 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3578 mkexpr(rD), dividend, divisor ); 3579 } 3580 } else { 3581 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3582 if (flag_OE) { 3583 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3584 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3585 } 3586 } 3587 /* Note: 3588 if (0x8000_0000 / -1) or (x / 0) 3589 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3590 => But _no_ exception raised. */ 3591 break; 3592 3593 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3594 DIP("divwu%s%s r%u,r%u,r%u\n", 3595 flag_OE ? "o" : "", flag_rC ? ".":"", 3596 rD_addr, rA_addr, rB_addr); 3597 if (mode64) { 3598 /* Note: 3599 XER settings are mode independent, and reflect the 3600 overflow of the low-order 32bit result 3601 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3602 */ 3603 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3604 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3605 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3606 divisor) ) ); 3607 if (flag_OE) { 3608 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3609 mkexpr(rD), dividend, divisor ); 3610 } 3611 } else { 3612 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3613 if (flag_OE) { 3614 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3615 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3616 } 3617 } 3618 /* Note: ditto comment divw, for (x / 0) */ 3619 break; 3620 3621 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3622 if (flag_OE != 0) { 3623 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3624 return False; 3625 } 3626 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3627 rD_addr, rA_addr, rB_addr); 3628 if (mode64) { 3629 /* rD[hi32] are undefined: setting them to sign of lo32 3630 - makes set_CR0 happy */ 3631 assign( rD, binop(Iop_Sar64, 3632 binop(Iop_Mul64, 3633 mk64lo32Sto64( mkexpr(rA) ), 3634 mk64lo32Sto64( mkexpr(rB) )), 3635 mkU8(32)) ); 3636 } else { 3637 assign( rD, unop(Iop_64HIto32, 3638 binop(Iop_MullS32, 3639 mkexpr(rA), mkexpr(rB))) ); 3640 } 3641 break; 3642 3643 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3644 if (flag_OE != 0) { 3645 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3646 return False; 3647 } 3648 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3649 rD_addr, rA_addr, rB_addr); 3650 if (mode64) { 3651 /* rD[hi32] are undefined: setting them to sign of lo32 3652 - makes set_CR0 happy */ 3653 assign( rD, binop(Iop_Sar64, 3654 binop(Iop_Mul64, 3655 mk64lo32Uto64( mkexpr(rA) ), 3656 mk64lo32Uto64( mkexpr(rB) ) ), 3657 mkU8(32)) ); 3658 } else { 3659 assign( rD, unop(Iop_64HIto32, 3660 binop(Iop_MullU32, 3661 mkexpr(rA), mkexpr(rB))) ); 3662 } 3663 break; 3664 3665 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3666 DIP("mullw%s%s r%u,r%u,r%u\n", 3667 flag_OE ? "o" : "", flag_rC ? ".":"", 3668 rD_addr, rA_addr, rB_addr); 3669 if (mode64) { 3670 /* rD[hi32] are undefined: setting them to sign of lo32 3671 - set_XER_OV() and set_CR0() depend on this */ 3672 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3673 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3674 assign( rD, binop(Iop_MullS32, a, b) ); 3675 if (flag_OE) { 3676 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3677 mkexpr(rD), 3678 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3679 } 3680 } else { 3681 assign( rD, unop(Iop_64to32, 3682 binop(Iop_MullU32, 3683 mkexpr(rA), mkexpr(rB))) ); 3684 if (flag_OE) { 3685 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3686 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3687 } 3688 } 3689 break; 3690 3691 case 0x068: // neg (Negate, PPC32 p493) 3692 if (rB_addr != 0) { 3693 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3694 return False; 3695 } 3696 DIP("neg%s%s r%u,r%u\n", 3697 flag_OE ? "o" : "", flag_rC ? ".":"", 3698 rD_addr, rA_addr); 3699 // rD = (~rA) + 1 3700 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3701 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3702 mkSzImm(ty, 1)) ); 3703 if (flag_OE) { 3704 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3705 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3706 } 3707 break; 3708 3709 case 0x028: // subf (Subtract From, PPC32 p537) 3710 DIP("subf%s%s r%u,r%u,r%u\n", 3711 flag_OE ? "o" : "", flag_rC ? ".":"", 3712 rD_addr, rA_addr, rB_addr); 3713 // rD = rB - rA 3714 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3715 mkexpr(rB), mkexpr(rA)) ); 3716 if (flag_OE) { 3717 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3718 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3719 } 3720 break; 3721 3722 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3723 DIP("subfc%s%s r%u,r%u,r%u\n", 3724 flag_OE ? "o" : "", flag_rC ? ".":"", 3725 rD_addr, rA_addr, rB_addr); 3726 // rD = rB - rA 3727 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3728 mkexpr(rB), mkexpr(rA)) ); 3729 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3730 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3731 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3732 if (flag_OE) { 3733 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3734 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3735 } 3736 break; 3737 3738 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3739 IRTemp old_xer_ca = newTemp(ty); 3740 DIP("subfe%s%s r%u,r%u,r%u\n", 3741 flag_OE ? "o" : "", flag_rC ? ".":"", 3742 rD_addr, rA_addr, rB_addr); 3743 // rD = (log not)rA + rB + XER[CA] 3744 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3745 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3746 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3747 binop( mkSzOp(ty, Iop_Add8), 3748 mkexpr(rB), mkexpr(old_xer_ca))) ); 3749 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3750 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3751 mkexpr(old_xer_ca) ); 3752 if (flag_OE) { 3753 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3754 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3755 } 3756 break; 3757 } 3758 3759 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3760 IRTemp old_xer_ca = newTemp(ty); 3761 IRExpr *min_one; 3762 if (rB_addr != 0) { 3763 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3764 return False; 3765 } 3766 DIP("subfme%s%s r%u,r%u\n", 3767 flag_OE ? "o" : "", flag_rC ? ".":"", 3768 rD_addr, rA_addr); 3769 // rD = (log not)rA + (-1) + XER[CA] 3770 // => Just another form of subfe 3771 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3772 min_one = mkSzImm(ty, (Long)-1); 3773 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3774 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3775 binop( mkSzOp(ty, Iop_Add8), 3776 min_one, mkexpr(old_xer_ca))) ); 3777 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3778 mkexpr(rD), mkexpr(rA), min_one, 3779 mkexpr(old_xer_ca) ); 3780 if (flag_OE) { 3781 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3782 mkexpr(rD), mkexpr(rA), min_one ); 3783 } 3784 break; 3785 } 3786 3787 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3788 IRTemp old_xer_ca = newTemp(ty); 3789 if (rB_addr != 0) { 3790 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3791 return False; 3792 } 3793 DIP("subfze%s%s r%u,r%u\n", 3794 flag_OE ? "o" : "", flag_rC ? ".":"", 3795 rD_addr, rA_addr); 3796 // rD = (log not)rA + (0) + XER[CA] 3797 // => Just another form of subfe 3798 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3799 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3800 unop( mkSzOp(ty, Iop_Not8), 3801 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3802 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3803 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3804 mkexpr(old_xer_ca) ); 3805 if (flag_OE) { 3806 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3807 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3808 } 3809 break; 3810 } 3811 3812 3813 /* 64bit Arithmetic */ 3814 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3815 if (flag_OE != 0) { 3816 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3817 return False; 3818 } 3819 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3820 rD_addr, rA_addr, rB_addr); 3821 assign( rD, unop(Iop_128HIto64, 3822 binop(Iop_MullS64, 3823 mkexpr(rA), mkexpr(rB))) ); 3824 3825 break; 3826 3827 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3828 if (flag_OE != 0) { 3829 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3830 return False; 3831 } 3832 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3833 rD_addr, rA_addr, rB_addr); 3834 assign( rD, unop(Iop_128HIto64, 3835 binop(Iop_MullU64, 3836 mkexpr(rA), mkexpr(rB))) ); 3837 break; 3838 3839 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3840 DIP("mulld%s%s r%u,r%u,r%u\n", 3841 flag_OE ? "o" : "", flag_rC ? ".":"", 3842 rD_addr, rA_addr, rB_addr); 3843 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3844 if (flag_OE) { 3845 set_XER_OV( ty, PPCG_FLAG_OP_MULLD, 3846 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3847 } 3848 break; 3849 3850 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3851 DIP("divd%s%s r%u,r%u,r%u\n", 3852 flag_OE ? "o" : "", flag_rC ? ".":"", 3853 rD_addr, rA_addr, rB_addr); 3854 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3855 if (flag_OE) { 3856 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3857 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3858 } 3859 break; 3860 /* Note: 3861 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3862 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3863 => But _no_ exception raised. */ 3864 3865 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3866 DIP("divdu%s%s r%u,r%u,r%u\n", 3867 flag_OE ? "o" : "", flag_rC ? ".":"", 3868 rD_addr, rA_addr, rB_addr); 3869 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3870 if (flag_OE) { 3871 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3872 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3873 } 3874 break; 3875 /* Note: ditto comment divd, for (x / 0) */ 3876 3877 case 0x18B: // divweu (Divide Word Extended Unsigned) 3878 { 3879 /* 3880 * If (RA) >= (RB), or if an attempt is made to perform the division 3881 * <anything> / 0 3882 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3883 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3884 * to 1. 3885 */ 3886 IRTemp res = newTemp(Ity_I32); 3887 IRExpr * dividend, * divisor; 3888 DIP("divweu%s%s r%u,r%u,r%u\n", 3889 flag_OE ? "o" : "", flag_rC ? ".":"", 3890 rD_addr, rA_addr, rB_addr); 3891 if (mode64) { 3892 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3893 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3894 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3895 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3896 } else { 3897 dividend = mkexpr( rA ); 3898 divisor = mkexpr( rB ); 3899 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3900 assign( rD, mkexpr( res) ); 3901 } 3902 3903 if (flag_OE) { 3904 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 3905 mkexpr(res), dividend, divisor ); 3906 } 3907 break; 3908 } 3909 3910 case 0x1AB: // divwe (Divide Word Extended) 3911 { 3912 /* 3913 * If the quotient cannot be represented in 32 bits, or if an 3914 * attempt is made to perform the division 3915 * <anything> / 0 3916 * then the contents of register RD are undefined as are (if 3917 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3918 * Field 0. In these cases, if OE=1 then OV is set to 1. 3919 */ 3920 3921 IRTemp res = newTemp(Ity_I32); 3922 IRExpr * dividend, * divisor; 3923 DIP("divwe%s%s r%u,r%u,r%u\n", 3924 flag_OE ? "o" : "", flag_rC ? ".":"", 3925 rD_addr, rA_addr, rB_addr); 3926 if (mode64) { 3927 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3928 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3929 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3930 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3931 } else { 3932 dividend = mkexpr( rA ); 3933 divisor = mkexpr( rB ); 3934 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3935 assign( rD, mkexpr( res) ); 3936 } 3937 3938 if (flag_OE) { 3939 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 3940 mkexpr(res), dividend, divisor ); 3941 } 3942 break; 3943 } 3944 3945 3946 case 0x1A9: // divde (Divide Doubleword Extended) 3947 /* 3948 * If the quotient cannot be represented in 64 bits, or if an 3949 * attempt is made to perform the division 3950 * <anything> / 0 3951 * then the contents of register RD are undefined as are (if 3952 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3953 * Field 0. In these cases, if OE=1 then OV is set to 1. 3954 */ 3955 DIP("divde%s%s r%u,r%u,r%u\n", 3956 flag_OE ? "o" : "", flag_rC ? ".":"", 3957 rD_addr, rA_addr, rB_addr); 3958 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 3959 if (flag_OE) { 3960 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 3961 mkexpr( rA ), mkexpr( rB ) ); 3962 } 3963 break; 3964 3965 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 3966 // Same CR and OV rules as given for divweu above 3967 DIP("divdeu%s%s r%u,r%u,r%u\n", 3968 flag_OE ? "o" : "", flag_rC ? ".":"", 3969 rD_addr, rA_addr, rB_addr); 3970 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 3971 if (flag_OE) { 3972 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 3973 mkexpr( rA ), mkexpr( rB ) ); 3974 } 3975 break; 3976 3977 default: 3978 vex_printf("dis_int_arith(ppc)(opc2)\n"); 3979 return False; 3980 } 3981 break; 3982 3983 default: 3984 vex_printf("dis_int_arith(ppc)(opc1)\n"); 3985 return False; 3986 } 3987 3988 putIReg( rD_addr, mkexpr(rD) ); 3989 3990 if (do_rc && flag_rC) { 3991 set_CR0( mkexpr(rD) ); 3992 } 3993 return True; 3994 } 3995 3996 3997 3998 /* 3999 Integer Compare Instructions 4000 */ 4001 static Bool dis_int_cmp ( UInt theInstr ) 4002 { 4003 /* D-Form, X-Form */ 4004 UChar opc1 = ifieldOPC(theInstr); 4005 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 4006 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 4007 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 4008 UChar rA_addr = ifieldRegA(theInstr); 4009 UInt uimm16 = ifieldUIMM16(theInstr); 4010 UChar rB_addr = ifieldRegB(theInstr); 4011 UInt opc2 = ifieldOPClo10(theInstr); 4012 UChar b0 = ifieldBIT0(theInstr); 4013 4014 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4015 IRExpr *a = getIReg(rA_addr); 4016 IRExpr *b; 4017 4018 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 4019 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 4020 return False; 4021 } 4022 4023 if (b22 != 0) { 4024 vex_printf("dis_int_cmp(ppc)(b22)\n"); 4025 return False; 4026 } 4027 4028 switch (opc1) { 4029 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 4030 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 4031 (Int)extend_s_16to32(uimm16)); 4032 b = mkSzExtendS16( ty, uimm16 ); 4033 if (flag_L == 1) { 4034 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4035 } else { 4036 a = mkNarrowTo32( ty, a ); 4037 b = mkNarrowTo32( ty, b ); 4038 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 4039 } 4040 putCR0( crfD, getXER_SO() ); 4041 break; 4042 4043 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 4044 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 4045 b = mkSzImm( ty, uimm16 ); 4046 if (flag_L == 1) { 4047 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4048 } else { 4049 a = mkNarrowTo32( ty, a ); 4050 b = mkNarrowTo32( ty, b ); 4051 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4052 } 4053 putCR0( crfD, getXER_SO() ); 4054 break; 4055 4056 /* X Form */ 4057 case 0x1F: 4058 if (b0 != 0) { 4059 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 4060 return False; 4061 } 4062 b = getIReg(rB_addr); 4063 4064 switch (opc2) { 4065 case 0x000: // cmp (Compare, PPC32 p367) 4066 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4067 /* Comparing a reg with itself produces a result which 4068 doesn't depend on the contents of the reg. Therefore 4069 remove the false dependency, which has been known to cause 4070 memcheck to produce false errors. */ 4071 if (rA_addr == rB_addr) 4072 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4073 ? mkU64(0) : mkU32(0); 4074 if (flag_L == 1) { 4075 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4076 } else { 4077 a = mkNarrowTo32( ty, a ); 4078 b = mkNarrowTo32( ty, b ); 4079 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 4080 } 4081 putCR0( crfD, getXER_SO() ); 4082 break; 4083 4084 case 0x020: // cmpl (Compare Logical, PPC32 p369) 4085 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4086 /* Comparing a reg with itself produces a result which 4087 doesn't depend on the contents of the reg. Therefore 4088 remove the false dependency, which has been known to cause 4089 memcheck to produce false errors. */ 4090 if (rA_addr == rB_addr) 4091 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4092 ? mkU64(0) : mkU32(0); 4093 if (flag_L == 1) { 4094 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4095 } else { 4096 a = mkNarrowTo32( ty, a ); 4097 b = mkNarrowTo32( ty, b ); 4098 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4099 } 4100 putCR0( crfD, getXER_SO() ); 4101 break; 4102 4103 default: 4104 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 4105 return False; 4106 } 4107 break; 4108 4109 default: 4110 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 4111 return False; 4112 } 4113 4114 return True; 4115 } 4116 4117 4118 /* 4119 Integer Logical Instructions 4120 */ 4121 static Bool dis_int_logic ( UInt theInstr ) 4122 { 4123 /* D-Form, X-Form */ 4124 UChar opc1 = ifieldOPC(theInstr); 4125 UChar rS_addr = ifieldRegDS(theInstr); 4126 UChar rA_addr = ifieldRegA(theInstr); 4127 UInt uimm16 = ifieldUIMM16(theInstr); 4128 UChar rB_addr = ifieldRegB(theInstr); 4129 UInt opc2 = ifieldOPClo10(theInstr); 4130 UChar flag_rC = ifieldBIT0(theInstr); 4131 4132 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4133 IRTemp rS = newTemp(ty); 4134 IRTemp rA = newTemp(ty); 4135 IRTemp rB = newTemp(ty); 4136 IRExpr* irx; 4137 Bool do_rc = False; 4138 4139 assign( rS, getIReg(rS_addr) ); 4140 assign( rB, getIReg(rB_addr) ); 4141 4142 switch (opc1) { 4143 case 0x1C: // andi. (AND Immediate, PPC32 p358) 4144 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4145 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4146 mkSzImm(ty, uimm16)) ); 4147 do_rc = True; // Always record to CR 4148 flag_rC = 1; 4149 break; 4150 4151 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 4152 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4153 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4154 mkSzImm(ty, uimm16 << 16)) ); 4155 do_rc = True; // Always record to CR 4156 flag_rC = 1; 4157 break; 4158 4159 case 0x18: // ori (OR Immediate, PPC32 p497) 4160 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4161 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4162 mkSzImm(ty, uimm16)) ); 4163 break; 4164 4165 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 4166 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4167 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4168 mkSzImm(ty, uimm16 << 16)) ); 4169 break; 4170 4171 case 0x1A: // xori (XOR Immediate, PPC32 p550) 4172 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4173 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4174 mkSzImm(ty, uimm16)) ); 4175 break; 4176 4177 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 4178 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4179 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4180 mkSzImm(ty, uimm16 << 16)) ); 4181 break; 4182 4183 /* X Form */ 4184 case 0x1F: 4185 do_rc = True; // All below record to CR, except for where we return at case end. 4186 4187 switch (opc2) { 4188 case 0x01C: // and (AND, PPC32 p356) 4189 DIP("and%s r%u,r%u,r%u\n", 4190 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4191 assign(rA, binop( mkSzOp(ty, Iop_And8), 4192 mkexpr(rS), mkexpr(rB))); 4193 break; 4194 4195 case 0x03C: // andc (AND with Complement, PPC32 p357) 4196 DIP("andc%s r%u,r%u,r%u\n", 4197 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4198 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4199 unop( mkSzOp(ty, Iop_Not8), 4200 mkexpr(rB)))); 4201 break; 4202 4203 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 4204 IRExpr* lo32; 4205 if (rB_addr!=0) { 4206 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 4207 return False; 4208 } 4209 DIP("cntlzw%s r%u,r%u\n", 4210 flag_rC ? ".":"", rA_addr, rS_addr); 4211 4212 // mode64: count in low word only 4213 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 4214 4215 // Iop_Clz32 undefined for arg==0, so deal with that case: 4216 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 4217 assign(rA, mkWidenFrom32(ty, 4218 IRExpr_ITE( irx, 4219 unop(Iop_Clz32, lo32), 4220 mkU32(32)), 4221 False)); 4222 4223 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 4224 break; 4225 } 4226 4227 case 0x11C: // eqv (Equivalent, PPC32 p396) 4228 DIP("eqv%s r%u,r%u,r%u\n", 4229 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4230 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4231 binop( mkSzOp(ty, Iop_Xor8), 4232 mkexpr(rS), mkexpr(rB))) ); 4233 break; 4234 4235 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 4236 if (rB_addr!=0) { 4237 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 4238 return False; 4239 } 4240 DIP("extsb%s r%u,r%u\n", 4241 flag_rC ? ".":"", rA_addr, rS_addr); 4242 if (mode64) 4243 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 4244 else 4245 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 4246 break; 4247 4248 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 4249 if (rB_addr!=0) { 4250 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 4251 return False; 4252 } 4253 DIP("extsh%s r%u,r%u\n", 4254 flag_rC ? ".":"", rA_addr, rS_addr); 4255 if (mode64) 4256 assign( rA, unop(Iop_16Sto64, 4257 unop(Iop_64to16, mkexpr(rS))) ); 4258 else 4259 assign( rA, unop(Iop_16Sto32, 4260 unop(Iop_32to16, mkexpr(rS))) ); 4261 break; 4262 4263 case 0x1DC: // nand (NAND, PPC32 p492) 4264 DIP("nand%s r%u,r%u,r%u\n", 4265 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4266 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4267 binop( mkSzOp(ty, Iop_And8), 4268 mkexpr(rS), mkexpr(rB))) ); 4269 break; 4270 4271 case 0x07C: // nor (NOR, PPC32 p494) 4272 DIP("nor%s r%u,r%u,r%u\n", 4273 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4274 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4275 binop( mkSzOp(ty, Iop_Or8), 4276 mkexpr(rS), mkexpr(rB))) ); 4277 break; 4278 4279 case 0x1BC: // or (OR, PPC32 p495) 4280 if ((!flag_rC) && rS_addr == rB_addr) { 4281 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 4282 assign( rA, mkexpr(rS) ); 4283 } else { 4284 DIP("or%s r%u,r%u,r%u\n", 4285 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4286 assign( rA, binop( mkSzOp(ty, Iop_Or8), 4287 mkexpr(rS), mkexpr(rB)) ); 4288 } 4289 break; 4290 4291 case 0x19C: // orc (OR with Complement, PPC32 p496) 4292 DIP("orc%s r%u,r%u,r%u\n", 4293 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4294 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4295 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 4296 break; 4297 4298 case 0x13C: // xor (XOR, PPC32 p549) 4299 DIP("xor%s r%u,r%u,r%u\n", 4300 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4301 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 4302 mkexpr(rS), mkexpr(rB)) ); 4303 break; 4304 4305 4306 /* 64bit Integer Logical Instructions */ 4307 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 4308 if (rB_addr!=0) { 4309 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 4310 return False; 4311 } 4312 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 4313 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 4314 break; 4315 4316 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 4317 if (rB_addr!=0) { 4318 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 4319 return False; 4320 } 4321 DIP("cntlzd%s r%u,r%u\n", 4322 flag_rC ? ".":"", rA_addr, rS_addr); 4323 // Iop_Clz64 undefined for arg==0, so deal with that case: 4324 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 4325 assign(rA, IRExpr_ITE( irx, 4326 unop(Iop_Clz64, mkexpr(rS)), 4327 mkU64(64) )); 4328 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 4329 break; 4330 4331 case 0x1FC: // cmpb (Power6: compare bytes) 4332 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4333 4334 if (mode64) 4335 assign( rA, unop( Iop_V128to64, 4336 binop( Iop_CmpEQ8x16, 4337 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 4338 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 4339 )) ); 4340 else 4341 assign( rA, unop( Iop_V128to32, 4342 binop( Iop_CmpEQ8x16, 4343 unop( Iop_32UtoV128, mkexpr(rS) ), 4344 unop( Iop_32UtoV128, mkexpr(rB) ) 4345 )) ); 4346 break; 4347 4348 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 4349 IRTemp frB = newTemp(Ity_F64); 4350 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 4351 4352 assign( frB, getFReg(rB_addr)); // always F64 4353 if (mode64) 4354 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 4355 else 4356 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 4357 4358 putIReg( rS_addr, mkexpr(rA)); 4359 return True; 4360 } 4361 4362 case 0x25F: { // mffgpr (move floating-point from general purpose register) 4363 IRTemp frA = newTemp(Ity_F64); 4364 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 4365 4366 if (mode64) 4367 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 4368 else 4369 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 4370 4371 putFReg( rS_addr, mkexpr(frA)); 4372 return True; 4373 } 4374 case 0x1FA: // popcntd (population count doubleword 4375 { 4376 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4377 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 4378 putIReg( rA_addr, mkexpr(result) ); 4379 return True; 4380 } 4381 case 0x17A: // popcntw (Population Count Words) 4382 { 4383 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4384 if (mode64) { 4385 IRTemp resultHi, resultLo; 4386 IRTemp argLo = newTemp(Ity_I32); 4387 IRTemp argHi = newTemp(Ity_I32); 4388 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4389 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4390 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 4391 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 4392 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4393 } else { 4394 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 4395 putIReg( rA_addr, mkexpr(result) ); 4396 } 4397 return True; 4398 } 4399 case 0x7A: // popcntb (Population Count Byte) 4400 { 4401 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4402 4403 if (mode64) { 4404 IRTemp resultHi, resultLo; 4405 IRTemp argLo = newTemp(Ity_I32); 4406 IRTemp argHi = newTemp(Ity_I32); 4407 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4408 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4409 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 4410 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 4411 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4412 mkexpr(resultLo))); 4413 } else { 4414 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 4415 putIReg( rA_addr, mkexpr(result) ); 4416 } 4417 return True; 4418 } 4419 case 0x0FC: // bpermd (Bit Permute Doubleword) 4420 { 4421 /* This is a lot of rigmarole to emulate bpermd like this, as it 4422 * could be done much faster by implementing a call to the native 4423 * instruction. However, where possible I want to avoid using new 4424 * native instructions so that we can use valgrind to emulate those 4425 * instructions on older PPC64 hardware. 4426 */ 4427 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4428 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4429 int i; 4430 IRExpr * rS_expr = mkexpr(rS); 4431 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4432 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4433 for (i = 0; i < 8; i++) { 4434 IRTemp idx_tmp = newTemp( Ity_I64 ); 4435 IRTemp perm_bit = newTemp( Ity_I64 ); 4436 IRTemp idx = newTemp( Ity_I8 ); 4437 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4438 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4439 4440 assign( idx_tmp, 4441 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4442 assign( idx_LT64, 4443 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4444 assign( idx, 4445 binop( Iop_And8, 4446 unop( Iop_1Sto8, 4447 mkexpr(idx_LT64) ), 4448 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4449 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4450 * to determine which bit of rB to use for the perm bit, and then we shift 4451 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4452 * to set the final perm bit. 4453 */ 4454 assign( idx_LT64_ity64, 4455 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4456 assign( perm_bit, 4457 binop( Iop_And64, 4458 mkexpr( idx_LT64_ity64 ), 4459 binop( Iop_Shr64, 4460 binop( Iop_And64, 4461 mkU64( BPERMD_BIT_MASK ), 4462 binop( Iop_Shl64, 4463 mkexpr( rB ), 4464 mkexpr( idx ) ) ), 4465 mkU8( 63 ) ) ) ); 4466 res = binop( Iop_Or64, 4467 res, 4468 binop( Iop_Shl64, 4469 mkexpr( perm_bit ), 4470 mkU8( i ) ) ); 4471 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4472 } 4473 putIReg(rA_addr, res); 4474 return True; 4475 } 4476 4477 default: 4478 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4479 return False; 4480 } 4481 break; 4482 4483 default: 4484 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4485 return False; 4486 } 4487 4488 putIReg( rA_addr, mkexpr(rA) ); 4489 4490 if (do_rc && flag_rC) { 4491 set_CR0( mkexpr(rA) ); 4492 } 4493 return True; 4494 } 4495 4496 /* 4497 Integer Parity Instructions 4498 */ 4499 static Bool dis_int_parity ( UInt theInstr ) 4500 { 4501 /* X-Form */ 4502 UChar opc1 = ifieldOPC(theInstr); 4503 UChar rS_addr = ifieldRegDS(theInstr); 4504 UChar rA_addr = ifieldRegA(theInstr); 4505 UChar rB_addr = ifieldRegB(theInstr); 4506 UInt opc2 = ifieldOPClo10(theInstr); 4507 UChar b0 = ifieldBIT0(theInstr); 4508 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4509 4510 IRTemp rS = newTemp(ty); 4511 IRTemp rA = newTemp(ty); 4512 IRTemp iTot1 = newTemp(Ity_I32); 4513 IRTemp iTot2 = newTemp(Ity_I32); 4514 IRTemp iTot3 = newTemp(Ity_I32); 4515 IRTemp iTot4 = newTemp(Ity_I32); 4516 IRTemp iTot5 = newTemp(Ity_I32); 4517 IRTemp iTot6 = newTemp(Ity_I32); 4518 IRTemp iTot7 = newTemp(Ity_I32); 4519 IRTemp iTot8 = newTemp(Ity_I32); 4520 IRTemp rS1 = newTemp(ty); 4521 IRTemp rS2 = newTemp(ty); 4522 IRTemp rS3 = newTemp(ty); 4523 IRTemp rS4 = newTemp(ty); 4524 IRTemp rS5 = newTemp(ty); 4525 IRTemp rS6 = newTemp(ty); 4526 IRTemp rS7 = newTemp(ty); 4527 IRTemp iHi = newTemp(Ity_I32); 4528 IRTemp iLo = newTemp(Ity_I32); 4529 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4530 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4531 4532 if (opc1 != 0x1f || rB_addr || b0) { 4533 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4534 return False; 4535 } 4536 4537 assign( rS, getIReg(rS_addr) ); 4538 4539 switch (opc2) { 4540 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4541 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4542 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4543 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4544 assign( iTot2, binop(Iop_Add32, 4545 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4546 mkexpr(iTot1)) ); 4547 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4548 assign( iTot3, binop(Iop_Add32, 4549 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4550 mkexpr(iTot2)) ); 4551 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4552 assign( iTot4, binop(Iop_Add32, 4553 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4554 mkexpr(iTot3)) ); 4555 if (mode64) { 4556 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4557 assign( iTot5, binop(Iop_Add32, 4558 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4559 mkexpr(iTot4)) ); 4560 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4561 assign( iTot6, binop(Iop_Add32, 4562 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4563 mkexpr(iTot5)) ); 4564 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4565 assign( iTot7, binop(Iop_Add32, 4566 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4567 mkexpr(iTot6)) ); 4568 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4569 assign( iTot8, binop(Iop_Add32, 4570 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4571 mkexpr(iTot7)) ); 4572 assign( rA, unop(Iop_32Uto64, 4573 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4574 } else 4575 assign( rA, mkexpr(iTot4) ); 4576 4577 break; 4578 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4579 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4580 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4581 assign( iTot2, binop(Iop_Add32, 4582 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4583 mkexpr(iTot1)) ); 4584 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4585 assign( iTot3, binop(Iop_Add32, 4586 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4587 mkexpr(iTot2)) ); 4588 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4589 assign( iTot4, binop(Iop_Add32, 4590 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4591 mkexpr(iTot3)) ); 4592 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4593 4594 if (mode64) { 4595 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4596 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4597 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4598 assign( iTot6, binop(Iop_Add32, 4599 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4600 mkexpr(iTot5)) ); 4601 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4602 assign( iTot7, binop(Iop_Add32, 4603 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4604 mkexpr(iTot6)) ); 4605 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4606 assign( iTot8, binop(Iop_Add32, 4607 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4608 mkexpr(iTot7)) ); 4609 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4610 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4611 } else 4612 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4613 break; 4614 default: 4615 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4616 return False; 4617 } 4618 4619 putIReg( rA_addr, mkexpr(rA) ); 4620 4621 return True; 4622 } 4623 4624 4625 /* 4626 Integer Rotate Instructions 4627 */ 4628 static Bool dis_int_rot ( UInt theInstr ) 4629 { 4630 /* M-Form, MDS-Form */ 4631 UChar opc1 = ifieldOPC(theInstr); 4632 UChar rS_addr = ifieldRegDS(theInstr); 4633 UChar rA_addr = ifieldRegA(theInstr); 4634 UChar rB_addr = ifieldRegB(theInstr); 4635 UChar sh_imm = rB_addr; 4636 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4637 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4638 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4639 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4640 UChar b1 = ifieldBIT1(theInstr); 4641 UChar flag_rC = ifieldBIT0(theInstr); 4642 4643 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4644 IRTemp rS = newTemp(ty); 4645 IRTemp rA = newTemp(ty); 4646 IRTemp rB = newTemp(ty); 4647 IRTemp rot = newTemp(ty); 4648 IRExpr *r; 4649 UInt mask32; 4650 ULong mask64; 4651 4652 assign( rS, getIReg(rS_addr) ); 4653 assign( rB, getIReg(rB_addr) ); 4654 4655 switch (opc1) { 4656 case 0x14: { 4657 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4658 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4659 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4660 if (mode64) { 4661 // tmp32 = (ROTL(rS_Lo32, Imm) 4662 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4663 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4664 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4665 r = unop(Iop_32Uto64, r); 4666 assign( rot, binop(Iop_Or64, r, 4667 binop(Iop_Shl64, r, mkU8(32))) ); 4668 assign( rA, 4669 binop(Iop_Or64, 4670 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4671 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4672 } 4673 else { 4674 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4675 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4676 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4677 assign( rA, 4678 binop(Iop_Or32, 4679 binop(Iop_And32, mkU32(mask32), r), 4680 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4681 } 4682 break; 4683 } 4684 4685 case 0x15: { 4686 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4687 vassert(MaskBeg < 32); 4688 vassert(MaskEnd < 32); 4689 vassert(sh_imm < 32); 4690 4691 if (mode64) { 4692 IRTemp rTmp = newTemp(Ity_I64); 4693 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4694 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4695 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4696 // tmp32 = (ROTL(rS_Lo32, Imm) 4697 // rA = ((tmp32 || tmp32) & mask64) 4698 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4699 r = unop(Iop_32Uto64, r); 4700 assign( rTmp, r ); 4701 r = NULL; 4702 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4703 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4704 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4705 } 4706 else { 4707 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4708 /* Special-case the ,n,0,31-n form as that is just n-bit 4709 shift left, PPC32 p501 */ 4710 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4711 rA_addr, rS_addr, sh_imm); 4712 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4713 } 4714 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4715 /* Special-case the ,32-n,n,31 form as that is just n-bit 4716 unsigned shift right, PPC32 p501 */ 4717 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4718 rA_addr, rS_addr, MaskBeg); 4719 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4720 } 4721 else { 4722 /* General case. */ 4723 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4724 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4725 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4726 // rA = ROTL(rS, Imm) & mask 4727 assign( rA, binop(Iop_And32, 4728 ROTL(mkexpr(rS), mkU8(sh_imm)), 4729 mkU32(mask32)) ); 4730 } 4731 } 4732 break; 4733 } 4734 4735 case 0x17: { 4736 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4737 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4738 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4739 if (mode64) { 4740 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4741 /* weird insn alert! 4742 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4743 rA = ((tmp32 || tmp32) & mask64) 4744 */ 4745 // note, ROTL does the masking, so we don't do it here 4746 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4747 unop(Iop_64to8, mkexpr(rB)) ); 4748 r = unop(Iop_32Uto64, r); 4749 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4750 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4751 } else { 4752 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4753 // rA = ROTL(rS, rB[0-4]) & mask 4754 // note, ROTL does the masking, so we don't do it here 4755 assign( rA, binop(Iop_And32, 4756 ROTL(mkexpr(rS), 4757 unop(Iop_32to8, mkexpr(rB))), 4758 mkU32(mask32)) ); 4759 } 4760 break; 4761 } 4762 4763 /* 64bit Integer Rotates */ 4764 case 0x1E: { 4765 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4766 sh_imm |= b1 << 5; 4767 4768 vassert( msk_imm < 64 ); 4769 vassert( sh_imm < 64 ); 4770 4771 switch (opc2) { 4772 case 0x4: { 4773 /* r = ROTL64( rS, rB_lo6) */ 4774 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4775 4776 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4777 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4778 rA_addr, rS_addr, rB_addr, msk_imm); 4779 // note, ROTL does the masking, so we don't do it here 4780 mask64 = MASK64(0, 63-msk_imm); 4781 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4782 break; 4783 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4784 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4785 rA_addr, rS_addr, rB_addr, msk_imm); 4786 mask64 = MASK64(63-msk_imm, 63); 4787 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4788 break; 4789 } 4790 break; 4791 } 4792 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4793 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4794 rA_addr, rS_addr, sh_imm, msk_imm); 4795 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4796 mask64 = MASK64(sh_imm, 63-msk_imm); 4797 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4798 break; 4799 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4800 /* 4801 Hmm... looks like this'll do the job more simply: 4802 r = SHL(rS, sh_imm) 4803 m = ~(1 << (63-msk_imm)) 4804 assign(rA, r & m); 4805 */ 4806 4807 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4808 if (mode64 4809 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4810 /* special-case the ,64-n,n form as that is just 4811 unsigned shift-right by n */ 4812 DIP("srdi%s r%u,r%u,%u\n", 4813 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4814 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4815 } else { 4816 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4817 rA_addr, rS_addr, sh_imm, msk_imm); 4818 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4819 mask64 = MASK64(0, 63-msk_imm); 4820 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4821 } 4822 break; 4823 4824 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4825 if (mode64 4826 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4827 /* special-case the ,n,63-n form as that is just 4828 shift-left by n */ 4829 DIP("sldi%s r%u,r%u,%u\n", 4830 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4831 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4832 } else { 4833 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4834 rA_addr, rS_addr, sh_imm, msk_imm); 4835 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4836 mask64 = MASK64(63-msk_imm, 63); 4837 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4838 } 4839 break; 4840 4841 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4842 IRTemp rA_orig = newTemp(ty); 4843 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4844 rA_addr, rS_addr, sh_imm, msk_imm); 4845 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4846 mask64 = MASK64(sh_imm, 63-msk_imm); 4847 assign( rA_orig, getIReg(rA_addr) ); 4848 assign( rA, binop(Iop_Or64, 4849 binop(Iop_And64, mkU64(mask64), r), 4850 binop(Iop_And64, mkU64(~mask64), 4851 mkexpr(rA_orig))) ); 4852 break; 4853 } 4854 default: 4855 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4856 return False; 4857 } 4858 break; 4859 } 4860 4861 default: 4862 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4863 return False; 4864 } 4865 4866 putIReg( rA_addr, mkexpr(rA) ); 4867 4868 if (flag_rC) { 4869 set_CR0( mkexpr(rA) ); 4870 } 4871 return True; 4872 } 4873 4874 4875 /* 4876 Integer Load Instructions 4877 */ 4878 static Bool dis_int_load ( UInt theInstr ) 4879 { 4880 /* D-Form, X-Form, DS-Form */ 4881 UChar opc1 = ifieldOPC(theInstr); 4882 UChar rD_addr = ifieldRegDS(theInstr); 4883 UChar rA_addr = ifieldRegA(theInstr); 4884 UInt uimm16 = ifieldUIMM16(theInstr); 4885 UChar rB_addr = ifieldRegB(theInstr); 4886 UInt opc2 = ifieldOPClo10(theInstr); 4887 UChar b1 = ifieldBIT1(theInstr); 4888 UChar b0 = ifieldBIT0(theInstr); 4889 4890 Int simm16 = extend_s_16to32(uimm16); 4891 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4892 IRTemp EA = newTemp(ty); 4893 IRExpr* val; 4894 4895 switch (opc1) { 4896 case 0x1F: // register offset 4897 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4898 break; 4899 case 0x38: // immediate offset: 64bit: lq: maskoff 4900 // lowest 4 bits of immediate before forming EA 4901 simm16 = simm16 & 0xFFFFFFF0; 4902 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4903 break; 4904 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 4905 // lowest 2 bits of immediate before forming EA 4906 simm16 = simm16 & 0xFFFFFFFC; 4907 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4908 break; 4909 default: // immediate offset 4910 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4911 break; 4912 } 4913 4914 switch (opc1) { 4915 case 0x22: // lbz (Load B & Zero, PPC32 p433) 4916 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4917 val = load(Ity_I8, mkexpr(EA)); 4918 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4919 break; 4920 4921 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 4922 if (rA_addr == 0 || rA_addr == rD_addr) { 4923 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 4924 return False; 4925 } 4926 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4927 val = load(Ity_I8, mkexpr(EA)); 4928 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4929 putIReg( rA_addr, mkexpr(EA) ); 4930 break; 4931 4932 case 0x2A: // lha (Load HW Alg, PPC32 p445) 4933 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4934 val = load(Ity_I16, mkexpr(EA)); 4935 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4936 break; 4937 4938 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 4939 if (rA_addr == 0 || rA_addr == rD_addr) { 4940 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 4941 return False; 4942 } 4943 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4944 val = load(Ity_I16, mkexpr(EA)); 4945 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4946 putIReg( rA_addr, mkexpr(EA) ); 4947 break; 4948 4949 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 4950 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4951 val = load(Ity_I16, mkexpr(EA)); 4952 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4953 break; 4954 4955 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 4956 if (rA_addr == 0 || rA_addr == rD_addr) { 4957 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 4958 return False; 4959 } 4960 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4961 val = load(Ity_I16, mkexpr(EA)); 4962 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4963 putIReg( rA_addr, mkexpr(EA) ); 4964 break; 4965 4966 case 0x20: // lwz (Load W & Zero, PPC32 p460) 4967 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4968 val = load(Ity_I32, mkexpr(EA)); 4969 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4970 break; 4971 4972 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 4973 if (rA_addr == 0 || rA_addr == rD_addr) { 4974 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 4975 return False; 4976 } 4977 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4978 val = load(Ity_I32, mkexpr(EA)); 4979 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4980 putIReg( rA_addr, mkexpr(EA) ); 4981 break; 4982 4983 /* X Form */ 4984 case 0x1F: 4985 if (b0 != 0) { 4986 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 4987 return False; 4988 } 4989 4990 switch (opc2) { 4991 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 4992 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4993 if (rA_addr == 0 || rA_addr == rD_addr) { 4994 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4995 return False; 4996 } 4997 val = load(Ity_I8, mkexpr(EA)); 4998 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4999 putIReg( rA_addr, mkexpr(EA) ); 5000 break; 5001 5002 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 5003 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5004 val = load(Ity_I8, mkexpr(EA)); 5005 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5006 break; 5007 5008 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 5009 if (rA_addr == 0 || rA_addr == rD_addr) { 5010 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 5011 return False; 5012 } 5013 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5014 val = load(Ity_I16, mkexpr(EA)); 5015 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5016 putIReg( rA_addr, mkexpr(EA) ); 5017 break; 5018 5019 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 5020 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5021 val = load(Ity_I16, mkexpr(EA)); 5022 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5023 break; 5024 5025 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 5026 if (rA_addr == 0 || rA_addr == rD_addr) { 5027 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 5028 return False; 5029 } 5030 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5031 val = load(Ity_I16, mkexpr(EA)); 5032 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5033 putIReg( rA_addr, mkexpr(EA) ); 5034 break; 5035 5036 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 5037 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5038 val = load(Ity_I16, mkexpr(EA)); 5039 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5040 break; 5041 5042 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 5043 if (rA_addr == 0 || rA_addr == rD_addr) { 5044 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5045 return False; 5046 } 5047 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5048 val = load(Ity_I32, mkexpr(EA)); 5049 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5050 putIReg( rA_addr, mkexpr(EA) ); 5051 break; 5052 5053 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 5054 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5055 val = load(Ity_I32, mkexpr(EA)); 5056 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5057 break; 5058 5059 5060 /* 64bit Loads */ 5061 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 5062 if (rA_addr == 0 || rA_addr == rD_addr) { 5063 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 5064 return False; 5065 } 5066 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5067 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5068 putIReg( rA_addr, mkexpr(EA) ); 5069 break; 5070 5071 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 5072 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5073 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5074 break; 5075 5076 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 5077 if (rA_addr == 0 || rA_addr == rD_addr) { 5078 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 5079 return False; 5080 } 5081 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5082 putIReg( rD_addr, 5083 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5084 putIReg( rA_addr, mkexpr(EA) ); 5085 break; 5086 5087 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 5088 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5089 putIReg( rD_addr, 5090 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5091 break; 5092 5093 default: 5094 vex_printf("dis_int_load(ppc)(opc2)\n"); 5095 return False; 5096 } 5097 break; 5098 5099 /* DS Form - 64bit Loads. In each case EA will have been formed 5100 with the lowest 2 bits masked off the immediate offset. */ 5101 case 0x3A: 5102 switch ((b1<<1) | b0) { 5103 case 0x0: // ld (Load DWord, PPC64 p472) 5104 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5105 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5106 break; 5107 5108 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 5109 if (rA_addr == 0 || rA_addr == rD_addr) { 5110 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 5111 return False; 5112 } 5113 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5114 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5115 putIReg( rA_addr, mkexpr(EA) ); 5116 break; 5117 5118 case 0x2: // lwa (Load Word Alg, PPC64 p499) 5119 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5120 putIReg( rD_addr, 5121 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5122 break; 5123 5124 default: 5125 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5126 return False; 5127 } 5128 break; 5129 5130 case 0x38: { 5131 IRTemp high = newTemp(ty); 5132 IRTemp low = newTemp(ty); 5133 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 5134 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5135 /* NOTE: there are some changes to XER[41:42] that have not been 5136 * implemented. 5137 */ 5138 // trap if EA misaligned on 16 byte address 5139 if (mode64) { 5140 if (host_endness == VexEndnessBE) { 5141 assign(high, load(ty, mkexpr( EA ) ) ); 5142 assign(low, load(ty, binop( Iop_Add64, 5143 mkexpr( EA ), 5144 mkU64( 8 ) ) ) ); 5145 } else { 5146 assign(low, load(ty, mkexpr( EA ) ) ); 5147 assign(high, load(ty, binop( Iop_Add64, 5148 mkexpr( EA ), 5149 mkU64( 8 ) ) ) ); 5150 } 5151 } else { 5152 assign(high, load(ty, binop( Iop_Add32, 5153 mkexpr( EA ), 5154 mkU32( 4 ) ) ) ); 5155 assign(low, load(ty, binop( Iop_Add32, 5156 mkexpr( EA ), 5157 mkU32( 12 ) ) ) ); 5158 } 5159 gen_SIGBUS_if_misaligned( EA, 16 ); 5160 putIReg( rD_addr, mkexpr( high) ); 5161 putIReg( rD_addr+1, mkexpr( low) ); 5162 break; 5163 } 5164 default: 5165 vex_printf("dis_int_load(ppc)(opc1)\n"); 5166 return False; 5167 } 5168 return True; 5169 } 5170 5171 5172 5173 /* 5174 Integer Store Instructions 5175 */ 5176 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 5177 { 5178 /* D-Form, X-Form, DS-Form */ 5179 UChar opc1 = ifieldOPC(theInstr); 5180 UInt rS_addr = ifieldRegDS(theInstr); 5181 UInt rA_addr = ifieldRegA(theInstr); 5182 UInt uimm16 = ifieldUIMM16(theInstr); 5183 UInt rB_addr = ifieldRegB(theInstr); 5184 UInt opc2 = ifieldOPClo10(theInstr); 5185 UChar b1 = ifieldBIT1(theInstr); 5186 UChar b0 = ifieldBIT0(theInstr); 5187 5188 Int simm16 = extend_s_16to32(uimm16); 5189 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5190 IRTemp rS = newTemp(ty); 5191 IRTemp rB = newTemp(ty); 5192 IRTemp EA = newTemp(ty); 5193 5194 assign( rB, getIReg(rB_addr) ); 5195 assign( rS, getIReg(rS_addr) ); 5196 5197 switch (opc1) { 5198 case 0x1F: // register offset 5199 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5200 break; 5201 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 5202 // lowest 2 bits of immediate before forming EA 5203 simm16 = simm16 & 0xFFFFFFFC; 5204 default: // immediate offset 5205 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5206 break; 5207 } 5208 5209 switch (opc1) { 5210 case 0x26: // stb (Store B, PPC32 p509) 5211 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5212 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5213 break; 5214 5215 case 0x27: // stbu (Store B, Update, PPC32 p510) 5216 if (rA_addr == 0 ) { 5217 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 5218 return False; 5219 } 5220 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5221 putIReg( rA_addr, mkexpr(EA) ); 5222 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5223 break; 5224 5225 case 0x2C: // sth (Store HW, PPC32 p522) 5226 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5227 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5228 break; 5229 5230 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 5231 if (rA_addr == 0) { 5232 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 5233 return False; 5234 } 5235 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5236 putIReg( rA_addr, mkexpr(EA) ); 5237 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5238 break; 5239 5240 case 0x24: // stw (Store W, PPC32 p530) 5241 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5242 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5243 break; 5244 5245 case 0x25: // stwu (Store W, Update, PPC32 p534) 5246 if (rA_addr == 0) { 5247 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 5248 return False; 5249 } 5250 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5251 putIReg( rA_addr, mkexpr(EA) ); 5252 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5253 break; 5254 5255 /* X Form : all these use EA_indexed */ 5256 case 0x1F: 5257 if (b0 != 0) { 5258 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 5259 return False; 5260 } 5261 5262 switch (opc2) { 5263 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 5264 if (rA_addr == 0) { 5265 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 5266 return False; 5267 } 5268 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5269 putIReg( rA_addr, mkexpr(EA) ); 5270 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5271 break; 5272 5273 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 5274 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5275 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5276 break; 5277 5278 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 5279 if (rA_addr == 0) { 5280 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 5281 return False; 5282 } 5283 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5284 putIReg( rA_addr, mkexpr(EA) ); 5285 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5286 break; 5287 5288 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 5289 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5290 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5291 break; 5292 5293 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 5294 if (rA_addr == 0) { 5295 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 5296 return False; 5297 } 5298 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5299 putIReg( rA_addr, mkexpr(EA) ); 5300 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5301 break; 5302 5303 case 0x097: // stwx (Store W Indexed, PPC32 p536) 5304 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5305 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5306 break; 5307 5308 5309 /* 64bit Stores */ 5310 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 5311 if (rA_addr == 0) { 5312 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 5313 return False; 5314 } 5315 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5316 putIReg( rA_addr, mkexpr(EA) ); 5317 store( mkexpr(EA), mkexpr(rS) ); 5318 break; 5319 5320 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 5321 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5322 store( mkexpr(EA), mkexpr(rS) ); 5323 break; 5324 5325 default: 5326 vex_printf("dis_int_store(ppc)(opc2)\n"); 5327 return False; 5328 } 5329 break; 5330 5331 /* DS Form - 64bit Stores. In each case EA will have been formed 5332 with the lowest 2 bits masked off the immediate offset. */ 5333 case 0x3E: 5334 switch ((b1<<1) | b0) { 5335 case 0x0: // std (Store DWord, PPC64 p580) 5336 if (!mode64) 5337 return False; 5338 5339 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5340 store( mkexpr(EA), mkexpr(rS) ); 5341 break; 5342 5343 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 5344 if (!mode64) 5345 return False; 5346 5347 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5348 putIReg( rA_addr, mkexpr(EA) ); 5349 store( mkexpr(EA), mkexpr(rS) ); 5350 break; 5351 5352 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 5353 IRTemp EA_hi = newTemp(ty); 5354 IRTemp EA_lo = newTemp(ty); 5355 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5356 5357 if (mode64) { 5358 if (host_endness == VexEndnessBE) { 5359 5360 /* upper 64-bits */ 5361 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 5362 5363 /* lower 64-bits */ 5364 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5365 } else { 5366 /* upper 64-bits */ 5367 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5368 5369 /* lower 64-bits */ 5370 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 5371 } 5372 } else { 5373 /* upper half of upper 64-bits */ 5374 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 5375 5376 /* lower half of upper 64-bits */ 5377 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 5378 } 5379 store( mkexpr(EA_hi), mkexpr(rS) ); 5380 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 5381 break; 5382 } 5383 default: 5384 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5385 return False; 5386 } 5387 break; 5388 5389 default: 5390 vex_printf("dis_int_store(ppc)(opc1)\n"); 5391 return False; 5392 } 5393 return True; 5394 } 5395 5396 5397 5398 /* 5399 Integer Load/Store Multiple Instructions 5400 */ 5401 static Bool dis_int_ldst_mult ( UInt theInstr ) 5402 { 5403 /* D-Form */ 5404 UChar opc1 = ifieldOPC(theInstr); 5405 UChar rD_addr = ifieldRegDS(theInstr); 5406 UChar rS_addr = rD_addr; 5407 UChar rA_addr = ifieldRegA(theInstr); 5408 UInt uimm16 = ifieldUIMM16(theInstr); 5409 5410 Int simm16 = extend_s_16to32(uimm16); 5411 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5412 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 5413 IRTemp EA = newTemp(ty); 5414 UInt r = 0; 5415 UInt ea_off = 0; 5416 IRExpr* irx_addr; 5417 5418 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5419 5420 switch (opc1) { 5421 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 5422 if (rA_addr >= rD_addr) { 5423 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 5424 return False; 5425 } 5426 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5427 for (r = rD_addr; r <= 31; r++) { 5428 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5429 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 5430 False) ); 5431 ea_off += 4; 5432 } 5433 break; 5434 5435 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 5436 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5437 for (r = rS_addr; r <= 31; r++) { 5438 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5439 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 5440 ea_off += 4; 5441 } 5442 break; 5443 5444 default: 5445 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 5446 return False; 5447 } 5448 return True; 5449 } 5450 5451 5452 5453 /* 5454 Integer Load/Store String Instructions 5455 */ 5456 static 5457 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5458 IRTemp EA, // EA 5459 Int rD, // first dst register 5460 Int maxBytes ) // 32 or 128 5461 { 5462 Int i, shift = 24; 5463 IRExpr* e_nbytes = mkexpr(tNBytes); 5464 IRExpr* e_EA = mkexpr(EA); 5465 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5466 5467 vassert(rD >= 0 && rD < 32); 5468 rD--; if (rD < 0) rD = 31; 5469 5470 for (i = 0; i < maxBytes; i++) { 5471 /* if (nBytes < (i+1)) goto NIA; */ 5472 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5473 Ijk_Boring, 5474 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5475 /* when crossing into a new dest register, set it to zero. */ 5476 if ((i % 4) == 0) { 5477 rD++; if (rD == 32) rD = 0; 5478 putIReg(rD, mkSzImm(ty, 0)); 5479 shift = 24; 5480 } 5481 /* rD |= (8Uto32(*(EA+i))) << shift */ 5482 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5483 putIReg( 5484 rD, 5485 mkWidenFrom32( 5486 ty, 5487 binop( 5488 Iop_Or32, 5489 mkNarrowTo32(ty, getIReg(rD)), 5490 binop( 5491 Iop_Shl32, 5492 unop( 5493 Iop_8Uto32, 5494 load( Ity_I8, 5495 binop( mkSzOp(ty,Iop_Add8), 5496 e_EA, mkSzImm(ty,i))) 5497 ), 5498 mkU8(toUChar(shift)) 5499 ) 5500 ), 5501 /*Signed*/False 5502 ) 5503 ); 5504 shift -= 8; 5505 } 5506 } 5507 5508 static 5509 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5510 IRTemp EA, // EA 5511 Int rS, // first src register 5512 Int maxBytes ) // 32 or 128 5513 { 5514 Int i, shift = 24; 5515 IRExpr* e_nbytes = mkexpr(tNBytes); 5516 IRExpr* e_EA = mkexpr(EA); 5517 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5518 5519 vassert(rS >= 0 && rS < 32); 5520 rS--; if (rS < 0) rS = 31; 5521 5522 for (i = 0; i < maxBytes; i++) { 5523 /* if (nBytes < (i+1)) goto NIA; */ 5524 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5525 Ijk_Boring, 5526 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5527 /* check for crossing into a new src register. */ 5528 if ((i % 4) == 0) { 5529 rS++; if (rS == 32) rS = 0; 5530 shift = 24; 5531 } 5532 /* *(EA+i) = 32to8(rS >> shift) */ 5533 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5534 store( 5535 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5536 unop( Iop_32to8, 5537 binop( Iop_Shr32, 5538 mkNarrowTo32( ty, getIReg(rS) ), 5539 mkU8( toUChar(shift) ))) 5540 ); 5541 shift -= 8; 5542 } 5543 } 5544 5545 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5546 { 5547 /* X-Form */ 5548 UChar opc1 = ifieldOPC(theInstr); 5549 UChar rD_addr = ifieldRegDS(theInstr); 5550 UChar rS_addr = rD_addr; 5551 UChar rA_addr = ifieldRegA(theInstr); 5552 UChar rB_addr = ifieldRegB(theInstr); 5553 UChar NumBytes = rB_addr; 5554 UInt opc2 = ifieldOPClo10(theInstr); 5555 UChar b0 = ifieldBIT0(theInstr); 5556 5557 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5558 IRTemp t_EA = newTemp(ty); 5559 IRTemp t_nbytes = IRTemp_INVALID; 5560 5561 *stopHere = False; 5562 5563 if (opc1 != 0x1F || b0 != 0) { 5564 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5565 return False; 5566 } 5567 5568 switch (opc2) { 5569 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5570 /* NB: does not reject the case where RA is in the range of 5571 registers to be loaded. It should. */ 5572 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5573 assign( t_EA, ea_rAor0(rA_addr) ); 5574 if (NumBytes == 8 && !mode64) { 5575 /* Special case hack */ 5576 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5577 putIReg( rD_addr, 5578 load(Ity_I32, mkexpr(t_EA)) ); 5579 putIReg( (rD_addr+1) % 32, 5580 load(Ity_I32, 5581 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5582 } else { 5583 t_nbytes = newTemp(Ity_I32); 5584 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5585 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5586 *stopHere = True; 5587 } 5588 return True; 5589 5590 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5591 /* NB: does not reject the case where RA is in the range of 5592 registers to be loaded. It should. Although considering 5593 that that can only be detected at run time, it's not easy to 5594 do so. */ 5595 if (rD_addr == rA_addr || rD_addr == rB_addr) 5596 return False; 5597 if (rD_addr == 0 && rA_addr == 0) 5598 return False; 5599 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5600 t_nbytes = newTemp(Ity_I32); 5601 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5602 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5603 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5604 *stopHere = True; 5605 return True; 5606 5607 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5608 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5609 assign( t_EA, ea_rAor0(rA_addr) ); 5610 if (NumBytes == 8 && !mode64) { 5611 /* Special case hack */ 5612 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5613 store( mkexpr(t_EA), 5614 getIReg(rD_addr) ); 5615 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5616 getIReg((rD_addr+1) % 32) ); 5617 } else { 5618 t_nbytes = newTemp(Ity_I32); 5619 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5620 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5621 *stopHere = True; 5622 } 5623 return True; 5624 5625 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5626 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5627 t_nbytes = newTemp(Ity_I32); 5628 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5629 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5630 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5631 *stopHere = True; 5632 return True; 5633 5634 default: 5635 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5636 return False; 5637 } 5638 return True; 5639 } 5640 5641 5642 /* ------------------------------------------------------------------ 5643 Integer Branch Instructions 5644 ------------------------------------------------------------------ */ 5645 5646 /* 5647 Branch helper function 5648 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5649 Returns an I32 which is 0x00000000 if the ctr condition failed 5650 and 0xFFFFFFFF otherwise. 5651 */ 5652 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5653 { 5654 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5655 IRTemp ok = newTemp(Ity_I32); 5656 5657 if ((BO >> 2) & 1) { // independent of ctr 5658 assign( ok, mkU32(0xFFFFFFFF) ); 5659 } else { 5660 if ((BO >> 1) & 1) { // ctr == 0 ? 5661 assign( ok, unop( Iop_1Sto32, 5662 binop( mkSzOp(ty, Iop_CmpEQ8), 5663 getGST( PPC_GST_CTR ), 5664 mkSzImm(ty,0))) ); 5665 } else { // ctr != 0 ? 5666 assign( ok, unop( Iop_1Sto32, 5667 binop( mkSzOp(ty, Iop_CmpNE8), 5668 getGST( PPC_GST_CTR ), 5669 mkSzImm(ty,0))) ); 5670 } 5671 } 5672 return mkexpr(ok); 5673 } 5674 5675 5676 /* 5677 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5678 Returns an I32 which is either 0 if the condition failed or 5679 some arbitrary nonzero value otherwise. */ 5680 5681 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5682 { 5683 Int where; 5684 IRTemp res = newTemp(Ity_I32); 5685 IRTemp cr_bi = newTemp(Ity_I32); 5686 5687 if ((BO >> 4) & 1) { 5688 assign( res, mkU32(1) ); 5689 } else { 5690 // ok = (CR[BI] == BO[3]) Note, the following relies on 5691 // getCRbit_anywhere returning a value which 5692 // is either zero or has exactly 1 bit set. 5693 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5694 5695 if ((BO >> 3) & 1) { 5696 /* We can use cr_bi as-is. */ 5697 assign( res, mkexpr(cr_bi) ); 5698 } else { 5699 /* We have to invert the sense of the information held in 5700 cr_bi. For that we need to know which bit 5701 getCRbit_anywhere regards as significant. */ 5702 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5703 mkU32(1<<where)) ); 5704 } 5705 } 5706 return mkexpr(res); 5707 } 5708 5709 5710 /* 5711 Integer Branch Instructions 5712 */ 5713 static Bool dis_branch ( UInt theInstr, 5714 const VexAbiInfo* vbi, 5715 /*OUT*/DisResult* dres, 5716 Bool (*resteerOkFn)(void*,Addr), 5717 void* callback_opaque ) 5718 { 5719 UChar opc1 = ifieldOPC(theInstr); 5720 UChar BO = ifieldRegDS(theInstr); 5721 UChar BI = ifieldRegA(theInstr); 5722 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5723 UChar b11to15 = ifieldRegB(theInstr); 5724 UInt opc2 = ifieldOPClo10(theInstr); 5725 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5726 UChar flag_AA = ifieldBIT1(theInstr); 5727 UChar flag_LK = ifieldBIT0(theInstr); 5728 5729 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5730 Addr64 tgt = 0; 5731 Int BD = extend_s_16to32(BD_u16); 5732 IRTemp do_branch = newTemp(Ity_I32); 5733 IRTemp ctr_ok = newTemp(Ity_I32); 5734 IRTemp cond_ok = newTemp(Ity_I32); 5735 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5736 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5737 IRTemp lr_old = newTemp(ty); 5738 5739 /* Hack to pass through code that just wants to read the PC */ 5740 if (theInstr == 0x429F0005) { 5741 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5742 putGST( PPC_GST_LR, e_nia ); 5743 return True; 5744 } 5745 5746 /* The default what-next. Individual cases can override it. */ 5747 dres->whatNext = Dis_StopHere; 5748 vassert(dres->jk_StopHere == Ijk_INVALID); 5749 5750 switch (opc1) { 5751 case 0x12: // b (Branch, PPC32 p360) 5752 if (flag_AA) { 5753 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5754 } else { 5755 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5756 (Long)extend_s_26to64(LI_u26) ); 5757 } 5758 if (mode64) { 5759 DIP("b%s%s 0x%llx\n", 5760 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5761 } else { 5762 DIP("b%s%s 0x%x\n", 5763 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5764 } 5765 5766 if (flag_LK) { 5767 putGST( PPC_GST_LR, e_nia ); 5768 if (vbi->guest_ppc_zap_RZ_at_bl 5769 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5770 IRTemp t_tgt = newTemp(ty); 5771 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5772 make_redzone_AbiHint( vbi, t_tgt, 5773 "branch-and-link (unconditional call)" ); 5774 } 5775 } 5776 5777 if (resteerOkFn( callback_opaque, tgt )) { 5778 dres->whatNext = Dis_ResteerU; 5779 dres->continueAt = tgt; 5780 } else { 5781 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5782 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5783 } 5784 break; 5785 5786 case 0x10: // bc (Branch Conditional, PPC32 p361) 5787 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5788 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5789 5790 if (!(BO & 0x4)) { 5791 putGST( PPC_GST_CTR, 5792 binop(mkSzOp(ty, Iop_Sub8), 5793 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5794 } 5795 5796 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5797 cond_ok is either zero or nonzero, since that's the cheapest 5798 way to compute it. Anding them together gives a value which 5799 is either zero or non zero and so that's what we must test 5800 for in the IRStmt_Exit. */ 5801 assign( ctr_ok, branch_ctr_ok( BO ) ); 5802 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5803 assign( do_branch, 5804 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5805 5806 if (flag_AA) { 5807 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5808 } else { 5809 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5810 (Long)extend_s_16to64(BD_u16)); 5811 } 5812 if (flag_LK) 5813 putGST( PPC_GST_LR, e_nia ); 5814 5815 stmt( IRStmt_Exit( 5816 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5817 flag_LK ? Ijk_Call : Ijk_Boring, 5818 mkSzConst(ty, tgt), OFFB_CIA ) ); 5819 5820 dres->jk_StopHere = Ijk_Boring; 5821 putGST( PPC_GST_CIA, e_nia ); 5822 break; 5823 5824 case 0x13: 5825 /* For bclr and bcctr, it appears that the lowest two bits of 5826 b11to15 are a branch hint, and so we only need to ensure it's 5827 of the form 000XX. */ 5828 if ((b11to15 & ~3) != 0) { 5829 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 5830 return False; 5831 } 5832 5833 switch (opc2) { 5834 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5835 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5836 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5837 return False; 5838 } 5839 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5840 5841 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5842 5843 /* FIXME: this is confusing. lr_old holds the old value 5844 of ctr, not lr :-) */ 5845 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5846 5847 if (flag_LK) 5848 putGST( PPC_GST_LR, e_nia ); 5849 5850 stmt( IRStmt_Exit( 5851 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5852 Ijk_Boring, 5853 c_nia, OFFB_CIA )); 5854 5855 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5856 make_redzone_AbiHint( vbi, lr_old, 5857 "b-ctr-l (indirect call)" ); 5858 } 5859 5860 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5861 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5862 break; 5863 5864 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5865 Bool vanilla_return = False; 5866 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5867 DIP("blr\n"); 5868 vanilla_return = True; 5869 } else { 5870 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5871 } 5872 5873 if (!(BO & 0x4)) { 5874 putGST( PPC_GST_CTR, 5875 binop(mkSzOp(ty, Iop_Sub8), 5876 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5877 } 5878 5879 /* See comments above for 'bc' about this */ 5880 assign( ctr_ok, branch_ctr_ok( BO ) ); 5881 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5882 assign( do_branch, 5883 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5884 5885 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5886 5887 if (flag_LK) 5888 putGST( PPC_GST_LR, e_nia ); 5889 5890 stmt( IRStmt_Exit( 5891 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 5892 Ijk_Boring, 5893 c_nia, OFFB_CIA )); 5894 5895 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 5896 make_redzone_AbiHint( vbi, lr_old, 5897 "branch-to-lr (unconditional return)" ); 5898 } 5899 5900 /* blrl is pretty strange; it's like a return that sets the 5901 return address of its caller to the insn following this 5902 one. Mark it as a return. */ 5903 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 5904 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5905 break; 5906 } 5907 default: 5908 vex_printf("dis_int_branch(ppc)(opc2)\n"); 5909 return False; 5910 } 5911 break; 5912 5913 default: 5914 vex_printf("dis_int_branch(ppc)(opc1)\n"); 5915 return False; 5916 } 5917 5918 return True; 5919 } 5920 5921 5922 5923 /* 5924 Condition Register Logical Instructions 5925 */ 5926 static Bool dis_cond_logic ( UInt theInstr ) 5927 { 5928 /* XL-Form */ 5929 UChar opc1 = ifieldOPC(theInstr); 5930 UChar crbD_addr = ifieldRegDS(theInstr); 5931 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 5932 UChar crbA_addr = ifieldRegA(theInstr); 5933 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 5934 UChar crbB_addr = ifieldRegB(theInstr); 5935 UInt opc2 = ifieldOPClo10(theInstr); 5936 UChar b0 = ifieldBIT0(theInstr); 5937 5938 IRTemp crbD = newTemp(Ity_I32); 5939 IRTemp crbA = newTemp(Ity_I32); 5940 IRTemp crbB = newTemp(Ity_I32); 5941 5942 if (opc1 != 19 || b0 != 0) { 5943 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 5944 return False; 5945 } 5946 5947 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 5948 if (((crbD_addr & 0x3) != 0) || 5949 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 5950 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 5951 return False; 5952 } 5953 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 5954 putCR0( crfD_addr, getCR0( crfS_addr) ); 5955 putCR321( crfD_addr, getCR321(crfS_addr) ); 5956 } else { 5957 assign( crbA, getCRbit(crbA_addr) ); 5958 if (crbA_addr == crbB_addr) 5959 crbB = crbA; 5960 else 5961 assign( crbB, getCRbit(crbB_addr) ); 5962 5963 switch (opc2) { 5964 case 0x101: // crand (Cond Reg AND, PPC32 p372) 5965 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5966 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 5967 break; 5968 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 5969 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5970 assign( crbD, binop(Iop_And32, 5971 mkexpr(crbA), 5972 unop(Iop_Not32, mkexpr(crbB))) ); 5973 break; 5974 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 5975 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5976 assign( crbD, unop(Iop_Not32, 5977 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 5978 break; 5979 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 5980 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5981 assign( crbD, unop(Iop_Not32, 5982 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 5983 break; 5984 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 5985 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5986 assign( crbD, unop(Iop_Not32, 5987 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 5988 break; 5989 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 5990 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5991 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 5992 break; 5993 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 5994 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5995 assign( crbD, binop(Iop_Or32, 5996 mkexpr(crbA), 5997 unop(Iop_Not32, mkexpr(crbB))) ); 5998 break; 5999 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 6000 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6001 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 6002 break; 6003 default: 6004 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 6005 return False; 6006 } 6007 6008 putCRbit( crbD_addr, mkexpr(crbD) ); 6009 } 6010 return True; 6011 } 6012 6013 6014 /* 6015 Trap instructions 6016 */ 6017 6018 /* Do the code generation for a trap. Returned Bool is true iff 6019 this is an unconditional trap. If the two arg IRExpr*s are 6020 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 6021 then they are 64-bit, and we must be disassembling 64-bit 6022 instructions. */ 6023 static Bool do_trap ( UChar TO, 6024 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 6025 { 6026 IRTemp argL, argR; 6027 IRExpr *argLe, *argRe, *cond, *tmp; 6028 6029 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 6030 6031 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 6032 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 6033 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 6034 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 6035 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 6036 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 6037 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 6038 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 6039 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 6040 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 6041 6042 const UChar b11100 = 0x1C; 6043 const UChar b00111 = 0x07; 6044 6045 if (is32bit) { 6046 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 6047 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 6048 } else { 6049 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 6050 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 6051 vassert( mode64 ); 6052 } 6053 6054 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 6055 /* Unconditional trap. Just do the exit without 6056 testing the arguments. */ 6057 stmt( IRStmt_Exit( 6058 binop(opCMPEQ, const0, const0), 6059 Ijk_SigTRAP, 6060 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6061 OFFB_CIA 6062 )); 6063 return True; /* unconditional trap */ 6064 } 6065 6066 if (is32bit) { 6067 argL = newTemp(Ity_I32); 6068 argR = newTemp(Ity_I32); 6069 } else { 6070 argL = newTemp(Ity_I64); 6071 argR = newTemp(Ity_I64); 6072 } 6073 6074 assign( argL, argL0 ); 6075 assign( argR, argR0 ); 6076 6077 argLe = mkexpr(argL); 6078 argRe = mkexpr(argR); 6079 6080 cond = const0; 6081 if (TO & 16) { // L <s R 6082 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 6083 cond = binop(opOR, tmp, cond); 6084 } 6085 if (TO & 8) { // L >s R 6086 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 6087 cond = binop(opOR, tmp, cond); 6088 } 6089 if (TO & 4) { // L == R 6090 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 6091 cond = binop(opOR, tmp, cond); 6092 } 6093 if (TO & 2) { // L <u R 6094 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 6095 cond = binop(opOR, tmp, cond); 6096 } 6097 if (TO & 1) { // L >u R 6098 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 6099 cond = binop(opOR, tmp, cond); 6100 } 6101 stmt( IRStmt_Exit( 6102 binop(opCMPNE, cond, const0), 6103 Ijk_SigTRAP, 6104 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6105 OFFB_CIA 6106 )); 6107 return False; /* not an unconditional trap */ 6108 } 6109 6110 static Bool dis_trapi ( UInt theInstr, 6111 /*OUT*/DisResult* dres ) 6112 { 6113 /* D-Form */ 6114 UChar opc1 = ifieldOPC(theInstr); 6115 UChar TO = ifieldRegDS(theInstr); 6116 UChar rA_addr = ifieldRegA(theInstr); 6117 UInt uimm16 = ifieldUIMM16(theInstr); 6118 ULong simm16 = extend_s_16to64(uimm16); 6119 Addr64 cia = guest_CIA_curr_instr; 6120 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6121 Bool uncond = False; 6122 6123 switch (opc1) { 6124 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 6125 uncond = do_trap( TO, 6126 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6127 : getIReg(rA_addr), 6128 mkU32( (UInt)simm16 ), 6129 cia ); 6130 if (TO == 4) { 6131 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 6132 } else { 6133 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 6134 } 6135 break; 6136 case 0x02: // tdi 6137 if (!mode64) 6138 return False; 6139 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 6140 if (TO == 4) { 6141 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 6142 } else { 6143 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 6144 } 6145 break; 6146 default: 6147 return False; 6148 } 6149 6150 if (uncond) { 6151 /* If the trap shows signs of being unconditional, don't 6152 continue decoding past it. */ 6153 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6154 dres->jk_StopHere = Ijk_Boring; 6155 dres->whatNext = Dis_StopHere; 6156 } 6157 6158 return True; 6159 } 6160 6161 static Bool dis_trap ( UInt theInstr, 6162 /*OUT*/DisResult* dres ) 6163 { 6164 /* X-Form */ 6165 UInt opc2 = ifieldOPClo10(theInstr); 6166 UChar TO = ifieldRegDS(theInstr); 6167 UChar rA_addr = ifieldRegA(theInstr); 6168 UChar rB_addr = ifieldRegB(theInstr); 6169 Addr64 cia = guest_CIA_curr_instr; 6170 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6171 Bool uncond = False; 6172 6173 if (ifieldBIT0(theInstr) != 0) 6174 return False; 6175 6176 switch (opc2) { 6177 case 0x004: // tw (Trap Word, PPC64 p540) 6178 uncond = do_trap( TO, 6179 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6180 : getIReg(rA_addr), 6181 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 6182 : getIReg(rB_addr), 6183 cia ); 6184 if (TO == 4) { 6185 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6186 } else { 6187 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6188 } 6189 break; 6190 case 0x044: // td (Trap Doubleword, PPC64 p534) 6191 if (!mode64) 6192 return False; 6193 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 6194 if (TO == 4) { 6195 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6196 } else { 6197 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6198 } 6199 break; 6200 default: 6201 return False; 6202 } 6203 6204 if (uncond) { 6205 /* If the trap shows signs of being unconditional, don't 6206 continue decoding past it. */ 6207 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6208 dres->jk_StopHere = Ijk_Boring; 6209 dres->whatNext = Dis_StopHere; 6210 } 6211 6212 return True; 6213 } 6214 6215 6216 /* 6217 System Linkage Instructions 6218 */ 6219 static Bool dis_syslink ( UInt theInstr, 6220 const VexAbiInfo* abiinfo, DisResult* dres ) 6221 { 6222 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6223 6224 if (theInstr != 0x44000002) { 6225 vex_printf("dis_syslink(ppc)(theInstr)\n"); 6226 return False; 6227 } 6228 6229 // sc (System Call, PPC32 p504) 6230 DIP("sc\n"); 6231 6232 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 6233 Valgrind can back the guest up to this instruction if it needs 6234 to restart the syscall. */ 6235 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 6236 6237 /* It's important that all ArchRegs carry their up-to-date value 6238 at this point. So we declare an end-of-block here, which 6239 forces any TempRegs caching ArchRegs to be flushed. */ 6240 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6241 6242 dres->whatNext = Dis_StopHere; 6243 dres->jk_StopHere = Ijk_Sys_syscall; 6244 return True; 6245 } 6246 6247 6248 /* 6249 Memory Synchronization Instructions 6250 6251 Note on Reservations: 6252 We rely on the assumption that V will in fact only allow one thread at 6253 once to run. In effect, a thread can make a reservation, but we don't 6254 check any stores it does. Instead, the reservation is cancelled when 6255 the scheduler switches to another thread (run_thread_for_a_while()). 6256 */ 6257 static Bool dis_memsync ( UInt theInstr ) 6258 { 6259 /* X-Form, XL-Form */ 6260 UChar opc1 = ifieldOPC(theInstr); 6261 UInt b11to25 = IFIELD(theInstr, 11, 15); 6262 UChar flag_L = ifieldRegDS(theInstr); 6263 UInt b11to20 = IFIELD(theInstr, 11, 10); 6264 UChar rD_addr = ifieldRegDS(theInstr); 6265 UChar rS_addr = rD_addr; 6266 UChar rA_addr = ifieldRegA(theInstr); 6267 UChar rB_addr = ifieldRegB(theInstr); 6268 UInt opc2 = ifieldOPClo10(theInstr); 6269 UChar b0 = ifieldBIT0(theInstr); 6270 6271 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6272 IRTemp EA = newTemp(ty); 6273 6274 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6275 6276 switch (opc1) { 6277 /* XL-Form */ 6278 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 6279 if (opc2 != 0x096) { 6280 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 6281 return False; 6282 } 6283 if (b11to25 != 0 || b0 != 0) { 6284 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 6285 return False; 6286 } 6287 DIP("isync\n"); 6288 stmt( IRStmt_MBE(Imbe_Fence) ); 6289 break; 6290 6291 /* X-Form */ 6292 case 0x1F: 6293 switch (opc2) { 6294 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 6295 if (b11to25 != 0 || b0 != 0) { 6296 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 6297 return False; 6298 } 6299 DIP("eieio\n"); 6300 /* Insert a memory fence, just to be on the safe side. */ 6301 stmt( IRStmt_MBE(Imbe_Fence) ); 6302 break; 6303 6304 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 6305 IRTemp res; 6306 /* According to the PowerPC ISA version 2.05, b0 (called EH 6307 in the documentation) is merely a hint bit to the 6308 hardware, I think as to whether or not contention is 6309 likely. So we can just ignore it. */ 6310 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6311 6312 // trap if misaligned 6313 gen_SIGBUS_if_misaligned( EA, 4 ); 6314 6315 // and actually do the load 6316 res = newTemp(Ity_I32); 6317 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6318 6319 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 6320 break; 6321 } 6322 6323 case 0x034: { // lbarx (Load Word and Reserve Indexed) 6324 IRTemp res; 6325 /* According to the PowerPC ISA version 2.05, b0 (called EH 6326 in the documentation) is merely a hint bit to the 6327 hardware, I think as to whether or not contention is 6328 likely. So we can just ignore it. */ 6329 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6330 6331 // and actually do the load 6332 res = newTemp(Ity_I8); 6333 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6334 6335 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 6336 break; 6337 } 6338 6339 case 0x074: { // lharx (Load Word and Reserve Indexed) 6340 IRTemp res; 6341 /* According to the PowerPC ISA version 2.05, b0 (called EH 6342 in the documentation) is merely a hint bit to the 6343 hardware, I think as to whether or not contention is 6344 likely. So we can just ignore it. */ 6345 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6346 6347 // trap if misaligned 6348 gen_SIGBUS_if_misaligned( EA, 2 ); 6349 6350 // and actually do the load 6351 res = newTemp(Ity_I16); 6352 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6353 6354 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 6355 break; 6356 } 6357 6358 case 0x096: { 6359 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 6360 // Note this has to handle stwcx. in both 32- and 64-bit modes, 6361 // so isn't quite as straightforward as it might otherwise be. 6362 IRTemp rS = newTemp(Ity_I32); 6363 IRTemp resSC; 6364 if (b0 != 1) { 6365 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6366 return False; 6367 } 6368 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6369 6370 // trap if misaligned 6371 gen_SIGBUS_if_misaligned( EA, 4 ); 6372 6373 // Get the data to be stored, and narrow to 32 bits if necessary 6374 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6375 6376 // Do the store, and get success/failure bit into resSC 6377 resSC = newTemp(Ity_I1); 6378 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6379 6380 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6381 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6382 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6383 putCR0(0, getXER_SO()); 6384 6385 /* Note: 6386 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6387 whether rS is stored is dependent on that value. */ 6388 /* So I guess we can just ignore this case? */ 6389 break; 6390 } 6391 6392 case 0x2B6: { 6393 // stbcx. (Store Byte Conditional Indexed) 6394 // Note this has to handle stbcx. in both 32- and 64-bit modes, 6395 // so isn't quite as straightforward as it might otherwise be. 6396 IRTemp rS = newTemp(Ity_I8); 6397 IRTemp resSC; 6398 if (b0 != 1) { 6399 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 6400 return False; 6401 } 6402 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6403 6404 // Get the data to be stored, and narrow to 32 bits if necessary 6405 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 6406 6407 // Do the store, and get success/failure bit into resSC 6408 resSC = newTemp(Ity_I1); 6409 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6410 6411 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6412 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6413 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6414 putCR0(0, getXER_SO()); 6415 6416 /* Note: 6417 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 6418 whether rS is stored is dependent on that value. */ 6419 /* So I guess we can just ignore this case? */ 6420 break; 6421 } 6422 6423 case 0x2D6: { 6424 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 6425 // Note this has to handle sthcx. in both 32- and 64-bit modes, 6426 // so isn't quite as straightforward as it might otherwise be. 6427 IRTemp rS = newTemp(Ity_I16); 6428 IRTemp resSC; 6429 if (b0 != 1) { 6430 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6431 return False; 6432 } 6433 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6434 6435 // trap if misaligned 6436 gen_SIGBUS_if_misaligned( EA, 2 ); 6437 6438 // Get the data to be stored, and narrow to 16 bits if necessary 6439 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 6440 6441 // Do the store, and get success/failure bit into resSC 6442 resSC = newTemp(Ity_I1); 6443 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6444 6445 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6446 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6447 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6448 putCR0(0, getXER_SO()); 6449 6450 /* Note: 6451 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 6452 whether rS is stored is dependent on that value. */ 6453 /* So I guess we can just ignore this case? */ 6454 break; 6455 } 6456 6457 case 0x256: // sync (Synchronize, PPC32 p543), 6458 // also lwsync (L==1), ptesync (L==2) 6459 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 6460 6461 The PowerPC architecture used in IBM chips has expanded 6462 the sync instruction into two variants: lightweight sync 6463 and heavyweight sync. The original sync instruction is 6464 the new heavyweight sync and lightweight sync is a strict 6465 subset of the heavyweight sync functionality. This allows 6466 the programmer to specify a less expensive operation on 6467 high-end systems when the full sync functionality is not 6468 necessary. 6469 6470 The basic "sync" mnemonic now utilizes an operand. "sync" 6471 without an operand now becomes a extended mnemonic for 6472 heavyweight sync. Processors without the lwsync 6473 instruction will not decode the L field and will perform a 6474 heavyweight sync. Everything is backward compatible. 6475 6476 sync = sync 0 6477 lwsync = sync 1 6478 ptesync = sync 2 *** TODO - not implemented *** 6479 */ 6480 if (b11to20 != 0 || b0 != 0) { 6481 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 6482 return False; 6483 } 6484 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 6485 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 6486 return False; 6487 } 6488 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 6489 /* Insert a memory fence. It's sometimes important that these 6490 are carried through to the generated code. */ 6491 stmt( IRStmt_MBE(Imbe_Fence) ); 6492 break; 6493 6494 /* 64bit Memsync */ 6495 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 6496 IRTemp res; 6497 /* According to the PowerPC ISA version 2.05, b0 (called EH 6498 in the documentation) is merely a hint bit to the 6499 hardware, I think as to whether or not contention is 6500 likely. So we can just ignore it. */ 6501 if (!mode64) 6502 return False; 6503 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6504 6505 // trap if misaligned 6506 gen_SIGBUS_if_misaligned( EA, 8 ); 6507 6508 // and actually do the load 6509 res = newTemp(Ity_I64); 6510 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 6511 6512 putIReg( rD_addr, mkexpr(res) ); 6513 break; 6514 } 6515 6516 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 6517 // A marginally simplified version of the stwcx. case 6518 IRTemp rS = newTemp(Ity_I64); 6519 IRTemp resSC; 6520 if (b0 != 1) { 6521 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 6522 return False; 6523 } 6524 if (!mode64) 6525 return False; 6526 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6527 6528 // trap if misaligned 6529 gen_SIGBUS_if_misaligned( EA, 8 ); 6530 6531 // Get the data to be stored 6532 assign( rS, getIReg(rS_addr) ); 6533 6534 // Do the store, and get success/failure bit into resSC 6535 resSC = newTemp(Ity_I1); 6536 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6537 6538 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6539 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6540 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6541 putCR0(0, getXER_SO()); 6542 6543 /* Note: 6544 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6545 whether rS is stored is dependent on that value. */ 6546 /* So I guess we can just ignore this case? */ 6547 break; 6548 } 6549 6550 /* 128bit Memsync */ 6551 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 6552 IRTemp res_hi = newTemp(ty); 6553 IRTemp res_lo = newTemp(ty); 6554 6555 /* According to the PowerPC ISA version 2.07, b0 (called EH 6556 in the documentation) is merely a hint bit to the 6557 hardware, I think as to whether or not contention is 6558 likely. So we can just ignore it. */ 6559 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6560 6561 // trap if misaligned 6562 gen_SIGBUS_if_misaligned( EA, 16 ); 6563 6564 // and actually do the load 6565 if (mode64) { 6566 if (host_endness == VexEndnessBE) { 6567 stmt( stmt_load( res_hi, 6568 mkexpr(EA), NULL/*this is a load*/) ); 6569 stmt( stmt_load( res_lo, 6570 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6571 NULL/*this is a load*/) ); 6572 } else { 6573 stmt( stmt_load( res_lo, 6574 mkexpr(EA), NULL/*this is a load*/) ); 6575 stmt( stmt_load( res_hi, 6576 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6577 NULL/*this is a load*/) ); 6578 } 6579 } else { 6580 stmt( stmt_load( res_hi, 6581 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 6582 NULL/*this is a load*/) ); 6583 stmt( stmt_load( res_lo, 6584 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 6585 NULL/*this is a load*/) ); 6586 } 6587 putIReg( rD_addr, mkexpr(res_hi) ); 6588 putIReg( rD_addr+1, mkexpr(res_lo) ); 6589 break; 6590 } 6591 6592 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 6593 // A marginally simplified version of the stwcx. case 6594 IRTemp rS_hi = newTemp(ty); 6595 IRTemp rS_lo = newTemp(ty); 6596 IRTemp resSC; 6597 if (b0 != 1) { 6598 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 6599 return False; 6600 } 6601 6602 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6603 6604 // trap if misaligned 6605 gen_SIGBUS_if_misaligned( EA, 16 ); 6606 // Get the data to be stored 6607 assign( rS_hi, getIReg(rS_addr) ); 6608 assign( rS_lo, getIReg(rS_addr+1) ); 6609 6610 // Do the store, and get success/failure bit into resSC 6611 resSC = newTemp(Ity_I1); 6612 6613 if (mode64) { 6614 if (host_endness == VexEndnessBE) { 6615 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 6616 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6617 mkexpr(rS_lo) ); 6618 } else { 6619 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 6620 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6621 mkexpr(rS_hi) ); 6622 } 6623 } else { 6624 stmt( stmt_load( resSC, binop( Iop_Add32, 6625 mkexpr(EA), 6626 mkU32(4) ), 6627 mkexpr(rS_hi) ) ); 6628 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 6629 } 6630 6631 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6632 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6633 putCR321(0, binop( Iop_Shl8, 6634 unop(Iop_1Uto8, mkexpr(resSC) ), 6635 mkU8(1))); 6636 putCR0(0, getXER_SO()); 6637 break; 6638 } 6639 6640 default: 6641 vex_printf("dis_memsync(ppc)(opc2)\n"); 6642 return False; 6643 } 6644 break; 6645 6646 default: 6647 vex_printf("dis_memsync(ppc)(opc1)\n"); 6648 return False; 6649 } 6650 return True; 6651 } 6652 6653 6654 6655 /* 6656 Integer Shift Instructions 6657 */ 6658 static Bool dis_int_shift ( UInt theInstr ) 6659 { 6660 /* X-Form, XS-Form */ 6661 UChar opc1 = ifieldOPC(theInstr); 6662 UChar rS_addr = ifieldRegDS(theInstr); 6663 UChar rA_addr = ifieldRegA(theInstr); 6664 UChar rB_addr = ifieldRegB(theInstr); 6665 UChar sh_imm = rB_addr; 6666 UInt opc2 = ifieldOPClo10(theInstr); 6667 UChar b1 = ifieldBIT1(theInstr); 6668 UChar flag_rC = ifieldBIT0(theInstr); 6669 6670 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6671 IRTemp rA = newTemp(ty); 6672 IRTemp rS = newTemp(ty); 6673 IRTemp rB = newTemp(ty); 6674 IRTemp outofrange = newTemp(Ity_I1); 6675 IRTemp rS_lo32 = newTemp(Ity_I32); 6676 IRTemp rB_lo32 = newTemp(Ity_I32); 6677 IRExpr* e_tmp; 6678 6679 assign( rS, getIReg(rS_addr) ); 6680 assign( rB, getIReg(rB_addr) ); 6681 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6682 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6683 6684 if (opc1 == 0x1F) { 6685 switch (opc2) { 6686 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6687 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6688 rA_addr, rS_addr, rB_addr); 6689 /* rA = rS << rB */ 6690 /* ppc32 semantics are: 6691 slw(x,y) = (x << (y & 31)) -- primary result 6692 & ~((y << 26) >>s 31) -- make result 0 6693 for y in 32 .. 63 6694 */ 6695 e_tmp = 6696 binop( Iop_And32, 6697 binop( Iop_Shl32, 6698 mkexpr(rS_lo32), 6699 unop( Iop_32to8, 6700 binop(Iop_And32, 6701 mkexpr(rB_lo32), mkU32(31)))), 6702 unop( Iop_Not32, 6703 binop( Iop_Sar32, 6704 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6705 mkU8(31))) ); 6706 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6707 break; 6708 } 6709 6710 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6711 IRTemp sh_amt = newTemp(Ity_I32); 6712 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6713 rA_addr, rS_addr, rB_addr); 6714 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6715 amt = rB & 63 6716 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6717 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6718 */ 6719 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6720 mkexpr(rB_lo32)) ); 6721 assign( outofrange, 6722 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 6723 e_tmp = binop( Iop_Sar32, 6724 mkexpr(rS_lo32), 6725 unop( Iop_32to8, 6726 IRExpr_ITE( mkexpr(outofrange), 6727 mkU32(31), 6728 mkexpr(sh_amt)) ) ); 6729 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6730 6731 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6732 mkexpr(rA), 6733 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6734 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6735 mkWidenFrom32(ty, getXER_CA32(), True) ); 6736 break; 6737 } 6738 6739 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6740 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6741 rA_addr, rS_addr, sh_imm); 6742 vassert(sh_imm < 32); 6743 if (mode64) { 6744 assign( rA, binop(Iop_Sar64, 6745 binop(Iop_Shl64, getIReg(rS_addr), 6746 mkU8(32)), 6747 mkU8(32 + sh_imm)) ); 6748 } else { 6749 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6750 mkU8(sh_imm)) ); 6751 } 6752 6753 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6754 mkexpr(rA), 6755 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6756 mkSzImm(ty, sh_imm), 6757 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6758 break; 6759 6760 case 0x218: // srw (Shift Right Word, PPC32 p508) 6761 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6762 rA_addr, rS_addr, rB_addr); 6763 /* rA = rS >>u rB */ 6764 /* ppc32 semantics are: 6765 srw(x,y) = (x >>u (y & 31)) -- primary result 6766 & ~((y << 26) >>s 31) -- make result 0 6767 for y in 32 .. 63 6768 */ 6769 e_tmp = 6770 binop( 6771 Iop_And32, 6772 binop( Iop_Shr32, 6773 mkexpr(rS_lo32), 6774 unop( Iop_32to8, 6775 binop(Iop_And32, mkexpr(rB_lo32), 6776 mkU32(31)))), 6777 unop( Iop_Not32, 6778 binop( Iop_Sar32, 6779 binop(Iop_Shl32, mkexpr(rB_lo32), 6780 mkU8(26)), 6781 mkU8(31)))); 6782 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6783 break; 6784 6785 6786 /* 64bit Shifts */ 6787 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6788 DIP("sld%s r%u,r%u,r%u\n", 6789 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6790 /* rA = rS << rB */ 6791 /* ppc64 semantics are: 6792 slw(x,y) = (x << (y & 63)) -- primary result 6793 & ~((y << 57) >>s 63) -- make result 0 6794 for y in 64 .. 6795 */ 6796 assign( rA, 6797 binop( 6798 Iop_And64, 6799 binop( Iop_Shl64, 6800 mkexpr(rS), 6801 unop( Iop_64to8, 6802 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6803 unop( Iop_Not64, 6804 binop( Iop_Sar64, 6805 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6806 mkU8(63)))) ); 6807 break; 6808 6809 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6810 IRTemp sh_amt = newTemp(Ity_I64); 6811 DIP("srad%s r%u,r%u,r%u\n", 6812 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6813 /* amt = rB & 127 6814 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6815 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6816 */ 6817 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6818 assign( outofrange, 6819 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 6820 assign( rA, 6821 binop( Iop_Sar64, 6822 mkexpr(rS), 6823 unop( Iop_64to8, 6824 IRExpr_ITE( mkexpr(outofrange), 6825 mkU64(63), 6826 mkexpr(sh_amt)) )) 6827 ); 6828 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6829 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6830 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6831 break; 6832 } 6833 6834 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6835 sh_imm |= b1<<5; 6836 vassert(sh_imm < 64); 6837 DIP("sradi%s r%u,r%u,%u\n", 6838 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6839 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6840 6841 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6842 mkexpr(rA), 6843 getIReg(rS_addr), 6844 mkU64(sh_imm), 6845 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6846 break; 6847 6848 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6849 DIP("srd%s r%u,r%u,r%u\n", 6850 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6851 /* rA = rS >>u rB */ 6852 /* ppc semantics are: 6853 srw(x,y) = (x >>u (y & 63)) -- primary result 6854 & ~((y << 57) >>s 63) -- make result 0 6855 for y in 64 .. 127 6856 */ 6857 assign( rA, 6858 binop( 6859 Iop_And64, 6860 binop( Iop_Shr64, 6861 mkexpr(rS), 6862 unop( Iop_64to8, 6863 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6864 unop( Iop_Not64, 6865 binop( Iop_Sar64, 6866 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6867 mkU8(63)))) ); 6868 break; 6869 6870 default: 6871 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6872 return False; 6873 } 6874 } else { 6875 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6876 return False; 6877 } 6878 6879 putIReg( rA_addr, mkexpr(rA) ); 6880 6881 if (flag_rC) { 6882 set_CR0( mkexpr(rA) ); 6883 } 6884 return True; 6885 } 6886 6887 6888 6889 /* 6890 Integer Load/Store Reverse Instructions 6891 */ 6892 /* Generates code to swap the byte order in an Ity_I32. */ 6893 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 6894 { 6895 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6896 return 6897 binop(Iop_Or32, 6898 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 6899 binop(Iop_Or32, 6900 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6901 mkU32(0x00FF0000)), 6902 binop(Iop_Or32, 6903 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6904 mkU32(0x0000FF00)), 6905 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 6906 mkU32(0x000000FF) ) 6907 ))); 6908 } 6909 6910 /* Generates code to swap the byte order in the lower half of an Ity_I32, 6911 and zeroes the upper half. */ 6912 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 6913 { 6914 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6915 return 6916 binop(Iop_Or32, 6917 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6918 mkU32(0x0000FF00)), 6919 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6920 mkU32(0x000000FF)) 6921 ); 6922 } 6923 6924 static Bool dis_int_ldst_rev ( UInt theInstr ) 6925 { 6926 /* X-Form */ 6927 UChar opc1 = ifieldOPC(theInstr); 6928 UChar rD_addr = ifieldRegDS(theInstr); 6929 UChar rS_addr = rD_addr; 6930 UChar rA_addr = ifieldRegA(theInstr); 6931 UChar rB_addr = ifieldRegB(theInstr); 6932 UInt opc2 = ifieldOPClo10(theInstr); 6933 UChar b0 = ifieldBIT0(theInstr); 6934 6935 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6936 IRTemp EA = newTemp(ty); 6937 IRTemp w1 = newTemp(Ity_I32); 6938 IRTemp w2 = newTemp(Ity_I32); 6939 6940 if (opc1 != 0x1F || b0 != 0) { 6941 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 6942 return False; 6943 } 6944 6945 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6946 6947 switch (opc2) { 6948 6949 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 6950 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6951 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 6952 assign( w2, gen_byterev16(w1) ); 6953 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6954 /* Signed */False) ); 6955 break; 6956 6957 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 6958 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6959 assign( w1, load(Ity_I32, mkexpr(EA)) ); 6960 assign( w2, gen_byterev32(w1) ); 6961 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6962 /* Signed */False) ); 6963 break; 6964 6965 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 6966 { 6967 IRExpr * nextAddr; 6968 IRTemp w3 = newTemp( Ity_I32 ); 6969 IRTemp w4 = newTemp( Ity_I32 ); 6970 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6971 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 6972 assign( w2, gen_byterev32( w1 ) ); 6973 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 6974 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 6975 assign( w3, load( Ity_I32, nextAddr ) ); 6976 assign( w4, gen_byterev32( w3 ) ); 6977 if (host_endness == VexEndnessLE) 6978 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 6979 else 6980 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 6981 break; 6982 } 6983 6984 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 6985 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6986 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6987 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 6988 break; 6989 6990 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 6991 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6992 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6993 store( mkexpr(EA), gen_byterev32(w1) ); 6994 break; 6995 6996 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 6997 { 6998 IRTemp lo = newTemp(Ity_I32); 6999 IRTemp hi = newTemp(Ity_I32); 7000 IRTemp rS = newTemp(Ity_I64); 7001 assign( rS, getIReg( rS_addr ) ); 7002 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7003 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 7004 assign(hi, unop(Iop_64to32, mkexpr(rS))); 7005 store( mkexpr( EA ), 7006 binop( Iop_32HLto64, gen_byterev32( hi ), 7007 gen_byterev32( lo ) ) ); 7008 break; 7009 } 7010 7011 default: 7012 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 7013 return False; 7014 } 7015 return True; 7016 } 7017 7018 7019 7020 /* 7021 Processor Control Instructions 7022 */ 7023 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 7024 { 7025 UChar opc1 = ifieldOPC(theInstr); 7026 7027 /* X-Form */ 7028 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7029 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7030 UChar rD_addr = ifieldRegDS(theInstr); 7031 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 7032 7033 /* XFX-Form */ 7034 UChar rS_addr = rD_addr; 7035 UInt SPR = b11to20; 7036 UInt TBR = b11to20; 7037 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 7038 UInt CRM = IFIELD( theInstr, 12, 8 ); 7039 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 7040 7041 UInt opc2 = ifieldOPClo10(theInstr); 7042 UChar b0 = ifieldBIT0(theInstr); 7043 7044 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7045 IRTemp rS = newTemp(ty); 7046 assign( rS, getIReg(rS_addr) ); 7047 7048 /* Reorder SPR field as per PPC32 p470 */ 7049 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 7050 /* Reorder TBR field as per PPC32 p475 */ 7051 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 7052 7053 /* b0 = 0, inst is treated as floating point inst for reservation purposes 7054 * b0 = 1, inst is treated as vector inst for reservation purposes 7055 */ 7056 if (opc1 != 0x1F) { 7057 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 7058 return False; 7059 } 7060 7061 switch (opc2) { 7062 /* X-Form */ 7063 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 7064 if (b21to22 != 0 || b11to20 != 0) { 7065 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 7066 return False; 7067 } 7068 DIP("mcrxr crf%d\n", crfD); 7069 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 7070 putGST_field( PPC_GST_CR, 7071 getGST_field( PPC_GST_XER, 7 ), 7072 crfD ); 7073 7074 // Clear XER[0-3] 7075 putXER_SO( mkU8(0) ); 7076 putXER_OV( mkU8(0) ); 7077 putXER_CA( mkU8(0) ); 7078 break; 7079 } 7080 7081 case 0x013: 7082 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 7083 // b20==1 & b11==0: mfocrf (Move from One CR Field) 7084 // However it seems that the 'mfcr' behaviour is an acceptable 7085 // implementation of mfocr (from the 2.02 arch spec) 7086 if (b11to20 == 0) { 7087 DIP("mfcr r%u\n", rD_addr); 7088 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7089 /* Signed */False) ); 7090 break; 7091 } 7092 if (b20 == 1 && b11 == 0) { 7093 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 7094 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7095 /* Signed */False) ); 7096 break; 7097 } 7098 /* not decodable */ 7099 return False; 7100 7101 /* XFX-Form */ 7102 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 7103 7104 switch (SPR) { // Choose a register... 7105 case 0x1: 7106 DIP("mfxer r%u\n", rD_addr); 7107 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 7108 /* Signed */False) ); 7109 break; 7110 case 0x8: 7111 DIP("mflr r%u\n", rD_addr); 7112 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 7113 break; 7114 case 0x9: 7115 DIP("mfctr r%u\n", rD_addr); 7116 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 7117 break; 7118 case 0x80: // 128 7119 DIP("mfspr r%u (TFHAR)\n", rD_addr); 7120 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 7121 break; 7122 case 0x81: // 129 7123 DIP("mfspr r%u (TFIAR)\n", rD_addr); 7124 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 7125 break; 7126 case 0x82: // 130 7127 DIP("mfspr r%u (TEXASR)\n", rD_addr); 7128 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 7129 break; 7130 case 0x83: // 131 7131 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 7132 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 7133 break; 7134 case 0x100: 7135 DIP("mfvrsave r%u\n", rD_addr); 7136 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 7137 /* Signed */False) ); 7138 break; 7139 7140 case 0x103: 7141 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 7142 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 7143 break; 7144 7145 /* Even a lowly PPC7400 can run the associated helper, so no 7146 obvious need for feature testing at this point. */ 7147 case 268 /* 0x10C */: 7148 case 269 /* 0x10D */: { 7149 UInt arg = SPR==268 ? 0 : 1; 7150 IRTemp val = newTemp(Ity_I32); 7151 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 7152 IRDirty* d = unsafeIRDirty_1_N( 7153 val, 7154 0/*regparms*/, 7155 "ppc32g_dirtyhelper_MFSPR_268_269", 7156 fnptr_to_fnentry 7157 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 7158 args 7159 ); 7160 /* execute the dirty call, dumping the result in val. */ 7161 stmt( IRStmt_Dirty(d) ); 7162 putIReg( rD_addr, 7163 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7164 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 7165 break; 7166 } 7167 7168 /* Again, runs natively on PPC7400 (7447, really). Not 7169 bothering with a feature test. */ 7170 case 287: /* 0x11F */ { 7171 IRTemp val = newTemp(Ity_I32); 7172 IRExpr** args = mkIRExprVec_0(); 7173 IRDirty* d = unsafeIRDirty_1_N( 7174 val, 7175 0/*regparms*/, 7176 "ppc32g_dirtyhelper_MFSPR_287", 7177 fnptr_to_fnentry 7178 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 7179 args 7180 ); 7181 /* execute the dirty call, dumping the result in val. */ 7182 stmt( IRStmt_Dirty(d) ); 7183 putIReg( rD_addr, 7184 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7185 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 7186 break; 7187 } 7188 7189 default: 7190 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 7191 return False; 7192 } 7193 break; 7194 7195 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 7196 IRTemp val = newTemp(Ity_I64); 7197 IRExpr** args = mkIRExprVec_0(); 7198 IRDirty* d = unsafeIRDirty_1_N( 7199 val, 7200 0/*regparms*/, 7201 "ppcg_dirtyhelper_MFTB", 7202 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 7203 args ); 7204 /* execute the dirty call, dumping the result in val. */ 7205 stmt( IRStmt_Dirty(d) ); 7206 7207 switch (TBR) { 7208 case 269: 7209 DIP("mftbu r%u", rD_addr); 7210 putIReg( rD_addr, 7211 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 7212 /* Signed */False) ); 7213 break; 7214 case 268: 7215 DIP("mftb r%u", rD_addr); 7216 putIReg( rD_addr, (mode64) ? mkexpr(val) : 7217 unop(Iop_64to32, mkexpr(val)) ); 7218 break; 7219 default: 7220 return False; /* illegal instruction */ 7221 } 7222 break; 7223 } 7224 7225 case 0x090: { 7226 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 7227 // b20==1: mtocrf (Move to One Cond Reg Field) 7228 Int cr; 7229 UChar shft; 7230 if (b11 != 0) 7231 return False; 7232 if (b20 == 1) { 7233 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 7234 1 field is written. It seems more robust to decline to 7235 decode the insn if so. */ 7236 switch (CRM) { 7237 case 0x01: case 0x02: case 0x04: case 0x08: 7238 case 0x10: case 0x20: case 0x40: case 0x80: 7239 break; 7240 default: 7241 return False; 7242 } 7243 } 7244 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 7245 CRM, rS_addr); 7246 /* Write to each field specified by CRM */ 7247 for (cr = 0; cr < 8; cr++) { 7248 if ((CRM & (1 << (7-cr))) == 0) 7249 continue; 7250 shft = 4*(7-cr); 7251 putGST_field( PPC_GST_CR, 7252 binop(Iop_Shr32, 7253 mkNarrowTo32(ty, mkexpr(rS)), 7254 mkU8(shft)), cr ); 7255 } 7256 break; 7257 } 7258 7259 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 7260 7261 switch (SPR) { // Choose a register... 7262 case 0x1: 7263 DIP("mtxer r%u\n", rS_addr); 7264 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 7265 break; 7266 case 0x8: 7267 DIP("mtlr r%u\n", rS_addr); 7268 putGST( PPC_GST_LR, mkexpr(rS) ); 7269 break; 7270 case 0x9: 7271 DIP("mtctr r%u\n", rS_addr); 7272 putGST( PPC_GST_CTR, mkexpr(rS) ); 7273 break; 7274 case 0x100: 7275 DIP("mtvrsave r%u\n", rS_addr); 7276 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 7277 break; 7278 case 0x80: // 128 7279 DIP("mtspr r%u (TFHAR)\n", rS_addr); 7280 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 7281 break; 7282 case 0x81: // 129 7283 DIP("mtspr r%u (TFIAR)\n", rS_addr); 7284 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 7285 break; 7286 case 0x82: // 130 7287 DIP("mtspr r%u (TEXASR)\n", rS_addr); 7288 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 7289 break; 7290 default: 7291 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 7292 return False; 7293 } 7294 break; 7295 7296 case 0x33: // mfvsrd 7297 { 7298 UChar XS = ifieldRegXS( theInstr ); 7299 UChar rA_addr = ifieldRegA(theInstr); 7300 IRExpr * high64; 7301 IRTemp vS = newTemp( Ity_V128 ); 7302 DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS); 7303 7304 /* XS = SX || S 7305 * For SX=0, mfvsrd is treated as a Floating-Point 7306 * instruction in terms of resource availability. 7307 * For SX=1, mfvsrd is treated as a Vector instruction in 7308 * terms of resource availability. 7309 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7310 */ 7311 assign( vS, getVSReg( XS ) ); 7312 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7313 putIReg( rA_addr, (mode64) ? high64 : 7314 unop( Iop_64to32, high64 ) ); 7315 break; 7316 } 7317 7318 case 0x73: // mfvsrwz 7319 { 7320 UChar XS = ifieldRegXS( theInstr ); 7321 UChar rA_addr = ifieldRegA(theInstr); 7322 IRExpr * high64; 7323 IRTemp vS = newTemp( Ity_V128 ); 7324 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS); 7325 /* XS = SX || S 7326 * For SX=0, mfvsrwz is treated as a Floating-Point 7327 * instruction in terms of resource availability. 7328 * For SX=1, mfvsrwz is treated as a Vector instruction in 7329 * terms of resource availability. 7330 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7331 */ 7332 7333 assign( vS, getVSReg( XS ) ); 7334 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7335 /* move value to the destination setting the upper 32-bits to zero */ 7336 putIReg( rA_addr, (mode64) ? 7337 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 7338 unop( Iop_64to32, 7339 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 7340 break; 7341 } 7342 7343 case 0xB3: // mtvsrd 7344 { 7345 UChar XT = ifieldRegXT( theInstr ); 7346 UChar rA_addr = ifieldRegA(theInstr); 7347 IRTemp rA = newTemp(ty); 7348 DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr); 7349 /* XS = SX || S 7350 * For SX=0, mfvsrd is treated as a Floating-Point 7351 * instruction in terms of resource availability. 7352 * For SX=1, mfvsrd is treated as a Vector instruction in 7353 * terms of resource availability. 7354 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7355 */ 7356 assign( rA, getIReg(rA_addr) ); 7357 7358 if (mode64) 7359 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 7360 else 7361 putVSReg( XT, binop( Iop_64HLtoV128, 7362 binop( Iop_32HLto64, 7363 mkU32( 0 ), 7364 mkexpr( rA ) ), 7365 mkU64( 0 ) ) ); 7366 break; 7367 } 7368 7369 case 0xD3: // mtvsrwa 7370 { 7371 UChar XT = ifieldRegXT( theInstr ); 7372 UChar rA_addr = ifieldRegA(theInstr); 7373 IRTemp rA = newTemp( Ity_I32 ); 7374 DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr); 7375 /* XS = SX || S 7376 * For SX=0, mtvsrwa is treated as a Floating-Point 7377 * instruction in terms of resource availability. 7378 * For SX=1, mtvsrwa is treated as a Vector instruction in 7379 * terms of resource availability. 7380 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7381 */ 7382 if (mode64) 7383 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7384 else 7385 assign( rA, getIReg(rA_addr) ); 7386 7387 putVSReg( XT, binop( Iop_64HLtoV128, 7388 unop( Iop_32Sto64, mkexpr( rA ) ), 7389 mkU64( 0 ) ) ); 7390 break; 7391 } 7392 7393 case 0xF3: // mtvsrwz 7394 { 7395 UChar XT = ifieldRegXT( theInstr ); 7396 UChar rA_addr = ifieldRegA(theInstr); 7397 IRTemp rA = newTemp( Ity_I32 ); 7398 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT); 7399 /* XS = SX || S 7400 * For SX=0, mtvsrwz is treated as a Floating-Point 7401 * instruction in terms of resource availability. 7402 * For SX=1, mtvsrwz is treated as a Vector instruction in 7403 * terms of resource availability. 7404 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7405 */ 7406 if (mode64) 7407 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7408 else 7409 assign( rA, getIReg(rA_addr) ); 7410 7411 putVSReg( XT, binop( Iop_64HLtoV128, 7412 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 7413 mkU64( 0 ) ) ); 7414 break; 7415 } 7416 7417 default: 7418 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 7419 return False; 7420 } 7421 return True; 7422 } 7423 7424 7425 /* 7426 Cache Management Instructions 7427 */ 7428 static Bool dis_cache_manage ( UInt theInstr, 7429 DisResult* dres, 7430 const VexArchInfo* guest_archinfo ) 7431 { 7432 /* X-Form */ 7433 UChar opc1 = ifieldOPC(theInstr); 7434 UChar b21to25 = ifieldRegDS(theInstr); 7435 UChar rA_addr = ifieldRegA(theInstr); 7436 UChar rB_addr = ifieldRegB(theInstr); 7437 UInt opc2 = ifieldOPClo10(theInstr); 7438 UChar b0 = ifieldBIT0(theInstr); 7439 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 7440 Bool is_dcbzl = False; 7441 7442 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7443 7444 // Check for valid hint values for dcbt and dcbtst as currently described in 7445 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 7446 // means of modeling the hint anyway. 7447 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 7448 if (b21to25 == 0x10 || b21to25 < 0x10) 7449 b21to25 = 0; 7450 } 7451 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 7452 b21to25 = 0; 7453 7454 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 7455 if (b21to25 == 1) { 7456 is_dcbzl = True; 7457 b21to25 = 0; 7458 if (!(guest_archinfo->ppc_dcbzl_szB)) { 7459 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 7460 return False; 7461 } 7462 } 7463 } 7464 7465 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 7466 if (0) vex_printf("dis_cache_manage %d %d %d\n", 7467 (Int)opc1, (Int)b21to25, (Int)b0); 7468 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 7469 return False; 7470 } 7471 7472 /* stay sane .. */ 7473 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 7474 7475 switch (opc2) { 7476 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 7477 //zz vassert(0); /* AWAITING TEST CASE */ 7478 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 7479 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 7480 //zz break; 7481 7482 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 7483 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 7484 /* nop as far as vex is concerned */ 7485 break; 7486 7487 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 7488 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 7489 /* nop as far as vex is concerned */ 7490 break; 7491 7492 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 7493 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 7494 /* nop as far as vex is concerned */ 7495 break; 7496 7497 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 7498 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 7499 /* nop as far as vex is concerned */ 7500 break; 7501 7502 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 7503 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 7504 /* Clear all bytes in cache block at (rA|0) + rB. */ 7505 IRTemp EA = newTemp(ty); 7506 IRTemp addr = newTemp(ty); 7507 IRExpr* irx_addr; 7508 UInt i; 7509 UInt clearszB; 7510 if (is_dcbzl) { 7511 clearszB = guest_archinfo->ppc_dcbzl_szB; 7512 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 7513 } 7514 else { 7515 clearszB = guest_archinfo->ppc_dcbz_szB; 7516 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 7517 } 7518 7519 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7520 7521 if (mode64) { 7522 /* Round EA down to the start of the containing block. */ 7523 assign( addr, binop( Iop_And64, 7524 mkexpr(EA), 7525 mkU64( ~((ULong)clearszB-1) )) ); 7526 7527 for (i = 0; i < clearszB / 8; i++) { 7528 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 7529 store( irx_addr, mkU64(0) ); 7530 } 7531 } else { 7532 /* Round EA down to the start of the containing block. */ 7533 assign( addr, binop( Iop_And32, 7534 mkexpr(EA), 7535 mkU32( ~(clearszB-1) )) ); 7536 7537 for (i = 0; i < clearszB / 4; i++) { 7538 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 7539 store( irx_addr, mkU32(0) ); 7540 } 7541 } 7542 break; 7543 } 7544 7545 case 0x3D6: { 7546 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 7547 /* Invalidate all translations containing code from the cache 7548 block at (rA|0) + rB. */ 7549 IRTemp EA = newTemp(ty); 7550 IRTemp addr = newTemp(ty); 7551 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 7552 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7553 7554 /* Round EA down to the start of the containing block. */ 7555 assign( addr, binop( mkSzOp(ty, Iop_And8), 7556 mkexpr(EA), 7557 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 7558 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 7559 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 7560 7561 /* be paranoid ... */ 7562 stmt( IRStmt_MBE(Imbe_Fence) ); 7563 7564 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 7565 dres->jk_StopHere = Ijk_InvalICache; 7566 dres->whatNext = Dis_StopHere; 7567 break; 7568 } 7569 7570 default: 7571 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 7572 return False; 7573 } 7574 return True; 7575 } 7576 7577 7578 /*------------------------------------------------------------*/ 7579 /*--- Floating Point Helpers ---*/ 7580 /*------------------------------------------------------------*/ 7581 7582 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 7583 /* Produces a value in 0 .. 3, which is encoded as per the type 7584 IRRoundingMode. PPCRoundingMode encoding is different to 7585 IRRoundingMode, so need to map it. 7586 */ 7587 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 7588 { 7589 /* 7590 rounding mode | PPC | IR 7591 ------------------------ 7592 to nearest | 00 | 00 7593 to zero | 01 | 11 7594 to +infinity | 10 | 10 7595 to -infinity | 11 | 01 7596 */ 7597 IRTemp rm_PPC32 = newTemp(Ity_I32); 7598 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 7599 7600 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7601 return binop( Iop_Xor32, 7602 mkexpr(rm_PPC32), 7603 binop( Iop_And32, 7604 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 7605 mkU32(2) )); 7606 } 7607 7608 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 7609 * mapping would still work with the extended three bit DFP rounding 7610 * mode designator. 7611 7612 * rounding mode | PPC | IR 7613 * ----------------------------------------------- 7614 * to nearest, ties to even | 000 | 000 7615 * to zero | 001 | 011 7616 * to +infinity | 010 | 010 7617 * to -infinity | 011 | 001 7618 * to nearest, ties away from 0 | 100 | 100 7619 * to nearest, ties toward 0 | 101 | 111 7620 * to away from 0 | 110 | 110 7621 * to prepare for shorter precision | 111 | 101 7622 */ 7623 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 7624 { 7625 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 7626 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 7627 7628 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7629 return binop( Iop_Xor32, 7630 mkexpr( rm_PPC32 ), 7631 binop( Iop_And32, 7632 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 7633 mkU32( 2 ) ) ); 7634 } 7635 7636 #define NANmaskSingle 0x7F800000 7637 #define NANmaskDouble 0x7FF00000 7638 7639 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 7640 { 7641 IRTemp exp_zero = newTemp(Ity_I8); 7642 IRTemp frac_mask = newTemp(Ity_I32); 7643 IRTemp frac_not_zero = newTemp(Ity_I8); 7644 7645 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 7646 * The input value is always 64-bits, for single precision values, the 7647 * lower 32 bits must be zero. 7648 * 7649 * Single Pricision 7650 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 7651 * [53:32] fraction field is zero for Infinity and non-zero for NAN 7652 * [31:0] unused for single precision representation 7653 * 7654 * Double Pricision 7655 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 7656 * [50:0] fraction field is zero for Infinity and non-zero for NAN 7657 * 7658 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 7659 */ 7660 assign( frac_mask, unop( Iop_Not32, 7661 binop( Iop_Or32, 7662 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 7663 7664 assign( exp_zero, 7665 unop( Iop_1Sto8, 7666 binop( Iop_CmpEQ32, 7667 binop( Iop_And32, 7668 unop( Iop_64HIto32, 7669 unop( Iop_ReinterpF64asI64, 7670 value ) ), 7671 Hi32Mask ), 7672 Hi32Mask ) ) ); 7673 assign( frac_not_zero, 7674 binop( Iop_Or8, 7675 unop( Iop_1Sto8, 7676 binop( Iop_CmpNE32, 7677 binop( Iop_And32, 7678 unop( Iop_64HIto32, 7679 unop( Iop_ReinterpF64asI64, 7680 value ) ), 7681 mkexpr( frac_mask ) ), 7682 mkU32( 0x0 ) ) ), 7683 unop( Iop_1Sto8, 7684 binop( Iop_CmpNE32, 7685 binop( Iop_And32, 7686 unop( Iop_64to32, 7687 unop( Iop_ReinterpF64asI64, 7688 value ) ), 7689 mkU32( 0xFFFFFFFF ) ), 7690 mkU32( 0x0 ) ) ) ) ); 7691 return unop( Iop_8Sto32, 7692 binop( Iop_And8, 7693 mkexpr( exp_zero ), 7694 mkexpr( frac_not_zero ) ) ); 7695 } 7696 7697 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 7698 { 7699 /* This function will only complement the 64-bit floating point value if it 7700 * is not Nan. NaN is not a signed value. Need to do computations using 7701 * 32-bit operands to ensure it will run in 32-bit mode. 7702 */ 7703 return binop( Iop_32HLto64, 7704 binop( Iop_Or32, 7705 binop( Iop_And32, 7706 nan_mask, 7707 unop( Iop_64HIto32, 7708 unop( Iop_ReinterpF64asI64, 7709 value ) ) ), 7710 binop( Iop_And32, 7711 unop( Iop_Not32, 7712 nan_mask ), 7713 unop( Iop_64HIto32, 7714 unop( Iop_ReinterpF64asI64, 7715 unop( Iop_NegF64, 7716 value ) ) ) ) ), 7717 unop( Iop_64to32, 7718 unop( Iop_ReinterpF64asI64, value ) ) ); 7719 } 7720 7721 /*------------------------------------------------------------*/ 7722 /*--- Floating Point Instruction Translation ---*/ 7723 /*------------------------------------------------------------*/ 7724 7725 /* 7726 Floating Point Load Instructions 7727 */ 7728 static Bool dis_fp_load ( UInt theInstr ) 7729 { 7730 /* X-Form, D-Form */ 7731 UChar opc1 = ifieldOPC(theInstr); 7732 UChar frD_addr = ifieldRegDS(theInstr); 7733 UChar rA_addr = ifieldRegA(theInstr); 7734 UChar rB_addr = ifieldRegB(theInstr); 7735 UInt opc2 = ifieldOPClo10(theInstr); 7736 UChar b0 = ifieldBIT0(theInstr); 7737 UInt uimm16 = ifieldUIMM16(theInstr); 7738 7739 Int simm16 = extend_s_16to32(uimm16); 7740 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7741 IRTemp EA = newTemp(ty); 7742 IRTemp rA = newTemp(ty); 7743 IRTemp rB = newTemp(ty); 7744 IRTemp iHi = newTemp(Ity_I32); 7745 IRTemp iLo = newTemp(Ity_I32); 7746 7747 assign( rA, getIReg(rA_addr) ); 7748 assign( rB, getIReg(rB_addr) ); 7749 7750 /* These are completely straightforward from a rounding and status 7751 bits perspective: no rounding involved and no funny status or CR 7752 bits affected. */ 7753 7754 switch (opc1) { 7755 case 0x30: // lfs (Load Float Single, PPC32 p441) 7756 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7757 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7758 putFReg( frD_addr, 7759 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7760 break; 7761 7762 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 7763 if (rA_addr == 0) 7764 return False; 7765 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7766 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7767 putFReg( frD_addr, 7768 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7769 putIReg( rA_addr, mkexpr(EA) ); 7770 break; 7771 7772 case 0x32: // lfd (Load Float Double, PPC32 p437) 7773 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7774 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7775 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7776 break; 7777 7778 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 7779 if (rA_addr == 0) 7780 return False; 7781 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7782 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7783 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7784 putIReg( rA_addr, mkexpr(EA) ); 7785 break; 7786 7787 case 0x1F: 7788 if (b0 != 0) { 7789 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 7790 return False; 7791 } 7792 7793 switch(opc2) { 7794 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7795 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7796 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7797 putFReg( frD_addr, unop( Iop_F32toF64, 7798 load(Ity_F32, mkexpr(EA))) ); 7799 break; 7800 7801 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7802 if (rA_addr == 0) 7803 return False; 7804 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7805 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7806 putFReg( frD_addr, 7807 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7808 putIReg( rA_addr, mkexpr(EA) ); 7809 break; 7810 7811 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7812 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7813 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7814 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7815 break; 7816 7817 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7818 if (rA_addr == 0) 7819 return False; 7820 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7821 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7822 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7823 putIReg( rA_addr, mkexpr(EA) ); 7824 break; 7825 7826 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7827 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7828 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7829 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7830 assign( iHi, binop(Iop_Sub32, 7831 mkU32(0), 7832 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7833 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7834 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7835 break; 7836 7837 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7838 { 7839 IRTemp dw = newTemp( Ity_I64 ); 7840 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7841 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7842 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7843 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7844 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7845 break; 7846 } 7847 7848 default: 7849 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7850 return False; 7851 } 7852 break; 7853 7854 default: 7855 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7856 return False; 7857 } 7858 return True; 7859 } 7860 7861 7862 7863 /* 7864 Floating Point Store Instructions 7865 */ 7866 static Bool dis_fp_store ( UInt theInstr ) 7867 { 7868 /* X-Form, D-Form */ 7869 UChar opc1 = ifieldOPC(theInstr); 7870 UChar frS_addr = ifieldRegDS(theInstr); 7871 UChar rA_addr = ifieldRegA(theInstr); 7872 UChar rB_addr = ifieldRegB(theInstr); 7873 UInt opc2 = ifieldOPClo10(theInstr); 7874 UChar b0 = ifieldBIT0(theInstr); 7875 Int uimm16 = ifieldUIMM16(theInstr); 7876 7877 Int simm16 = extend_s_16to32(uimm16); 7878 IRTemp frS = newTemp(Ity_F64); 7879 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7880 IRTemp EA = newTemp(ty); 7881 IRTemp rA = newTemp(ty); 7882 IRTemp rB = newTemp(ty); 7883 7884 assign( frS, getFReg(frS_addr) ); 7885 assign( rA, getIReg(rA_addr) ); 7886 assign( rB, getIReg(rB_addr) ); 7887 7888 /* These are straightforward from a status bits perspective: no 7889 funny status or CR bits affected. For single precision stores, 7890 the values are truncated and denormalised (not rounded) to turn 7891 them into single precision values. */ 7892 7893 switch (opc1) { 7894 7895 case 0x34: // stfs (Store Float Single, PPC32 p518) 7896 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7897 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7898 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 7899 the value to be stored in the correct way, without any 7900 rounding. */ 7901 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7902 break; 7903 7904 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 7905 if (rA_addr == 0) 7906 return False; 7907 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7908 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7909 /* See comment for stfs */ 7910 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7911 putIReg( rA_addr, mkexpr(EA) ); 7912 break; 7913 7914 case 0x36: // stfd (Store Float Double, PPC32 p513) 7915 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7916 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7917 store( mkexpr(EA), mkexpr(frS) ); 7918 break; 7919 7920 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 7921 if (rA_addr == 0) 7922 return False; 7923 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7924 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7925 store( mkexpr(EA), mkexpr(frS) ); 7926 putIReg( rA_addr, mkexpr(EA) ); 7927 break; 7928 7929 case 0x1F: 7930 if (b0 != 0) { 7931 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 7932 return False; 7933 } 7934 switch(opc2) { 7935 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 7936 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7937 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7938 /* See note for stfs */ 7939 store( mkexpr(EA), 7940 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7941 break; 7942 7943 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 7944 if (rA_addr == 0) 7945 return False; 7946 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7947 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7948 /* See note for stfs */ 7949 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7950 putIReg( rA_addr, mkexpr(EA) ); 7951 break; 7952 7953 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 7954 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7955 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7956 store( mkexpr(EA), mkexpr(frS) ); 7957 break; 7958 7959 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 7960 if (rA_addr == 0) 7961 return False; 7962 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7963 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7964 store( mkexpr(EA), mkexpr(frS) ); 7965 putIReg( rA_addr, mkexpr(EA) ); 7966 break; 7967 7968 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 7969 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7970 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7971 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7972 store( mkexpr(EA), 7973 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 7974 break; 7975 7976 default: 7977 vex_printf("dis_fp_store(ppc)(opc2)\n"); 7978 return False; 7979 } 7980 break; 7981 7982 default: 7983 vex_printf("dis_fp_store(ppc)(opc1)\n"); 7984 return False; 7985 } 7986 return True; 7987 } 7988 7989 7990 7991 /* 7992 Floating Point Arith Instructions 7993 */ 7994 static Bool dis_fp_arith ( UInt theInstr ) 7995 { 7996 /* A-Form */ 7997 UChar opc1 = ifieldOPC(theInstr); 7998 UChar frD_addr = ifieldRegDS(theInstr); 7999 UChar frA_addr = ifieldRegA(theInstr); 8000 UChar frB_addr = ifieldRegB(theInstr); 8001 UChar frC_addr = ifieldRegC(theInstr); 8002 UChar opc2 = ifieldOPClo5(theInstr); 8003 UChar flag_rC = ifieldBIT0(theInstr); 8004 8005 IRTemp frD = newTemp(Ity_F64); 8006 IRTemp frA = newTemp(Ity_F64); 8007 IRTemp frB = newTemp(Ity_F64); 8008 IRTemp frC = newTemp(Ity_F64); 8009 IRExpr* rm = get_IR_roundingmode(); 8010 8011 /* By default, we will examine the results of the operation and set 8012 fpscr[FPRF] accordingly. */ 8013 Bool set_FPRF = True; 8014 8015 /* By default, if flag_RC is set, we will clear cr1 after the 8016 operation. In reality we should set cr1 to indicate the 8017 exception status of the operation, but since we're not 8018 simulating exceptions, the exception status will appear to be 8019 zero. Hence cr1 should be cleared if this is a . form insn. */ 8020 Bool clear_CR1 = True; 8021 8022 assign( frA, getFReg(frA_addr)); 8023 assign( frB, getFReg(frB_addr)); 8024 assign( frC, getFReg(frC_addr)); 8025 8026 switch (opc1) { 8027 case 0x3B: 8028 switch (opc2) { 8029 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 8030 if (frC_addr != 0) 8031 return False; 8032 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8033 frD_addr, frA_addr, frB_addr); 8034 assign( frD, triop( Iop_DivF64r32, 8035 rm, mkexpr(frA), mkexpr(frB) )); 8036 break; 8037 8038 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 8039 if (frC_addr != 0) 8040 return False; 8041 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8042 frD_addr, frA_addr, frB_addr); 8043 assign( frD, triop( Iop_SubF64r32, 8044 rm, mkexpr(frA), mkexpr(frB) )); 8045 break; 8046 8047 case 0x15: // fadds (Floating Add Single, PPC32 p401) 8048 if (frC_addr != 0) 8049 return False; 8050 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8051 frD_addr, frA_addr, frB_addr); 8052 assign( frD, triop( Iop_AddF64r32, 8053 rm, mkexpr(frA), mkexpr(frB) )); 8054 break; 8055 8056 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 8057 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8058 if (frA_addr != 0 || frC_addr != 0) 8059 return False; 8060 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 8061 frD_addr, frB_addr); 8062 // however illogically, on ppc970 this insn behaves identically 8063 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 8064 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 8065 break; 8066 8067 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 8068 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8069 if (frA_addr != 0 || frC_addr != 0) 8070 return False; 8071 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 8072 frD_addr, frB_addr); 8073 { IRExpr* ieee_one 8074 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8075 assign( frD, triop( Iop_DivF64r32, 8076 rm, 8077 ieee_one, mkexpr(frB) )); 8078 } 8079 break; 8080 8081 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 8082 if (frB_addr != 0) 8083 return False; 8084 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8085 frD_addr, frA_addr, frC_addr); 8086 assign( frD, triop( Iop_MulF64r32, 8087 rm, mkexpr(frA), mkexpr(frC) )); 8088 break; 8089 8090 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 8091 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8092 // Undocumented instruction? 8093 if (frA_addr != 0 || frC_addr != 0) 8094 return False; 8095 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 8096 frD_addr, frB_addr); 8097 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8098 break; 8099 8100 default: 8101 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 8102 return False; 8103 } 8104 break; 8105 8106 case 0x3F: 8107 switch (opc2) { 8108 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 8109 if (frC_addr != 0) 8110 return False; 8111 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8112 frD_addr, frA_addr, frB_addr); 8113 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 8114 break; 8115 8116 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 8117 if (frC_addr != 0) 8118 return False; 8119 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8120 frD_addr, frA_addr, frB_addr); 8121 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 8122 break; 8123 8124 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 8125 if (frC_addr != 0) 8126 return False; 8127 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8128 frD_addr, frA_addr, frB_addr); 8129 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 8130 break; 8131 8132 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 8133 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 8134 if (frA_addr != 0 || frC_addr != 0) 8135 return False; 8136 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 8137 frD_addr, frB_addr); 8138 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 8139 break; 8140 8141 case 0x17: { // fsel (Floating Select, PPC32 p426) 8142 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8143 IRTemp cc = newTemp(Ity_I32); 8144 IRTemp cc_b0 = newTemp(Ity_I32); 8145 8146 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8147 frD_addr, frA_addr, frC_addr, frB_addr); 8148 8149 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 8150 // => GT|EQ == (cc & 0x1 == 0) 8151 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 8152 IRExpr_Const(IRConst_F64(0))) ); 8153 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 8154 8155 // frD = (frA >= 0.0) ? frC : frB 8156 // = (cc_b0 == 0) ? frC : frB 8157 assign( frD, 8158 IRExpr_ITE( 8159 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 8160 mkexpr(frC), 8161 mkexpr(frB) )); 8162 8163 /* One of the rare ones which don't mess with FPRF */ 8164 set_FPRF = False; 8165 break; 8166 } 8167 8168 case 0x18: // fre (Floating Reciprocal Estimate) 8169 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8170 // Note: unclear whether this insn really exists or not 8171 // ppc970 doesn't have it, but POWER5 does 8172 if (frA_addr != 0 || frC_addr != 0) 8173 return False; 8174 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 8175 frD_addr, frB_addr); 8176 { IRExpr* ieee_one 8177 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 8178 assign( frD, triop( Iop_DivF64, 8179 rm, 8180 ieee_one, mkexpr(frB) )); 8181 } 8182 break; 8183 8184 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 8185 if (frB_addr != 0) 8186 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 8187 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8188 frD_addr, frA_addr, frC_addr); 8189 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 8190 break; 8191 8192 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 8193 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8194 if (frA_addr != 0 || frC_addr != 0) 8195 return False; 8196 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 8197 frD_addr, frB_addr); 8198 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 8199 break; 8200 8201 default: 8202 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 8203 return False; 8204 } 8205 break; 8206 8207 default: 8208 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 8209 return False; 8210 } 8211 8212 putFReg( frD_addr, mkexpr(frD) ); 8213 8214 if (set_FPRF) { 8215 // XXX XXX XXX FIXME 8216 // set FPRF from frD 8217 } 8218 8219 if (flag_rC && clear_CR1) { 8220 putCR321( 1, mkU8(0) ); 8221 putCR0( 1, mkU8(0) ); 8222 } 8223 8224 return True; 8225 } 8226 8227 8228 8229 /* 8230 Floating Point Mult-Add Instructions 8231 */ 8232 static Bool dis_fp_multadd ( UInt theInstr ) 8233 { 8234 /* A-Form */ 8235 UChar opc1 = ifieldOPC(theInstr); 8236 UChar frD_addr = ifieldRegDS(theInstr); 8237 UChar frA_addr = ifieldRegA(theInstr); 8238 UChar frB_addr = ifieldRegB(theInstr); 8239 UChar frC_addr = ifieldRegC(theInstr); 8240 UChar opc2 = ifieldOPClo5(theInstr); 8241 UChar flag_rC = ifieldBIT0(theInstr); 8242 8243 IRTemp frD = newTemp(Ity_F64); 8244 IRTemp frA = newTemp(Ity_F64); 8245 IRTemp frB = newTemp(Ity_F64); 8246 IRTemp frC = newTemp(Ity_F64); 8247 IRTemp rmt = newTemp(Ity_I32); 8248 IRTemp tmp = newTemp(Ity_F64); 8249 IRTemp sign_tmp = newTemp(Ity_I64); 8250 IRTemp nan_mask = newTemp(Ity_I32); 8251 IRExpr* rm; 8252 8253 /* By default, we will examine the results of the operation and set 8254 fpscr[FPRF] accordingly. */ 8255 Bool set_FPRF = True; 8256 8257 /* By default, if flag_RC is set, we will clear cr1 after the 8258 operation. In reality we should set cr1 to indicate the 8259 exception status of the operation, but since we're not 8260 simulating exceptions, the exception status will appear to be 8261 zero. Hence cr1 should be cleared if this is a . form insn. */ 8262 Bool clear_CR1 = True; 8263 8264 /* Bind the rounding mode expression to a temp; there's no 8265 point in creating gratuitous CSEs, as we know we'll need 8266 to use it twice. */ 8267 assign( rmt, get_IR_roundingmode() ); 8268 rm = mkexpr(rmt); 8269 8270 assign( frA, getFReg(frA_addr)); 8271 assign( frB, getFReg(frB_addr)); 8272 assign( frC, getFReg(frC_addr)); 8273 8274 /* The rounding in this is all a bit dodgy. The idea is to only do 8275 one rounding. That clearly isn't achieveable without dedicated 8276 four-input IR primops, although in the single precision case we 8277 can sort-of simulate it by doing the inner multiply in double 8278 precision. 8279 8280 In the negated cases, the negation happens after rounding. */ 8281 8282 switch (opc1) { 8283 case 0x3B: 8284 switch (opc2) { 8285 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 8286 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8287 frD_addr, frA_addr, frC_addr, frB_addr); 8288 assign( frD, qop( Iop_MSubF64r32, rm, 8289 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8290 break; 8291 8292 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 8293 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8294 frD_addr, frA_addr, frC_addr, frB_addr); 8295 assign( frD, qop( Iop_MAddF64r32, rm, 8296 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8297 break; 8298 8299 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 8300 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 8301 8302 if (opc2 == 0x1E) { 8303 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8304 frD_addr, frA_addr, frC_addr, frB_addr); 8305 assign( tmp, qop( Iop_MSubF64r32, rm, 8306 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8307 } else { 8308 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8309 frD_addr, frA_addr, frC_addr, frB_addr); 8310 assign( tmp, qop( Iop_MAddF64r32, rm, 8311 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8312 } 8313 8314 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8315 mkU32( NANmaskSingle ) ) ); 8316 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8317 mkexpr( nan_mask ) ) ); 8318 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8319 break; 8320 8321 default: 8322 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 8323 return False; 8324 } 8325 break; 8326 8327 case 0x3F: 8328 switch (opc2) { 8329 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 8330 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8331 frD_addr, frA_addr, frC_addr, frB_addr); 8332 assign( frD, qop( Iop_MSubF64, rm, 8333 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8334 break; 8335 8336 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 8337 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8338 frD_addr, frA_addr, frC_addr, frB_addr); 8339 assign( frD, qop( Iop_MAddF64, rm, 8340 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8341 break; 8342 8343 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 8344 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 8345 8346 if (opc2 == 0x1E) { 8347 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8348 frD_addr, frA_addr, frC_addr, frB_addr); 8349 assign( tmp, qop( Iop_MSubF64, rm, 8350 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8351 } else { 8352 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8353 frD_addr, frA_addr, frC_addr, frB_addr); 8354 assign( tmp, qop( Iop_MAddF64, rm, 8355 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8356 } 8357 8358 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8359 mkU32( NANmaskDouble ) ) ); 8360 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8361 mkexpr( nan_mask ) ) ); 8362 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8363 break; 8364 8365 default: 8366 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 8367 return False; 8368 } 8369 break; 8370 8371 default: 8372 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 8373 return False; 8374 } 8375 8376 putFReg( frD_addr, mkexpr(frD) ); 8377 8378 if (set_FPRF) { 8379 // XXX XXX XXX FIXME 8380 // set FPRF from frD 8381 } 8382 8383 if (flag_rC && clear_CR1) { 8384 putCR321( 1, mkU8(0) ); 8385 putCR0( 1, mkU8(0) ); 8386 } 8387 8388 return True; 8389 } 8390 8391 /* 8392 * fe_flag is set to 1 if any of the following conditions occurs: 8393 * - The floating-point operand in register FRB is a Zero, a 8394 * NaN, an Infinity, or a negative value. 8395 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 8396 * Otherwise fe_flag is set to 0. 8397 * 8398 * fg_flag is set to 1 if either of the following conditions occurs. 8399 * - The floating-point operand in register FRB is a Zero, an 8400 * Infinity, or a denormalized value. 8401 * Otherwise fg_flag is set to 0. 8402 * 8403 */ 8404 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8405 { 8406 // The following temps are for holding intermediate results 8407 IRTemp e_b = newTemp(Ity_I32); 8408 IRExpr * fe_flag, * fg_flag; 8409 IRTemp frB_exp_shR = newTemp(Ity_I32); 8410 UInt bias = sp? 127 : 1023; 8411 IRExpr * frbNaN, * frbDenorm, * frBNeg; 8412 IRExpr * eb_LTE; 8413 IRTemp frbZero_tmp = newTemp(Ity_I1); 8414 IRTemp frbInf_tmp = newTemp(Ity_I1); 8415 *fe_flag_tmp = newTemp(Ity_I32); 8416 *fg_flag_tmp = newTemp(Ity_I32); 8417 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 8418 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8419 8420 ////////////////// fe_flag tests BEGIN ////////////////////// 8421 /* We first do all tests that may result in setting fe_flag to '1'. 8422 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 8423 * for details.) 8424 */ 8425 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 8426 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 8427 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 8428 { 8429 // Test_value = -970 for double precision 8430 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 8431 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 8432 } 8433 frBNeg = binop( Iop_CmpEQ32, 8434 binop( Iop_Shr32, 8435 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 8436 mkU8( 31 ) ), 8437 mkU32( 1 ) ); 8438 ////////////////// fe_flag tests END ////////////////////// 8439 8440 ////////////////// fg_flag tests BEGIN ////////////////////// 8441 /* 8442 * The following tests were already performed above in the fe_flag 8443 * tests. So these conditions will result in both fe_ and fg_ flags 8444 * being set. 8445 * - Test if FRB is Zero 8446 * - Test if FRB is an Infinity 8447 */ 8448 8449 /* 8450 * Test if FRB holds a denormalized value. A denormalized value is one where 8451 * the exp is 0 and the fraction is non-zero. 8452 */ 8453 if (sp) { 8454 IRTemp frac_part = newTemp(Ity_I32); 8455 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 8456 frbDenorm 8457 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8458 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 8459 } else { 8460 IRExpr * hi32, * low32, * fraction_is_nonzero; 8461 IRTemp frac_part = newTemp(Ity_I64); 8462 8463 assign( frac_part, FP_FRAC_PART(frB_Int) ); 8464 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8465 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8466 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8467 mkU32( 0 ) ); 8468 frbDenorm 8469 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8470 fraction_is_nonzero ); 8471 } 8472 ////////////////// fg_flag tests END ////////////////////// 8473 8474 ///////////////////////// 8475 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 8476 mkOR1( frbNaN, 8477 mkOR1( mkexpr( frbInf_tmp ), 8478 mkOR1( frBNeg, eb_LTE ) ) ) ); 8479 8480 fe_flag = unop(Iop_1Uto32, fe_flag); 8481 8482 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 8483 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 8484 fg_flag = unop(Iop_1Uto32, fg_flag); 8485 assign (*fg_flag_tmp, fg_flag); 8486 assign (*fe_flag_tmp, fe_flag); 8487 } 8488 /* 8489 * fe_flag is set to 1 if any of the following conditions occurs: 8490 * - The double-precision floating-point operand in register FRA is a NaN or an 8491 * Infinity. 8492 * - The double-precision floating-point operand in register FRB is a Zero, a 8493 * NaN, or an Infinity. 8494 * - e_b is less than or equal to -1022. 8495 * - e_b is greater than or equal to 1021. 8496 * - The double-precision floating-point operand in register FRA is not a zero 8497 * and the difference, e_a - e_b, is greater than or equal to 1023. 8498 * - The double-precision floating-point operand in register FRA is not a zero 8499 * and the difference, e_a - e_b, is less than or equal to -1021. 8500 * - The double-precision floating-point operand in register FRA is not a zero 8501 * and e_a is less than or equal to -970 8502 * Otherwise fe_flag is set to 0. 8503 * 8504 * fg_flag is set to 1 if either of the following conditions occurs. 8505 * - The double-precision floating-point operand in register FRA is an Infinity. 8506 * - The double-precision floating-point operand in register FRB is a Zero, an 8507 * Infinity, or a denormalized value. 8508 * Otherwise fg_flag is set to 0. 8509 * 8510 */ 8511 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8512 { 8513 // The following temps are for holding intermediate results 8514 IRTemp e_a = newTemp(Ity_I32); 8515 IRTemp e_b = newTemp(Ity_I32); 8516 IRTemp frA_exp_shR = newTemp(Ity_I32); 8517 IRTemp frB_exp_shR = newTemp(Ity_I32); 8518 8519 UInt bias = sp? 127 : 1023; 8520 *fe_flag_tmp = newTemp(Ity_I32); 8521 *fg_flag_tmp = newTemp(Ity_I32); 8522 8523 /* The following variables hold boolean results from tests 8524 * that are OR'ed together for setting the fe_ and fg_ flags. 8525 * For some cases, the booleans are used more than once, so 8526 * I make those IRTemp's instead of IRExpr's. 8527 */ 8528 IRExpr * fraNaN, * frbNaN, * frbDenorm; 8529 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 8530 IRTemp fraInf_tmp = newTemp(Ity_I1); 8531 IRTemp frbZero_tmp = newTemp(Ity_I1); 8532 IRTemp frbInf_tmp = newTemp(Ity_I1); 8533 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 8534 8535 /* The following are the flags that are set by OR'ing the results of 8536 * all the tests done for tdiv. These flags are the input to the specified CR. 8537 */ 8538 IRExpr * fe_flag, * fg_flag; 8539 8540 // Create temps that will be used throughout the following tests. 8541 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 8542 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 8543 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 8544 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 8545 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8546 8547 8548 ////////////////// fe_flag tests BEGIN ////////////////////// 8549 /* We first do all tests that may result in setting fe_flag to '1'. */ 8550 8551 /* 8552 * Test if the double-precision floating-point operand in register FRA is 8553 * a NaN: 8554 */ 8555 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 8556 /* 8557 * Test if the double-precision floating-point operand in register FRA is 8558 * an Infinity. 8559 */ 8560 assign(fraInf_tmp, is_Inf(frA_int, sp)); 8561 8562 /* 8563 * Test if the double-precision floating-point operand in register FRB is 8564 * a NaN: 8565 */ 8566 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 8567 /* 8568 * Test if the double-precision floating-point operand in register FRB is 8569 * an Infinity. 8570 */ 8571 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 8572 /* 8573 * Test if the double-precision floating-point operand in register FRB is 8574 * a Zero. 8575 */ 8576 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 8577 8578 /* 8579 * Test if e_b <= -1022 for double precision; 8580 * or e_b <= -126 for single precision 8581 */ 8582 { 8583 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 8584 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 8585 } 8586 8587 /* 8588 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 8589 * or e_b >= -125 (125 < e_b) for single precision 8590 */ 8591 { 8592 Int test_value = sp ? 125 : 1021; 8593 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 8594 } 8595 8596 /* 8597 * Test if FRA != Zero and (e_a - e_b) >= bias 8598 */ 8599 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 8600 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 8601 binop( Iop_CmpLT32S, mkU32( bias ), 8602 binop( Iop_Sub32, mkexpr( e_a ), 8603 mkexpr( e_b ) ) ) ); 8604 8605 /* 8606 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 8607 */ 8608 { 8609 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 8610 8611 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 8612 binop( Iop_CmpLE32S, 8613 binop( Iop_Sub32, 8614 mkexpr( e_a ), 8615 mkexpr( e_b ) ), 8616 mkU32( test_value ) ) ); 8617 } 8618 8619 /* 8620 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 8621 */ 8622 { 8623 UInt test_value = 0xfffffc36; //Int test_value = -970; 8624 8625 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 8626 mkexpr( e_a ), 8627 mkU32( test_value ) ) ); 8628 } 8629 ////////////////// fe_flag tests END ////////////////////// 8630 8631 ////////////////// fg_flag tests BEGIN ////////////////////// 8632 /* 8633 * The following tests were already performed above in the fe_flag 8634 * tests. So these conditions will result in both fe_ and fg_ flags 8635 * being set. 8636 * - Test if FRA is an Infinity 8637 * - Test if FRB ix Zero 8638 * - Test if FRB is an Infinity 8639 */ 8640 8641 /* 8642 * Test if FRB holds a denormalized value. A denormalized value is one where 8643 * the exp is 0 and the fraction is non-zero. 8644 */ 8645 { 8646 IRExpr * fraction_is_nonzero; 8647 8648 if (sp) { 8649 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 8650 mkU32( 0 ) ); 8651 } else { 8652 IRExpr * hi32, * low32; 8653 IRTemp frac_part = newTemp(Ity_I64); 8654 assign( frac_part, FP_FRAC_PART(frB_int) ); 8655 8656 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8657 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8658 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8659 mkU32( 0 ) ); 8660 } 8661 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 8662 mkU32( 0x0 ) ), fraction_is_nonzero ); 8663 8664 } 8665 ////////////////// fg_flag tests END ////////////////////// 8666 8667 fe_flag 8668 = mkOR1( 8669 fraNaN, 8670 mkOR1( 8671 mkexpr( fraInf_tmp ), 8672 mkOR1( 8673 mkexpr( frbZero_tmp ), 8674 mkOR1( 8675 frbNaN, 8676 mkOR1( 8677 mkexpr( frbInf_tmp ), 8678 mkOR1( eb_LTE, 8679 mkOR1( eb_GTE, 8680 mkOR1( ea_eb_GTE, 8681 mkOR1( ea_eb_LTE, 8682 ea_LTE ) ) ) ) ) ) ) ) ); 8683 8684 fe_flag = unop(Iop_1Uto32, fe_flag); 8685 8686 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 8687 mkOR1( mkexpr( frbInf_tmp ), 8688 frbDenorm ) ) ); 8689 fg_flag = unop(Iop_1Uto32, fg_flag); 8690 assign(*fe_flag_tmp, fe_flag); 8691 assign(*fg_flag_tmp, fg_flag); 8692 } 8693 8694 /* See description for _do_fp_tdiv() above. */ 8695 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 8696 { 8697 IRTemp fe_flag, fg_flag; 8698 ///////////////////////// 8699 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8700 * where fl_flag == 1 on ppc64. 8701 */ 8702 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 8703 fe_flag = fg_flag = IRTemp_INVALID; 8704 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 8705 return binop( Iop_Or32, 8706 binop( Iop_Or32, 8707 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 8708 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8709 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 8710 } 8711 8712 static Bool dis_fp_tests ( UInt theInstr ) 8713 { 8714 UChar opc1 = ifieldOPC(theInstr); 8715 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8716 UChar frB_addr = ifieldRegB(theInstr); 8717 UChar b0 = ifieldBIT0(theInstr); 8718 UInt opc2 = ifieldOPClo10(theInstr); 8719 IRTemp frB_I64 = newTemp(Ity_I64); 8720 8721 if (opc1 != 0x3F || b0 != 0 ){ 8722 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8723 return False; 8724 } 8725 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 8726 8727 switch (opc2) { 8728 case 0x080: // ftdiv 8729 { 8730 UChar frA_addr = ifieldRegA(theInstr); 8731 IRTemp frA_I64 = newTemp(Ity_I64); 8732 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8733 if (b21to22 != 0 ) { 8734 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8735 return False; 8736 } 8737 8738 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 8739 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 8740 8741 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8742 break; 8743 } 8744 case 0x0A0: // ftsqrt 8745 { 8746 IRTemp flags = newTemp(Ity_I32); 8747 IRTemp fe_flag, fg_flag; 8748 fe_flag = fg_flag = IRTemp_INVALID; 8749 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 8750 if ( b18to22 != 0) { 8751 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 8752 return False; 8753 } 8754 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 8755 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 8756 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8757 * where fl_flag == 1 on ppc64. 8758 */ 8759 assign( flags, 8760 binop( Iop_Or32, 8761 binop( Iop_Or32, mkU32( 8 ), // fl_flag 8762 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8763 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 8764 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 8765 break; 8766 } 8767 8768 default: 8769 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 8770 return False; 8771 8772 } 8773 return True; 8774 } 8775 8776 /* 8777 Floating Point Compare Instructions 8778 */ 8779 static Bool dis_fp_cmp ( UInt theInstr ) 8780 { 8781 /* X-Form */ 8782 UChar opc1 = ifieldOPC(theInstr); 8783 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8784 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8785 UChar frA_addr = ifieldRegA(theInstr); 8786 UChar frB_addr = ifieldRegB(theInstr); 8787 UInt opc2 = ifieldOPClo10(theInstr); 8788 UChar b0 = ifieldBIT0(theInstr); 8789 8790 IRTemp ccIR = newTemp(Ity_I32); 8791 IRTemp ccPPC32 = newTemp(Ity_I32); 8792 8793 IRTemp frA = newTemp(Ity_F64); 8794 IRTemp frB = newTemp(Ity_F64); 8795 8796 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 8797 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 8798 return False; 8799 } 8800 8801 assign( frA, getFReg(frA_addr)); 8802 assign( frB, getFReg(frB_addr)); 8803 8804 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 8805 8806 /* Map compare result from IR to PPC32 */ 8807 /* 8808 FP cmp result | PPC | IR 8809 -------------------------- 8810 UN | 0x1 | 0x45 8811 EQ | 0x2 | 0x40 8812 GT | 0x4 | 0x00 8813 LT | 0x8 | 0x01 8814 */ 8815 8816 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 8817 // | ((ccIR ^ (ccIR>>6)) & 1) 8818 assign( 8819 ccPPC32, 8820 binop( 8821 Iop_Shl32, 8822 mkU32(1), 8823 unop( 8824 Iop_32to8, 8825 binop( 8826 Iop_Or32, 8827 binop( 8828 Iop_And32, 8829 unop( 8830 Iop_Not32, 8831 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 8832 ), 8833 mkU32(2) 8834 ), 8835 binop( 8836 Iop_And32, 8837 binop( 8838 Iop_Xor32, 8839 mkexpr(ccIR), 8840 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 8841 ), 8842 mkU32(1) 8843 ) 8844 ) 8845 ) 8846 ) 8847 ); 8848 8849 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 8850 8851 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 8852 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 8853 */ 8854 // XXX XXX XXX FIXME 8855 // Also write the result into FPRF (it's not entirely clear how) 8856 8857 /* Note: Differences between fcmpu and fcmpo are only in exception 8858 flag settings, which aren't supported anyway. */ 8859 switch (opc2) { 8860 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 8861 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8862 break; 8863 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 8864 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8865 break; 8866 default: 8867 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 8868 return False; 8869 } 8870 return True; 8871 } 8872 8873 8874 8875 /* 8876 Floating Point Rounding/Conversion Instructions 8877 */ 8878 static Bool dis_fp_round ( UInt theInstr ) 8879 { 8880 /* X-Form */ 8881 UChar opc1 = ifieldOPC(theInstr); 8882 UChar b16to20 = ifieldRegA(theInstr); 8883 UChar frD_addr = ifieldRegDS(theInstr); 8884 UChar frB_addr = ifieldRegB(theInstr); 8885 UInt opc2 = ifieldOPClo10(theInstr); 8886 UChar flag_rC = ifieldBIT0(theInstr); 8887 8888 IRTemp frD = newTemp(Ity_F64); 8889 IRTemp frB = newTemp(Ity_F64); 8890 IRTemp r_tmp32 = newTemp(Ity_I32); 8891 IRTemp r_tmp64 = newTemp(Ity_I64); 8892 IRExpr* rm = get_IR_roundingmode(); 8893 8894 /* By default, we will examine the results of the operation and set 8895 fpscr[FPRF] accordingly. */ 8896 Bool set_FPRF = True; 8897 8898 /* By default, if flag_RC is set, we will clear cr1 after the 8899 operation. In reality we should set cr1 to indicate the 8900 exception status of the operation, but since we're not 8901 simulating exceptions, the exception status will appear to be 8902 zero. Hence cr1 should be cleared if this is a . form insn. */ 8903 Bool clear_CR1 = True; 8904 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 8905 vex_printf("dis_fp_round(ppc)(instr)\n"); 8906 return False; 8907 } 8908 8909 assign( frB, getFReg(frB_addr)); 8910 if (opc1 == 0x3B) { 8911 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 8912 * they're very similar to the other instructions handled here, but have 8913 * a different primary opcode. 8914 */ 8915 switch (opc2) { 8916 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 8917 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8918 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8919 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 8920 mkexpr( r_tmp64 ) ) ) ); 8921 goto putFR; 8922 8923 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 8924 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8925 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8926 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 8927 goto putFR; 8928 } 8929 } 8930 8931 8932 switch (opc2) { 8933 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 8934 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8935 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 8936 break; 8937 8938 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 8939 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8940 assign( r_tmp32, 8941 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 8942 assign( frD, unop( Iop_ReinterpI64asF64, 8943 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8944 /* FPRF is undefined after fctiw. Leave unchanged. */ 8945 set_FPRF = False; 8946 break; 8947 8948 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 8949 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8950 assign( r_tmp32, 8951 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 8952 assign( frD, unop( Iop_ReinterpI64asF64, 8953 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8954 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8955 set_FPRF = False; 8956 break; 8957 8958 case 0x08F: case 0x08E: // fctiwu[z] 8959 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 8960 flag_rC ? ".":"", frD_addr, frB_addr); 8961 assign( r_tmp32, 8962 binop( Iop_F64toI32U, 8963 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 8964 mkexpr( frB ) ) ); 8965 assign( frD, unop( Iop_ReinterpI64asF64, 8966 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8967 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8968 set_FPRF = False; 8969 break; 8970 8971 8972 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 8973 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8974 assign( r_tmp64, 8975 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 8976 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8977 /* FPRF is undefined after fctid. Leave unchanged. */ 8978 set_FPRF = False; 8979 break; 8980 8981 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 8982 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8983 assign( r_tmp64, 8984 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8985 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8986 /* FPRF is undefined after fctidz. Leave unchanged. */ 8987 set_FPRF = False; 8988 break; 8989 8990 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 8991 { 8992 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 8993 flag_rC ? ".":"", frD_addr, frB_addr); 8994 assign( r_tmp64, 8995 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 8996 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8997 /* FPRF is undefined after fctidz. Leave unchanged. */ 8998 set_FPRF = False; 8999 break; 9000 } 9001 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 9002 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9003 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9004 assign( frD, 9005 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 9006 break; 9007 9008 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 9009 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9010 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 9011 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 9012 break; 9013 9014 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 9015 switch(opc2) { 9016 case 0x188: // frin (Floating Round to Integer Nearest) 9017 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9018 assign( r_tmp64, 9019 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 9020 break; 9021 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 9022 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9023 assign( r_tmp64, 9024 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 9025 break; 9026 case 0x1C8: // frip (Floating Round to Integer Plus) 9027 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9028 assign( r_tmp64, 9029 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 9030 break; 9031 case 0x1E8: // frim (Floating Round to Integer Minus) 9032 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9033 assign( r_tmp64, 9034 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 9035 break; 9036 } 9037 9038 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 9039 /* F64 has only log10(2**52) significant digits anyway */ 9040 /* need to preserve sign of zero */ 9041 /* frD = (fabs(frB) > 9e18) ? frB : 9042 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 9043 assign(frD, IRExpr_ITE( 9044 binop(Iop_CmpNE8, 9045 unop(Iop_32to8, 9046 binop(Iop_CmpF64, 9047 IRExpr_Const(IRConst_F64(9e18)), 9048 unop(Iop_AbsF64, mkexpr(frB)))), 9049 mkU8(0)), 9050 mkexpr(frB), 9051 IRExpr_ITE( 9052 binop(Iop_CmpNE32, 9053 binop(Iop_Shr32, 9054 unop(Iop_64HIto32, 9055 unop(Iop_ReinterpF64asI64, 9056 mkexpr(frB))), 9057 mkU8(31)), 9058 mkU32(0)), 9059 unop(Iop_NegF64, 9060 unop( Iop_AbsF64, 9061 binop(Iop_I64StoF64, mkU32(0), 9062 mkexpr(r_tmp64)) )), 9063 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 9064 ) 9065 )); 9066 break; 9067 9068 default: 9069 vex_printf("dis_fp_round(ppc)(opc2)\n"); 9070 return False; 9071 } 9072 putFR: 9073 putFReg( frD_addr, mkexpr(frD) ); 9074 9075 if (set_FPRF) { 9076 // XXX XXX XXX FIXME 9077 // set FPRF from frD 9078 } 9079 9080 if (flag_rC && clear_CR1) { 9081 putCR321( 1, mkU8(0) ); 9082 putCR0( 1, mkU8(0) ); 9083 } 9084 9085 return True; 9086 } 9087 9088 /* 9089 Floating Point Pair Instructions 9090 */ 9091 static Bool dis_fp_pair ( UInt theInstr ) 9092 { 9093 /* X-Form/DS-Form */ 9094 UChar opc1 = ifieldOPC(theInstr); 9095 UChar frT_hi_addr = ifieldRegDS(theInstr); 9096 UChar frT_lo_addr = frT_hi_addr + 1; 9097 UChar rA_addr = ifieldRegA(theInstr); 9098 UChar rB_addr = ifieldRegB(theInstr); 9099 UInt uimm16 = ifieldUIMM16(theInstr); 9100 Int simm16 = extend_s_16to32(uimm16); 9101 UInt opc2 = ifieldOPClo10(theInstr); 9102 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9103 IRTemp EA_hi = newTemp(ty); 9104 IRTemp EA_lo = newTemp(ty); 9105 IRTemp frT_hi = newTemp(Ity_F64); 9106 IRTemp frT_lo = newTemp(Ity_F64); 9107 UChar b0 = ifieldBIT0(theInstr); 9108 Bool is_load = 0; 9109 9110 if ((frT_hi_addr %2) != 0) { 9111 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 9112 return False; 9113 } 9114 9115 switch (opc1) { 9116 case 0x1F: // register offset 9117 switch(opc2) { 9118 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 9119 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9120 is_load = 1; 9121 break; 9122 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 9123 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 9124 break; 9125 default: 9126 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 9127 return False; 9128 } 9129 9130 if (b0 != 0) { 9131 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 9132 return False; 9133 } 9134 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 9135 break; 9136 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 9137 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9138 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9139 is_load = 1; 9140 break; 9141 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 9142 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 9143 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 9144 break; 9145 default: // immediate offset 9146 vex_printf("dis_fp_pair(ppc)(instr)\n"); 9147 return False; 9148 } 9149 9150 if (mode64) 9151 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 9152 else 9153 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 9154 9155 assign( frT_hi, getFReg(frT_hi_addr) ); 9156 assign( frT_lo, getFReg(frT_lo_addr) ); 9157 9158 if (is_load) { 9159 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) ); 9160 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) ); 9161 } else { 9162 store( mkexpr(EA_hi), mkexpr(frT_hi) ); 9163 store( mkexpr(EA_lo), mkexpr(frT_lo) ); 9164 } 9165 9166 return True; 9167 } 9168 9169 9170 /* 9171 Floating Point Merge Instructions 9172 */ 9173 static Bool dis_fp_merge ( UInt theInstr ) 9174 { 9175 /* X-Form */ 9176 UInt opc2 = ifieldOPClo10(theInstr); 9177 UChar frD_addr = ifieldRegDS(theInstr); 9178 UChar frA_addr = ifieldRegA(theInstr); 9179 UChar frB_addr = ifieldRegB(theInstr); 9180 9181 IRTemp frD = newTemp(Ity_F64); 9182 IRTemp frA = newTemp(Ity_F64); 9183 IRTemp frB = newTemp(Ity_F64); 9184 9185 assign( frA, getFReg(frA_addr)); 9186 assign( frB, getFReg(frB_addr)); 9187 9188 switch (opc2) { 9189 case 0x3c6: // fmrgew floating merge even word 9190 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9191 9192 assign( frD, unop( Iop_ReinterpI64asF64, 9193 binop( Iop_32HLto64, 9194 unop( Iop_64HIto32, 9195 unop( Iop_ReinterpF64asI64, 9196 mkexpr(frA) ) ), 9197 unop( Iop_64HIto32, 9198 unop( Iop_ReinterpF64asI64, 9199 mkexpr(frB) ) ) ) ) ); 9200 break; 9201 9202 case 0x346: // fmrgow floating merge odd word 9203 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 9204 9205 assign( frD, unop( Iop_ReinterpI64asF64, 9206 binop( Iop_32HLto64, 9207 unop( Iop_64to32, 9208 unop( Iop_ReinterpF64asI64, 9209 mkexpr(frA) ) ), 9210 unop( Iop_64to32, 9211 unop( Iop_ReinterpF64asI64, 9212 mkexpr(frB) ) ) ) ) ); 9213 break; 9214 9215 default: 9216 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 9217 return False; 9218 } 9219 9220 putFReg( frD_addr, mkexpr(frD) ); 9221 return True; 9222 } 9223 9224 /* 9225 Floating Point Move Instructions 9226 */ 9227 static Bool dis_fp_move ( UInt theInstr ) 9228 { 9229 /* X-Form */ 9230 UChar opc1 = ifieldOPC(theInstr); 9231 UChar frD_addr = ifieldRegDS(theInstr); 9232 UChar frA_addr = ifieldRegA(theInstr); 9233 UChar frB_addr = ifieldRegB(theInstr); 9234 UInt opc2 = ifieldOPClo10(theInstr); 9235 UChar flag_rC = ifieldBIT0(theInstr); 9236 9237 IRTemp frD = newTemp(Ity_F64); 9238 IRTemp frB = newTemp(Ity_F64); 9239 IRTemp itmpB = newTemp(Ity_F64); 9240 IRTemp frA; 9241 IRTemp signA; 9242 IRTemp hiD; 9243 9244 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 9245 vex_printf("dis_fp_move(ppc)(instr)\n"); 9246 return False; 9247 } 9248 9249 assign( frB, getFReg(frB_addr)); 9250 9251 switch (opc2) { 9252 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 9253 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 9254 frB_addr); 9255 signA = newTemp(Ity_I32); 9256 hiD = newTemp(Ity_I32); 9257 itmpB = newTemp(Ity_I64); 9258 frA = newTemp(Ity_F64); 9259 assign( frA, getFReg(frA_addr) ); 9260 9261 /* get A's sign bit */ 9262 assign(signA, binop(Iop_And32, 9263 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 9264 mkexpr(frA))), 9265 mkU32(0x80000000)) ); 9266 9267 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 9268 9269 /* mask off B's sign bit and or in A's sign bit */ 9270 assign(hiD, binop(Iop_Or32, 9271 binop(Iop_And32, 9272 unop(Iop_64HIto32, 9273 mkexpr(itmpB)), /* frB's high 32 bits */ 9274 mkU32(0x7fffffff)), 9275 mkexpr(signA)) ); 9276 9277 /* combine hiD/loB into frD */ 9278 assign( frD, unop(Iop_ReinterpI64asF64, 9279 binop(Iop_32HLto64, 9280 mkexpr(hiD), 9281 unop(Iop_64to32, 9282 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 9283 break; 9284 9285 case 0x028: // fneg (Floating Negate, PPC32 p416) 9286 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9287 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 9288 break; 9289 9290 case 0x048: // fmr (Floating Move Register, PPC32 p410) 9291 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9292 assign( frD, mkexpr(frB) ); 9293 break; 9294 9295 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 9296 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9297 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 9298 break; 9299 9300 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 9301 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9302 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 9303 break; 9304 9305 default: 9306 vex_printf("dis_fp_move(ppc)(opc2)\n"); 9307 return False; 9308 } 9309 9310 putFReg( frD_addr, mkexpr(frD) ); 9311 9312 /* None of these change FPRF. cr1 is set in the usual way though, 9313 if flag_rC is set. */ 9314 9315 if (flag_rC) { 9316 putCR321( 1, mkU8(0) ); 9317 putCR0( 1, mkU8(0) ); 9318 } 9319 9320 return True; 9321 } 9322 9323 9324 9325 /* 9326 Floating Point Status/Control Register Instructions 9327 */ 9328 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 9329 { 9330 /* Many forms - see each switch case */ 9331 UChar opc1 = ifieldOPC(theInstr); 9332 UInt opc2 = ifieldOPClo10(theInstr); 9333 UChar flag_rC = ifieldBIT0(theInstr); 9334 9335 if (opc1 != 0x3F) { 9336 vex_printf("dis_fp_scr(ppc)(instr)\n"); 9337 return False; 9338 } 9339 9340 switch (opc2) { 9341 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 9342 // Bit crbD of the FPSCR is set. 9343 UChar crbD = ifieldRegDS(theInstr); 9344 UInt b11to20 = IFIELD(theInstr, 11, 10); 9345 9346 if (b11to20 != 0) { 9347 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 9348 return False; 9349 } 9350 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 9351 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 9352 1ULL << ( 31 - crbD ) ); 9353 break; 9354 } 9355 9356 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 9357 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9358 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9359 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 9360 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 9361 IRTemp tmp = newTemp(Ity_I32); 9362 IRExpr* fpscr_all; 9363 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 9364 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 9365 return False; 9366 } 9367 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 9368 vassert(crfD < 8); 9369 vassert(crfS < 8); 9370 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9371 assign( tmp, binop(Iop_And32, 9372 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 9373 mkU32(0xF)) ); 9374 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 9375 break; 9376 } 9377 9378 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 9379 // Bit crbD of the FPSCR is cleared. 9380 UChar crbD = ifieldRegDS(theInstr); 9381 UInt b11to20 = IFIELD(theInstr, 11, 10); 9382 9383 if (b11to20 != 0) { 9384 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 9385 return False; 9386 } 9387 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 9388 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 9389 break; 9390 } 9391 9392 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 9393 UInt crfD = IFIELD( theInstr, 23, 3 ); 9394 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 9395 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 9396 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9397 UChar Wbit; 9398 9399 if (b16to22 != 0 || b11 != 0) { 9400 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 9401 return False; 9402 } 9403 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 9404 if (GX_level) { 9405 /* This implies that Decimal Floating Point is supported, and the 9406 * FPSCR must be managed as a 64-bit register. 9407 */ 9408 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9409 } else { 9410 Wbit = 0; 9411 } 9412 crfD = crfD + (8 * (1 - Wbit) ); 9413 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 9414 break; 9415 } 9416 9417 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 9418 UChar frD_addr = ifieldRegDS(theInstr); 9419 UInt b11to20 = IFIELD(theInstr, 11, 10); 9420 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9421 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, 9422 MASK_FPSCR_DRN ); 9423 9424 if (b11to20 != 0) { 9425 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 9426 return False; 9427 } 9428 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 9429 putFReg( frD_addr, 9430 unop( Iop_ReinterpI64asF64, 9431 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 9432 break; 9433 } 9434 9435 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 9436 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 9437 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 9438 UChar frB_addr = ifieldRegB(theInstr); 9439 IRTemp frB = newTemp(Ity_F64); 9440 IRTemp rB_64 = newTemp( Ity_I64 ); 9441 Int i; 9442 ULong mask; 9443 UChar Wbit; 9444 #define BFP_MASK_SEED 0x3000000000000000ULL 9445 #define DFP_MASK_SEED 0x7000000000000000ULL 9446 9447 if (GX_level) { 9448 /* This implies that Decimal Floating Point is supported, and the 9449 * FPSCR must be managed as a 64-bit register. 9450 */ 9451 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9452 } else { 9453 Wbit = 0; 9454 } 9455 9456 if (b25 == 1) { 9457 /* new 64 bit move variant for power 6. If L field (bit 25) is 9458 * a one do a full 64 bit move. Note, the FPSCR is not really 9459 * properly modeled. This instruciton only changes the value of 9460 * the rounding mode. The HW exception bits do not get set in 9461 * the simulator. 1/12/09 9462 */ 9463 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 9464 mask = 0xFF; 9465 9466 } else { 9467 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 9468 // Build 32bit mask from FM: 9469 mask = 0; 9470 for (i=0; i<8; i++) { 9471 if ((FM & (1<<(7-i))) == 1) { 9472 /* FPSCR field k is set to the contents of the corresponding 9473 * field of register FRB, where k = i+8x(1-W). In the Power 9474 * ISA, register field numbering is from left to right, so field 9475 * 15 is the least significant field in a 64-bit register. To 9476 * generate the mask, we set all the appropriate rounding mode 9477 * bits in the highest order nibble (field 0) and shift right 9478 * 'k x nibble length'. 9479 */ 9480 if (Wbit) 9481 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9482 else 9483 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9484 } 9485 } 9486 } 9487 assign( frB, getFReg(frB_addr)); 9488 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 9489 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 9490 break; 9491 } 9492 9493 default: 9494 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 9495 return False; 9496 } 9497 return True; 9498 } 9499 9500 /*------------------------------------------------------------*/ 9501 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 9502 /*------------------------------------------------------------*/ 9503 #define DFP_LONG 1 9504 #define DFP_EXTND 2 9505 #define DFP_LONG_BIAS 398 9506 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 9507 #define DFP_EXTND_BIAS 6176 9508 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 9509 #define DFP_LONG_EXP_MSK 0XFF 9510 #define DFP_EXTND_EXP_MSK 0XFFF 9511 9512 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 9513 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 9514 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 9515 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 9516 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 9517 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 9518 #define DFP_LONG_EXP_MAX 369 // biased max 9519 #define DFP_LONG_EXP_MIN 0 // biased min 9520 #define DFP_EXTND_EXP_MAX 6111 // biased max 9521 #define DFP_EXTND_EXP_MIN 0 // biased min 9522 #define DFP_LONG_MAX_SIG_DIGITS 16 9523 #define DFP_EXTND_MAX_SIG_DIGITS 34 9524 #define MAX_DIGITS_IN_STRING 8 9525 9526 9527 #define AND(x, y) binop( Iop_And32, x, y ) 9528 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 9529 #define OR(x, y) binop( Iop_Or32, x, y ) 9530 #define OR3(x, y, z) OR( x, OR( y, z ) ) 9531 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 9532 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 9533 9534 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 9535 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 9536 9537 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 9538 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 9539 ((_b1) << 1) | ((_b0) << 0)) 9540 9541 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 9542 { 9543 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9544 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 9545 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 9546 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 9547 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 9548 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 9549 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9550 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9551 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9552 9553 /* The encodig is as follows: 9554 * lmd - left most digit 9555 * lme - left most 2-bits of the exponent 9556 * 9557 * lmd 9558 * 0 - 7 (lmexp << 3) | lmd 9559 * 8 0b11000 (24 decimal) if lme=0b00; 9560 * 0b11010 (26 decimal) if lme=0b01; 9561 * 0b11100 (28 decimal) if lme=0b10; 9562 * 9 0b11001 (25 decimal) if lme=0b00; 9563 * 0b11011 (27 decimal) if lme=0b01; 9564 * 0b11101 (29 decimal) if lme=0b10; 9565 */ 9566 9567 /* Generate the masks for each condition */ 9568 assign( lmd_07_mask, 9569 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 9570 assign( lmd_8_mask, 9571 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 9572 assign( lmd_9_mask, 9573 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 9574 assign( lmexp_00_mask, 9575 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 9576 assign( lmexp_01_mask, 9577 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 9578 assign( lmexp_10_mask, 9579 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 9580 9581 /* Generate the values for each LMD condition, assuming the condition 9582 * is TRUE. 9583 */ 9584 assign( lmd_07_val, 9585 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 9586 assign( lmd_8_val, 9587 binop( Iop_Or32, 9588 binop( Iop_Or32, 9589 binop( Iop_And32, 9590 mkexpr( lmexp_00_mask ), 9591 mkU32( 24 ) ), 9592 binop( Iop_And32, 9593 mkexpr( lmexp_01_mask ), 9594 mkU32( 26 ) ) ), 9595 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 9596 assign( lmd_9_val, 9597 binop( Iop_Or32, 9598 binop( Iop_Or32, 9599 binop( Iop_And32, 9600 mkexpr( lmexp_00_mask ), 9601 mkU32( 25 ) ), 9602 binop( Iop_And32, 9603 mkexpr( lmexp_01_mask ), 9604 mkU32( 27 ) ) ), 9605 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 9606 9607 /* generate the result from the possible LMD values */ 9608 return binop( Iop_Or32, 9609 binop( Iop_Or32, 9610 binop( Iop_And32, 9611 mkexpr( lmd_07_mask ), 9612 mkexpr( lmd_07_val ) ), 9613 binop( Iop_And32, 9614 mkexpr( lmd_8_mask ), 9615 mkexpr( lmd_8_val ) ) ), 9616 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 9617 } 9618 9619 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 9620 { 9621 /* Extract the exponent and the left most digit of the mantissa 9622 * from the G field bits [0:4]. 9623 */ 9624 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9625 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 9626 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 9627 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 9628 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 9629 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 9630 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 9631 9632 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9633 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9634 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9635 9636 /* The left most digit (LMD) encoding is as follows: 9637 * lmd 9638 * 0 - 7 (lmexp << 3) | lmd 9639 * 8 0b11000 (24 decimal) if lme=0b00; 9640 * 0b11010 (26 decimal) if lme=0b01; 9641 * 0b11100 (28 decimal) if lme=0b10 9642 * 9 0b11001 (25 decimal) if lme=0b00; 9643 * 0b11011 (27 decimal) if lme=0b01; 9644 * 0b11101 (29 decimal) if lme=0b10; 9645 */ 9646 9647 /* Generate the masks for each condition of LMD and exponent bits */ 9648 assign( lmd_07_mask, 9649 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 9650 gfield_0_4, 9651 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 9652 assign( lmd_8_00_mask, 9653 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9654 gfield_0_4, 9655 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 9656 assign( lmd_8_01_mask, 9657 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9658 gfield_0_4, 9659 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 9660 assign( lmd_8_10_mask, 9661 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9662 gfield_0_4, 9663 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 9664 assign( lmd_9_00_mask, 9665 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9666 gfield_0_4, 9667 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 9668 assign( lmd_9_01_mask, 9669 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9670 gfield_0_4, 9671 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 9672 assign( lmd_9_10_mask, 9673 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9674 gfield_0_4, 9675 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 9676 9677 /* Generate the values for each LMD condition, assuming the condition 9678 * is TRUE. 9679 */ 9680 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 9681 assign( lmd_8_val, mkU32( 0x8 ) ); 9682 assign( lmd_9_val, mkU32( 0x9 ) ); 9683 9684 assign( *lmd, 9685 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 9686 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 9687 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 9688 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 9689 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 9690 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 9691 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 9692 ) ) ); 9693 } 9694 9695 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 9696 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 9697 #define DIGIT3_SHR 12 9698 #define DIGIT4_SHR 16 9699 #define DIGIT5_SHR 20 9700 #define DIGIT6_SHR 24 9701 #define DIGIT7_SHR 28 9702 9703 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 9704 { 9705 /* 60-bit BCD string stored in two 32-bit values. Check that each, 9706 * digit is a valid BCD number, i.e. less then 9. 9707 */ 9708 IRTemp valid = newTemp( Ity_I32 ); 9709 9710 assign( valid, 9711 AND4( AND4 ( unop( Iop_1Sto32, 9712 binop( Iop_CmpLE32U, 9713 binop( Iop_And32, 9714 bcd_l, 9715 mkU32 ( 0xF ) ), 9716 mkU32( 0x9 ) ) ), 9717 unop( Iop_1Sto32, 9718 binop( Iop_CmpLE32U, 9719 binop( Iop_And32, 9720 binop( Iop_Shr32, 9721 bcd_l, 9722 mkU8 ( DIGIT1_SHR ) ), 9723 mkU32 ( 0xF ) ), 9724 mkU32( 0x9 ) ) ), 9725 unop( Iop_1Sto32, 9726 binop( Iop_CmpLE32U, 9727 binop( Iop_And32, 9728 binop( Iop_Shr32, 9729 bcd_l, 9730 mkU8 ( DIGIT2_SHR ) ), 9731 mkU32 ( 0xF ) ), 9732 mkU32( 0x9 ) ) ), 9733 unop( Iop_1Sto32, 9734 binop( Iop_CmpLE32U, 9735 binop( Iop_And32, 9736 binop( Iop_Shr32, 9737 bcd_l, 9738 mkU8 ( DIGIT3_SHR ) ), 9739 mkU32 ( 0xF ) ), 9740 mkU32( 0x9 ) ) ) ), 9741 AND4 ( unop( Iop_1Sto32, 9742 binop( Iop_CmpLE32U, 9743 binop( Iop_And32, 9744 binop( Iop_Shr32, 9745 bcd_l, 9746 mkU8 ( DIGIT4_SHR ) ), 9747 mkU32 ( 0xF ) ), 9748 mkU32( 0x9 ) ) ), 9749 unop( Iop_1Sto32, 9750 binop( Iop_CmpLE32U, 9751 binop( Iop_And32, 9752 binop( Iop_Shr32, 9753 bcd_l, 9754 mkU8 ( DIGIT5_SHR ) ), 9755 mkU32 ( 0xF ) ), 9756 mkU32( 0x9 ) ) ), 9757 unop( Iop_1Sto32, 9758 binop( Iop_CmpLE32U, 9759 binop( Iop_And32, 9760 binop( Iop_Shr32, 9761 bcd_l, 9762 mkU8 ( DIGIT6_SHR ) ), 9763 mkU32 ( 0xF ) ), 9764 mkU32( 0x9 ) ) ), 9765 unop( Iop_1Sto32, 9766 binop( Iop_CmpLE32U, 9767 binop( Iop_And32, 9768 binop( Iop_Shr32, 9769 bcd_l, 9770 mkU8 ( DIGIT7_SHR ) ), 9771 mkU32 ( 0xF ) ), 9772 mkU32( 0x9 ) ) ) ), 9773 AND4( unop( Iop_1Sto32, 9774 binop( Iop_CmpLE32U, 9775 binop( Iop_And32, 9776 bcd_u, 9777 mkU32 ( 0xF ) ), 9778 mkU32( 0x9 ) ) ), 9779 unop( Iop_1Sto32, 9780 binop( Iop_CmpLE32U, 9781 binop( Iop_And32, 9782 binop( Iop_Shr32, 9783 bcd_u, 9784 mkU8 ( DIGIT1_SHR ) ), 9785 mkU32 ( 0xF ) ), 9786 mkU32( 0x9 ) ) ), 9787 unop( Iop_1Sto32, 9788 binop( Iop_CmpLE32U, 9789 binop( Iop_And32, 9790 binop( Iop_Shr32, 9791 bcd_u, 9792 mkU8 ( DIGIT2_SHR ) ), 9793 mkU32 ( 0xF ) ), 9794 mkU32( 0x9 ) ) ), 9795 unop( Iop_1Sto32, 9796 binop( Iop_CmpLE32U, 9797 binop( Iop_And32, 9798 binop( Iop_Shr32, 9799 bcd_u, 9800 mkU8 ( DIGIT3_SHR ) ), 9801 mkU32 ( 0xF ) ), 9802 mkU32( 0x9 ) ) ) ), 9803 AND4( unop( Iop_1Sto32, 9804 binop( Iop_CmpLE32U, 9805 binop( Iop_And32, 9806 binop( Iop_Shr32, 9807 bcd_u, 9808 mkU8 ( DIGIT4_SHR ) ), 9809 mkU32 ( 0xF ) ), 9810 mkU32( 0x9 ) ) ), 9811 unop( Iop_1Sto32, 9812 binop( Iop_CmpLE32U, 9813 binop( Iop_And32, 9814 binop( Iop_Shr32, 9815 bcd_u, 9816 mkU8 ( DIGIT5_SHR ) ), 9817 mkU32 ( 0xF ) ), 9818 mkU32( 0x9 ) ) ), 9819 unop( Iop_1Sto32, 9820 binop( Iop_CmpLE32U, 9821 binop( Iop_And32, 9822 binop( Iop_Shr32, 9823 bcd_u, 9824 mkU8 ( DIGIT6_SHR ) ), 9825 mkU32 ( 0xF ) ), 9826 mkU32( 0x9 ) ) ), 9827 unop( Iop_1Sto32, 9828 binop( Iop_CmpLE32U, 9829 binop( Iop_And32, 9830 binop( Iop_Shr32, 9831 bcd_u, 9832 mkU8 ( DIGIT7_SHR ) ), 9833 mkU32 ( 0xF ) ), 9834 mkU32( 0x9 ) ) ) ) ) ); 9835 9836 return unop( Iop_Not32, mkexpr( valid ) ); 9837 } 9838 #undef DIGIT1_SHR 9839 #undef DIGIT2_SHR 9840 #undef DIGIT3_SHR 9841 #undef DIGIT4_SHR 9842 #undef DIGIT5_SHR 9843 #undef DIGIT6_SHR 9844 #undef DIGIT7_SHR 9845 9846 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 9847 { 9848 return binop( Iop_Or32, 9849 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 9850 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 9851 ); 9852 } 9853 9854 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 9855 { 9856 return binop( Iop_Or32, 9857 binop( Iop_Or32, 9858 unop( Iop_1Sto32, 9859 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 9860 unop( Iop_1Sto32, 9861 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 9862 binop( Iop_Or32, 9863 unop( Iop_1Sto32, 9864 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 9865 unop( Iop_1Sto32, 9866 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 9867 } 9868 9869 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 9870 IRExpr * neg_sign_mask ) 9871 { 9872 return binop( Iop_Or32, 9873 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 9874 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 9875 } 9876 9877 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 9878 IRExpr * pos_sign_mask, 9879 IRExpr * neg_sign_mask ) 9880 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 9881 { 9882 return binop( Iop_Or32, 9883 invalid_bcd_mask, 9884 unop( Iop_1Sto32, 9885 binop( Iop_CmpEQ32, 9886 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 9887 mkU32( 0x0 ) ) ) ); 9888 } 9889 9890 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 9891 IRTemp * top_12_l, IRTemp * mid_60_u, 9892 IRTemp * mid_60_l, IRTemp * low_60_u, 9893 IRTemp * low_60_l) 9894 { 9895 IRTemp tmplow60 = newTemp( Ity_I64 ); 9896 IRTemp tmpmid60 = newTemp( Ity_I64 ); 9897 IRTemp tmptop12 = newTemp( Ity_I64 ); 9898 IRTemp low_50 = newTemp( Ity_I64 ); 9899 IRTemp mid_50 = newTemp( Ity_I64 ); 9900 IRTemp top_10 = newTemp( Ity_I64 ); 9901 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 9902 9903 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 9904 9905 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 9906 assign( low_50, 9907 binop( Iop_32HLto64, 9908 binop( Iop_And32, 9909 unop( Iop_64HIto32, frBI64_lo ), 9910 mkU32( 0x3FFFF ) ), 9911 unop( Iop_64to32, frBI64_lo ) ) ); 9912 9913 /* Convert the 50 bit densely packed BCD string to a 60 bit 9914 * BCD string. 9915 */ 9916 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 9917 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 9918 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 9919 9920 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 9921 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 9922 */ 9923 assign( mid_50, 9924 binop( Iop_32HLto64, 9925 binop( Iop_Or32, 9926 binop( Iop_Shl32, 9927 binop( Iop_And32, 9928 unop( Iop_64HIto32, frBI64_hi ), 9929 mkU32( 0xF ) ), 9930 mkU8( 14 ) ), 9931 binop( Iop_Shr32, 9932 unop( Iop_64to32, frBI64_hi ), 9933 mkU8( 18 ) ) ), 9934 binop( Iop_Or32, 9935 binop( Iop_Shl32, 9936 unop( Iop_64to32, frBI64_hi ), 9937 mkU8( 14 ) ), 9938 binop( Iop_Shr32, 9939 unop( Iop_64HIto32, frBI64_lo ), 9940 mkU8( 18 ) ) ) ) ); 9941 9942 /* Convert the 50 bit densely packed BCD string to a 60 bit 9943 * BCD string. 9944 */ 9945 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 9946 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 9947 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 9948 9949 /* top_10[49:0] = frBI64_hi[45:36]) | */ 9950 assign( top_10, 9951 binop( Iop_32HLto64, 9952 mkU32( 0 ), 9953 binop( Iop_And32, 9954 binop( Iop_Shr32, 9955 unop( Iop_64HIto32, frBI64_hi ), 9956 mkU8( 4 ) ), 9957 mkU32( 0x3FF ) ) ) ); 9958 9959 /* Convert the 10 bit densely packed BCD string to a 12 bit 9960 * BCD string. 9961 */ 9962 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 9963 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 9964 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 9965 } 9966 9967 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 9968 IRTemp * final_cnt, IRTemp * final_flag, 9969 IRExpr * string ) 9970 { 9971 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 9972 int digits = MAX_DIGITS_IN_STRING; 9973 int i; 9974 9975 cnt[start-1] = newTemp( Ity_I8 ); 9976 flag[start-1] = newTemp( Ity_I8 ); 9977 assign( cnt[start-1], init_cnt); 9978 assign( flag[start-1], init_flag); 9979 9980 for ( i = start; i <= digits; i++) { 9981 cnt[i] = newTemp( Ity_I8 ); 9982 flag[i] = newTemp( Ity_I8 ); 9983 assign( cnt[i], 9984 binop( Iop_Add8, 9985 mkexpr( cnt[i-1] ), 9986 binop(Iop_And8, 9987 unop( Iop_1Uto8, 9988 binop(Iop_CmpEQ32, 9989 binop(Iop_And32, 9990 string, 9991 mkU32( 0xF << 9992 ( ( digits - i ) * 4) ) ), 9993 mkU32( 0 ) ) ), 9994 binop( Iop_Xor8, /* complement flag */ 9995 mkexpr( flag[i - 1] ), 9996 mkU8( 0xFF ) ) ) ) ); 9997 9998 /* set flag to 1 if digit was not a zero */ 9999 assign( flag[i], 10000 binop(Iop_Or8, 10001 unop( Iop_1Sto8, 10002 binop(Iop_CmpNE32, 10003 binop(Iop_And32, 10004 string, 10005 mkU32( 0xF << 10006 ( (digits - i) * 4) ) ), 10007 mkU32( 0 ) ) ), 10008 mkexpr( flag[i - 1] ) ) ); 10009 } 10010 10011 *final_cnt = cnt[digits]; 10012 *final_flag = flag[digits]; 10013 } 10014 10015 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 10016 IRExpr * low_32 ) 10017 { 10018 IRTemp num_lmd = newTemp( Ity_I8 ); 10019 IRTemp num_upper = newTemp( Ity_I8 ); 10020 IRTemp num_low = newTemp( Ity_I8 ); 10021 IRTemp lmd_flag = newTemp( Ity_I8 ); 10022 IRTemp upper_flag = newTemp( Ity_I8 ); 10023 IRTemp low_flag = newTemp( Ity_I8 ); 10024 10025 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10026 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10027 10028 Count_zeros( 2, 10029 mkexpr( num_lmd ), 10030 mkexpr( lmd_flag ), 10031 &num_upper, 10032 &upper_flag, 10033 upper_28 ); 10034 10035 Count_zeros( 1, 10036 mkexpr( num_upper ), 10037 mkexpr( upper_flag ), 10038 &num_low, 10039 &low_flag, 10040 low_32 ); 10041 10042 return mkexpr( num_low ); 10043 } 10044 10045 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 10046 IRExpr * mid_60_u, IRExpr * mid_60_l, 10047 IRExpr * low_60_u, IRExpr * low_60_l) 10048 { 10049 IRTemp num_lmd = newTemp( Ity_I8 ); 10050 IRTemp num_top = newTemp( Ity_I8 ); 10051 IRTemp num_mid_u = newTemp( Ity_I8 ); 10052 IRTemp num_mid_l = newTemp( Ity_I8 ); 10053 IRTemp num_low_u = newTemp( Ity_I8 ); 10054 IRTemp num_low_l = newTemp( Ity_I8 ); 10055 10056 IRTemp lmd_flag = newTemp( Ity_I8 ); 10057 IRTemp top_flag = newTemp( Ity_I8 ); 10058 IRTemp mid_u_flag = newTemp( Ity_I8 ); 10059 IRTemp mid_l_flag = newTemp( Ity_I8 ); 10060 IRTemp low_u_flag = newTemp( Ity_I8 ); 10061 IRTemp low_l_flag = newTemp( Ity_I8 ); 10062 10063 /* Check the LMD, digit 16, to see if it is zero. */ 10064 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 10065 10066 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 10067 10068 Count_zeros( 6, 10069 mkexpr( num_lmd ), 10070 mkexpr( lmd_flag ), 10071 &num_top, 10072 &top_flag, 10073 top_12_l ); 10074 10075 Count_zeros( 1, 10076 mkexpr( num_top ), 10077 mkexpr( top_flag ), 10078 &num_mid_u, 10079 &mid_u_flag, 10080 binop( Iop_Or32, 10081 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 10082 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 10083 10084 Count_zeros( 2, 10085 mkexpr( num_mid_u ), 10086 mkexpr( mid_u_flag ), 10087 &num_mid_l, 10088 &mid_l_flag, 10089 mid_60_l ); 10090 10091 Count_zeros( 1, 10092 mkexpr( num_mid_l ), 10093 mkexpr( mid_l_flag ), 10094 &num_low_u, 10095 &low_u_flag, 10096 binop( Iop_Or32, 10097 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 10098 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 10099 10100 Count_zeros( 2, 10101 mkexpr( num_low_u ), 10102 mkexpr( low_u_flag ), 10103 &num_low_l, 10104 &low_l_flag, 10105 low_60_l ); 10106 10107 return mkexpr( num_low_l ); 10108 } 10109 10110 static IRExpr * Check_unordered(IRExpr * val) 10111 { 10112 IRTemp gfield0to5 = newTemp( Ity_I32 ); 10113 10114 /* Extract G[0:4] */ 10115 assign( gfield0to5, 10116 binop( Iop_And32, 10117 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 10118 mkU32( 0x1F ) ) ); 10119 10120 /* Check for unordered, return all 1'x if true */ 10121 return binop( Iop_Or32, /* QNaN check */ 10122 unop( Iop_1Sto32, 10123 binop( Iop_CmpEQ32, 10124 mkexpr( gfield0to5 ), 10125 mkU32( 0x1E ) ) ), 10126 unop( Iop_1Sto32, /* SNaN check */ 10127 binop( Iop_CmpEQ32, 10128 mkexpr( gfield0to5 ), 10129 mkU32( 0x1F ) ) ) ); 10130 } 10131 10132 #undef AND 10133 #undef AND4 10134 #undef OR 10135 #undef OR3 10136 #undef OR4 10137 #undef NOT 10138 #undef SHR 10139 #undef SHL 10140 #undef BITS5 10141 10142 /*------------------------------------------------------------*/ 10143 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 10144 /*------------------------------------------------------------*/ 10145 10146 /* DFP Arithmetic instructions */ 10147 static Bool dis_dfp_arith(UInt theInstr) 10148 { 10149 UInt opc2 = ifieldOPClo10( theInstr ); 10150 UChar frS_addr = ifieldRegDS( theInstr ); 10151 UChar frA_addr = ifieldRegA( theInstr ); 10152 UChar frB_addr = ifieldRegB( theInstr ); 10153 UChar flag_rC = ifieldBIT0( theInstr ); 10154 10155 IRTemp frA = newTemp( Ity_D64 ); 10156 IRTemp frB = newTemp( Ity_D64 ); 10157 IRTemp frS = newTemp( Ity_D64 ); 10158 IRExpr* round = get_IR_roundingmode_DFP(); 10159 10160 /* By default, if flag_RC is set, we will clear cr1 after the 10161 * operation. In reality we should set cr1 to indicate the 10162 * exception status of the operation, but since we're not 10163 * simulating exceptions, the exception status will appear to be 10164 * zero. Hence cr1 should be cleared if this is a . form insn. 10165 */ 10166 Bool clear_CR1 = True; 10167 10168 assign( frA, getDReg( frA_addr ) ); 10169 assign( frB, getDReg( frB_addr ) ); 10170 10171 switch (opc2) { 10172 case 0x2: // dadd 10173 DIP( "dadd%s fr%u,fr%u,fr%u\n", 10174 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10175 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10176 break; 10177 case 0x202: // dsub 10178 DIP( "dsub%s fr%u,fr%u,fr%u\n", 10179 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10180 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10181 break; 10182 case 0x22: // dmul 10183 DIP( "dmul%s fr%u,fr%u,fr%u\n", 10184 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10185 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10186 break; 10187 case 0x222: // ddiv 10188 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 10189 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10190 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 10191 break; 10192 } 10193 10194 putDReg( frS_addr, mkexpr( frS ) ); 10195 10196 if (flag_rC && clear_CR1) { 10197 putCR321( 1, mkU8( 0 ) ); 10198 putCR0( 1, mkU8( 0 ) ); 10199 } 10200 10201 return True; 10202 } 10203 10204 /* Quad DFP Arithmetic instructions */ 10205 static Bool dis_dfp_arithq(UInt theInstr) 10206 { 10207 UInt opc2 = ifieldOPClo10( theInstr ); 10208 UChar frS_addr = ifieldRegDS( theInstr ); 10209 UChar frA_addr = ifieldRegA( theInstr ); 10210 UChar frB_addr = ifieldRegB( theInstr ); 10211 UChar flag_rC = ifieldBIT0( theInstr ); 10212 10213 IRTemp frA = newTemp( Ity_D128 ); 10214 IRTemp frB = newTemp( Ity_D128 ); 10215 IRTemp frS = newTemp( Ity_D128 ); 10216 IRExpr* round = get_IR_roundingmode_DFP(); 10217 10218 /* By default, if flag_RC is set, we will clear cr1 after the 10219 * operation. In reality we should set cr1 to indicate the 10220 * exception status of the operation, but since we're not 10221 * simulating exceptions, the exception status will appear to be 10222 * zero. Hence cr1 should be cleared if this is a . form insn. 10223 */ 10224 Bool clear_CR1 = True; 10225 10226 assign( frA, getDReg_pair( frA_addr ) ); 10227 assign( frB, getDReg_pair( frB_addr ) ); 10228 10229 switch (opc2) { 10230 case 0x2: // daddq 10231 DIP( "daddq%s fr%u,fr%u,fr%u\n", 10232 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10233 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10234 break; 10235 case 0x202: // dsubq 10236 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 10237 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10238 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10239 break; 10240 case 0x22: // dmulq 10241 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 10242 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10243 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10244 break; 10245 case 0x222: // ddivq 10246 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 10247 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10248 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 10249 break; 10250 } 10251 10252 putDReg_pair( frS_addr, mkexpr( frS ) ); 10253 10254 if (flag_rC && clear_CR1) { 10255 putCR321( 1, mkU8( 0 ) ); 10256 putCR0( 1, mkU8( 0 ) ); 10257 } 10258 10259 return True; 10260 } 10261 10262 /* DFP 64-bit logical shift instructions */ 10263 static Bool dis_dfp_shift(UInt theInstr) { 10264 UInt opc2 = ifieldOPClo9( theInstr ); 10265 UChar frS_addr = ifieldRegDS( theInstr ); 10266 UChar frA_addr = ifieldRegA( theInstr ); 10267 UChar shift_val = IFIELD(theInstr, 10, 6); 10268 UChar flag_rC = ifieldBIT0( theInstr ); 10269 10270 IRTemp frA = newTemp( Ity_D64 ); 10271 IRTemp frS = newTemp( Ity_D64 ); 10272 Bool clear_CR1 = True; 10273 10274 assign( frA, getDReg( frA_addr ) ); 10275 10276 switch (opc2) { 10277 case 0x42: // dscli 10278 DIP( "dscli%s fr%u,fr%u,%u\n", 10279 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10280 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10281 break; 10282 case 0x62: // dscri 10283 DIP( "dscri%s fr%u,fr%u,%u\n", 10284 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10285 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 10286 break; 10287 } 10288 10289 putDReg( frS_addr, mkexpr( frS ) ); 10290 10291 if (flag_rC && clear_CR1) { 10292 putCR321( 1, mkU8( 0 ) ); 10293 putCR0( 1, mkU8( 0 ) ); 10294 } 10295 10296 return True; 10297 } 10298 10299 /* Quad DFP logical shift instructions */ 10300 static Bool dis_dfp_shiftq(UInt theInstr) { 10301 UInt opc2 = ifieldOPClo9( theInstr ); 10302 UChar frS_addr = ifieldRegDS( theInstr ); 10303 UChar frA_addr = ifieldRegA( theInstr ); 10304 UChar shift_val = IFIELD(theInstr, 10, 6); 10305 UChar flag_rC = ifieldBIT0( theInstr ); 10306 10307 IRTemp frA = newTemp( Ity_D128 ); 10308 IRTemp frS = newTemp( Ity_D128 ); 10309 Bool clear_CR1 = True; 10310 10311 assign( frA, getDReg_pair( frA_addr ) ); 10312 10313 switch (opc2) { 10314 case 0x42: // dscliq 10315 DIP( "dscliq%s fr%u,fr%u,%u\n", 10316 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10317 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10318 break; 10319 case 0x62: // dscriq 10320 DIP( "dscriq%s fr%u,fr%u,%u\n", 10321 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10322 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10323 break; 10324 } 10325 10326 putDReg_pair( frS_addr, mkexpr( frS ) ); 10327 10328 if (flag_rC && clear_CR1) { 10329 putCR321( 1, mkU8( 0 ) ); 10330 putCR0( 1, mkU8( 0 ) ); 10331 } 10332 10333 return True; 10334 } 10335 10336 /* DFP 64-bit format conversion instructions */ 10337 static Bool dis_dfp_fmt_conv(UInt theInstr) { 10338 UInt opc2 = ifieldOPClo10( theInstr ); 10339 UChar frS_addr = ifieldRegDS( theInstr ); 10340 UChar frB_addr = ifieldRegB( theInstr ); 10341 IRExpr* round = get_IR_roundingmode_DFP(); 10342 UChar flag_rC = ifieldBIT0( theInstr ); 10343 IRTemp frB; 10344 IRTemp frS; 10345 Bool clear_CR1 = True; 10346 10347 switch (opc2) { 10348 case 0x102: //dctdp 10349 DIP( "dctdp%s fr%u,fr%u\n", 10350 flag_rC ? ".":"", frS_addr, frB_addr ); 10351 10352 frB = newTemp( Ity_D32 ); 10353 frS = newTemp( Ity_D64 ); 10354 assign( frB, getDReg32( frB_addr ) ); 10355 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 10356 putDReg( frS_addr, mkexpr( frS ) ); 10357 break; 10358 case 0x302: // drsp 10359 DIP( "drsp%s fr%u,fr%u\n", 10360 flag_rC ? ".":"", frS_addr, frB_addr ); 10361 frB = newTemp( Ity_D64 ); 10362 frS = newTemp( Ity_D32 ); 10363 assign( frB, getDReg( frB_addr ) ); 10364 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 10365 putDReg32( frS_addr, mkexpr( frS ) ); 10366 break; 10367 case 0x122: // dctfix 10368 { 10369 IRTemp tmp = newTemp( Ity_I64 ); 10370 10371 DIP( "dctfix%s fr%u,fr%u\n", 10372 flag_rC ? ".":"", frS_addr, frB_addr ); 10373 frB = newTemp( Ity_D64 ); 10374 frS = newTemp( Ity_D64 ); 10375 assign( frB, getDReg( frB_addr ) ); 10376 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 10377 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10378 putDReg( frS_addr, mkexpr( frS ) ); 10379 } 10380 break; 10381 case 0x322: // dcffix 10382 DIP( "dcffix%s fr%u,fr%u\n", 10383 flag_rC ? ".":"", frS_addr, frB_addr ); 10384 frB = newTemp( Ity_D64 ); 10385 frS = newTemp( Ity_D64 ); 10386 assign( frB, getDReg( frB_addr ) ); 10387 assign( frS, binop( Iop_I64StoD64, 10388 round, 10389 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 10390 putDReg( frS_addr, mkexpr( frS ) ); 10391 break; 10392 } 10393 10394 if (flag_rC && clear_CR1) { 10395 putCR321( 1, mkU8( 0 ) ); 10396 putCR0( 1, mkU8( 0 ) ); 10397 } 10398 10399 return True; 10400 } 10401 10402 /* Quad DFP format conversion instructions */ 10403 static Bool dis_dfp_fmt_convq(UInt theInstr) { 10404 UInt opc2 = ifieldOPClo10( theInstr ); 10405 UChar frS_addr = ifieldRegDS( theInstr ); 10406 UChar frB_addr = ifieldRegB( theInstr ); 10407 IRExpr* round = get_IR_roundingmode_DFP(); 10408 IRTemp frB64 = newTemp( Ity_D64 ); 10409 IRTemp frB128 = newTemp( Ity_D128 ); 10410 IRTemp frS64 = newTemp( Ity_D64 ); 10411 IRTemp frS128 = newTemp( Ity_D128 ); 10412 UChar flag_rC = ifieldBIT0( theInstr ); 10413 Bool clear_CR1 = True; 10414 10415 switch (opc2) { 10416 case 0x102: // dctqpq 10417 DIP( "dctqpq%s fr%u,fr%u\n", 10418 flag_rC ? ".":"", frS_addr, frB_addr ); 10419 assign( frB64, getDReg( frB_addr ) ); 10420 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 10421 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10422 break; 10423 case 0x122: // dctfixq 10424 { 10425 IRTemp tmp = newTemp( Ity_I64 ); 10426 10427 DIP( "dctfixq%s fr%u,fr%u\n", 10428 flag_rC ? ".":"", frS_addr, frB_addr ); 10429 assign( frB128, getDReg_pair( frB_addr ) ); 10430 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 10431 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10432 putDReg( frS_addr, mkexpr( frS64 ) ); 10433 } 10434 break; 10435 case 0x302: //drdpq 10436 DIP( "drdpq%s fr%u,fr%u\n", 10437 flag_rC ? ".":"", frS_addr, frB_addr ); 10438 assign( frB128, getDReg_pair( frB_addr ) ); 10439 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 10440 putDReg( frS_addr, mkexpr( frS64 ) ); 10441 break; 10442 case 0x322: // dcffixq 10443 { 10444 /* Have to introduce an IOP for this instruction so it will work 10445 * on POWER 6 because emulating the instruction requires a POWER 7 10446 * DFP instruction in the emulation code. 10447 */ 10448 DIP( "dcffixq%s fr%u,fr%u\n", 10449 flag_rC ? ".":"", frS_addr, frB_addr ); 10450 assign( frB64, getDReg( frB_addr ) ); 10451 assign( frS128, unop( Iop_I64StoD128, 10452 unop( Iop_ReinterpD64asI64, 10453 mkexpr( frB64 ) ) ) ); 10454 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10455 break; 10456 } 10457 } 10458 10459 if (flag_rC && clear_CR1) { 10460 putCR321( 1, mkU8( 0 ) ); 10461 putCR0( 1, mkU8( 0 ) ); 10462 } 10463 10464 return True; 10465 } 10466 10467 static Bool dis_dfp_round( UInt theInstr ) { 10468 UChar frS_addr = ifieldRegDS(theInstr); 10469 UChar R = IFIELD(theInstr, 16, 1); 10470 UChar RMC = IFIELD(theInstr, 9, 2); 10471 UChar frB_addr = ifieldRegB( theInstr ); 10472 UChar flag_rC = ifieldBIT0( theInstr ); 10473 IRTemp frB = newTemp( Ity_D64 ); 10474 IRTemp frS = newTemp( Ity_D64 ); 10475 UInt opc2 = ifieldOPClo8( theInstr ); 10476 Bool clear_CR1 = True; 10477 10478 switch (opc2) { 10479 /* drintn, is the same as drintx. The only difference is this 10480 * instruction does not generate an exception for an inexact operation. 10481 * Currently not supporting inexact exceptions. 10482 */ 10483 case 0x63: // drintx 10484 case 0xE3: // drintn 10485 DIP( "drintx/drintn%s fr%u,fr%u\n", 10486 flag_rC ? ".":"", frS_addr, frB_addr ); 10487 10488 /* NOTE, this instruction takes a DFP value and rounds to the 10489 * neares floating point integer value, i.e. fractional part 10490 * is zero. The result is a floating point number. 10491 */ 10492 /* pass the value of R and RMC in the same field */ 10493 assign( frB, getDReg( frB_addr ) ); 10494 assign( frS, binop( Iop_RoundD64toInt, 10495 mkU32( ( R << 3 ) | RMC ), 10496 mkexpr( frB ) ) ); 10497 putDReg( frS_addr, mkexpr( frS ) ); 10498 break; 10499 default: 10500 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 10501 return False; 10502 } 10503 10504 if (flag_rC && clear_CR1) { 10505 putCR321( 1, mkU8( 0 ) ); 10506 putCR0( 1, mkU8( 0 ) ); 10507 } 10508 10509 return True; 10510 } 10511 10512 static Bool dis_dfp_roundq(UInt theInstr) { 10513 UChar frS_addr = ifieldRegDS( theInstr ); 10514 UChar frB_addr = ifieldRegB( theInstr ); 10515 UChar R = IFIELD(theInstr, 16, 1); 10516 UChar RMC = IFIELD(theInstr, 9, 2); 10517 UChar flag_rC = ifieldBIT0( theInstr ); 10518 IRTemp frB = newTemp( Ity_D128 ); 10519 IRTemp frS = newTemp( Ity_D128 ); 10520 Bool clear_CR1 = True; 10521 UInt opc2 = ifieldOPClo8( theInstr ); 10522 10523 switch (opc2) { 10524 /* drintnq, is the same as drintxq. The only difference is this 10525 * instruction does not generate an exception for an inexact operation. 10526 * Currently not supporting inexact exceptions. 10527 */ 10528 case 0x63: // drintxq 10529 case 0xE3: // drintnq 10530 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 10531 flag_rC ? ".":"", frS_addr, frB_addr ); 10532 10533 /* pass the value of R and RMC in the same field */ 10534 assign( frB, getDReg_pair( frB_addr ) ); 10535 assign( frS, binop( Iop_RoundD128toInt, 10536 mkU32( ( R << 3 ) | RMC ), 10537 mkexpr( frB ) ) ); 10538 putDReg_pair( frS_addr, mkexpr( frS ) ); 10539 break; 10540 default: 10541 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 10542 return False; 10543 } 10544 10545 if (flag_rC && clear_CR1) { 10546 putCR321( 1, mkU8( 0 ) ); 10547 putCR0( 1, mkU8( 0 ) ); 10548 } 10549 10550 return True; 10551 } 10552 10553 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 10554 UInt opc2 = ifieldOPClo8( theInstr ); 10555 UChar frS_addr = ifieldRegDS( theInstr ); 10556 UChar frA_addr = ifieldRegA( theInstr ); 10557 UChar frB_addr = ifieldRegB( theInstr ); 10558 UChar flag_rC = ifieldBIT0( theInstr ); 10559 UInt TE_value = IFIELD(theInstr, 16, 4); 10560 UInt TE_sign = IFIELD(theInstr, 20, 1); 10561 UInt RMC = IFIELD(theInstr, 9, 2); 10562 IRTemp frA = newTemp( Ity_D64 ); 10563 IRTemp frB = newTemp( Ity_D64 ); 10564 IRTemp frS = newTemp( Ity_D64 ); 10565 Bool clear_CR1 = True; 10566 10567 assign( frB, getDReg( frB_addr ) ); 10568 10569 switch (opc2) { 10570 case 0x43: // dquai 10571 DIP( "dquai%s fr%u,fr%u,fr%u\n", 10572 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10573 IRTemp TE_I64 = newTemp( Ity_I64 ); 10574 10575 /* Generate a reference DFP value frA with the desired exponent 10576 * given by TE using significand from frB. Need to add the bias 10577 * 398 to TE. TE is stored as a 2's complement number. 10578 */ 10579 if (TE_sign == 1) { 10580 /* Take 2's complement of the 5-bit value and subtract from bias. 10581 * Bias is adjusted for the +1 required when taking 2's complement. 10582 */ 10583 assign( TE_I64, 10584 unop( Iop_32Uto64, 10585 binop( Iop_Sub32, mkU32( 397 ), 10586 binop( Iop_And32, mkU32( 0xF ), 10587 unop( Iop_Not32, mkU32( TE_value ) ) 10588 ) ) ) ); 10589 10590 } else { 10591 assign( TE_I64, 10592 unop( Iop_32Uto64, 10593 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 10594 ) ); 10595 } 10596 10597 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 10598 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 10599 10600 assign( frS, triop( Iop_QuantizeD64, 10601 mkU32( RMC ), 10602 mkexpr( frA ), 10603 mkexpr( frB ) ) ); 10604 break; 10605 10606 case 0x3: // dqua 10607 DIP( "dqua%s fr%u,fr%u,fr%u\n", 10608 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10609 assign( frA, getDReg( frA_addr ) ); 10610 assign( frS, triop( Iop_QuantizeD64, 10611 mkU32( RMC ), 10612 mkexpr( frA ), 10613 mkexpr( frB ) ) ); 10614 break; 10615 case 0x23: // drrnd 10616 { 10617 IRTemp tmp = newTemp( Ity_I8 ); 10618 10619 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 10620 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10621 assign( frA, getDReg( frA_addr ) ); 10622 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 10623 assign( tmp, unop( Iop_32to8, 10624 unop( Iop_64to32, 10625 unop( Iop_ReinterpD64asI64, 10626 mkexpr( frA ) ) ) ) ); 10627 assign( frS, triop( Iop_SignificanceRoundD64, 10628 mkU32( RMC ), 10629 mkexpr( tmp ), 10630 mkexpr( frB ) ) ); 10631 } 10632 break; 10633 default: 10634 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 10635 return False; 10636 } 10637 putDReg( frS_addr, mkexpr( frS ) ); 10638 10639 if (flag_rC && clear_CR1) { 10640 putCR321( 1, mkU8( 0 ) ); 10641 putCR0( 1, mkU8( 0 ) ); 10642 } 10643 10644 return True; 10645 } 10646 10647 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 10648 UInt opc2 = ifieldOPClo8( theInstr ); 10649 UChar frS_addr = ifieldRegDS( theInstr ); 10650 UChar frA_addr = ifieldRegA( theInstr ); 10651 UChar frB_addr = ifieldRegB( theInstr ); 10652 UChar flag_rC = ifieldBIT0( theInstr ); 10653 UInt TE_value = IFIELD(theInstr, 16, 4); 10654 UInt TE_sign = IFIELD(theInstr, 20, 1); 10655 UInt RMC = IFIELD(theInstr, 9, 2); 10656 IRTemp frA = newTemp( Ity_D128 ); 10657 IRTemp frB = newTemp( Ity_D128 ); 10658 IRTemp frS = newTemp( Ity_D128 ); 10659 Bool clear_CR1 = True; 10660 10661 assign( frB, getDReg_pair( frB_addr ) ); 10662 10663 switch (opc2) { 10664 case 0x43: // dquaiq 10665 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10666 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10667 IRTemp TE_I64 = newTemp( Ity_I64 ); 10668 10669 /* Generate a reference DFP value frA with the desired exponent 10670 * given by TE using significand of 1. Need to add the bias 10671 * 6176 to TE. 10672 */ 10673 if (TE_sign == 1) { 10674 /* Take 2's complement of the 5-bit value and subtract from bias. 10675 * Bias adjusted for the +1 required when taking 2's complement. 10676 */ 10677 assign( TE_I64, 10678 unop( Iop_32Uto64, 10679 binop( Iop_Sub32, mkU32( 6175 ), 10680 binop( Iop_And32, mkU32( 0xF ), 10681 unop( Iop_Not32, mkU32( TE_value ) ) 10682 ) ) ) ); 10683 10684 } else { 10685 assign( TE_I64, 10686 unop( Iop_32Uto64, 10687 binop( Iop_Add32, 10688 mkU32( 6176 ), 10689 mkU32( TE_value ) ) ) ); 10690 } 10691 10692 assign( frA, 10693 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 10694 unop( Iop_D64toD128, 10695 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 10696 assign( frS, triop( Iop_QuantizeD128, 10697 mkU32( RMC ), 10698 mkexpr( frA ), 10699 mkexpr( frB ) ) ); 10700 break; 10701 case 0x3: // dquaq 10702 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10703 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10704 assign( frA, getDReg_pair( frA_addr ) ); 10705 assign( frS, triop( Iop_QuantizeD128, 10706 mkU32( RMC ), 10707 mkexpr( frA ), 10708 mkexpr( frB ) ) ); 10709 break; 10710 case 0x23: // drrndq 10711 { 10712 IRTemp tmp = newTemp( Ity_I8 ); 10713 10714 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 10715 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10716 assign( frA, getDReg_pair( frA_addr ) ); 10717 assign( tmp, unop( Iop_32to8, 10718 unop( Iop_64to32, 10719 unop( Iop_ReinterpD64asI64, 10720 unop( Iop_D128HItoD64, 10721 mkexpr( frA ) ) ) ) ) ); 10722 assign( frS, triop( Iop_SignificanceRoundD128, 10723 mkU32( RMC ), 10724 mkexpr( tmp ), 10725 mkexpr( frB ) ) ); 10726 } 10727 break; 10728 default: 10729 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 10730 return False; 10731 } 10732 putDReg_pair( frS_addr, mkexpr( frS ) ); 10733 10734 if (flag_rC && clear_CR1) { 10735 putCR321( 1, mkU8( 0 ) ); 10736 putCR0( 1, mkU8( 0 ) ); 10737 } 10738 10739 return True; 10740 } 10741 10742 static Bool dis_dfp_extract_insert(UInt theInstr) { 10743 UInt opc2 = ifieldOPClo10( theInstr ); 10744 UChar frS_addr = ifieldRegDS( theInstr ); 10745 UChar frA_addr = ifieldRegA( theInstr ); 10746 UChar frB_addr = ifieldRegB( theInstr ); 10747 UChar flag_rC = ifieldBIT0( theInstr ); 10748 Bool clear_CR1 = True; 10749 10750 IRTemp frA = newTemp( Ity_D64 ); 10751 IRTemp frB = newTemp( Ity_D64 ); 10752 IRTemp frS = newTemp( Ity_D64 ); 10753 IRTemp tmp = newTemp( Ity_I64 ); 10754 10755 assign( frA, getDReg( frA_addr ) ); 10756 assign( frB, getDReg( frB_addr ) ); 10757 10758 switch (opc2) { 10759 case 0x162: // dxex 10760 DIP( "dxex%s fr%u,fr%u,fr%u\n", 10761 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10762 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 10763 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10764 break; 10765 case 0x362: // diex 10766 DIP( "diex%s fr%u,fr%u,fr%u\n", 10767 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10768 assign( frS, binop( Iop_InsertExpD64, 10769 unop( Iop_ReinterpD64asI64, 10770 mkexpr( frA ) ), 10771 mkexpr( frB ) ) ); 10772 break; 10773 default: 10774 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 10775 return False; 10776 } 10777 10778 putDReg( frS_addr, mkexpr( frS ) ); 10779 10780 if (flag_rC && clear_CR1) { 10781 putCR321( 1, mkU8( 0 ) ); 10782 putCR0( 1, mkU8( 0 ) ); 10783 } 10784 10785 return True; 10786 } 10787 10788 static Bool dis_dfp_extract_insertq(UInt theInstr) { 10789 UInt opc2 = ifieldOPClo10( theInstr ); 10790 UChar frS_addr = ifieldRegDS( theInstr ); 10791 UChar frA_addr = ifieldRegA( theInstr ); 10792 UChar frB_addr = ifieldRegB( theInstr ); 10793 UChar flag_rC = ifieldBIT0( theInstr ); 10794 10795 IRTemp frA = newTemp( Ity_D64 ); 10796 IRTemp frB = newTemp( Ity_D128 ); 10797 IRTemp frS64 = newTemp( Ity_D64 ); 10798 IRTemp frS = newTemp( Ity_D128 ); 10799 IRTemp tmp = newTemp( Ity_I64 ); 10800 Bool clear_CR1 = True; 10801 10802 assign( frB, getDReg_pair( frB_addr ) ); 10803 10804 switch (opc2) { 10805 case 0x162: // dxexq 10806 DIP( "dxexq%s fr%u,fr%u\n", 10807 flag_rC ? ".":"", frS_addr, frB_addr ); 10808 /* Instruction actually returns a 64-bit result. So as to be 10809 * consistent and not have to add a new struct, the emulation returns 10810 * the 64-bit result in the upper and lower register. 10811 */ 10812 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 10813 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10814 putDReg( frS_addr, mkexpr( frS64 ) ); 10815 break; 10816 case 0x362: // diexq 10817 DIP( "diexq%s fr%u,fr%u,fr%u\n", 10818 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10819 assign( frA, getDReg( frA_addr ) ); 10820 assign( frS, binop( Iop_InsertExpD128, 10821 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 10822 mkexpr( frB ) ) ); 10823 putDReg_pair( frS_addr, mkexpr( frS ) ); 10824 break; 10825 default: 10826 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 10827 return False; 10828 } 10829 10830 if (flag_rC && clear_CR1) { 10831 putCR321( 1, mkU8( 0 ) ); 10832 putCR0( 1, mkU8( 0 ) ); 10833 } 10834 10835 return True; 10836 } 10837 10838 /* DFP 64-bit comparison instructions */ 10839 static Bool dis_dfp_compare(UInt theInstr) { 10840 /* X-Form */ 10841 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10842 UChar frA_addr = ifieldRegA( theInstr ); 10843 UChar frB_addr = ifieldRegB( theInstr ); 10844 UInt opc1 = ifieldOPC( theInstr ); 10845 IRTemp frA; 10846 IRTemp frB; 10847 10848 IRTemp ccIR = newTemp( Ity_I32 ); 10849 IRTemp ccPPC32 = newTemp( Ity_I32 ); 10850 10851 10852 /* Note: Differences between dcmpu and dcmpo are only in exception 10853 flag settings, which aren't supported anyway. */ 10854 switch (opc1) { 10855 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 10856 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10857 frA = newTemp( Ity_D64 ); 10858 frB = newTemp( Ity_D64 ); 10859 10860 assign( frA, getDReg( frA_addr ) ); 10861 assign( frB, getDReg( frB_addr ) ); 10862 10863 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 10864 break; 10865 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 10866 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10867 frA = newTemp( Ity_D128 ); 10868 frB = newTemp( Ity_D128 ); 10869 10870 assign( frA, getDReg_pair( frA_addr ) ); 10871 assign( frB, getDReg_pair( frB_addr ) ); 10872 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 10873 break; 10874 default: 10875 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 10876 return False; 10877 } 10878 10879 /* Map compare result from IR to PPC32 */ 10880 /* 10881 FP cmp result | PPC | IR 10882 -------------------------- 10883 UN | 0x1 | 0x45 10884 EQ | 0x2 | 0x40 10885 GT | 0x4 | 0x00 10886 LT | 0x8 | 0x01 10887 */ 10888 10889 assign( ccPPC32, 10890 binop( Iop_Shl32, 10891 mkU32( 1 ), 10892 unop( Iop_32to8, 10893 binop( Iop_Or32, 10894 binop( Iop_And32, 10895 unop( Iop_Not32, 10896 binop( Iop_Shr32, 10897 mkexpr( ccIR ), 10898 mkU8( 5 ) ) ), 10899 mkU32( 2 ) ), 10900 binop( Iop_And32, 10901 binop( Iop_Xor32, 10902 mkexpr( ccIR ), 10903 binop( Iop_Shr32, 10904 mkexpr( ccIR ), 10905 mkU8( 6 ) ) ), 10906 mkU32( 1 ) ) ) ) ) ); 10907 10908 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 10909 return True; 10910 } 10911 10912 /* Test class/group/exponent/significance instructions. */ 10913 static Bool dis_dfp_exponent_test ( UInt theInstr ) 10914 { 10915 UChar frA_addr = ifieldRegA( theInstr ); 10916 UChar frB_addr = ifieldRegB( theInstr ); 10917 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10918 IRTemp frA = newTemp( Ity_D64 ); 10919 IRTemp frB = newTemp( Ity_D64 ); 10920 IRTemp frA128 = newTemp( Ity_D128 ); 10921 IRTemp frB128 = newTemp( Ity_D128 ); 10922 UInt opc1 = ifieldOPC( theInstr ); 10923 IRTemp gfield_A = newTemp( Ity_I32 ); 10924 IRTemp gfield_B = newTemp( Ity_I32 ); 10925 IRTemp gfield_mask = newTemp( Ity_I32 ); 10926 IRTemp exponent_A = newTemp( Ity_I32 ); 10927 IRTemp exponent_B = newTemp( Ity_I32 ); 10928 IRTemp A_NaN_true = newTemp( Ity_I32 ); 10929 IRTemp B_NaN_true = newTemp( Ity_I32 ); 10930 IRTemp A_inf_true = newTemp( Ity_I32 ); 10931 IRTemp B_inf_true = newTemp( Ity_I32 ); 10932 IRTemp A_equals_B = newTemp( Ity_I32 ); 10933 IRTemp finite_number = newTemp( Ity_I32 ); 10934 IRTemp cc0 = newTemp( Ity_I32 ); 10935 IRTemp cc1 = newTemp( Ity_I32 ); 10936 IRTemp cc2 = newTemp( Ity_I32 ); 10937 IRTemp cc3 = newTemp( Ity_I32 ); 10938 10939 /* The dtstex and dtstexg instructions only differ in the size of the 10940 * exponent field. The following switch statement takes care of the size 10941 * specific setup. Once the value of the exponents, the G-field shift 10942 * and mask is setup the remaining code is identical. 10943 */ 10944 switch (opc1) { 10945 case 0x3b: // dtstex Extended instruction setup 10946 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10947 assign( frA, getDReg( frA_addr ) ); 10948 assign( frB, getDReg( frB_addr ) ); 10949 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10950 assign(exponent_A, unop( Iop_64to32, 10951 unop( Iop_ExtractExpD64, 10952 mkexpr( frA ) ) ) ); 10953 assign(exponent_B, unop( Iop_64to32, 10954 unop( Iop_ExtractExpD64, 10955 mkexpr( frB ) ) ) ); 10956 break; 10957 10958 case 0x3F: // dtstexq Quad instruction setup 10959 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10960 assign( frA128, getDReg_pair( frA_addr ) ); 10961 assign( frB128, getDReg_pair( frB_addr ) ); 10962 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 10963 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 10964 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10965 assign( exponent_A, unop( Iop_64to32, 10966 unop( Iop_ExtractExpD128, 10967 mkexpr( frA128 ) ) ) ); 10968 assign( exponent_B, unop( Iop_64to32, 10969 unop( Iop_ExtractExpD128, 10970 mkexpr( frB128 ) ) ) ); 10971 break; 10972 default: 10973 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 10974 return False; 10975 } 10976 10977 /* Extract the Gfield */ 10978 assign( gfield_A, binop( Iop_And32, 10979 mkexpr( gfield_mask ), 10980 unop( Iop_64HIto32, 10981 unop( Iop_ReinterpD64asI64, 10982 mkexpr(frA) ) ) ) ); 10983 10984 assign( gfield_B, binop( Iop_And32, 10985 mkexpr( gfield_mask ), 10986 unop( Iop_64HIto32, 10987 unop( Iop_ReinterpD64asI64, 10988 mkexpr(frB) ) ) ) ); 10989 10990 /* check for NAN */ 10991 assign( A_NaN_true, binop(Iop_Or32, 10992 unop( Iop_1Sto32, 10993 binop( Iop_CmpEQ32, 10994 mkexpr( gfield_A ), 10995 mkU32( 0x7C000000 ) ) ), 10996 unop( Iop_1Sto32, 10997 binop( Iop_CmpEQ32, 10998 mkexpr( gfield_A ), 10999 mkU32( 0x7E000000 ) ) 11000 ) ) ); 11001 assign( B_NaN_true, binop(Iop_Or32, 11002 unop( Iop_1Sto32, 11003 binop( Iop_CmpEQ32, 11004 mkexpr( gfield_B ), 11005 mkU32( 0x7C000000 ) ) ), 11006 unop( Iop_1Sto32, 11007 binop( Iop_CmpEQ32, 11008 mkexpr( gfield_B ), 11009 mkU32( 0x7E000000 ) ) 11010 ) ) ); 11011 11012 /* check for infinity */ 11013 assign( A_inf_true, 11014 unop( Iop_1Sto32, 11015 binop( Iop_CmpEQ32, 11016 mkexpr( gfield_A ), 11017 mkU32( 0x78000000 ) ) ) ); 11018 11019 assign( B_inf_true, 11020 unop( Iop_1Sto32, 11021 binop( Iop_CmpEQ32, 11022 mkexpr( gfield_B ), 11023 mkU32( 0x78000000 ) ) ) ); 11024 11025 assign( finite_number, 11026 unop( Iop_Not32, 11027 binop( Iop_Or32, 11028 binop( Iop_Or32, 11029 mkexpr( A_NaN_true ), 11030 mkexpr( B_NaN_true ) ), 11031 binop( Iop_Or32, 11032 mkexpr( A_inf_true ), 11033 mkexpr( B_inf_true ) ) ) ) ); 11034 11035 /* Calculate the condition code bits 11036 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 11037 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 11038 * cc0, cc1 and cc0 reflect the results of the comparisons. 11039 */ 11040 assign( A_equals_B, 11041 binop( Iop_Or32, 11042 unop( Iop_1Uto32, 11043 binop( Iop_CmpEQ32, 11044 mkexpr( exponent_A ), 11045 mkexpr( exponent_B ) ) ), 11046 binop( Iop_Or32, 11047 binop( Iop_And32, 11048 mkexpr( A_inf_true ), 11049 mkexpr( B_inf_true ) ), 11050 binop( Iop_And32, 11051 mkexpr( A_NaN_true ), 11052 mkexpr( B_NaN_true ) ) ) ) ); 11053 11054 assign( cc0, binop( Iop_And32, 11055 mkexpr( finite_number ), 11056 binop( Iop_Shl32, 11057 unop( Iop_1Uto32, 11058 binop( Iop_CmpLT32U, 11059 mkexpr( exponent_A ), 11060 mkexpr( exponent_B ) ) ), 11061 mkU8( 3 ) ) ) ); 11062 11063 assign( cc1, binop( Iop_And32, 11064 mkexpr( finite_number ), 11065 binop( Iop_Shl32, 11066 unop( Iop_1Uto32, 11067 binop( Iop_CmpLT32U, 11068 mkexpr( exponent_B ), 11069 mkexpr( exponent_A ) ) ), 11070 mkU8( 2 ) ) ) ); 11071 11072 assign( cc2, binop( Iop_Shl32, 11073 binop( Iop_And32, 11074 mkexpr( A_equals_B ), 11075 mkU32( 1 ) ), 11076 mkU8( 1 ) ) ); 11077 11078 assign( cc3, binop( Iop_And32, 11079 unop( Iop_Not32, mkexpr( A_equals_B ) ), 11080 binop( Iop_And32, 11081 mkU32( 0x1 ), 11082 binop( Iop_Or32, 11083 binop( Iop_Or32, 11084 mkexpr ( A_inf_true ), 11085 mkexpr ( B_inf_true ) ), 11086 binop( Iop_Or32, 11087 mkexpr ( A_NaN_true ), 11088 mkexpr ( B_NaN_true ) ) ) 11089 ) ) ); 11090 11091 /* store the condition code */ 11092 putGST_field( PPC_GST_CR, 11093 binop( Iop_Or32, 11094 mkexpr( cc0 ), 11095 binop( Iop_Or32, 11096 mkexpr( cc1 ), 11097 binop( Iop_Or32, 11098 mkexpr( cc2 ), 11099 mkexpr( cc3 ) ) ) ), 11100 crfD ); 11101 return True; 11102 } 11103 11104 /* Test class/group/exponent/significance instructions. */ 11105 static Bool dis_dfp_class_test ( UInt theInstr ) 11106 { 11107 UChar frA_addr = ifieldRegA( theInstr ); 11108 IRTemp frA = newTemp( Ity_D64 ); 11109 IRTemp abs_frA = newTemp( Ity_D64 ); 11110 IRTemp frAI64_hi = newTemp( Ity_I64 ); 11111 IRTemp frAI64_lo = newTemp( Ity_I64 ); 11112 UInt opc1 = ifieldOPC( theInstr ); 11113 UInt opc2 = ifieldOPClo9( theInstr ); 11114 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 11115 UInt DCM = IFIELD( theInstr, 10, 6 ); 11116 IRTemp DCM_calc = newTemp( Ity_I32 ); 11117 UInt max_exp = 0; 11118 UInt min_exp = 0; 11119 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 11120 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 11121 IRTemp significand64 = newTemp( Ity_D64 ); 11122 IRTemp significand128 = newTemp( Ity_D128 ); 11123 IRTemp exp_min_normal = newTemp( Ity_I64 ); 11124 IRTemp exponent = newTemp( Ity_I32 ); 11125 11126 IRTemp infinity_true = newTemp( Ity_I32 ); 11127 IRTemp SNaN_true = newTemp( Ity_I32 ); 11128 IRTemp QNaN_true = newTemp( Ity_I32 ); 11129 IRTemp subnormal_true = newTemp( Ity_I32 ); 11130 IRTemp normal_true = newTemp( Ity_I32 ); 11131 IRTemp extreme_true = newTemp( Ity_I32 ); 11132 IRTemp lmd = newTemp( Ity_I32 ); 11133 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 11134 IRTemp zero_true = newTemp( Ity_I32 ); 11135 IRTemp sign = newTemp( Ity_I32 ); 11136 IRTemp field = newTemp( Ity_I32 ); 11137 IRTemp ccIR_zero = newTemp( Ity_I32 ); 11138 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 11139 11140 /* UInt size = DFP_LONG; JRS:unused */ 11141 IRTemp gfield = newTemp( Ity_I32 ); 11142 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 11143 IRTemp gfield_mask = newTemp( Ity_I32 ); 11144 IRTemp dcm0 = newTemp( Ity_I32 ); 11145 IRTemp dcm1 = newTemp( Ity_I32 ); 11146 IRTemp dcm2 = newTemp( Ity_I32 ); 11147 IRTemp dcm3 = newTemp( Ity_I32 ); 11148 IRTemp dcm4 = newTemp( Ity_I32 ); 11149 IRTemp dcm5 = newTemp( Ity_I32 ); 11150 11151 /* The only difference between the dtstdc and dtstdcq instructions is 11152 * size of the T and G fields. The calculation of the 4 bit field 11153 * is the same. Setup the parameters and values that are DFP size 11154 * specific. The rest of the code is independent of the DFP size. 11155 * 11156 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 11157 * The interpretation of the ccIR values is as follows: 11158 * 11159 * DFP cmp result | IR 11160 * -------------------------- 11161 * UN | 0x45 11162 * EQ | 0x40 11163 * GT | 0x00 11164 * LT | 0x01 11165 */ 11166 11167 assign( frA, getDReg( frA_addr ) ); 11168 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 11169 11170 assign( abs_frA, unop( Iop_ReinterpI64asD64, 11171 binop( Iop_And64, 11172 unop( Iop_ReinterpD64asI64, 11173 mkexpr( frA ) ), 11174 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 11175 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 11176 switch (opc1) { 11177 case 0x3b: // dtstdc, dtstdg 11178 DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 11179 crfD, frA_addr, DCM); 11180 /* setup the parameters for the long format of the two instructions */ 11181 assign( frAI64_lo, mkU64( 0 ) ); 11182 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 11183 max_exp = DFP_LONG_EXP_MAX; 11184 min_exp = DFP_LONG_EXP_MIN; 11185 11186 assign( exponent, unop( Iop_64to32, 11187 unop( Iop_ExtractExpD64, 11188 mkexpr( frA ) ) ) ); 11189 assign( significand64, 11190 unop( Iop_ReinterpI64asD64, 11191 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 11192 assign( exp_min_normal,mkU64( 398 - 383 ) ); 11193 assign( min_subnormalD64, 11194 binop( Iop_InsertExpD64, 11195 mkexpr( exp_min_normal ), 11196 mkexpr( significand64 ) ) ); 11197 11198 assign( ccIR_subnormal, 11199 binop( Iop_CmpD64, 11200 mkexpr( abs_frA ), 11201 mkexpr( min_subnormalD64 ) ) ); 11202 11203 /* compare absolute value of frA with zero */ 11204 assign( ccIR_zero, 11205 binop( Iop_CmpD64, 11206 mkexpr( abs_frA ), 11207 unop( Iop_ReinterpI64asD64, 11208 mkU64( 0x2238000000000000ULL ) ) ) ); 11209 11210 /* size = DFP_LONG; JRS: unused */ 11211 break; 11212 11213 case 0x3F: // dtstdcq, dtstdgq 11214 DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 11215 crfD, frA_addr, DCM); 11216 /* setup the parameters for the extended format of the 11217 * two instructions 11218 */ 11219 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 11220 getDReg( frA_addr+1 ) ) ); 11221 11222 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 11223 max_exp = DFP_EXTND_EXP_MAX; 11224 min_exp = DFP_EXTND_EXP_MIN; 11225 assign( exponent, unop( Iop_64to32, 11226 unop( Iop_ExtractExpD128, 11227 getDReg_pair( frA_addr) ) ) ); 11228 11229 /* create quand exponent for minimum normal number */ 11230 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 11231 assign( significand128, 11232 unop( Iop_D64toD128, 11233 unop( Iop_ReinterpI64asD64, 11234 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 11235 11236 assign( min_subnormalD128, 11237 binop( Iop_InsertExpD128, 11238 mkexpr( exp_min_normal ), 11239 mkexpr( significand128 ) ) ); 11240 11241 assign( ccIR_subnormal, 11242 binop( Iop_CmpD128, 11243 binop( Iop_D64HLtoD128, 11244 unop( Iop_ReinterpI64asD64, 11245 binop( Iop_And64, 11246 unop( Iop_ReinterpD64asI64, 11247 mkexpr( frA ) ), 11248 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 11249 getDReg( frA_addr+1 ) ), 11250 mkexpr( min_subnormalD128 ) ) ); 11251 assign( ccIR_zero, 11252 binop( Iop_CmpD128, 11253 binop( Iop_D64HLtoD128, 11254 mkexpr( abs_frA ), 11255 getDReg( frA_addr+1 ) ), 11256 unop( Iop_D64toD128, 11257 unop( Iop_ReinterpI64asD64, 11258 mkU64( 0x0ULL ) ) ) ) ); 11259 11260 /* size = DFP_EXTND; JRS:unused */ 11261 break; 11262 default: 11263 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 11264 return False; 11265 } 11266 11267 /* The G-field is in the upper 32-bits. The I64 logical operations 11268 * do not seem to be supported in 32-bit mode so keep things as 32-bit 11269 * operations. 11270 */ 11271 assign( gfield, binop( Iop_And32, 11272 mkexpr( gfield_mask ), 11273 unop( Iop_64HIto32, 11274 mkexpr(frAI64_hi) ) ) ); 11275 11276 /* There is a lot of code that is the same to do the class and group 11277 * instructions. Later there is an if statement to handle the specific 11278 * instruction. 11279 * 11280 * Will be using I32 values, compares, shifts and logical operations for 11281 * this code as the 64-bit compare, shifts, logical operations are not 11282 * supported in 32-bit mode. 11283 */ 11284 11285 /* Check the bits for Infinity, QNaN or Signaling NaN */ 11286 assign( infinity_true, 11287 unop( Iop_1Sto32, 11288 binop( Iop_CmpEQ32, 11289 binop( Iop_And32, 11290 mkU32( 0x7C000000 ), 11291 mkexpr( gfield ) ), 11292 mkU32( 0x78000000 ) ) ) ); 11293 11294 assign( SNaN_true, 11295 unop( Iop_1Sto32, 11296 binop( Iop_CmpEQ32, 11297 binop( Iop_And32, 11298 mkU32( 0x7E000000 ), 11299 mkexpr( gfield ) ), 11300 mkU32( 0x7E000000 ) ) ) ); 11301 11302 assign( QNaN_true, 11303 binop( Iop_And32, 11304 unop( Iop_1Sto32, 11305 binop( Iop_CmpEQ32, 11306 binop( Iop_And32, 11307 mkU32( 0x7E000000 ), 11308 mkexpr( gfield ) ), 11309 mkU32( 0x7C000000 ) ) ), 11310 unop( Iop_Not32, 11311 mkexpr( SNaN_true ) ) ) ); 11312 11313 assign( zero_true, 11314 binop( Iop_And32, 11315 unop(Iop_1Sto32, 11316 binop( Iop_CmpEQ32, 11317 mkexpr( ccIR_zero ), 11318 mkU32( 0x40 ) ) ), // ccIR code for Equal 11319 unop( Iop_Not32, 11320 binop( Iop_Or32, 11321 mkexpr( infinity_true ), 11322 binop( Iop_Or32, 11323 mkexpr( QNaN_true ), 11324 mkexpr( SNaN_true ) ) ) ) ) ); 11325 11326 /* Do compare of frA the minimum normal value. Comparison is size 11327 * depenent and was done above to get the ccIR value. 11328 */ 11329 assign( subnormal_true, 11330 binop( Iop_And32, 11331 binop( Iop_Or32, 11332 unop( Iop_1Sto32, 11333 binop( Iop_CmpEQ32, 11334 mkexpr( ccIR_subnormal ), 11335 mkU32( 0x40 ) ) ), // ccIR code for Equal 11336 unop( Iop_1Sto32, 11337 binop( Iop_CmpEQ32, 11338 mkexpr( ccIR_subnormal ), 11339 mkU32( 0x1 ) ) ) ), // ccIR code for LT 11340 unop( Iop_Not32, 11341 binop( Iop_Or32, 11342 binop( Iop_Or32, 11343 mkexpr( infinity_true ), 11344 mkexpr( zero_true) ), 11345 binop( Iop_Or32, 11346 mkexpr( QNaN_true ), 11347 mkexpr( SNaN_true ) ) ) ) ) ); 11348 11349 /* Normal number is not subnormal, infinity, NaN or Zero */ 11350 assign( normal_true, 11351 unop( Iop_Not32, 11352 binop( Iop_Or32, 11353 binop( Iop_Or32, 11354 mkexpr( infinity_true ), 11355 mkexpr( zero_true ) ), 11356 binop( Iop_Or32, 11357 mkexpr( subnormal_true ), 11358 binop( Iop_Or32, 11359 mkexpr( QNaN_true ), 11360 mkexpr( SNaN_true ) ) ) ) ) ); 11361 11362 /* Calculate the DCM bit field based on the tests for the specific 11363 * instruction 11364 */ 11365 if (opc2 == 0xC2) { // dtstdc, dtstdcq 11366 /* DCM[0:5] Bit Data Class definition 11367 * 0 Zero 11368 * 1 Subnormal 11369 * 2 Normal 11370 * 3 Infinity 11371 * 4 Quiet NaN 11372 * 5 Signaling NaN 11373 */ 11374 11375 assign( dcm0, binop( Iop_Shl32, 11376 mkexpr( zero_true ), 11377 mkU8( 5 ) ) ); 11378 assign( dcm1, binop( Iop_Shl32, 11379 binop( Iop_And32, 11380 mkexpr( subnormal_true ), 11381 mkU32( 1 ) ), 11382 mkU8( 4 ) ) ); 11383 assign( dcm2, binop( Iop_Shl32, 11384 binop( Iop_And32, 11385 mkexpr( normal_true ), 11386 mkU32( 1 ) ), 11387 mkU8( 3 ) ) ); 11388 assign( dcm3, binop( Iop_Shl32, 11389 binop( Iop_And32, 11390 mkexpr( infinity_true), 11391 mkU32( 1 ) ), 11392 mkU8( 2 ) ) ); 11393 assign( dcm4, binop( Iop_Shl32, 11394 binop( Iop_And32, 11395 mkexpr( QNaN_true ), 11396 mkU32( 1 ) ), 11397 mkU8( 1 ) ) ); 11398 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 11399 11400 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 11401 /* check if the exponent is extreme */ 11402 assign( extreme_true, binop( Iop_Or32, 11403 unop( Iop_1Sto32, 11404 binop( Iop_CmpEQ32, 11405 mkexpr( exponent ), 11406 mkU32( max_exp ) ) ), 11407 unop( Iop_1Sto32, 11408 binop( Iop_CmpEQ32, 11409 mkexpr( exponent ), 11410 mkU32( min_exp ) ) ) ) ); 11411 11412 /* Check if LMD is zero */ 11413 Get_lmd( &lmd, binop( Iop_Shr32, 11414 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 11415 11416 assign( lmd_zero_true, unop( Iop_1Sto32, 11417 binop( Iop_CmpEQ32, 11418 mkexpr( lmd ), 11419 mkU32( 0 ) ) ) ); 11420 11421 /* DCM[0:5] Bit Data Class definition 11422 * 0 Zero with non-extreme exponent 11423 * 1 Zero with extreme exponent 11424 * 2 Subnormal or (Normal with extreme exponent) 11425 * 3 Normal with non-extreme exponent and 11426 * leftmost zero digit in significand 11427 * 4 Normal with non-extreme exponent and 11428 * leftmost nonzero digit in significand 11429 * 5 Special symbol (Infinity, QNaN, or SNaN) 11430 */ 11431 assign( dcm0, binop( Iop_Shl32, 11432 binop( Iop_And32, 11433 binop( Iop_And32, 11434 unop( Iop_Not32, 11435 mkexpr( extreme_true ) ), 11436 mkexpr( zero_true ) ), 11437 mkU32( 0x1 ) ), 11438 mkU8( 5 ) ) ); 11439 11440 assign( dcm1, binop( Iop_Shl32, 11441 binop( Iop_And32, 11442 binop( Iop_And32, 11443 mkexpr( extreme_true ), 11444 mkexpr( zero_true ) ), 11445 mkU32( 0x1 ) ), 11446 mkU8( 4 ) ) ); 11447 11448 assign( dcm2, binop( Iop_Shl32, 11449 binop( Iop_And32, 11450 binop( Iop_Or32, 11451 binop( Iop_And32, 11452 mkexpr( extreme_true ), 11453 mkexpr( normal_true ) ), 11454 mkexpr( subnormal_true ) ), 11455 mkU32( 0x1 ) ), 11456 mkU8( 3 ) ) ); 11457 11458 assign( dcm3, binop( Iop_Shl32, 11459 binop( Iop_And32, 11460 binop( Iop_And32, 11461 binop( Iop_And32, 11462 unop( Iop_Not32, 11463 mkexpr( extreme_true ) ), 11464 mkexpr( normal_true ) ), 11465 unop( Iop_1Sto32, 11466 binop( Iop_CmpEQ32, 11467 mkexpr( lmd ), 11468 mkU32( 0 ) ) ) ), 11469 mkU32( 0x1 ) ), 11470 mkU8( 2 ) ) ); 11471 11472 assign( dcm4, binop( Iop_Shl32, 11473 binop( Iop_And32, 11474 binop( Iop_And32, 11475 binop( Iop_And32, 11476 unop( Iop_Not32, 11477 mkexpr( extreme_true ) ), 11478 mkexpr( normal_true ) ), 11479 unop( Iop_1Sto32, 11480 binop( Iop_CmpNE32, 11481 mkexpr( lmd ), 11482 mkU32( 0 ) ) ) ), 11483 mkU32( 0x1 ) ), 11484 mkU8( 1 ) ) ); 11485 11486 assign( dcm5, binop( Iop_And32, 11487 binop( Iop_Or32, 11488 mkexpr( SNaN_true), 11489 binop( Iop_Or32, 11490 mkexpr( QNaN_true), 11491 mkexpr( infinity_true) ) ), 11492 mkU32( 0x1 ) ) ); 11493 } 11494 11495 /* create DCM field */ 11496 assign( DCM_calc, 11497 binop( Iop_Or32, 11498 mkexpr( dcm0 ), 11499 binop( Iop_Or32, 11500 mkexpr( dcm1 ), 11501 binop( Iop_Or32, 11502 mkexpr( dcm2 ), 11503 binop( Iop_Or32, 11504 mkexpr( dcm3 ), 11505 binop( Iop_Or32, 11506 mkexpr( dcm4 ), 11507 mkexpr( dcm5 ) ) ) ) ) ) ); 11508 11509 /* Get the sign of the DFP number, ignore sign for QNaN */ 11510 assign( sign, 11511 unop( Iop_1Uto32, 11512 binop( Iop_CmpEQ32, 11513 binop( Iop_Shr32, 11514 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 11515 mkU8( 63 - 32 ) ), 11516 mkU32( 1 ) ) ) ); 11517 11518 /* This instruction generates a four bit field to be stored in the 11519 * condition code register. The condition code register consists of 7 11520 * fields. The field to be written to is specified by the BF (AKA crfD) 11521 * field. 11522 * 11523 * The field layout is as follows: 11524 * 11525 * Field Meaning 11526 * 0000 Operand positive with no match 11527 * 0100 Operand positive with at least one match 11528 * 0001 Operand negative with no match 11529 * 0101 Operand negative with at least one match 11530 */ 11531 assign( field, binop( Iop_Or32, 11532 binop( Iop_Shl32, 11533 mkexpr( sign ), 11534 mkU8( 3 ) ), 11535 binop( Iop_Shl32, 11536 unop( Iop_1Uto32, 11537 binop( Iop_CmpNE32, 11538 binop( Iop_And32, 11539 mkU32( DCM ), 11540 mkexpr( DCM_calc ) ), 11541 mkU32( 0 ) ) ), 11542 mkU8( 1 ) ) ) ); 11543 11544 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 11545 return True; 11546 } 11547 11548 static Bool dis_dfp_bcd(UInt theInstr) { 11549 UInt opc2 = ifieldOPClo10( theInstr ); 11550 ULong sp = IFIELD(theInstr, 19, 2); 11551 ULong s = IFIELD(theInstr, 20, 1); 11552 UChar frT_addr = ifieldRegDS( theInstr ); 11553 UChar frB_addr = ifieldRegB( theInstr ); 11554 IRTemp frB = newTemp( Ity_D64 ); 11555 IRTemp frBI64 = newTemp( Ity_I64 ); 11556 IRTemp result = newTemp( Ity_I64 ); 11557 IRTemp resultD64 = newTemp( Ity_D64 ); 11558 IRTemp bcd64 = newTemp( Ity_I64 ); 11559 IRTemp bcd_u = newTemp( Ity_I32 ); 11560 IRTemp bcd_l = newTemp( Ity_I32 ); 11561 IRTemp dbcd_u = newTemp( Ity_I32 ); 11562 IRTemp dbcd_l = newTemp( Ity_I32 ); 11563 IRTemp lmd = newTemp( Ity_I32 ); 11564 11565 assign( frB, getDReg( frB_addr ) ); 11566 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11567 11568 switch ( opc2 ) { 11569 case 0x142: // ddedpd DFP Decode DPD to BCD 11570 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11571 11572 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11573 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 11574 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 11575 11576 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11577 /* Unsigned BCD string */ 11578 Get_lmd( &lmd, 11579 binop( Iop_Shr32, 11580 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11581 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11582 11583 assign( result, 11584 binop( Iop_32HLto64, 11585 binop( Iop_Or32, 11586 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 11587 mkexpr( bcd_u ) ), 11588 mkexpr( bcd_l ) ) ); 11589 11590 } else { 11591 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11592 * the positive and negative values are encoded in the least 11593 * significant bits. 11594 */ 11595 IRTemp sign = newTemp( Ity_I32 ); 11596 11597 if (sp == 2) { 11598 /* Positive sign = 0xC, negative sign = 0xD */ 11599 11600 assign( sign, 11601 binop( Iop_Or32, 11602 binop( Iop_Shr32, 11603 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11604 mkU8( 31 ) ), 11605 mkU32( 0xC ) ) ); 11606 11607 } else if ( sp == 3 ) { 11608 /* Positive sign = 0xF, negative sign = 0xD */ 11609 IRTemp tmp32 = newTemp( Ity_I32 ); 11610 11611 /* Complement sign bit then OR into bit position 1 */ 11612 assign( tmp32, 11613 binop( Iop_Xor32, 11614 binop( Iop_Shr32, 11615 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11616 mkU8( 30 ) ), 11617 mkU32( 0x2 ) ) ); 11618 11619 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11620 11621 } else { 11622 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11623 } 11624 11625 /* Put sign in bottom 4 bits, move most significant 4-bits from 11626 * bcd_l to bcd_u. 11627 */ 11628 assign( result, 11629 binop( Iop_32HLto64, 11630 binop( Iop_Or32, 11631 binop( Iop_Shr32, 11632 mkexpr( bcd_l ), 11633 mkU8( 28 ) ), 11634 binop( Iop_Shl32, 11635 mkexpr( bcd_u ), 11636 mkU8( 4 ) ) ), 11637 binop( Iop_Or32, 11638 mkexpr( sign ), 11639 binop( Iop_Shl32, 11640 mkexpr( bcd_l ), 11641 mkU8( 4 ) ) ) ) ); 11642 } 11643 11644 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 11645 break; 11646 11647 case 0x342: // denbcd DFP Encode BCD to DPD 11648 { 11649 IRTemp valid_mask = newTemp( Ity_I32 ); 11650 IRTemp invalid_mask = newTemp( Ity_I32 ); 11651 IRTemp without_lmd = newTemp( Ity_I64 ); 11652 IRTemp tmp64 = newTemp( Ity_I64 ); 11653 IRTemp dbcd64 = newTemp( Ity_I64 ); 11654 IRTemp left_exp = newTemp( Ity_I32 ); 11655 IRTemp g0_4 = newTemp( Ity_I32 ); 11656 11657 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11658 11659 if ( s == 0 ) { 11660 /* Unsigned BCD string */ 11661 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 11662 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 11663 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 11664 11665 assign( lmd, 11666 binop( Iop_Shr32, 11667 binop( Iop_And32, 11668 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11669 mkU32( 0xF0000000 ) ), 11670 mkU8( 28 ) ) ); 11671 11672 assign( invalid_mask, 11673 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11674 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 11675 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11676 11677 assign( without_lmd, 11678 unop( Iop_ReinterpD64asI64, 11679 binop( Iop_InsertExpD64, 11680 mkU64( DFP_LONG_BIAS ), 11681 unop( Iop_ReinterpI64asD64, 11682 binop( Iop_32HLto64, 11683 mkexpr( dbcd_u ), 11684 mkexpr( dbcd_l ) ) ) ) ) ); 11685 assign( left_exp, 11686 binop( Iop_Shr32, 11687 binop( Iop_And32, 11688 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 11689 mkU32( 0x60000000 ) ), 11690 mkU8( 29 ) ) ); 11691 11692 assign( g0_4, 11693 binop( Iop_Shl32, 11694 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 11695 mkU8( 26 ) ) ); 11696 11697 assign( tmp64, 11698 binop( Iop_32HLto64, 11699 binop( Iop_Or32, 11700 binop( Iop_And32, 11701 unop( Iop_64HIto32, 11702 mkexpr( without_lmd ) ), 11703 mkU32( 0x83FFFFFF ) ), 11704 mkexpr( g0_4 ) ), 11705 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 11706 11707 } else if ( s == 1 ) { 11708 IRTemp sign = newTemp( Ity_I32 ); 11709 IRTemp sign_bit = newTemp( Ity_I32 ); 11710 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11711 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11712 IRTemp tmp = newTemp( Ity_I64 ); 11713 11714 /* Signed BCD string, least significant 4 bits are sign bits 11715 * positive sign = 0xC, negative sign = 0xD 11716 */ 11717 assign( tmp, unop( Iop_BCDtoDPB, 11718 binop( Iop_32HLto64, 11719 binop( Iop_Shr32, 11720 unop( Iop_64HIto32, 11721 mkexpr( frBI64 ) ), 11722 mkU8( 4 ) ), 11723 binop( Iop_Or32, 11724 binop( Iop_Shr32, 11725 unop( Iop_64to32, 11726 mkexpr( frBI64 ) ), 11727 mkU8( 4 ) ), 11728 binop( Iop_Shl32, 11729 unop( Iop_64HIto32, 11730 mkexpr( frBI64 ) ), 11731 mkU8( 28 ) ) ) ) ) ); 11732 11733 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 11734 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 11735 11736 /* Get the sign of the BCD string. */ 11737 assign( sign, 11738 binop( Iop_And32, 11739 unop( Iop_64to32, mkexpr( frBI64 ) ), 11740 mkU32( 0xF ) ) ); 11741 11742 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11743 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11744 assign( sign_bit, 11745 Generate_sign_bit( mkexpr( pos_sign_mask ), 11746 mkexpr( neg_sign_mask ) ) ); 11747 11748 /* Check for invalid sign and BCD digit. Don't check the bottom 11749 * four bits of bcd_l as that is the sign value. 11750 */ 11751 assign( invalid_mask, 11752 Generate_inv_mask( 11753 bcd_digit_inval( unop( Iop_64HIto32, 11754 mkexpr( frBI64 ) ), 11755 binop( Iop_Shr32, 11756 unop( Iop_64to32, 11757 mkexpr( frBI64 ) ), 11758 mkU8( 4 ) ) ), 11759 mkexpr( pos_sign_mask ), 11760 mkexpr( neg_sign_mask ) ) ); 11761 11762 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11763 11764 /* Generate the result assuming the sign value was valid. */ 11765 assign( tmp64, 11766 unop( Iop_ReinterpD64asI64, 11767 binop( Iop_InsertExpD64, 11768 mkU64( DFP_LONG_BIAS ), 11769 unop( Iop_ReinterpI64asD64, 11770 binop( Iop_32HLto64, 11771 binop( Iop_Or32, 11772 mkexpr( dbcd_u ), 11773 mkexpr( sign_bit ) ), 11774 mkexpr( dbcd_l ) ) ) ) ) ); 11775 } 11776 11777 /* Generate the value to store depending on the validity of the 11778 * sign value and the validity of the BCD digits. 11779 */ 11780 assign( resultD64, 11781 unop( Iop_ReinterpI64asD64, 11782 binop( Iop_32HLto64, 11783 binop( Iop_Or32, 11784 binop( Iop_And32, 11785 mkexpr( valid_mask ), 11786 unop( Iop_64HIto32, 11787 mkexpr( tmp64 ) ) ), 11788 binop( Iop_And32, 11789 mkU32( 0x7C000000 ), 11790 mkexpr( invalid_mask ) ) ), 11791 binop( Iop_Or32, 11792 binop( Iop_And32, 11793 mkexpr( valid_mask ), 11794 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 11795 binop( Iop_And32, 11796 mkU32( 0x0 ), 11797 mkexpr( invalid_mask ) ) ) ) ) ); 11798 putDReg( frT_addr, mkexpr( resultD64 ) ); 11799 } 11800 break; 11801 default: 11802 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 11803 return False; 11804 } 11805 return True; 11806 } 11807 11808 static Bool dis_dfp_bcdq( UInt theInstr ) 11809 { 11810 UInt opc2 = ifieldOPClo10( theInstr ); 11811 ULong sp = IFIELD(theInstr, 19, 2); 11812 ULong s = IFIELD(theInstr, 20, 1); 11813 IRTemp frB_hi = newTemp( Ity_D64 ); 11814 IRTemp frB_lo = newTemp( Ity_D64 ); 11815 IRTemp frBI64_hi = newTemp( Ity_I64 ); 11816 IRTemp frBI64_lo = newTemp( Ity_I64 ); 11817 UChar frT_addr = ifieldRegDS( theInstr ); 11818 UChar frB_addr = ifieldRegB( theInstr ); 11819 11820 IRTemp lmd = newTemp( Ity_I32 ); 11821 IRTemp result_hi = newTemp( Ity_I64 ); 11822 IRTemp result_lo = newTemp( Ity_I64 ); 11823 11824 assign( frB_hi, getDReg( frB_addr ) ); 11825 assign( frB_lo, getDReg( frB_addr + 1 ) ); 11826 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 11827 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 11828 11829 switch ( opc2 ) { 11830 case 0x142: // ddedpdq DFP Decode DPD to BCD 11831 { 11832 IRTemp low_60_u = newTemp( Ity_I32 ); 11833 IRTemp low_60_l = newTemp( Ity_I32 ); 11834 IRTemp mid_60_u = newTemp( Ity_I32 ); 11835 IRTemp mid_60_l = newTemp( Ity_I32 ); 11836 IRTemp top_12_l = newTemp( Ity_I32 ); 11837 11838 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11839 11840 /* Note, instruction only stores the lower 32 BCD digits in 11841 * the result 11842 */ 11843 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 11844 mkexpr( frBI64_lo ), 11845 &top_12_l, 11846 &mid_60_u, 11847 &mid_60_l, 11848 &low_60_u, 11849 &low_60_l ); 11850 11851 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11852 /* Unsigned BCD string */ 11853 assign( result_hi, 11854 binop( Iop_32HLto64, 11855 binop( Iop_Or32, 11856 binop( Iop_Shl32, 11857 mkexpr( top_12_l ), 11858 mkU8( 24 ) ), 11859 binop( Iop_Shr32, 11860 mkexpr( mid_60_u ), 11861 mkU8( 4 ) ) ), 11862 binop( Iop_Or32, 11863 binop( Iop_Shl32, 11864 mkexpr( mid_60_u ), 11865 mkU8( 28 ) ), 11866 binop( Iop_Shr32, 11867 mkexpr( mid_60_l ), 11868 mkU8( 4 ) ) ) ) ); 11869 11870 assign( result_lo, 11871 binop( Iop_32HLto64, 11872 binop( Iop_Or32, 11873 binop( Iop_Shl32, 11874 mkexpr( mid_60_l ), 11875 mkU8( 28 ) ), 11876 mkexpr( low_60_u ) ), 11877 mkexpr( low_60_l ) ) ); 11878 11879 } else { 11880 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11881 * the positive and negative values are encoded in the least 11882 * significant bits. 11883 */ 11884 IRTemp sign = newTemp( Ity_I32 ); 11885 11886 if ( sp == 2 ) { 11887 /* Positive sign = 0xC, negative sign = 0xD */ 11888 assign( sign, 11889 binop( Iop_Or32, 11890 binop( Iop_Shr32, 11891 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11892 mkU8( 31 ) ), 11893 mkU32( 0xC ) ) ); 11894 11895 } else if ( sp == 3 ) { 11896 IRTemp tmp32 = newTemp( Ity_I32 ); 11897 11898 /* Positive sign = 0xF, negative sign = 0xD. 11899 * Need to complement sign bit then OR into bit position 1. 11900 */ 11901 assign( tmp32, 11902 binop( Iop_Xor32, 11903 binop( Iop_Shr32, 11904 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11905 mkU8( 30 ) ), 11906 mkU32( 0x2 ) ) ); 11907 11908 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11909 11910 } else { 11911 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11912 } 11913 11914 assign( result_hi, 11915 binop( Iop_32HLto64, 11916 binop( Iop_Or32, 11917 binop( Iop_Shl32, 11918 mkexpr( top_12_l ), 11919 mkU8( 28 ) ), 11920 mkexpr( mid_60_u ) ), 11921 mkexpr( mid_60_l ) ) ); 11922 11923 assign( result_lo, 11924 binop( Iop_32HLto64, 11925 binop( Iop_Or32, 11926 binop( Iop_Shl32, 11927 mkexpr( low_60_u ), 11928 mkU8( 4 ) ), 11929 binop( Iop_Shr32, 11930 mkexpr( low_60_l ), 11931 mkU8( 28 ) ) ), 11932 binop( Iop_Or32, 11933 binop( Iop_Shl32, 11934 mkexpr( low_60_l ), 11935 mkU8( 4 ) ), 11936 mkexpr( sign ) ) ) ); 11937 } 11938 11939 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11940 putDReg( frT_addr + 1, 11941 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11942 } 11943 break; 11944 case 0x342: // denbcdq DFP Encode BCD to DPD 11945 { 11946 IRTemp valid_mask = newTemp( Ity_I32 ); 11947 IRTemp invalid_mask = newTemp( Ity_I32 ); 11948 IRTemp result128 = newTemp( Ity_D128 ); 11949 IRTemp dfp_significand = newTemp( Ity_D128 ); 11950 IRTemp tmp_hi = newTemp( Ity_I64 ); 11951 IRTemp tmp_lo = newTemp( Ity_I64 ); 11952 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 11953 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 11954 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 11955 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 11956 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 11957 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 11958 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 11959 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 11960 IRTemp sign_bit = newTemp( Ity_I32 ); 11961 IRTemp tmptop10 = newTemp( Ity_I64 ); 11962 IRTemp tmpmid50 = newTemp( Ity_I64 ); 11963 IRTemp tmplow50 = newTemp( Ity_I64 ); 11964 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 11965 11966 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11967 11968 if ( s == 0 ) { 11969 /* Unsigned BCD string */ 11970 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 11971 11972 assign( bcd_top_8, 11973 binop( Iop_32HLto64, 11974 mkU32( 0 ), 11975 binop( Iop_And32, 11976 binop( Iop_Shr32, 11977 unop( Iop_64HIto32, 11978 mkexpr( frBI64_hi ) ), 11979 mkU8( 24 ) ), 11980 mkU32( 0xFF ) ) ) ); 11981 assign( bcd_mid_60, 11982 binop( Iop_32HLto64, 11983 binop( Iop_Or32, 11984 binop( Iop_Shr32, 11985 unop( Iop_64to32, 11986 mkexpr( frBI64_hi ) ), 11987 mkU8( 28 ) ), 11988 binop( Iop_Shl32, 11989 unop( Iop_64HIto32, 11990 mkexpr( frBI64_hi ) ), 11991 mkU8( 4 ) ) ), 11992 binop( Iop_Or32, 11993 binop( Iop_Shl32, 11994 unop( Iop_64to32, 11995 mkexpr( frBI64_hi ) ), 11996 mkU8( 4 ) ), 11997 binop( Iop_Shr32, 11998 unop( Iop_64HIto32, 11999 mkexpr( frBI64_lo ) ), 12000 mkU8( 28 ) ) ) ) ); 12001 12002 /* Note, the various helper functions ignores top 4-bits */ 12003 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 12004 12005 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 12006 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12007 12008 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 12009 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12010 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12011 12012 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12013 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12014 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12015 12016 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 12017 * value is not part of the final result. Only the right most 12018 * BCD digits are stored. 12019 */ 12020 assign( lmd, mkU32( 0 ) ); 12021 12022 assign( invalid_mask, 12023 binop( Iop_Or32, 12024 bcd_digit_inval( mkU32( 0 ), 12025 unop( Iop_64to32, 12026 mkexpr( bcd_top_8 ) ) ), 12027 binop( Iop_Or32, 12028 bcd_digit_inval( unop( Iop_64HIto32, 12029 mkexpr( bcd_mid_60 ) ), 12030 unop( Iop_64to32, 12031 mkexpr( bcd_mid_60 ) ) ), 12032 bcd_digit_inval( unop( Iop_64HIto32, 12033 mkexpr( bcd_low_60 ) ), 12034 unop( Iop_64to32, 12035 mkexpr( bcd_low_60 ) ) 12036 ) ) ) ); 12037 12038 } else if ( s == 1 ) { 12039 IRTemp sign = newTemp( Ity_I32 ); 12040 IRTemp zero = newTemp( Ity_I32 ); 12041 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 12042 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 12043 12044 /* The sign of the BCD string is stored in lower 4 bits */ 12045 assign( sign, 12046 binop( Iop_And32, 12047 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 12048 mkU32( 0xF ) ) ); 12049 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 12050 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 12051 assign( sign_bit, 12052 Generate_sign_bit( mkexpr( pos_sign_mask ), 12053 mkexpr( neg_sign_mask ) ) ); 12054 12055 /* Generate the value assuminig the sign and BCD digits are vaild */ 12056 assign( bcd_top_8, 12057 binop( Iop_32HLto64, 12058 mkU32( 0x0 ), 12059 binop( Iop_Shr32, 12060 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12061 mkU8( 28 ) ) ) ); 12062 12063 /* The various helper routines ignore the upper 4-bits */ 12064 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 12065 12066 /* Remove bottom four sign bits */ 12067 assign( bcd_low_60, 12068 binop( Iop_32HLto64, 12069 binop( Iop_Shr32, 12070 unop( Iop_64HIto32, 12071 mkexpr( frBI64_lo ) ), 12072 mkU8( 4 ) ), 12073 binop( Iop_Or32, 12074 binop( Iop_Shl32, 12075 unop( Iop_64HIto32, 12076 mkexpr( frBI64_lo ) ), 12077 mkU8( 28 ) ), 12078 binop( Iop_Shr32, 12079 unop( Iop_64to32, 12080 mkexpr( frBI64_lo ) ), 12081 mkU8( 4 ) ) ) ) ); 12082 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 12083 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 12084 12085 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 12086 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 12087 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 12088 12089 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 12090 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 12091 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 12092 12093 /* The entire BCD string fits in lower 110-bits. The LMD value 12094 * is not stored in the final result for the DFP Long instruction. 12095 */ 12096 assign( lmd, mkU32( 0 ) ); 12097 12098 /* Check for invalid sign and invalid BCD digit. Don't check the 12099 * bottom four bits of frBI64_lo as that is the sign value. 12100 */ 12101 assign( zero, mkU32( 0 ) ); 12102 assign( inval_bcd_digit_mask, 12103 binop( Iop_Or32, 12104 bcd_digit_inval( mkexpr( zero ), 12105 unop( Iop_64to32, 12106 mkexpr( bcd_top_8 ) ) ), 12107 binop( Iop_Or32, 12108 bcd_digit_inval( unop( Iop_64HIto32, 12109 mkexpr( bcd_mid_60 ) ), 12110 unop( Iop_64to32, 12111 mkexpr( bcd_mid_60 ) ) ), 12112 bcd_digit_inval( unop( Iop_64HIto32, 12113 mkexpr( frBI64_lo ) ), 12114 binop( Iop_Shr32, 12115 unop( Iop_64to32, 12116 mkexpr( frBI64_lo ) ), 12117 mkU8( 4 ) ) ) ) ) ); 12118 assign( invalid_mask, 12119 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 12120 mkexpr( pos_sign_mask ), 12121 mkexpr( neg_sign_mask ) ) ); 12122 12123 } 12124 12125 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 12126 12127 /* Calculate the value of the result assuming sign and BCD digits 12128 * are all valid. 12129 */ 12130 assign( dfp_significand, 12131 binop( Iop_D64HLtoD128, 12132 unop( Iop_ReinterpI64asD64, 12133 binop( Iop_32HLto64, 12134 binop( Iop_Or32, 12135 mkexpr( sign_bit ), 12136 mkexpr( dbcd_top_l ) ), 12137 binop( Iop_Or32, 12138 binop( Iop_Shl32, 12139 mkexpr( dbcd_mid_u ), 12140 mkU8( 18 ) ), 12141 binop( Iop_Shr32, 12142 mkexpr( dbcd_mid_l ), 12143 mkU8( 14 ) ) ) ) ), 12144 unop( Iop_ReinterpI64asD64, 12145 binop( Iop_32HLto64, 12146 binop( Iop_Or32, 12147 mkexpr( dbcd_low_u ), 12148 binop( Iop_Shl32, 12149 mkexpr( dbcd_mid_l ), 12150 mkU8( 18 ) ) ), 12151 mkexpr( dbcd_low_l ) ) ) ) ); 12152 12153 /* Break the result back down to 32-bit chunks and replace chunks. 12154 * If there was an invalid BCD digit or invalid sign value, replace 12155 * the calculated result with the invalid bit string. 12156 */ 12157 assign( result128, 12158 binop( Iop_InsertExpD128, 12159 mkU64( DFP_EXTND_BIAS ), 12160 mkexpr( dfp_significand ) ) ); 12161 12162 assign( tmp_hi, 12163 unop( Iop_ReinterpD64asI64, 12164 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 12165 12166 assign( tmp_lo, 12167 unop( Iop_ReinterpD64asI64, 12168 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 12169 12170 assign( result_hi, 12171 binop( Iop_32HLto64, 12172 binop( Iop_Or32, 12173 binop( Iop_And32, 12174 mkexpr( valid_mask ), 12175 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 12176 binop( Iop_And32, 12177 mkU32( 0x7C000000 ), 12178 mkexpr( invalid_mask ) ) ), 12179 binop( Iop_Or32, 12180 binop( Iop_And32, 12181 mkexpr( valid_mask ), 12182 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 12183 binop( Iop_And32, 12184 mkU32( 0x0 ), 12185 mkexpr( invalid_mask ) ) ) ) ); 12186 12187 assign( result_lo, 12188 binop( Iop_32HLto64, 12189 binop( Iop_Or32, 12190 binop( Iop_And32, 12191 mkexpr( valid_mask ), 12192 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 12193 binop( Iop_And32, 12194 mkU32( 0x0 ), 12195 mkexpr( invalid_mask ) ) ), 12196 binop( Iop_Or32, 12197 binop( Iop_And32, 12198 mkexpr( valid_mask ), 12199 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 12200 binop( Iop_And32, 12201 mkU32( 0x0 ), 12202 mkexpr( invalid_mask ) ) ) ) ); 12203 12204 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 12205 putDReg( frT_addr + 1, 12206 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 12207 12208 } 12209 break; 12210 default: 12211 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 12212 break; 12213 } 12214 return True; 12215 } 12216 12217 static Bool dis_dfp_significant_digits( UInt theInstr ) 12218 { 12219 UChar frA_addr = ifieldRegA( theInstr ); 12220 UChar frB_addr = ifieldRegB( theInstr ); 12221 IRTemp frA = newTemp( Ity_D64 ); 12222 UInt opc1 = ifieldOPC( theInstr ); 12223 IRTemp B_sig = newTemp( Ity_I8 ); 12224 IRTemp K = newTemp( Ity_I8 ); 12225 IRTemp lmd_B = newTemp( Ity_I32 ); 12226 IRTemp field = newTemp( Ity_I32 ); 12227 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 12228 IRTemp Unordered_true = newTemp( Ity_I32 ); 12229 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 12230 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 12231 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 12232 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 12233 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 12234 12235 /* Get the reference singificance stored in frA */ 12236 assign( frA, getDReg( frA_addr ) ); 12237 12238 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 12239 * supported in 32-bit mode. 12240 */ 12241 assign( K, unop( Iop_32to8, 12242 binop( Iop_And32, 12243 unop( Iop_64to32, 12244 unop( Iop_ReinterpD64asI64, 12245 mkexpr( frA ) ) ), 12246 mkU32( 0x3F ) ) ) ); 12247 12248 switch ( opc1 ) { 12249 case 0x3b: // dtstsf DFP Test Significance 12250 { 12251 IRTemp frB = newTemp( Ity_D64 ); 12252 IRTemp frBI64 = newTemp( Ity_I64 ); 12253 IRTemp B_bcd_u = newTemp( Ity_I32 ); 12254 IRTemp B_bcd_l = newTemp( Ity_I32 ); 12255 IRTemp tmp64 = newTemp( Ity_I64 ); 12256 12257 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12258 12259 assign( frB, getDReg( frB_addr ) ); 12260 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 12261 12262 /* Get the BCD string for the value stored in a series of I32 values. 12263 * Count the number of leading zeros. Subtract the number of leading 12264 * zeros from 16 (maximum number of significant digits in DFP 12265 * Long). 12266 */ 12267 Get_lmd( &lmd_B, 12268 binop( Iop_Shr32, 12269 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 12270 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12271 12272 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 12273 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 12274 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 12275 12276 assign( B_sig, 12277 binop( Iop_Sub8, 12278 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 12279 Count_leading_zeros_60( mkexpr( lmd_B ), 12280 mkexpr( B_bcd_u ), 12281 mkexpr( B_bcd_l ) ) ) ); 12282 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) ); 12283 } 12284 break; 12285 case 0x3F: // dtstsfq DFP Test Significance 12286 { 12287 IRTemp frB_hi = newTemp( Ity_D64 ); 12288 IRTemp frB_lo = newTemp( Ity_D64 ); 12289 IRTemp frBI64_hi = newTemp( Ity_I64 ); 12290 IRTemp frBI64_lo = newTemp( Ity_I64 ); 12291 IRTemp B_low_60_u = newTemp( Ity_I32 ); 12292 IRTemp B_low_60_l = newTemp( Ity_I32 ); 12293 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 12294 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 12295 IRTemp B_top_12_l = newTemp( Ity_I32 ); 12296 12297 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12298 12299 assign( frB_hi, getDReg( frB_addr ) ); 12300 assign( frB_lo, getDReg( frB_addr + 1 ) ); 12301 12302 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 12303 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 12304 12305 /* Get the BCD string for the value stored in a series of I32 values. 12306 * Count the number of leading zeros. Subtract the number of leading 12307 * zeros from 32 (maximum number of significant digits in DFP 12308 * extended). 12309 */ 12310 Get_lmd( &lmd_B, 12311 binop( Iop_Shr32, 12312 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12313 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12314 12315 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 12316 mkexpr( frBI64_lo ), 12317 &B_top_12_l, 12318 &B_mid_60_u, 12319 &B_mid_60_l, 12320 &B_low_60_u, 12321 &B_low_60_l ); 12322 12323 assign( B_sig, 12324 binop( Iop_Sub8, 12325 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 12326 Count_leading_zeros_128( mkexpr( lmd_B ), 12327 mkexpr( B_top_12_l ), 12328 mkexpr( B_mid_60_u ), 12329 mkexpr( B_mid_60_l ), 12330 mkexpr( B_low_60_u ), 12331 mkexpr( B_low_60_l ) ) ) ); 12332 12333 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) ); 12334 } 12335 break; 12336 } 12337 12338 /* Compare (16 - cnt[0]) against K and set the condition code field 12339 * accordingly. 12340 * 12341 * The field layout is as follows: 12342 * 12343 * bit[3:0] Description 12344 * 3 K != 0 and K < Number of significant digits if FRB 12345 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 12346 * 1 K != 0 and K = Number of significant digits if FRB 12347 * 0 K ? Number of significant digits if FRB 12348 */ 12349 assign( Eq_true_mask, 12350 unop( Iop_1Sto32, 12351 binop( Iop_CmpEQ32, 12352 unop( Iop_8Uto32, mkexpr( K ) ), 12353 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12354 assign( Lt_true_mask, 12355 unop( Iop_1Sto32, 12356 binop( Iop_CmpLT32U, 12357 unop( Iop_8Uto32, mkexpr( K ) ), 12358 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12359 assign( Gt_true_mask, 12360 unop( Iop_1Sto32, 12361 binop( Iop_CmpLT32U, 12362 unop( Iop_8Uto32, mkexpr( B_sig ) ), 12363 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 12364 12365 assign( KisZero_true_mask, 12366 unop( Iop_1Sto32, 12367 binop( Iop_CmpEQ32, 12368 unop( Iop_8Uto32, mkexpr( K ) ), 12369 mkU32( 0 ) ) ) ); 12370 assign( KisZero_false_mask, 12371 unop( Iop_1Sto32, 12372 binop( Iop_CmpNE32, 12373 unop( Iop_8Uto32, mkexpr( K ) ), 12374 mkU32( 0 ) ) ) ); 12375 12376 assign( field, 12377 binop( Iop_Or32, 12378 binop( Iop_And32, 12379 mkexpr( KisZero_false_mask ), 12380 binop( Iop_Or32, 12381 binop( Iop_And32, 12382 mkexpr( Lt_true_mask ), 12383 mkU32( 0x8 ) ), 12384 binop( Iop_Or32, 12385 binop( Iop_And32, 12386 mkexpr( Gt_true_mask ), 12387 mkU32( 0x4 ) ), 12388 binop( Iop_And32, 12389 mkexpr( Eq_true_mask ), 12390 mkU32( 0x2 ) ) ) ) ), 12391 binop( Iop_And32, 12392 mkexpr( KisZero_true_mask ), 12393 mkU32( 0x4 ) ) ) ); 12394 12395 putGST_field( PPC_GST_CR, 12396 binop( Iop_Or32, 12397 binop( Iop_And32, 12398 mkexpr( Unordered_true ), 12399 mkU32( 0x1 ) ), 12400 binop( Iop_And32, 12401 unop( Iop_Not32, mkexpr( Unordered_true ) ), 12402 mkexpr( field ) ) ), 12403 crfD ); 12404 12405 return True; 12406 } 12407 12408 /*------------------------------------------------------------*/ 12409 /*--- AltiVec Instruction Translation ---*/ 12410 /*------------------------------------------------------------*/ 12411 12412 /* 12413 Altivec Cache Control Instructions (Data Streams) 12414 */ 12415 static Bool dis_av_datastream ( UInt theInstr ) 12416 { 12417 /* X-Form */ 12418 UChar opc1 = ifieldOPC(theInstr); 12419 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 12420 UChar flag_A = flag_T; 12421 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 12422 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 12423 UChar rA_addr = ifieldRegA(theInstr); 12424 UChar rB_addr = ifieldRegB(theInstr); 12425 UInt opc2 = ifieldOPClo10(theInstr); 12426 UChar b0 = ifieldBIT0(theInstr); 12427 12428 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 12429 vex_printf("dis_av_datastream(ppc)(instr)\n"); 12430 return False; 12431 } 12432 12433 switch (opc2) { 12434 case 0x156: // dst (Data Stream Touch, AV p115) 12435 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12436 rA_addr, rB_addr, STRM); 12437 break; 12438 12439 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 12440 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12441 rA_addr, rB_addr, STRM); 12442 break; 12443 12444 case 0x336: // dss (Data Stream Stop, AV p114) 12445 if (rA_addr != 0 || rB_addr != 0) { 12446 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 12447 return False; 12448 } 12449 if (flag_A == 0) { 12450 DIP("dss %d\n", STRM); 12451 } else { 12452 DIP("dssall\n"); 12453 } 12454 break; 12455 12456 default: 12457 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 12458 return False; 12459 } 12460 return True; 12461 } 12462 12463 /* 12464 AltiVec Processor Control Instructions 12465 */ 12466 static Bool dis_av_procctl ( UInt theInstr ) 12467 { 12468 /* VX-Form */ 12469 UChar opc1 = ifieldOPC(theInstr); 12470 UChar vD_addr = ifieldRegDS(theInstr); 12471 UChar vA_addr = ifieldRegA(theInstr); 12472 UChar vB_addr = ifieldRegB(theInstr); 12473 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12474 12475 if (opc1 != 0x4) { 12476 vex_printf("dis_av_procctl(ppc)(instr)\n"); 12477 return False; 12478 } 12479 12480 switch (opc2) { 12481 case 0x604: // mfvscr (Move from VSCR, AV p129) 12482 if (vA_addr != 0 || vB_addr != 0) { 12483 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12484 return False; 12485 } 12486 DIP("mfvscr v%d\n", vD_addr); 12487 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 12488 break; 12489 12490 case 0x644: { // mtvscr (Move to VSCR, AV p130) 12491 IRTemp vB = newTemp(Ity_V128); 12492 if (vD_addr != 0 || vA_addr != 0) { 12493 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12494 return False; 12495 } 12496 DIP("mtvscr v%d\n", vB_addr); 12497 assign( vB, getVReg(vB_addr)); 12498 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 12499 break; 12500 } 12501 default: 12502 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 12503 return False; 12504 } 12505 return True; 12506 } 12507 12508 /* 12509 * VSX scalar and vector convert instructions 12510 */ 12511 static Bool 12512 dis_vx_conv ( UInt theInstr, UInt opc2 ) 12513 { 12514 /* XX2-Form */ 12515 UChar opc1 = ifieldOPC( theInstr ); 12516 UChar XT = ifieldRegXT( theInstr ); 12517 UChar XB = ifieldRegXB( theInstr ); 12518 IRTemp xB, xB2; 12519 IRTemp b3, b2, b1, b0; 12520 xB = xB2 = IRTemp_INVALID; 12521 12522 if (opc1 != 0x3C) { 12523 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 12524 return False; 12525 } 12526 12527 /* Create and assign temps only as needed for the given instruction. */ 12528 switch (opc2) { 12529 // scalar double-precision floating point argument 12530 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090: 12531 xB = newTemp(Ity_F64); 12532 assign( xB, 12533 unop( Iop_ReinterpI64asF64, 12534 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12535 break; 12536 // vector double-precision floating point arguments 12537 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 12538 12539 xB = newTemp(Ity_F64); 12540 xB2 = newTemp(Ity_F64); 12541 assign( xB, 12542 unop( Iop_ReinterpI64asF64, 12543 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12544 assign( xB2, 12545 unop( Iop_ReinterpI64asF64, 12546 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 12547 break; 12548 // vector single precision or [un]signed integer word arguments 12549 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 12550 case 0x1f0: case 0x1d0: 12551 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12552 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 12553 break; 12554 // vector [un]signed integer doubleword argument 12555 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 12556 xB = newTemp(Ity_I64); 12557 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12558 xB2 = newTemp(Ity_I64); 12559 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 12560 break; 12561 // scalar [un]signed integer doubleword argument 12562 case 0x250: case 0x270: case 0x2D0: case 0x2F0: 12563 xB = newTemp(Ity_I64); 12564 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12565 break; 12566 // scalar single precision argument 12567 case 0x292: // xscvspdp 12568 xB = newTemp(Ity_I32); 12569 12570 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32, 12571 unop( Iop_V128HIto64, 12572 getVSReg( XB ) ) ) ) ); 12573 break; 12574 case 0x296: // xscvspdpn (non signaling version of xscvpdp) 12575 xB = newTemp(Ity_I32); 12576 assign( xB, 12577 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12578 break; 12579 12580 /* Certain instructions have their complete implementation in the main switch statement 12581 * that follows this one; thus we have a "do nothing" case for those instructions here. 12582 */ 12583 case 0x170: case 0x150: 12584 break; // do nothing 12585 12586 default: 12587 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12588 return False; 12589 } 12590 12591 12592 switch (opc2) { 12593 case 0x2B0: 12594 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 12595 // to Signed Integer Doubleword format with Saturate) 12596 DIP("xscvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12597 putVSReg( XT, 12598 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 12599 mkU32( Irrm_ZERO ), 12600 mkexpr( xB ) ), mkU64( 0 ) ) ); 12601 break; 12602 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 12603 // Convert to Signed Integer Word format with Saturate) 12604 DIP("xscvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12605 putVSReg( XT, 12606 binop( Iop_64HLtoV128, 12607 unop( Iop_32Sto64, 12608 binop( Iop_F64toI32S, 12609 mkU32( Irrm_ZERO ), 12610 mkexpr( xB ) ) ), 12611 mkU64( 0ULL ) ) ); 12612 break; 12613 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 12614 // to Unsigned Integer Doubleword format with Saturate) 12615 DIP("xscvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12616 putVSReg( XT, 12617 binop( Iop_64HLtoV128, 12618 binop( Iop_F64toI64U, 12619 mkU32( Irrm_ZERO ), 12620 mkexpr( xB ) ), 12621 mkU64( 0ULL ) ) ); 12622 break; 12623 case 0x270: 12624 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword 12625 // to Single-Precision format) 12626 DIP("xscvsxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12627 putVSReg( XT, 12628 binop( Iop_64HLtoV128, 12629 unop( Iop_ReinterpF64asI64, 12630 binop( Iop_RoundF64toF32, 12631 get_IR_roundingmode(), 12632 binop( Iop_I64StoF64, 12633 get_IR_roundingmode(), 12634 mkexpr( xB ) ) ) ), 12635 mkU64( 0 ) ) ); 12636 break; 12637 case 0x2F0: 12638 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 12639 // Double-Precision format) 12640 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12641 putVSReg( XT, 12642 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12643 binop( Iop_I64StoF64, get_IR_roundingmode(), 12644 mkexpr( xB ) ) ), 12645 mkU64( 0 ) ) ); 12646 break; 12647 case 0x250: 12648 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer 12649 // Doubleword to Singel-Precision format) 12650 DIP("xscvuxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12651 putVSReg( XT, 12652 binop( Iop_64HLtoV128, 12653 unop( Iop_ReinterpF64asI64, 12654 binop( Iop_RoundF64toF32, 12655 get_IR_roundingmode(), 12656 binop( Iop_I64UtoF64, 12657 get_IR_roundingmode(), 12658 mkexpr( xB ) ) ) ), 12659 mkU64( 0 ) ) ); 12660 break; 12661 case 0x2D0: 12662 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 12663 // Double-Precision format) 12664 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12665 putVSReg( XT, 12666 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12667 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12668 mkexpr( xB ) ) ), 12669 mkU64( 0 ) ) ); 12670 break; 12671 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 12672 // to Signed Integer Word format with Saturate) 12673 { 12674 IRTemp hiResult_32 = newTemp(Ity_I32); 12675 IRTemp loResult_32 = newTemp(Ity_I32); 12676 IRExpr* rmZero = mkU32(Irrm_ZERO); 12677 12678 DIP("xvcvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12679 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 12680 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 12681 putVSReg( XT, 12682 binop( Iop_64HLtoV128, 12683 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 12684 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 12685 break; 12686 } 12687 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 12688 // (VSX Vector truncate Single-Precision to integer and 12689 // Convert to [Un]signed Integer Word format with Saturate) 12690 { 12691 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 12692 IRTemp tempResult = newTemp(Ity_V128); 12693 IRTemp res0 = newTemp(Ity_I32); 12694 IRTemp res1 = newTemp(Ity_I32); 12695 IRTemp res2 = newTemp(Ity_I32); 12696 IRTemp res3 = newTemp(Ity_I32); 12697 IRTemp hi64 = newTemp(Ity_I64); 12698 IRTemp lo64 = newTemp(Ity_I64); 12699 Bool un_signed = (opc2 == 0x110); 12700 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 12701 12702 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB); 12703 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 12704 * then result is set to 0x80000000. */ 12705 assign(tempResult, unop(op, getVSReg(XB))); 12706 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 12707 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 12708 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 12709 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 12710 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 12711 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 12712 12713 b3_result = IRExpr_ITE(is_NaN_32(b3), 12714 // then: result is 0x{8|0}80000000 12715 mkU32(un_signed ? 0x00000000 : 0x80000000), 12716 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12717 mkexpr(res3)); 12718 b2_result = IRExpr_ITE(is_NaN_32(b2), 12719 // then: result is 0x{8|0}80000000 12720 mkU32(un_signed ? 0x00000000 : 0x80000000), 12721 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12722 mkexpr(res2)); 12723 b1_result = IRExpr_ITE(is_NaN_32(b1), 12724 // then: result is 0x{8|0}80000000 12725 mkU32(un_signed ? 0x00000000 : 0x80000000), 12726 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12727 mkexpr(res1)); 12728 b0_result = IRExpr_ITE(is_NaN_32(b0), 12729 // then: result is 0x{8|0}80000000 12730 mkU32(un_signed ? 0x00000000 : 0x80000000), 12731 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12732 mkexpr(res0)); 12733 12734 putVSReg( XT, 12735 binop( Iop_64HLtoV128, 12736 binop( Iop_32HLto64, b3_result, b2_result ), 12737 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 12738 break; 12739 } 12740 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 12741 // Convert to Single-Precision format 12742 DIP("xscvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12743 putVSReg( XT, 12744 binop( Iop_64HLtoV128, 12745 binop( Iop_32HLto64, 12746 unop( Iop_ReinterpF32asI32, 12747 unop( Iop_TruncF64asF32, 12748 binop( Iop_RoundF64toF32, 12749 get_IR_roundingmode(), 12750 mkexpr( xB ) ) ) ), 12751 mkU32( 0 ) ), 12752 mkU64( 0ULL ) ) ); 12753 break; 12754 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to 12755 vector Single-Precision non-signalling */ 12756 DIP("xscvdpspn v%u,v%u\n", (UInt)XT, (UInt)XB); 12757 putVSReg( XT, 12758 binop( Iop_64HLtoV128, 12759 binop( Iop_32HLto64, 12760 unop( Iop_ReinterpF32asI32, 12761 unop( Iop_TruncF64asF32, 12762 mkexpr( xB ) ) ), 12763 mkU32( 0 ) ), 12764 mkU64( 0ULL ) ) ); 12765 break; 12766 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 12767 // and Convert to Unsigned Integer Word format with Saturate) 12768 DIP("xscvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12769 putVSReg( XT, 12770 binop( Iop_64HLtoV128, 12771 binop( Iop_32HLto64, 12772 mkU32( 0 ), 12773 binop( Iop_F64toI32U, 12774 mkU32( Irrm_ZERO ), 12775 mkexpr( xB ) ) ), 12776 mkU64( 0ULL ) ) ); 12777 break; 12778 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling) 12779 DIP("xscvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12780 putVSReg( XT, 12781 binop( Iop_64HLtoV128, 12782 unop( Iop_ReinterpF64asI64, 12783 unop( Iop_F32toF64, 12784 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12785 mkU64( 0ULL ) ) ); 12786 break; 12787 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling) 12788 DIP("xscvspdpn v%u,v%u\n", (UInt)XT, (UInt)XB); 12789 putVSReg( XT, 12790 binop( Iop_64HLtoV128, 12791 unop( Iop_ReinterpF64asI64, 12792 unop( Iop_F32toF64, 12793 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12794 mkU64( 0ULL ) ) ); 12795 break; 12796 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 12797 // and Convert to Single-Precision format) 12798 DIP("xvcvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12799 putVSReg( XT, 12800 binop( Iop_64HLtoV128, 12801 binop( Iop_32HLto64, 12802 unop( Iop_ReinterpF32asI32, 12803 unop( Iop_TruncF64asF32, 12804 binop( Iop_RoundF64toF32, 12805 get_IR_roundingmode(), 12806 mkexpr( xB ) ) ) ), 12807 mkU32( 0 ) ), 12808 binop( Iop_32HLto64, 12809 unop( Iop_ReinterpF32asI32, 12810 unop( Iop_TruncF64asF32, 12811 binop( Iop_RoundF64toF32, 12812 get_IR_roundingmode(), 12813 mkexpr( xB2 ) ) ) ), 12814 mkU32( 0 ) ) ) ); 12815 break; 12816 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 12817 // and Convert to Unsigned Integer Doubleword format 12818 // with Saturate) 12819 DIP("xvcvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12820 putVSReg( XT, 12821 binop( Iop_64HLtoV128, 12822 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12823 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12824 break; 12825 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 12826 // Convert to Unsigned Integer Word format with Saturate) 12827 DIP("xvcvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12828 putVSReg( XT, 12829 binop( Iop_64HLtoV128, 12830 binop( Iop_32HLto64, 12831 binop( Iop_F64toI32U, 12832 mkU32( Irrm_ZERO ), 12833 mkexpr( xB ) ), 12834 mkU32( 0 ) ), 12835 binop( Iop_32HLto64, 12836 binop( Iop_F64toI32U, 12837 mkU32( Irrm_ZERO ), 12838 mkexpr( xB2 ) ), 12839 mkU32( 0 ) ) ) ); 12840 break; 12841 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 12842 DIP("xvcvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12843 putVSReg( XT, 12844 binop( Iop_64HLtoV128, 12845 unop( Iop_ReinterpF64asI64, 12846 unop( Iop_F32toF64, 12847 unop( Iop_ReinterpI32asF32, 12848 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ), 12849 unop( Iop_ReinterpF64asI64, 12850 unop( Iop_F32toF64, 12851 unop( Iop_ReinterpI32asF32, 12852 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) ); 12853 break; 12854 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 12855 // Convert to Signed Integer Doubleword format with Saturate) 12856 DIP("xvcvspsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12857 putVSReg( XT, 12858 binop( Iop_64HLtoV128, 12859 binop( Iop_F64toI64S, 12860 mkU32( Irrm_ZERO ), 12861 unop( Iop_F32toF64, 12862 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12863 binop( Iop_F64toI64S, 12864 mkU32( Irrm_ZERO ), 12865 unop( Iop_F32toF64, 12866 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12867 break; 12868 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 12869 // Convert to Unsigned Integer Doubleword format with Saturate) 12870 DIP("xvcvspuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12871 putVSReg( XT, 12872 binop( Iop_64HLtoV128, 12873 binop( Iop_F64toI64U, 12874 mkU32( Irrm_ZERO ), 12875 unop( Iop_F32toF64, 12876 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12877 binop( Iop_F64toI64U, 12878 mkU32( Irrm_ZERO ), 12879 unop( Iop_F32toF64, 12880 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12881 break; 12882 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 12883 // Convert to Signed Integer Doubleword format with Saturate) 12884 DIP("xvcvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12885 putVSReg( XT, 12886 binop( Iop_64HLtoV128, 12887 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12888 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12889 break; 12890 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 12891 // to Double-Precision format) 12892 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12893 putVSReg( XT, 12894 binop( Iop_64HLtoV128, 12895 unop( Iop_ReinterpF64asI64, 12896 binop( Iop_I64StoF64, 12897 get_IR_roundingmode(), 12898 mkexpr( xB ) ) ), 12899 unop( Iop_ReinterpF64asI64, 12900 binop( Iop_I64StoF64, 12901 get_IR_roundingmode(), 12902 mkexpr( xB2 ) ) ) ) ); 12903 break; 12904 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 12905 // to Double-Precision format) 12906 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12907 putVSReg( XT, 12908 binop( Iop_64HLtoV128, 12909 unop( Iop_ReinterpF64asI64, 12910 binop( Iop_I64UtoF64, 12911 get_IR_roundingmode(), 12912 mkexpr( xB ) ) ), 12913 unop( Iop_ReinterpF64asI64, 12914 binop( Iop_I64UtoF64, 12915 get_IR_roundingmode(), 12916 mkexpr( xB2 ) ) ) ) ); 12917 12918 break; 12919 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 12920 // to Single-Precision format) 12921 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12922 putVSReg( XT, 12923 binop( Iop_64HLtoV128, 12924 binop( Iop_32HLto64, 12925 unop( Iop_ReinterpF32asI32, 12926 unop( Iop_TruncF64asF32, 12927 binop( Iop_RoundF64toF32, 12928 get_IR_roundingmode(), 12929 binop( Iop_I64StoF64, 12930 get_IR_roundingmode(), 12931 mkexpr( xB ) ) ) ) ), 12932 mkU32( 0 ) ), 12933 binop( Iop_32HLto64, 12934 unop( Iop_ReinterpF32asI32, 12935 unop( Iop_TruncF64asF32, 12936 binop( Iop_RoundF64toF32, 12937 get_IR_roundingmode(), 12938 binop( Iop_I64StoF64, 12939 get_IR_roundingmode(), 12940 mkexpr( xB2 ) ) ) ) ), 12941 mkU32( 0 ) ) ) ); 12942 break; 12943 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 12944 // to Single-Precision format) 12945 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12946 putVSReg( XT, 12947 binop( Iop_64HLtoV128, 12948 binop( Iop_32HLto64, 12949 unop( Iop_ReinterpF32asI32, 12950 unop( Iop_TruncF64asF32, 12951 binop( Iop_RoundF64toF32, 12952 get_IR_roundingmode(), 12953 binop( Iop_I64UtoF64, 12954 get_IR_roundingmode(), 12955 mkexpr( xB ) ) ) ) ), 12956 mkU32( 0 ) ), 12957 binop( Iop_32HLto64, 12958 unop( Iop_ReinterpF32asI32, 12959 unop( Iop_TruncF64asF32, 12960 binop( Iop_RoundF64toF32, 12961 get_IR_roundingmode(), 12962 binop( Iop_I64UtoF64, 12963 get_IR_roundingmode(), 12964 mkexpr( xB2 ) ) ) ) ), 12965 mkU32( 0 ) ) ) ); 12966 break; 12967 12968 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 12969 DIP("xvcvsxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12970 putVSReg( XT, 12971 binop( Iop_64HLtoV128, 12972 unop( Iop_ReinterpF64asI64, 12973 binop( Iop_I64StoF64, get_IR_roundingmode(), 12974 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 12975 unop( Iop_ReinterpF64asI64, 12976 binop( Iop_I64StoF64, get_IR_roundingmode(), 12977 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 12978 break; 12979 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 12980 DIP("xvcvuxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12981 putVSReg( XT, 12982 binop( Iop_64HLtoV128, 12983 unop( Iop_ReinterpF64asI64, 12984 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12985 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 12986 unop( Iop_ReinterpF64asI64, 12987 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12988 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 12989 break; 12990 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 12991 DIP("xvcvsxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12992 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 12993 break; 12994 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 12995 DIP("xvcvuxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12996 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 12997 break; 12998 12999 default: 13000 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 13001 return False; 13002 } 13003 return True; 13004 } 13005 13006 /* 13007 * VSX vector Double Precision Floating Point Arithmetic Instructions 13008 */ 13009 static Bool 13010 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 13011 { 13012 /* XX3-Form */ 13013 UChar opc1 = ifieldOPC( theInstr ); 13014 UChar XT = ifieldRegXT( theInstr ); 13015 UChar XA = ifieldRegXA( theInstr ); 13016 UChar XB = ifieldRegXB( theInstr ); 13017 IRExpr* rm = get_IR_roundingmode(); 13018 IRTemp frA = newTemp(Ity_F64); 13019 IRTemp frB = newTemp(Ity_F64); 13020 IRTemp frA2 = newTemp(Ity_F64); 13021 IRTemp frB2 = newTemp(Ity_F64); 13022 13023 if (opc1 != 0x3C) { 13024 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 13025 return False; 13026 } 13027 13028 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 13029 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13030 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 13031 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 13032 13033 switch (opc2) { 13034 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 13035 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 13036 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 13037 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 13038 { 13039 IROp mOp; 13040 const HChar * oper_name; 13041 switch (opc2) { 13042 case 0x1E0: 13043 mOp = Iop_DivF64; 13044 oper_name = "div"; 13045 break; 13046 case 0x1C0: 13047 mOp = Iop_MulF64; 13048 oper_name = "mul"; 13049 break; 13050 case 0x180: 13051 mOp = Iop_AddF64; 13052 oper_name = "add"; 13053 break; 13054 case 0x1A0: 13055 mOp = Iop_SubF64; 13056 oper_name = "sub"; 13057 break; 13058 13059 default: 13060 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 13061 } 13062 IRTemp hiResult = newTemp(Ity_I64); 13063 IRTemp loResult = newTemp(Ity_I64); 13064 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB); 13065 13066 assign( hiResult, 13067 unop( Iop_ReinterpF64asI64, 13068 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 13069 assign( loResult, 13070 unop( Iop_ReinterpF64asI64, 13071 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 13072 putVSReg( XT, 13073 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13074 break; 13075 } 13076 case 0x196: // xvsqrtdp 13077 { 13078 IRTemp hiResult = newTemp(Ity_I64); 13079 IRTemp loResult = newTemp(Ity_I64); 13080 DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13081 13082 assign( hiResult, 13083 unop( Iop_ReinterpF64asI64, 13084 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 13085 assign( loResult, 13086 unop( Iop_ReinterpF64asI64, 13087 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 13088 putVSReg( XT, 13089 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13090 break; 13091 } 13092 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 13093 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 13094 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 13095 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 13096 { 13097 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 13098 * XT == FRC 13099 * XA == FRA 13100 * XB == FRB 13101 * 13102 * and for xvm{add|sub}adp . . . 13103 * XT == FRB 13104 * XA == FRA 13105 * XB == FRC 13106 */ 13107 Bool negate; 13108 IROp mOp = Iop_INVALID; 13109 const HChar * oper_name = NULL; 13110 Bool mdp = False; 13111 13112 switch (opc2) { 13113 case 0x184: case 0x1A4: 13114 case 0x384: case 0x3A4: 13115 mOp = Iop_MAddF64; 13116 oper_name = "add"; 13117 mdp = (opc2 & 0x0FF) == 0x0A4; 13118 break; 13119 13120 case 0x1C4: case 0x1E4: 13121 case 0x3C4: case 0x3E4: 13122 mOp = Iop_MSubF64; 13123 oper_name = "sub"; 13124 mdp = (opc2 & 0x0FF) == 0x0E4; 13125 break; 13126 13127 default: 13128 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13129 } 13130 13131 switch (opc2) { 13132 case 0x384: case 0x3A4: 13133 case 0x3C4: case 0x3E4: 13134 negate = True; 13135 break; 13136 default: 13137 negate = False; 13138 } 13139 IRTemp hiResult = newTemp(Ity_I64); 13140 IRTemp loResult = newTemp(Ity_I64); 13141 IRTemp frT = newTemp(Ity_F64); 13142 IRTemp frT2 = newTemp(Ity_F64); 13143 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 13144 (UInt)XT, (UInt)XA, (UInt)XB); 13145 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 13146 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 13147 13148 assign( hiResult, 13149 unop( Iop_ReinterpF64asI64, 13150 qop( mOp, 13151 rm, 13152 mkexpr( frA ), 13153 mkexpr( mdp ? frT : frB ), 13154 mkexpr( mdp ? frB : frT ) ) ) ); 13155 assign( loResult, 13156 unop( Iop_ReinterpF64asI64, 13157 qop( mOp, 13158 rm, 13159 mkexpr( frA2 ), 13160 mkexpr( mdp ? frT2 : frB2 ), 13161 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 13162 putVSReg( XT, 13163 binop( Iop_64HLtoV128, 13164 mkexpr( negate ? getNegatedResult( hiResult ) 13165 : hiResult ), 13166 mkexpr( negate ? getNegatedResult( loResult ) 13167 : loResult ) ) ); 13168 break; 13169 } 13170 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 13171 { 13172 IRTemp frBHi_I64 = newTemp(Ity_I64); 13173 IRTemp frBLo_I64 = newTemp(Ity_I64); 13174 IRTemp flagsHi = newTemp(Ity_I32); 13175 IRTemp flagsLo = newTemp(Ity_I32); 13176 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13177 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13178 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13179 13180 DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 13181 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13182 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13183 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 13184 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 13185 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13186 * where fl_flag == 1 on ppc64. 13187 */ 13188 assign( flagsHi, 13189 binop( Iop_Or32, 13190 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13191 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13192 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13193 assign( flagsLo, 13194 binop( Iop_Or32, 13195 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13196 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13197 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13198 putGST_field( PPC_GST_CR, 13199 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13200 crfD ); 13201 break; 13202 } 13203 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 13204 { 13205 IRTemp frBHi_I64 = newTemp(Ity_I64); 13206 IRTemp frBLo_I64 = newTemp(Ity_I64); 13207 IRTemp frAHi_I64 = newTemp(Ity_I64); 13208 IRTemp frALo_I64 = newTemp(Ity_I64); 13209 IRTemp flagsHi = newTemp(Ity_I32); 13210 IRTemp flagsLo = newTemp(Ity_I32); 13211 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13212 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 13213 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 13214 13215 DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 13216 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 13217 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 13218 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13219 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 13220 13221 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 13222 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 13223 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13224 * where fl_flag == 1 on ppc64. 13225 */ 13226 assign( flagsHi, 13227 binop( Iop_Or32, 13228 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13229 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 13230 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 13231 assign( flagsLo, 13232 binop( Iop_Or32, 13233 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13234 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 13235 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 13236 putGST_field( PPC_GST_CR, 13237 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 13238 crfD ); 13239 break; 13240 } 13241 13242 default: 13243 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 13244 return False; 13245 } 13246 return True; 13247 } 13248 13249 /* 13250 * VSX vector Single Precision Floating Point Arithmetic Instructions 13251 */ 13252 static Bool 13253 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 13254 { 13255 /* XX3-Form */ 13256 UChar opc1 = ifieldOPC( theInstr ); 13257 UChar XT = ifieldRegXT( theInstr ); 13258 UChar XA = ifieldRegXA( theInstr ); 13259 UChar XB = ifieldRegXB( theInstr ); 13260 IRExpr* rm = get_IR_roundingmode(); 13261 IRTemp a3, a2, a1, a0; 13262 IRTemp b3, b2, b1, b0; 13263 IRTemp res0 = newTemp(Ity_I32); 13264 IRTemp res1 = newTemp(Ity_I32); 13265 IRTemp res2 = newTemp(Ity_I32); 13266 IRTemp res3 = newTemp(Ity_I32); 13267 13268 a3 = a2 = a1 = a0 = IRTemp_INVALID; 13269 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13270 13271 if (opc1 != 0x3C) { 13272 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 13273 return False; 13274 } 13275 13276 switch (opc2) { 13277 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 13278 DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13279 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4 13280 putVSReg( XT, triop(Iop_Add32Fx4, rm, 13281 getVSReg( XA ), getVSReg( XB )) ); 13282 break; 13283 13284 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 13285 DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13286 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4 13287 putVSReg( XT, triop(Iop_Mul32Fx4, rm, 13288 getVSReg( XA ), getVSReg( XB )) ); 13289 break; 13290 13291 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 13292 DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13293 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4 13294 putVSReg( XT, triop(Iop_Sub32Fx4, rm, 13295 getVSReg( XA ), getVSReg( XB )) ); 13296 break; 13297 13298 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 13299 { 13300 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 13301 * So there are two choices: 13302 * 1. Implement the xvdivsp with a native insn; or 13303 * 2. Extract the 4 single precision floats from each vector 13304 * register inputs and perform fdivs on each pair 13305 * I will do the latter, due to the general philosophy of 13306 * reusing existing implementations when practical. 13307 */ 13308 DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13309 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13310 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13311 13312 assign( res0, 13313 unop( Iop_ReinterpF32asI32, 13314 unop( Iop_TruncF64asF32, 13315 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 13316 assign( res1, 13317 unop( Iop_ReinterpF32asI32, 13318 unop( Iop_TruncF64asF32, 13319 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 13320 assign( res2, 13321 unop( Iop_ReinterpF32asI32, 13322 unop( Iop_TruncF64asF32, 13323 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 13324 assign( res3, 13325 unop( Iop_ReinterpF32asI32, 13326 unop( Iop_TruncF64asF32, 13327 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 13328 13329 putVSReg( XT, 13330 binop( Iop_64HLtoV128, 13331 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13332 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13333 break; 13334 } 13335 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 13336 { 13337 DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 13338 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13339 /* Note: The native xvsqrtsp insruction does not always give the same precision 13340 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 13341 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 13342 * to the actual instruction. 13343 */ 13344 13345 assign( res0, 13346 unop( Iop_ReinterpF32asI32, 13347 unop( Iop_TruncF64asF32, 13348 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 13349 assign( res1, 13350 unop( Iop_ReinterpF32asI32, 13351 unop( Iop_TruncF64asF32, 13352 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 13353 assign( res2, 13354 unop( Iop_ReinterpF32asI32, 13355 unop( Iop_TruncF64asF32, 13356 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 13357 assign( res3, 13358 unop( Iop_ReinterpF32asI32, 13359 unop( Iop_TruncF64asF32, 13360 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 13361 13362 putVSReg( XT, 13363 binop( Iop_64HLtoV128, 13364 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13365 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13366 break; 13367 } 13368 13369 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 13370 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 13371 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 13372 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 13373 { 13374 IRTemp t3, t2, t1, t0; 13375 Bool msp = False; 13376 Bool negate; 13377 const HChar * oper_name = NULL; 13378 IROp mOp = Iop_INVALID; 13379 switch (opc2) { 13380 case 0x104: case 0x124: 13381 case 0x304: case 0x324: 13382 msp = (opc2 & 0x0FF) == 0x024; 13383 mOp = Iop_MAddF64r32; 13384 oper_name = "madd"; 13385 break; 13386 13387 case 0x144: case 0x164: 13388 case 0x344: case 0x364: 13389 msp = (opc2 & 0x0FF) == 0x064; 13390 mOp = Iop_MSubF64r32; 13391 oper_name = "sub"; 13392 break; 13393 13394 default: 13395 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13396 } 13397 13398 switch (opc2) { 13399 case 0x304: case 0x324: 13400 case 0x344: case 0x364: 13401 negate = True; 13402 break; 13403 13404 default: 13405 negate = False; 13406 } 13407 13408 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp", 13409 (UInt)XT, (UInt)XA, (UInt)XB); 13410 13411 t3 = t2 = t1 = t0 = IRTemp_INVALID; 13412 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13413 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13414 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 13415 13416 assign( res0, 13417 unop( Iop_ReinterpF32asI32, 13418 unop( Iop_TruncF64asF32, 13419 qop( mOp, 13420 rm, 13421 mkexpr( a0 ), 13422 mkexpr( msp ? t0 : b0 ), 13423 mkexpr( msp ? b0 : t0 ) ) ) ) ); 13424 assign( res1, 13425 unop( Iop_ReinterpF32asI32, 13426 unop( Iop_TruncF64asF32, 13427 qop( mOp, 13428 rm, 13429 mkexpr( a1 ), 13430 mkexpr( msp ? t1 : b1 ), 13431 mkexpr( msp ? b1 : t1 ) ) ) ) ); 13432 assign( res2, 13433 unop( Iop_ReinterpF32asI32, 13434 unop( Iop_TruncF64asF32, 13435 qop( mOp, 13436 rm, 13437 mkexpr( a2 ), 13438 mkexpr( msp ? t2 : b2 ), 13439 mkexpr( msp ? b2 : t2 ) ) ) ) ); 13440 assign( res3, 13441 unop( Iop_ReinterpF32asI32, 13442 unop( Iop_TruncF64asF32, 13443 qop( mOp, 13444 rm, 13445 mkexpr( a3 ), 13446 mkexpr( msp ? t3 : b3 ), 13447 mkexpr( msp ? b3 : t3 ) ) ) ) ); 13448 13449 putVSReg( XT, 13450 binop( Iop_64HLtoV128, 13451 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 13452 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 13453 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 13454 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 13455 13456 break; 13457 } 13458 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 13459 { 13460 IRTemp flags0 = newTemp(Ity_I32); 13461 IRTemp flags1 = newTemp(Ity_I32); 13462 IRTemp flags2 = newTemp(Ity_I32); 13463 IRTemp flags3 = newTemp(Ity_I32); 13464 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13465 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13466 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13467 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13468 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13469 DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 13470 13471 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13472 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13473 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13474 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13475 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13476 13477 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13478 * where fl_flag == 1 on ppc64. 13479 */ 13480 assign( flags0, 13481 binop( Iop_Or32, 13482 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13483 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13484 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13485 assign( flags1, 13486 binop( Iop_Or32, 13487 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13488 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13489 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13490 assign( flags2, 13491 binop( Iop_Or32, 13492 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13493 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13494 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13495 assign( flags3, 13496 binop( Iop_Or32, 13497 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13498 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13499 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13500 putGST_field( PPC_GST_CR, 13501 binop( Iop_Or32, 13502 mkexpr( flags0 ), 13503 binop( Iop_Or32, 13504 mkexpr( flags1 ), 13505 binop( Iop_Or32, 13506 mkexpr( flags2 ), 13507 mkexpr( flags3 ) ) ) ), 13508 crfD ); 13509 13510 break; 13511 } 13512 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 13513 { 13514 IRTemp flags0 = newTemp(Ity_I32); 13515 IRTemp flags1 = newTemp(Ity_I32); 13516 IRTemp flags2 = newTemp(Ity_I32); 13517 IRTemp flags3 = newTemp(Ity_I32); 13518 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13519 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13520 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13521 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13522 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13523 DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 13524 13525 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13526 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13527 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13528 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13529 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13530 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13531 13532 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13533 * where fl_flag == 1 on ppc64. 13534 */ 13535 assign( flags0, 13536 binop( Iop_Or32, 13537 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13538 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13539 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13540 assign( flags1, 13541 binop( Iop_Or32, 13542 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13543 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13544 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13545 assign( flags2, 13546 binop( Iop_Or32, 13547 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13548 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13549 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13550 assign( flags3, 13551 binop( Iop_Or32, 13552 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13553 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13554 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13555 putGST_field( PPC_GST_CR, 13556 binop( Iop_Or32, 13557 mkexpr( flags0 ), 13558 binop( Iop_Or32, 13559 mkexpr( flags1 ), 13560 binop( Iop_Or32, 13561 mkexpr( flags2 ), 13562 mkexpr( flags3 ) ) ) ), 13563 crfD ); 13564 13565 break; 13566 } 13567 13568 default: 13569 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 13570 return False; 13571 } 13572 return True; 13573 } 13574 13575 /* 13576 * Vector Population Count/bit matrix transpose 13577 */ 13578 static Bool 13579 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) 13580 { 13581 UChar vRB_addr = ifieldRegB(theInstr); 13582 UChar vRT_addr = ifieldRegDS(theInstr); 13583 UChar opc1 = ifieldOPC( theInstr ); 13584 IRTemp vB = newTemp(Ity_V128); 13585 assign( vB, getVReg(vRB_addr)); 13586 13587 if (opc1 != 0x4) { 13588 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" ); 13589 return False; 13590 } 13591 13592 switch (opc2) { 13593 case 0x702: // vclzb 13594 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr); 13595 putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) ); 13596 break; 13597 13598 case 0x742: // vclzh 13599 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr); 13600 putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) ); 13601 break; 13602 13603 case 0x782: // vclzw 13604 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr); 13605 putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) ); 13606 break; 13607 13608 case 0x7C2: // vclzd 13609 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr); 13610 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) ); 13611 break; 13612 13613 case 0x703: // vpopcntb 13614 { 13615 /* Break vector into 32-bit words and do the population count 13616 * on byte in the words 13617 */ 13618 IRType ty = Ity_I32; 13619 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13620 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13621 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13622 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13623 13624 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr); 13625 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13626 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE); 13627 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE); 13628 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE); 13629 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE); 13630 13631 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13632 cnt_bits32_63, cnt_bits0_31) ); 13633 break; 13634 } 13635 13636 case 0x743: // vpopcnth 13637 { 13638 /* Break vector into 32-bit words and do the population count 13639 * for each half word 13640 */ 13641 IRType ty = Ity_I32; 13642 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13643 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13644 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13645 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13646 13647 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr); 13648 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13649 13650 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD); 13651 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD); 13652 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD); 13653 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD); 13654 13655 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13656 cnt_bits32_63, cnt_bits0_31) ); 13657 break; 13658 } 13659 13660 case 0x783: // vpopcntw 13661 { 13662 /* Break vector into 32-bit words and do the population count 13663 * on each word. 13664 */ 13665 IRType ty = Ity_I32; 13666 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13667 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13668 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13669 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13670 13671 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr); 13672 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13673 13674 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD); 13675 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD); 13676 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD); 13677 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD); 13678 13679 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13680 cnt_bits32_63, cnt_bits0_31) ); 13681 break; 13682 } 13683 13684 case 0x7C3: // vpopcntd 13685 { 13686 if (mode64) { 13687 /* Break vector into 64-bit double words and do the population count 13688 * on each double word. 13689 */ 13690 IRType ty = Ity_I64; 13691 IRTemp bits0_63 = newTemp(Ity_I64); 13692 IRTemp bits64_127 = newTemp(Ity_I64); 13693 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13694 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13695 13696 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13697 13698 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) ); 13699 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 13700 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD); 13701 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD); 13702 13703 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13704 mkexpr( cnt_bits64_127 ), 13705 mkexpr( cnt_bits0_63 ) ) ); 13706 } else { 13707 /* Break vector into 32-bit words and do the population count 13708 * on each doubleword. 13709 */ 13710 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13711 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13712 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13713 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13714 13715 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13716 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13717 13718 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63); 13719 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127); 13720 13721 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13722 mkexpr( cnt_bits64_127 ), 13723 mkexpr( cnt_bits0_63 ) ) ); 13724 } 13725 break; 13726 } 13727 13728 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword 13729 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr); 13730 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) ); 13731 break; 13732 13733 default: 13734 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n"); 13735 return False; 13736 break; 13737 } 13738 return True; 13739 } 13740 13741 typedef enum { 13742 PPC_CMP_EQ = 2, 13743 PPC_CMP_GT = 4, 13744 PPC_CMP_GE = 6, 13745 PPC_CMP_LT = 8 13746 } ppc_cmp_t; 13747 13748 13749 /* 13750 This helper function takes as input the IRExpr returned 13751 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 13752 in IR form. This helper function converts it to PPC form. 13753 13754 Map compare result from IR to PPC 13755 13756 FP cmp result | PPC | IR 13757 -------------------------- 13758 UN | 0x1 | 0x45 13759 EQ | 0x2 | 0x40 13760 GT | 0x4 | 0x00 13761 LT | 0x8 | 0x01 13762 13763 condcode = Shl(1, (~(ccIR>>5) & 2) 13764 | ((ccIR ^ (ccIR>>6)) & 1) 13765 */ 13766 static IRTemp 13767 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 13768 { 13769 IRTemp condcode = newTemp( Ity_I32 ); 13770 IRTemp ccIR = newTemp( Ity_I32 ); 13771 13772 assign(ccIR, ccIR_expr); 13773 assign( condcode, 13774 binop( Iop_Shl32, 13775 mkU32( 1 ), 13776 unop( Iop_32to8, 13777 binop( Iop_Or32, 13778 binop( Iop_And32, 13779 unop( Iop_Not32, 13780 binop( Iop_Shr32, 13781 mkexpr( ccIR ), 13782 mkU8( 5 ) ) ), 13783 mkU32( 2 ) ), 13784 binop( Iop_And32, 13785 binop( Iop_Xor32, 13786 mkexpr( ccIR ), 13787 binop( Iop_Shr32, 13788 mkexpr( ccIR ), 13789 mkU8( 6 ) ) ), 13790 mkU32( 1 ) ) ) ) ) ); 13791 return condcode; 13792 } 13793 13794 /* 13795 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 13796 * following these special rules: 13797 * - The max/min of a QNaN and any value is that value 13798 * (When two QNaNs are being compared, the frA QNaN is the return value.) 13799 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 13800 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 13801 */ 13802 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 13803 { 13804 IRTemp frA_isNaN = newTemp(Ity_I1); 13805 IRTemp frB_isNaN = newTemp(Ity_I1); 13806 IRTemp frA_isSNaN = newTemp(Ity_I1); 13807 IRTemp frB_isSNaN = newTemp(Ity_I1); 13808 IRTemp frA_isQNaN = newTemp(Ity_I1); 13809 IRTemp frB_isQNaN = newTemp(Ity_I1); 13810 13811 assign( frA_isNaN, is_NaN( frA_I64 ) ); 13812 assign( frB_isNaN, is_NaN( frB_I64 ) ); 13813 // If operand is a NAN and bit 12 is '0', then it's an SNaN 13814 assign( frA_isSNaN, 13815 mkAND1( mkexpr(frA_isNaN), 13816 binop( Iop_CmpEQ32, 13817 binop( Iop_And32, 13818 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 13819 mkU32( 0x00080000 ) ), 13820 mkU32( 0 ) ) ) ); 13821 assign( frB_isSNaN, 13822 mkAND1( mkexpr(frB_isNaN), 13823 binop( Iop_CmpEQ32, 13824 binop( Iop_And32, 13825 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 13826 mkU32( 0x00080000 ) ), 13827 mkU32( 0 ) ) ) ); 13828 assign( frA_isQNaN, 13829 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 13830 assign( frB_isQNaN, 13831 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 13832 13833 /* Based on the rules specified in the function prologue, the algorithm is as follows: 13834 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13835 * if frA is a SNaN 13836 * result = frA converted to QNaN 13837 * else if frB is a SNaN 13838 * result = frB converted to QNaN 13839 * else if frB is a QNaN 13840 * result = frA 13841 * // One of frA or frB was a NaN in order for this function to be called, so 13842 * // if we get to this point, we KNOW that frA must be a QNaN. 13843 * else // frA is a QNaN 13844 * result = frB 13845 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13846 */ 13847 13848 #define SNAN_MASK 0x0008000000000000ULL 13849 return 13850 IRExpr_ITE(mkexpr(frA_isSNaN), 13851 /* then: result = frA converted to QNaN */ 13852 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)), 13853 /* else: if frB is a SNaN */ 13854 IRExpr_ITE(mkexpr(frB_isSNaN), 13855 /* then: result = frB converted to QNaN */ 13856 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)), 13857 /* else: if frB is a QNaN */ 13858 IRExpr_ITE(mkexpr(frB_isQNaN), 13859 /* then: result = frA */ 13860 mkexpr(frA_I64), 13861 /* else: frA is a QNaN, so result = frB */ 13862 mkexpr(frB_I64)))); 13863 } 13864 13865 /* 13866 * Helper function for get_max_min_fp. 13867 */ 13868 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 13869 { 13870 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 13871 unop( Iop_ReinterpI64asF64, 13872 mkexpr( src1 ) ), 13873 unop( Iop_ReinterpI64asF64, 13874 mkexpr( src2 ) ) ) ); 13875 13876 return IRExpr_ITE( binop( Iop_CmpEQ32, 13877 mkexpr( src1cmpsrc2 ), 13878 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ), 13879 /* then: use src1 */ 13880 mkexpr( src1 ), 13881 /* else: use src2 */ 13882 mkexpr( src2 ) ); 13883 } 13884 13885 /* 13886 * Helper function for "Maximum/Minimum Double Precision" operations. 13887 * Arguments: frA and frb are Ity_I64 13888 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 13889 */ 13890 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 13891 { 13892 /* There are three special cases where get_fp_cmp_CR_val is not helpful 13893 * for ascertaining the maximum between two doubles: 13894 * 1. The max/min of +0 and -0 is +0. 13895 * 2. The max/min of a QNaN and any value is that value. 13896 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 13897 * We perform the check for [+/-]0 here in this function and use the 13898 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 13899 * to do the standard comparison function. 13900 */ 13901 IRTemp anyNaN = newTemp(Ity_I1); 13902 IRTemp frA_isZero = newTemp(Ity_I1); 13903 IRTemp frB_isZero = newTemp(Ity_I1); 13904 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 13905 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 13906 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 13907 #define MINUS_ZERO 0x8000000000000000ULL 13908 13909 return IRExpr_ITE( /* If both arguments are zero . . . */ 13910 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ), 13911 /* then: if frA is -0 and isMin==True, return -0; 13912 * else if frA is +0 and isMin==False; return +0; 13913 * otherwise, simply return frB. */ 13914 IRExpr_ITE( binop( Iop_CmpEQ32, 13915 unop( Iop_64HIto32, 13916 mkexpr( frA_I64 ) ), 13917 mkU32( isMin ? 0x80000000 : 0 ) ), 13918 mkU64( isMin ? MINUS_ZERO : 0ULL ), 13919 mkexpr( frB_I64 ) ), 13920 /* else: check if either input is a NaN*/ 13921 IRExpr_ITE( mkexpr( anyNaN ), 13922 /* then: use "NaN helper" */ 13923 _get_maxmin_fp_NaN( frA_I64, frB_I64 ), 13924 /* else: use "comparison helper" */ 13925 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) )); 13926 } 13927 13928 static const HChar * _get_vsx_rdpi_suffix(UInt opc2) 13929 { 13930 switch (opc2 & 0x7F) { 13931 case 0x72: 13932 return "m"; 13933 case 0x52: 13934 return "p"; 13935 case 0x56: 13936 return "c"; 13937 case 0x32: 13938 return "z"; 13939 case 0x12: 13940 return ""; 13941 13942 default: // Impossible to get here 13943 vex_printf("Unrecognized opcode %x\n", opc2); 13944 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)"); 13945 } 13946 } 13947 13948 /* 13949 * Helper function for vector/scalar double precision fp round to integer instructions. 13950 */ 13951 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) 13952 { 13953 13954 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 13955 IRTemp frB = newTemp(Ity_F64); 13956 IRTemp frD = newTemp(Ity_F64); 13957 IRTemp intermediateResult = newTemp(Ity_I64); 13958 IRTemp is_SNAN = newTemp(Ity_I1); 13959 IRExpr * hi32; 13960 IRExpr * rxpi_rm; 13961 switch (opc2 & 0x7F) { 13962 case 0x72: 13963 rxpi_rm = mkU32(Irrm_NegINF); 13964 break; 13965 case 0x52: 13966 rxpi_rm = mkU32(Irrm_PosINF); 13967 break; 13968 case 0x56: 13969 rxpi_rm = get_IR_roundingmode(); 13970 break; 13971 case 0x32: 13972 rxpi_rm = mkU32(Irrm_ZERO); 13973 break; 13974 case 0x12: 13975 rxpi_rm = mkU32(Irrm_NEAREST); 13976 break; 13977 13978 default: // Impossible to get here 13979 vex_printf("Unrecognized opcode %x\n", opc2); 13980 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)"); 13981 } 13982 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 13983 assign( intermediateResult, 13984 binop( Iop_F64toI64S, rxpi_rm, 13985 mkexpr( frB ) ) ); 13986 13987 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 13988 /* F64 has only log10(2**52) significant digits anyway */ 13989 /* need to preserve sign of zero */ 13990 /* frD = (fabs(frB) > 9e18) ? frB : 13991 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 13992 assign( frD, 13993 IRExpr_ITE( 13994 binop( Iop_CmpNE8, 13995 unop( Iop_32to8, 13996 binop( Iop_CmpF64, 13997 IRExpr_Const( IRConst_F64( 9e18 ) ), 13998 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 13999 mkU8(0) ), 14000 mkexpr( frB ), 14001 IRExpr_ITE( 14002 binop( Iop_CmpNE32, 14003 binop( Iop_Shr32, 14004 unop( Iop_64HIto32, 14005 mkexpr( frB_I64 ) ), 14006 mkU8( 31 ) ), 14007 mkU32(0) ), 14008 unop( Iop_NegF64, 14009 unop( Iop_AbsF64, 14010 binop( Iop_I64StoF64, 14011 mkU32( 0 ), 14012 mkexpr( intermediateResult ) ) ) ), 14013 binop( Iop_I64StoF64, 14014 mkU32( 0 ), 14015 mkexpr( intermediateResult ) ) 14016 ) 14017 ) 14018 ); 14019 14020 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 14021 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 14022 */ 14023 #define SNAN_MASK 0x0008000000000000ULL 14024 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 14025 assign( is_SNAN, 14026 mkAND1( is_NaN( frB_I64 ), 14027 binop( Iop_CmpEQ32, 14028 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 14029 mkU32( 0 ) ) ) ); 14030 14031 return IRExpr_ITE( mkexpr( is_SNAN ), 14032 unop( Iop_ReinterpI64asF64, 14033 binop( Iop_Xor64, 14034 mkU64( SNAN_MASK ), 14035 mkexpr( frB_I64 ) ) ), 14036 mkexpr( frD )); 14037 } 14038 14039 /* 14040 * Miscellaneous VSX vector instructions 14041 */ 14042 static Bool 14043 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 14044 { 14045 /* XX3-Form */ 14046 UChar opc1 = ifieldOPC( theInstr ); 14047 UChar XT = ifieldRegXT( theInstr ); 14048 UChar XB = ifieldRegXB( theInstr ); 14049 14050 if (opc1 != 0x3C) { 14051 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 14052 return False; 14053 } 14054 14055 switch (opc2) { 14056 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 14057 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 14058 // Double-Precision) 14059 { 14060 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14061 IRExpr* rm = get_IR_roundingmode(); 14062 IRTemp frB = newTemp(Ity_I64); 14063 IRTemp frB2 = newTemp(Ity_I64); 14064 Bool redp = opc2 == 0x1B4; 14065 IRTemp sqrtHi = newTemp(Ity_F64); 14066 IRTemp sqrtLo = newTemp(Ity_F64); 14067 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14068 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14069 14070 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB); 14071 if (!redp) { 14072 assign( sqrtHi, 14073 binop( Iop_SqrtF64, 14074 rm, 14075 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 14076 assign( sqrtLo, 14077 binop( Iop_SqrtF64, 14078 rm, 14079 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 14080 } 14081 putVSReg( XT, 14082 binop( Iop_64HLtoV128, 14083 unop( Iop_ReinterpF64asI64, 14084 triop( Iop_DivF64, 14085 rm, 14086 ieee_one, 14087 redp ? unop( Iop_ReinterpI64asF64, 14088 mkexpr( frB ) ) 14089 : mkexpr( sqrtHi ) ) ), 14090 unop( Iop_ReinterpF64asI64, 14091 triop( Iop_DivF64, 14092 rm, 14093 ieee_one, 14094 redp ? unop( Iop_ReinterpI64asF64, 14095 mkexpr( frB2 ) ) 14096 : mkexpr( sqrtLo ) ) ) ) ); 14097 break; 14098 14099 } 14100 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 14101 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 14102 { 14103 IRTemp b3, b2, b1, b0; 14104 IRTemp res0 = newTemp(Ity_I32); 14105 IRTemp res1 = newTemp(Ity_I32); 14106 IRTemp res2 = newTemp(Ity_I32); 14107 IRTemp res3 = newTemp(Ity_I32); 14108 IRTemp sqrt3 = newTemp(Ity_F64); 14109 IRTemp sqrt2 = newTemp(Ity_F64); 14110 IRTemp sqrt1 = newTemp(Ity_F64); 14111 IRTemp sqrt0 = newTemp(Ity_F64); 14112 IRExpr* rm = get_IR_roundingmode(); 14113 Bool resp = opc2 == 0x134; 14114 14115 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14116 14117 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14118 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB); 14119 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14120 14121 if (!resp) { 14122 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 14123 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 14124 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 14125 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 14126 } 14127 14128 assign( res0, 14129 unop( Iop_ReinterpF32asI32, 14130 unop( Iop_TruncF64asF32, 14131 triop( Iop_DivF64r32, 14132 rm, 14133 ieee_one, 14134 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 14135 assign( res1, 14136 unop( Iop_ReinterpF32asI32, 14137 unop( Iop_TruncF64asF32, 14138 triop( Iop_DivF64r32, 14139 rm, 14140 ieee_one, 14141 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 14142 assign( res2, 14143 unop( Iop_ReinterpF32asI32, 14144 unop( Iop_TruncF64asF32, 14145 triop( Iop_DivF64r32, 14146 rm, 14147 ieee_one, 14148 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 14149 assign( res3, 14150 unop( Iop_ReinterpF32asI32, 14151 unop( Iop_TruncF64asF32, 14152 triop( Iop_DivF64r32, 14153 rm, 14154 ieee_one, 14155 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 14156 putVSReg( XT, 14157 binop( Iop_64HLtoV128, 14158 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14159 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14160 break; 14161 } 14162 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 14163 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 14164 { 14165 UChar XA = ifieldRegXA( theInstr ); 14166 IRTemp a3, a2, a1, a0; 14167 IRTemp b3, b2, b1, b0; 14168 IRTemp res0 = newTemp( Ity_I32 ); 14169 IRTemp res1 = newTemp( Ity_I32 ); 14170 IRTemp res2 = newTemp( Ity_I32 ); 14171 IRTemp res3 = newTemp( Ity_I32 ); 14172 IRTemp a0_I64 = newTemp( Ity_I64 ); 14173 IRTemp a1_I64 = newTemp( Ity_I64 ); 14174 IRTemp a2_I64 = newTemp( Ity_I64 ); 14175 IRTemp a3_I64 = newTemp( Ity_I64 ); 14176 IRTemp b0_I64 = newTemp( Ity_I64 ); 14177 IRTemp b1_I64 = newTemp( Ity_I64 ); 14178 IRTemp b2_I64 = newTemp( Ity_I64 ); 14179 IRTemp b3_I64 = newTemp( Ity_I64 ); 14180 14181 Bool isMin = opc2 == 0x320 ? True : False; 14182 14183 a3 = a2 = a1 = a0 = IRTemp_INVALID; 14184 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14185 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB); 14186 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 14187 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 14188 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 14189 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 14190 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 14191 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 14192 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 14193 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 14194 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 14195 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 14196 assign( res0, 14197 unop( Iop_ReinterpF32asI32, 14198 unop( Iop_TruncF64asF32, 14199 unop( Iop_ReinterpI64asF64, 14200 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 14201 assign( res1, 14202 unop( Iop_ReinterpF32asI32, 14203 unop( Iop_TruncF64asF32, 14204 unop( Iop_ReinterpI64asF64, 14205 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 14206 assign( res2, 14207 unop( Iop_ReinterpF32asI32, 14208 unop( Iop_TruncF64asF32, 14209 unop( Iop_ReinterpI64asF64, 14210 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 14211 assign( res3, 14212 unop( Iop_ReinterpF32asI32, 14213 unop( Iop_TruncF64asF32, 14214 unop( Iop_ReinterpI64asF64, 14215 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 14216 putVSReg( XT, 14217 binop( Iop_64HLtoV128, 14218 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 14219 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 14220 break; 14221 } 14222 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 14223 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 14224 { 14225 UChar XA = ifieldRegXA( theInstr ); 14226 IRTemp frA = newTemp(Ity_I64); 14227 IRTemp frB = newTemp(Ity_I64); 14228 IRTemp frA2 = newTemp(Ity_I64); 14229 IRTemp frB2 = newTemp(Ity_I64); 14230 Bool isMin = opc2 == 0x3A0 ? True : False; 14231 14232 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14233 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14234 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14235 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14236 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB); 14237 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 14238 14239 break; 14240 } 14241 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 14242 { 14243 UChar XA = ifieldRegXA( theInstr ); 14244 IRTemp frA = newTemp(Ity_I64); 14245 IRTemp frB = newTemp(Ity_I64); 14246 IRTemp frA2 = newTemp(Ity_I64); 14247 IRTemp frB2 = newTemp(Ity_I64); 14248 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 14249 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 14250 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 14251 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 14252 14253 DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14254 putVSReg( XT, 14255 binop( Iop_64HLtoV128, 14256 binop( Iop_Or64, 14257 binop( Iop_And64, 14258 mkexpr( frA ), 14259 mkU64( SIGN_BIT ) ), 14260 binop( Iop_And64, 14261 mkexpr( frB ), 14262 mkU64( SIGN_MASK ) ) ), 14263 binop( Iop_Or64, 14264 binop( Iop_And64, 14265 mkexpr( frA2 ), 14266 mkU64( SIGN_BIT ) ), 14267 binop( Iop_And64, 14268 mkexpr( frB2 ), 14269 mkU64( SIGN_MASK ) ) ) ) ); 14270 break; 14271 } 14272 case 0x340: // xvcpsgnsp 14273 { 14274 UChar XA = ifieldRegXA( theInstr ); 14275 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 14276 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 14277 IRTemp resHi = newTemp(Ity_I64); 14278 IRTemp resLo = newTemp(Ity_I64); 14279 14280 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 14281 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 14282 DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB); 14283 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 14284 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 14285 14286 assign( resHi, 14287 binop( Iop_32HLto64, 14288 binop( Iop_Or32, 14289 binop( Iop_And32, 14290 unop(Iop_64to32, mkexpr( a3_I64 ) ), 14291 mkU32( SIGN_BIT32 ) ), 14292 binop( Iop_And32, 14293 unop(Iop_64to32, mkexpr( b3_I64 ) ), 14294 mkU32( SIGN_MASK32) ) ), 14295 14296 binop( Iop_Or32, 14297 binop( Iop_And32, 14298 unop(Iop_64to32, mkexpr( a2_I64 ) ), 14299 mkU32( SIGN_BIT32 ) ), 14300 binop( Iop_And32, 14301 unop(Iop_64to32, mkexpr( b2_I64 ) ), 14302 mkU32( SIGN_MASK32 ) ) ) ) ); 14303 assign( resLo, 14304 binop( Iop_32HLto64, 14305 binop( Iop_Or32, 14306 binop( Iop_And32, 14307 unop(Iop_64to32, mkexpr( a1_I64 ) ), 14308 mkU32( SIGN_BIT32 ) ), 14309 binop( Iop_And32, 14310 unop(Iop_64to32, mkexpr( b1_I64 ) ), 14311 mkU32( SIGN_MASK32 ) ) ), 14312 14313 binop( Iop_Or32, 14314 binop( Iop_And32, 14315 unop(Iop_64to32, mkexpr( a0_I64 ) ), 14316 mkU32( SIGN_BIT32 ) ), 14317 binop( Iop_And32, 14318 unop(Iop_64to32, mkexpr( b0_I64 ) ), 14319 mkU32( SIGN_MASK32 ) ) ) ) ); 14320 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 14321 break; 14322 } 14323 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 14324 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 14325 { 14326 IRTemp frB = newTemp(Ity_F64); 14327 IRTemp frB2 = newTemp(Ity_F64); 14328 IRTemp abs_resultHi = newTemp(Ity_F64); 14329 IRTemp abs_resultLo = newTemp(Ity_F64); 14330 Bool make_negative = (opc2 == 0x3D2) ? True : False; 14331 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14332 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14333 14334 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB); 14335 if (make_negative) { 14336 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 14337 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 14338 14339 } else { 14340 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 14341 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 14342 } 14343 putVSReg( XT, binop( Iop_64HLtoV128, 14344 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 14345 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 14346 break; 14347 } 14348 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 14349 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 14350 { 14351 /* 14352 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 14353 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 14354 * of this function is so easy using shifts, I choose to emulate this instruction that 14355 * way versus a native instruction method of implementation. 14356 */ 14357 Bool make_negative = (opc2 == 0x352) ? True : False; 14358 IRTemp shiftVector = newTemp(Ity_V128); 14359 IRTemp absVal_vector = newTemp(Ity_V128); 14360 assign( shiftVector, 14361 binop( Iop_64HLtoV128, 14362 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 14363 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 14364 assign( absVal_vector, 14365 binop( Iop_Shr32x4, 14366 binop( Iop_Shl32x4, 14367 getVSReg( XB ), 14368 mkexpr( shiftVector ) ), 14369 mkexpr( shiftVector ) ) ); 14370 if (make_negative) { 14371 IRTemp signBit_vector = newTemp(Ity_V128); 14372 assign( signBit_vector, 14373 binop( Iop_64HLtoV128, 14374 binop( Iop_32HLto64, 14375 mkU32( 0x80000000 ), 14376 mkU32( 0x80000000 ) ), 14377 binop( Iop_32HLto64, 14378 mkU32( 0x80000000 ), 14379 mkU32( 0x80000000 ) ) ) ); 14380 putVSReg( XT, 14381 binop( Iop_OrV128, 14382 mkexpr( absVal_vector ), 14383 mkexpr( signBit_vector ) ) ); 14384 } else { 14385 putVSReg( XT, mkexpr( absVal_vector ) ); 14386 } 14387 break; 14388 } 14389 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 14390 { 14391 IRTemp frB = newTemp(Ity_F64); 14392 IRTemp frB2 = newTemp(Ity_F64); 14393 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14394 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14395 DIP("xvnegdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14396 putVSReg( XT, 14397 binop( Iop_64HLtoV128, 14398 unop( Iop_ReinterpF64asI64, 14399 unop( Iop_NegF64, mkexpr( frB ) ) ), 14400 unop( Iop_ReinterpF64asI64, 14401 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 14402 break; 14403 } 14404 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 14405 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 14406 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 14407 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 14408 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 14409 { 14410 IRTemp frBHi_I64 = newTemp(Ity_I64); 14411 IRTemp frBLo_I64 = newTemp(Ity_I64); 14412 IRExpr * frD_fp_roundHi = NULL; 14413 IRExpr * frD_fp_roundLo = NULL; 14414 14415 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 14416 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2); 14417 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 14418 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2); 14419 14420 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 14421 putVSReg( XT, 14422 binop( Iop_64HLtoV128, 14423 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 14424 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 14425 break; 14426 } 14427 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 14428 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 14429 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 14430 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 14431 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 14432 { 14433 const HChar * insn_suffix = NULL; 14434 IROp op; 14435 if (opc2 != 0x156) { 14436 // Use pre-defined IRop's for vrfi{m|n|p|z} 14437 switch (opc2) { 14438 case 0x112: 14439 insn_suffix = ""; 14440 op = Iop_RoundF32x4_RN; 14441 break; 14442 case 0x172: 14443 insn_suffix = "m"; 14444 op = Iop_RoundF32x4_RM; 14445 break; 14446 case 0x152: 14447 insn_suffix = "p"; 14448 op = Iop_RoundF32x4_RP; 14449 break; 14450 case 0x132: 14451 insn_suffix = "z"; 14452 op = Iop_RoundF32x4_RZ; 14453 break; 14454 14455 default: 14456 vex_printf("Unrecognized opcode %x\n", opc2); 14457 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n"); 14458 } 14459 DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 14460 putVSReg( XT, unop( op, getVSReg(XB) ) ); 14461 } else { 14462 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 14463 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 14464 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 14465 IRTemp b3_I64 = newTemp(Ity_I64); 14466 IRTemp b2_I64 = newTemp(Ity_I64); 14467 IRTemp b1_I64 = newTemp(Ity_I64); 14468 IRTemp b0_I64 = newTemp(Ity_I64); 14469 14470 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 14471 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 14472 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 14473 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 14474 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 14475 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 14476 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 14477 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 14478 _do_vsx_fp_roundToInt(b3_I64, opc2)); 14479 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 14480 _do_vsx_fp_roundToInt(b2_I64, opc2)); 14481 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 14482 _do_vsx_fp_roundToInt(b1_I64, opc2)); 14483 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 14484 _do_vsx_fp_roundToInt(b0_I64, opc2)); 14485 DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB); 14486 putVSReg( XT, 14487 binop( Iop_64HLtoV128, 14488 binop( Iop_32HLto64, 14489 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 14490 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 14491 binop( Iop_32HLto64, 14492 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 14493 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 14494 } 14495 break; 14496 } 14497 14498 default: 14499 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 14500 return False; 14501 } 14502 return True; 14503 } 14504 14505 14506 /* 14507 * VSX Scalar Floating Point Arithmetic Instructions 14508 */ 14509 static Bool 14510 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 14511 { 14512 /* XX3-Form */ 14513 UChar opc1 = ifieldOPC( theInstr ); 14514 UChar XT = ifieldRegXT( theInstr ); 14515 UChar XA = ifieldRegXA( theInstr ); 14516 UChar XB = ifieldRegXB( theInstr ); 14517 IRExpr* rm = get_IR_roundingmode(); 14518 IRTemp frA = newTemp(Ity_F64); 14519 IRTemp frB = newTemp(Ity_F64); 14520 14521 if (opc1 != 0x3C) { 14522 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 14523 return False; 14524 } 14525 14526 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14527 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14528 14529 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 14530 * of VSX[XT] are undefined after the operation; therefore, we can simply set 14531 * element to zero where it makes sense to do so. 14532 */ 14533 switch (opc2) { 14534 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision) 14535 DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14536 putVSReg( XT, binop( Iop_64HLtoV128, 14537 unop( Iop_ReinterpF64asI64, 14538 binop( Iop_RoundF64toF32, rm, 14539 triop( Iop_AddF64, rm, 14540 mkexpr( frA ), 14541 mkexpr( frB ) ) ) ), 14542 mkU64( 0 ) ) ); 14543 break; 14544 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision) 14545 DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14546 putVSReg( XT, binop( Iop_64HLtoV128, 14547 unop( Iop_ReinterpF64asI64, 14548 binop( Iop_RoundF64toF32, rm, 14549 triop( Iop_SubF64, rm, 14550 mkexpr( frA ), 14551 mkexpr( frB ) ) ) ), 14552 mkU64( 0 ) ) ); 14553 break; 14554 case 0x080: // xsadddp (VSX scalar add double-precision) 14555 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14556 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14557 triop( Iop_AddF64, rm, 14558 mkexpr( frA ), 14559 mkexpr( frB ) ) ), 14560 mkU64( 0 ) ) ); 14561 break; 14562 case 0x060: // xsdivsp (VSX scalar divide single-precision) 14563 DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14564 putVSReg( XT, binop( Iop_64HLtoV128, 14565 unop( Iop_ReinterpF64asI64, 14566 binop( Iop_RoundF64toF32, rm, 14567 triop( Iop_DivF64, rm, 14568 mkexpr( frA ), 14569 mkexpr( frB ) ) ) ), 14570 mkU64( 0 ) ) ); 14571 break; 14572 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 14573 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14574 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14575 triop( Iop_DivF64, rm, 14576 mkexpr( frA ), 14577 mkexpr( frB ) ) ), 14578 mkU64( 0 ) ) ); 14579 break; 14580 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add 14581 * single-precision) 14582 */ 14583 { 14584 IRTemp frT = newTemp(Ity_F64); 14585 Bool mdp = opc2 == 0x024; 14586 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14587 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14588 getVSReg( XT ) ) ) ); 14589 putVSReg( XT, 14590 binop( Iop_64HLtoV128, 14591 unop( Iop_ReinterpF64asI64, 14592 binop( Iop_RoundF64toF32, rm, 14593 qop( Iop_MAddF64, rm, 14594 mkexpr( frA ), 14595 mkexpr( mdp ? frT : frB ), 14596 mkexpr( mdp ? frB : frT ) ) ) ), 14597 mkU64( 0 ) ) ); 14598 break; 14599 } 14600 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 14601 { 14602 IRTemp frT = newTemp(Ity_F64); 14603 Bool mdp = opc2 == 0x0A4; 14604 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14605 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14606 getVSReg( XT ) ) ) ); 14607 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14608 qop( Iop_MAddF64, rm, 14609 mkexpr( frA ), 14610 mkexpr( mdp ? frT : frB ), 14611 mkexpr( mdp ? frB : frT ) ) ), 14612 mkU64( 0 ) ) ); 14613 break; 14614 } 14615 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar 14616 * multiply-subtract single-precision) 14617 */ 14618 { 14619 IRTemp frT = newTemp(Ity_F64); 14620 Bool mdp = opc2 == 0x064; 14621 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14622 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14623 getVSReg( XT ) ) ) ); 14624 putVSReg( XT, 14625 binop( Iop_64HLtoV128, 14626 unop( Iop_ReinterpF64asI64, 14627 binop( Iop_RoundF64toF32, rm, 14628 qop( Iop_MSubF64, rm, 14629 mkexpr( frA ), 14630 mkexpr( mdp ? frT : frB ), 14631 mkexpr( mdp ? frB : frT ) ) ) ), 14632 mkU64( 0 ) ) ); 14633 break; 14634 } 14635 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 14636 { 14637 IRTemp frT = newTemp(Ity_F64); 14638 Bool mdp = opc2 == 0x0E4; 14639 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14640 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14641 getVSReg( XT ) ) ) ); 14642 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14643 qop( Iop_MSubF64, rm, 14644 mkexpr( frA ), 14645 mkexpr( mdp ? frT : frB ), 14646 mkexpr( mdp ? frB : frT ) ) ), 14647 mkU64( 0 ) ) ); 14648 break; 14649 } 14650 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 14651 { 14652 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 14653 * of fnmadd and use pretty much the same code. However, that code has a bug in the 14654 * way it blindly negates the signbit, even if the floating point result is a NaN. 14655 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 14656 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 14657 * bit for NaN result. 14658 */ 14659 Bool mdp = opc2 == 0x2A4; 14660 IRTemp frT = newTemp(Ity_F64); 14661 IRTemp maddResult = newTemp(Ity_I64); 14662 14663 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14664 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14665 getVSReg( XT ) ) ) ); 14666 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 14667 mkexpr( frA ), 14668 mkexpr( mdp ? frT : frB ), 14669 mkexpr( mdp ? frB : frT ) ) ) ); 14670 14671 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 14672 mkU64( 0 ) ) ); 14673 break; 14674 } 14675 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar 14676 * multiply-add single-precision) 14677 */ 14678 { 14679 Bool mdp = opc2 == 0x224; 14680 IRTemp frT = newTemp(Ity_F64); 14681 IRTemp maddResult = newTemp(Ity_I64); 14682 14683 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14684 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14685 getVSReg( XT ) ) ) ); 14686 assign( maddResult, 14687 unop( Iop_ReinterpF64asI64, 14688 binop( Iop_RoundF64toF32, rm, 14689 qop( Iop_MAddF64, rm, 14690 mkexpr( frA ), 14691 mkexpr( mdp ? frT : frB ), 14692 mkexpr( mdp ? frB : frT ) ) ) ) ); 14693 14694 putVSReg( XT, binop( Iop_64HLtoV128, 14695 mkexpr( getNegatedResult(maddResult) ), 14696 mkU64( 0 ) ) ); 14697 break; 14698 } 14699 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative 14700 * Multiply-Subtract Single-Precision) 14701 */ 14702 { 14703 IRTemp frT = newTemp(Ity_F64); 14704 Bool mdp = opc2 == 0x264; 14705 IRTemp msubResult = newTemp(Ity_I64); 14706 14707 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14708 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14709 getVSReg( XT ) ) ) ); 14710 assign( msubResult, 14711 unop( Iop_ReinterpF64asI64, 14712 binop( Iop_RoundF64toF32, rm, 14713 qop( Iop_MSubF64, rm, 14714 mkexpr( frA ), 14715 mkexpr( mdp ? frT : frB ), 14716 mkexpr( mdp ? frB : frT ) ) ) ) ); 14717 14718 putVSReg( XT, binop( Iop_64HLtoV128, 14719 mkexpr( getNegatedResult(msubResult) ), 14720 mkU64( 0 ) ) ); 14721 14722 break; 14723 } 14724 14725 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 14726 { 14727 IRTemp frT = newTemp(Ity_F64); 14728 Bool mdp = opc2 == 0x2E4; 14729 IRTemp msubResult = newTemp(Ity_I64); 14730 14731 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14732 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14733 getVSReg( XT ) ) ) ); 14734 assign(msubResult, unop( Iop_ReinterpF64asI64, 14735 qop( Iop_MSubF64, 14736 rm, 14737 mkexpr( frA ), 14738 mkexpr( mdp ? frT : frB ), 14739 mkexpr( mdp ? frB : frT ) ) )); 14740 14741 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 14742 14743 break; 14744 } 14745 14746 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision) 14747 DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14748 putVSReg( XT, binop( Iop_64HLtoV128, 14749 unop( Iop_ReinterpF64asI64, 14750 binop( Iop_RoundF64toF32, rm, 14751 triop( Iop_MulF64, rm, 14752 mkexpr( frA ), 14753 mkexpr( frB ) ) ) ), 14754 mkU64( 0 ) ) ); 14755 break; 14756 14757 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 14758 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14759 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14760 triop( Iop_MulF64, rm, 14761 mkexpr( frA ), 14762 mkexpr( frB ) ) ), 14763 mkU64( 0 ) ) ); 14764 break; 14765 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 14766 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14767 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14768 triop( Iop_SubF64, rm, 14769 mkexpr( frA ), 14770 mkexpr( frB ) ) ), 14771 mkU64( 0 ) ) ); 14772 break; 14773 14774 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision) 14775 DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 14776 putVSReg( XT, 14777 binop( Iop_64HLtoV128, 14778 unop( Iop_ReinterpF64asI64, 14779 binop( Iop_RoundF64toF32, rm, 14780 binop( Iop_SqrtF64, rm, 14781 mkexpr( frB ) ) ) ), 14782 mkU64( 0 ) ) ); 14783 break; 14784 14785 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 14786 DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14787 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14788 binop( Iop_SqrtF64, rm, 14789 mkexpr( frB ) ) ), 14790 mkU64( 0 ) ) ); 14791 break; 14792 14793 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 14794 { 14795 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14796 IRTemp frA_I64 = newTemp(Ity_I64); 14797 IRTemp frB_I64 = newTemp(Ity_I64); 14798 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB); 14799 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 14800 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 14801 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 14802 break; 14803 } 14804 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 14805 { 14806 IRTemp frB_I64 = newTemp(Ity_I64); 14807 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14808 IRTemp flags = newTemp(Ity_I32); 14809 IRTemp fe_flag, fg_flag; 14810 fe_flag = fg_flag = IRTemp_INVALID; 14811 DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14812 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 14813 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 14814 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 14815 * where fl_flag == 1 on ppc64. 14816 */ 14817 assign( flags, 14818 binop( Iop_Or32, 14819 binop( Iop_Or32, mkU32( 8 ), // fl_flag 14820 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 14821 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 14822 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 14823 break; 14824 } 14825 14826 default: 14827 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 14828 return False; 14829 } 14830 14831 return True; 14832 } 14833 14834 14835 /* 14836 * VSX Floating Point Compare Instructions 14837 */ 14838 static Bool 14839 dis_vx_cmp( UInt theInstr, UInt opc2 ) 14840 { 14841 /* XX3-Form and XX2-Form */ 14842 UChar opc1 = ifieldOPC( theInstr ); 14843 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14844 IRTemp ccPPC32; 14845 UChar XA = ifieldRegXA ( theInstr ); 14846 UChar XB = ifieldRegXB ( theInstr ); 14847 IRTemp frA = newTemp(Ity_F64); 14848 IRTemp frB = newTemp(Ity_F64); 14849 14850 if (opc1 != 0x3C) { 14851 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 14852 return False; 14853 } 14854 14855 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14856 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14857 switch (opc2) { 14858 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 14859 /* Note: Differences between xscmpudp and xscmpodp are only in 14860 * exception flag settings, which aren't supported anyway. */ 14861 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 14862 crfD, (UInt)XA, (UInt)XB); 14863 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 14864 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 14865 break; 14866 14867 default: 14868 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 14869 return False; 14870 } 14871 return True; 14872 } 14873 14874 static void 14875 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 14876 ppc_cmp_t cmp_type ) 14877 { 14878 IRTemp frA_hi = newTemp(Ity_F64); 14879 IRTemp frB_hi = newTemp(Ity_F64); 14880 IRTemp frA_lo = newTemp(Ity_F64); 14881 IRTemp frB_lo = newTemp(Ity_F64); 14882 IRTemp ccPPC32 = newTemp(Ity_I32); 14883 IRTemp ccIR_hi; 14884 IRTemp ccIR_lo; 14885 14886 IRTemp hiResult = newTemp(Ity_I64); 14887 IRTemp loResult = newTemp(Ity_I64); 14888 IRTemp hiEQlo = newTemp(Ity_I1); 14889 IRTemp all_elem_true = newTemp(Ity_I32); 14890 IRTemp all_elem_false = newTemp(Ity_I32); 14891 14892 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 14893 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 14894 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 14895 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 14896 14897 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14898 mkexpr( frA_hi ), 14899 mkexpr( frB_hi ) ) ); 14900 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14901 mkexpr( frA_lo ), 14902 mkexpr( frB_lo ) ) ); 14903 14904 if (cmp_type != PPC_CMP_GE) { 14905 assign( hiResult, 14906 unop( Iop_1Sto64, 14907 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 14908 assign( loResult, 14909 unop( Iop_1Sto64, 14910 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 14911 } else { 14912 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 14913 // the other element compare may return "2" (for "equal to"). 14914 IRTemp lo_GE = newTemp(Ity_I1); 14915 IRTemp hi_GE = newTemp(Ity_I1); 14916 14917 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 14918 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 14919 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 14920 14921 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 14922 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 14923 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 14924 } 14925 14926 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 14927 assign( hiEQlo, 14928 binop( Iop_CmpEQ32, 14929 unop( Iop_64to32, mkexpr( hiResult ) ), 14930 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 14931 putVSReg( XT, 14932 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 14933 14934 assign( all_elem_true, 14935 unop( Iop_1Uto32, 14936 mkAND1( mkexpr( hiEQlo ), 14937 binop( Iop_CmpEQ32, 14938 mkU32( 0xffffffff ), 14939 unop( Iop_64to32, 14940 mkexpr( hiResult ) ) ) ) ) ); 14941 14942 assign( all_elem_false, 14943 unop( Iop_1Uto32, 14944 mkAND1( mkexpr( hiEQlo ), 14945 binop( Iop_CmpEQ32, 14946 mkU32( 0 ), 14947 unop( Iop_64to32, 14948 mkexpr( hiResult ) ) ) ) ) ); 14949 assign( ccPPC32, 14950 binop( Iop_Or32, 14951 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 14952 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 14953 14954 if (flag_rC) { 14955 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 14956 } 14957 } 14958 14959 /* 14960 * VSX Vector Compare Instructions 14961 */ 14962 static Bool 14963 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 14964 { 14965 /* XX3-Form */ 14966 UChar opc1 = ifieldOPC( theInstr ); 14967 UChar XT = ifieldRegXT ( theInstr ); 14968 UChar XA = ifieldRegXA ( theInstr ); 14969 UChar XB = ifieldRegXB ( theInstr ); 14970 UChar flag_rC = ifieldBIT10(theInstr); 14971 IRTemp vA = newTemp( Ity_V128 ); 14972 IRTemp vB = newTemp( Ity_V128 ); 14973 14974 if (opc1 != 0x3C) { 14975 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 14976 return False; 14977 } 14978 14979 assign( vA, getVSReg( XA ) ); 14980 assign( vB, getVSReg( XB ) ); 14981 14982 switch (opc2) { 14983 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 14984 { 14985 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14986 (UInt)XT, (UInt)XA, (UInt)XB); 14987 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 14988 break; 14989 } 14990 14991 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 14992 { 14993 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14994 (UInt)XT, (UInt)XA, (UInt)XB); 14995 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 14996 break; 14997 } 14998 14999 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 15000 { 15001 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15002 (UInt)XT, (UInt)XA, (UInt)XB); 15003 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 15004 break; 15005 } 15006 15007 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 15008 { 15009 IRTemp vD = newTemp(Ity_V128); 15010 15011 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15012 (UInt)XT, (UInt)XA, (UInt)XB); 15013 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 15014 putVSReg( XT, mkexpr(vD) ); 15015 if (flag_rC) { 15016 set_AV_CR6( mkexpr(vD), True ); 15017 } 15018 break; 15019 } 15020 15021 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 15022 { 15023 IRTemp vD = newTemp(Ity_V128); 15024 15025 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15026 (UInt)XT, (UInt)XA, (UInt)XB); 15027 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 15028 putVSReg( XT, mkexpr(vD) ); 15029 if (flag_rC) { 15030 set_AV_CR6( mkexpr(vD), True ); 15031 } 15032 break; 15033 } 15034 15035 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 15036 { 15037 IRTemp vD = newTemp(Ity_V128); 15038 15039 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 15040 (UInt)XT, (UInt)XA, (UInt)XB); 15041 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 15042 putVSReg( XT, mkexpr(vD) ); 15043 if (flag_rC) { 15044 set_AV_CR6( mkexpr(vD), True ); 15045 } 15046 break; 15047 } 15048 15049 default: 15050 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 15051 return False; 15052 } 15053 return True; 15054 } 15055 /* 15056 * Miscellaneous VSX Scalar Instructions 15057 */ 15058 static Bool 15059 dis_vxs_misc( UInt theInstr, UInt opc2 ) 15060 { 15061 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL 15062 /* XX3-Form and XX2-Form */ 15063 UChar opc1 = ifieldOPC( theInstr ); 15064 UChar XT = ifieldRegXT ( theInstr ); 15065 UChar XA = ifieldRegXA ( theInstr ); 15066 UChar XB = ifieldRegXB ( theInstr ); 15067 IRTemp vA = newTemp( Ity_V128 ); 15068 IRTemp vB = newTemp( Ity_V128 ); 15069 15070 if (opc1 != 0x3C) { 15071 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 15072 return False; 15073 } 15074 15075 assign( vA, getVSReg( XA ) ); 15076 assign( vB, getVSReg( XB ) ); 15077 15078 /* For all the VSX move instructions, the contents of doubleword element 1 15079 * of VSX[XT] are undefined after the operation; therefore, we can simply 15080 * move the entire array element where it makes sense to do so. 15081 */ 15082 15083 switch (opc2) { 15084 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 15085 { 15086 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 15087 IRTemp absVal = newTemp(Ity_V128); 15088 if (host_endness == VexEndnessLE) { 15089 IRTemp hi64 = newTemp(Ity_I64); 15090 IRTemp lo64 = newTemp(Ity_I64); 15091 assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15092 assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) ); 15093 assign( absVal, binop( Iop_64HLtoV128, 15094 binop( Iop_And64, mkexpr(hi64), 15095 mkU64(VG_PPC_SIGN_MASK) ), 15096 mkexpr(lo64) ) ); 15097 } else { 15098 assign(absVal, binop(Iop_ShrV128, 15099 binop(Iop_ShlV128, mkexpr(vB), 15100 mkU8(1)), mkU8(1))); 15101 } 15102 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15103 putVSReg(XT, mkexpr(absVal)); 15104 break; 15105 } 15106 case 0x2C0: // xscpsgndp 15107 { 15108 /* Scalar copy sign double-precision */ 15109 IRTemp vecA_signed = newTemp(Ity_I64); 15110 IRTemp vecB_unsigned = newTemp(Ity_I64); 15111 IRTemp vec_result = newTemp(Ity_V128); 15112 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15113 assign( vecA_signed, binop( Iop_And64, 15114 unop( Iop_V128HIto64, 15115 mkexpr(vA)), 15116 mkU64(~VG_PPC_SIGN_MASK) ) ); 15117 assign( vecB_unsigned, binop( Iop_And64, 15118 unop( Iop_V128HIto64, 15119 mkexpr(vB) ), 15120 mkU64(VG_PPC_SIGN_MASK) ) ); 15121 assign( vec_result, binop( Iop_64HLtoV128, 15122 binop( Iop_Or64, 15123 mkexpr(vecA_signed), 15124 mkexpr(vecB_unsigned) ), 15125 mkU64(0x0ULL))); 15126 putVSReg(XT, mkexpr(vec_result)); 15127 break; 15128 } 15129 case 0x2D2: // xsnabsdp 15130 { 15131 /* Scalar negative absolute value double-precision */ 15132 IRTemp BHi_signed = newTemp(Ity_I64); 15133 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15134 assign( BHi_signed, binop( Iop_Or64, 15135 unop( Iop_V128HIto64, 15136 mkexpr(vB) ), 15137 mkU64(~VG_PPC_SIGN_MASK) ) ); 15138 putVSReg(XT, binop( Iop_64HLtoV128, 15139 mkexpr(BHi_signed), mkU64(0x0ULL) ) ); 15140 break; 15141 } 15142 case 0x2F2: // xsnegdp 15143 { 15144 /* Scalar negate double-precision */ 15145 IRTemp BHi_signed = newTemp(Ity_I64); 15146 IRTemp BHi_unsigned = newTemp(Ity_I64); 15147 IRTemp BHi_negated = newTemp(Ity_I64); 15148 IRTemp BHi_negated_signbit = newTemp(Ity_I1); 15149 IRTemp vec_result = newTemp(Ity_V128); 15150 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 15151 assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) ); 15152 assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed), 15153 mkU64(VG_PPC_SIGN_MASK) ) ); 15154 assign( BHi_negated_signbit, 15155 unop( Iop_Not1, 15156 unop( Iop_32to1, 15157 binop( Iop_Shr32, 15158 unop( Iop_64HIto32, 15159 binop( Iop_And64, 15160 mkexpr(BHi_signed), 15161 mkU64(~VG_PPC_SIGN_MASK) ) 15162 ), 15163 mkU8(31) ) ) ) ); 15164 assign( BHi_negated, 15165 binop( Iop_Or64, 15166 binop( Iop_32HLto64, 15167 binop( Iop_Shl32, 15168 unop( Iop_1Uto32, 15169 mkexpr(BHi_negated_signbit) ), 15170 mkU8(31) ), 15171 mkU32(0) ), 15172 mkexpr(BHi_unsigned) ) ); 15173 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated), 15174 mkU64(0x0ULL))); 15175 putVSReg( XT, mkexpr(vec_result)); 15176 break; 15177 } 15178 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 15179 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 15180 { 15181 IRTemp frA = newTemp(Ity_I64); 15182 IRTemp frB = newTemp(Ity_I64); 15183 Bool isMin = opc2 == 0x2A0 ? True : False; 15184 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB); 15185 15186 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 15187 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 15188 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 15189 15190 break; 15191 } 15192 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 15193 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 15194 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 15195 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 15196 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 15197 { 15198 IRTemp frB_I64 = newTemp(Ity_I64); 15199 IRExpr * frD_fp_round = NULL; 15200 15201 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 15202 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2); 15203 15204 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 15205 putVSReg( XT, 15206 binop( Iop_64HLtoV128, 15207 unop( Iop_ReinterpF64asI64, frD_fp_round), 15208 mkU64( 0 ) ) ); 15209 break; 15210 } 15211 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision) 15212 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate 15213 * single-Precision) 15214 */ 15215 { 15216 IRTemp frB = newTemp(Ity_F64); 15217 IRTemp sqrt = newTemp(Ity_F64); 15218 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15219 IRExpr* rm = get_IR_roundingmode(); 15220 Bool redp = opc2 == 0x034; 15221 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT, 15222 (UInt)XB); 15223 15224 assign( frB, 15225 unop( Iop_ReinterpI64asF64, 15226 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15227 15228 if (!redp) 15229 assign( sqrt, 15230 binop( Iop_SqrtF64, 15231 rm, 15232 mkexpr(frB) ) ); 15233 putVSReg( XT, 15234 binop( Iop_64HLtoV128, 15235 unop( Iop_ReinterpF64asI64, 15236 binop( Iop_RoundF64toF32, rm, 15237 triop( Iop_DivF64, 15238 rm, 15239 ieee_one, 15240 redp ? mkexpr( frB ) : 15241 mkexpr( sqrt ) ) ) ), 15242 mkU64( 0 ) ) ); 15243 break; 15244 } 15245 15246 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 15247 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 15248 15249 { 15250 IRTemp frB = newTemp(Ity_F64); 15251 IRTemp sqrt = newTemp(Ity_F64); 15252 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 15253 IRExpr* rm = get_IR_roundingmode(); 15254 Bool redp = opc2 == 0x0B4; 15255 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB); 15256 assign( frB, 15257 unop( Iop_ReinterpI64asF64, 15258 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15259 15260 if (!redp) 15261 assign( sqrt, 15262 binop( Iop_SqrtF64, 15263 rm, 15264 mkexpr(frB) ) ); 15265 putVSReg( XT, 15266 binop( Iop_64HLtoV128, 15267 unop( Iop_ReinterpF64asI64, 15268 triop( Iop_DivF64, 15269 rm, 15270 ieee_one, 15271 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 15272 mkU64( 0 ) ) ); 15273 break; 15274 } 15275 15276 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision) 15277 { 15278 IRTemp frB = newTemp(Ity_F64); 15279 IRExpr* rm = get_IR_roundingmode(); 15280 DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB); 15281 assign( frB, 15282 unop( Iop_ReinterpI64asF64, 15283 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 15284 15285 putVSReg( XT, binop( Iop_64HLtoV128, 15286 unop( Iop_ReinterpF64asI64, 15287 binop( Iop_RoundF64toF32, 15288 rm, 15289 mkexpr( frB ) ) ), 15290 mkU64( 0 ) ) ); 15291 break; 15292 } 15293 15294 default: 15295 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 15296 return False; 15297 } 15298 return True; 15299 } 15300 15301 /* 15302 * VSX Logical Instructions 15303 */ 15304 static Bool 15305 dis_vx_logic ( UInt theInstr, UInt opc2 ) 15306 { 15307 /* XX3-Form */ 15308 UChar opc1 = ifieldOPC( theInstr ); 15309 UChar XT = ifieldRegXT ( theInstr ); 15310 UChar XA = ifieldRegXA ( theInstr ); 15311 UChar XB = ifieldRegXB ( theInstr ); 15312 IRTemp vA = newTemp( Ity_V128 ); 15313 IRTemp vB = newTemp( Ity_V128 ); 15314 15315 if (opc1 != 0x3C) { 15316 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 15317 return False; 15318 } 15319 15320 assign( vA, getVSReg( XA ) ); 15321 assign( vB, getVSReg( XB ) ); 15322 15323 switch (opc2) { 15324 case 0x268: // xxlxor 15325 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15326 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 15327 break; 15328 case 0x248: // xxlor 15329 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15330 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 15331 break; 15332 case 0x288: // xxlnor 15333 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15334 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 15335 mkexpr( vB ) ) ) ); 15336 break; 15337 case 0x208: // xxland 15338 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15339 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 15340 break; 15341 case 0x228: //xxlandc 15342 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15343 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 15344 mkexpr( vB ) ) ) ); 15345 break; 15346 case 0x2A8: // xxlorc (VSX Logical OR with complement) 15347 DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15348 putVSReg( XT, binop( Iop_OrV128, 15349 mkexpr( vA ), 15350 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 15351 break; 15352 case 0x2C8: // xxlnand (VSX Logical NAND) 15353 DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15354 putVSReg( XT, unop( Iop_NotV128, 15355 binop( Iop_AndV128, mkexpr( vA ), 15356 mkexpr( vB ) ) ) ); 15357 break; 15358 case 0x2E8: // xxleqv (VSX Logical Equivalence) 15359 DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15360 putVSReg( XT, unop( Iop_NotV128, 15361 binop( Iop_XorV128, 15362 mkexpr( vA ), mkexpr( vB ) ) ) ); 15363 break; 15364 default: 15365 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 15366 return False; 15367 } 15368 return True; 15369 } 15370 15371 /* 15372 * VSX Load Instructions 15373 * NOTE: VSX supports word-aligned storage access. 15374 */ 15375 static Bool 15376 dis_vx_load ( UInt theInstr ) 15377 { 15378 /* XX1-Form */ 15379 UChar opc1 = ifieldOPC( theInstr ); 15380 UChar XT = ifieldRegXT ( theInstr ); 15381 UChar rA_addr = ifieldRegA( theInstr ); 15382 UChar rB_addr = ifieldRegB( theInstr ); 15383 UInt opc2 = ifieldOPClo10( theInstr ); 15384 15385 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15386 IRTemp EA = newTemp( ty ); 15387 15388 if (opc1 != 0x1F) { 15389 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 15390 return False; 15391 } 15392 15393 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15394 15395 switch (opc2) { 15396 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) 15397 { 15398 IRExpr * exp; 15399 DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15400 15401 if (host_endness == VexEndnessLE) 15402 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15403 else 15404 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15405 15406 putVSReg( XT, binop( Iop_64HLtoV128, 15407 unop( Iop_32Uto64, exp), 15408 mkU64(0) ) ); 15409 break; 15410 } 15411 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) 15412 { 15413 IRExpr * exp; 15414 DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15415 15416 if (host_endness == VexEndnessLE) 15417 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) ); 15418 else 15419 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) ); 15420 15421 putVSReg( XT, binop( Iop_64HLtoV128, 15422 unop( Iop_32Sto64, exp), 15423 mkU64(0) ) ); 15424 break; 15425 } 15426 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed) 15427 { 15428 IRExpr * exp; 15429 DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15430 /* Take 32-bit floating point value in the upper half of the fetched 15431 * 64-bit value, convert to 64-bit floating point value and load into 15432 * top word of V128. 15433 */ 15434 exp = unop( Iop_ReinterpF64asI64, 15435 unop( Iop_F32toF64, 15436 unop( Iop_ReinterpI32asF32, 15437 load( Ity_I32, mkexpr( EA ) ) ) ) ); 15438 15439 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); 15440 break; 15441 } 15442 case 0x24C: // lxsdx 15443 { 15444 IRExpr * exp; 15445 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15446 exp = load( Ity_I64, mkexpr( EA ) ); 15447 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 15448 // we just performed is only a DW. But since the contents of VSR[XT] element 1 15449 // are undefined after this operation, we can just do a splat op. 15450 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 15451 break; 15452 } 15453 case 0x34C: // lxvd2x 15454 { 15455 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 15456 IRExpr * high, *low; 15457 ULong ea_off = 8; 15458 IRExpr* high_addr; 15459 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15460 high = load( Ity_I64, mkexpr( EA ) ); 15461 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 15462 : mkU32( ea_off ) ); 15463 low = load( Ity_I64, high_addr ); 15464 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 15465 break; 15466 } 15467 case 0x14C: // lxvdsx 15468 { 15469 IRTemp data = newTemp(Ity_I64); 15470 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15471 assign( data, load( Ity_I64, mkexpr( EA ) ) ); 15472 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 15473 break; 15474 } 15475 case 0x30C: 15476 { 15477 IRExpr *t0; 15478 15479 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15480 15481 /* The load will result in the data being in BE order. */ 15482 if (host_endness == VexEndnessLE) { 15483 IRExpr *t0_BE; 15484 IRTemp perm_LE = newTemp(Ity_V128); 15485 15486 t0_BE = load( Ity_V128, mkexpr( EA ) ); 15487 15488 /* Permute the data to LE format */ 15489 assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL), 15490 mkU64(0x0405060700010203ULL))); 15491 15492 t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) ); 15493 } else { 15494 t0 = load( Ity_V128, mkexpr( EA ) ); 15495 } 15496 15497 putVSReg( XT, t0 ); 15498 break; 15499 } 15500 default: 15501 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 15502 return False; 15503 } 15504 return True; 15505 } 15506 15507 /* 15508 * VSX Store Instructions 15509 * NOTE: VSX supports word-aligned storage access. 15510 */ 15511 static Bool 15512 dis_vx_store ( UInt theInstr ) 15513 { 15514 /* XX1-Form */ 15515 UChar opc1 = ifieldOPC( theInstr ); 15516 UChar XS = ifieldRegXS( theInstr ); 15517 UChar rA_addr = ifieldRegA( theInstr ); 15518 UChar rB_addr = ifieldRegB( theInstr ); 15519 IRTemp vS = newTemp( Ity_V128 ); 15520 UInt opc2 = ifieldOPClo10( theInstr ); 15521 15522 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15523 IRTemp EA = newTemp( ty ); 15524 15525 if (opc1 != 0x1F) { 15526 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 15527 return False; 15528 } 15529 15530 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15531 assign( vS, getVSReg( XS ) ); 15532 15533 switch (opc2) { 15534 case 0x08C: 15535 { 15536 /* Need the next to the most significant 32-bit word from 15537 * the 128-bit vector. 15538 */ 15539 IRExpr * high64, * low32; 15540 DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15541 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15542 low32 = unop( Iop_64to32, high64 ); 15543 store( mkexpr( EA ), low32 ); 15544 break; 15545 } 15546 case 0x28C: 15547 { 15548 IRTemp high64 = newTemp(Ity_F64); 15549 IRTemp val32 = newTemp(Ity_I32); 15550 DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15551 assign(high64, unop( Iop_ReinterpI64asF64, 15552 unop( Iop_V128HIto64, mkexpr( vS ) ) ) ); 15553 assign(val32, unop( Iop_ReinterpF32asI32, 15554 unop( Iop_TruncF64asF32, 15555 mkexpr(high64) ) ) ); 15556 store( mkexpr( EA ), mkexpr( val32 ) ); 15557 break; 15558 } 15559 case 0x2CC: 15560 { 15561 IRExpr * high64; 15562 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15563 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15564 store( mkexpr( EA ), high64 ); 15565 break; 15566 } 15567 case 0x3CC: 15568 { 15569 IRExpr * high64, *low64; 15570 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15571 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15572 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 15573 store( mkexpr( EA ), high64 ); 15574 store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15575 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 ); 15576 break; 15577 } 15578 case 0x38C: 15579 { 15580 UInt ea_off = 0; 15581 IRExpr* irx_addr; 15582 IRTemp hi64 = newTemp( Ity_I64 ); 15583 IRTemp lo64 = newTemp( Ity_I64 ); 15584 15585 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15586 15587 // This instruction supports word-aligned stores, so EA may not be 15588 // quad-word aligned. Therefore, do 4 individual word-size stores. 15589 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 15590 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 15591 store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 15592 ea_off += 4; 15593 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15594 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15595 store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 15596 ea_off += 4; 15597 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15598 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15599 store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 15600 ea_off += 4; 15601 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15602 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15603 store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 15604 15605 break; 15606 } 15607 default: 15608 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 15609 return False; 15610 } 15611 return True; 15612 } 15613 15614 /* 15615 * VSX permute and other miscealleous instructions 15616 */ 15617 static Bool 15618 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 15619 { 15620 /* XX3-Form */ 15621 UChar opc1 = ifieldOPC( theInstr ); 15622 UChar XT = ifieldRegXT ( theInstr ); 15623 UChar XA = ifieldRegXA ( theInstr ); 15624 UChar XB = ifieldRegXB ( theInstr ); 15625 IRTemp vT = newTemp( Ity_V128 ); 15626 IRTemp vA = newTemp( Ity_V128 ); 15627 IRTemp vB = newTemp( Ity_V128 ); 15628 15629 if (opc1 != 0x3C) { 15630 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 15631 return False; 15632 } 15633 15634 assign( vA, getVSReg( XA ) ); 15635 assign( vB, getVSReg( XB ) ); 15636 15637 switch (opc2) { 15638 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 15639 { 15640 UChar SHW = ifieldSHW ( theInstr ); 15641 IRTemp result = newTemp(Ity_V128); 15642 if ( SHW != 0 ) { 15643 IRTemp hi = newTemp(Ity_V128); 15644 IRTemp lo = newTemp(Ity_V128); 15645 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 15646 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 15647 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 15648 } else 15649 assign ( result, mkexpr(vA) ); 15650 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW); 15651 putVSReg( XT, mkexpr(result) ); 15652 break; 15653 } 15654 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 15655 { 15656 UChar DM = ifieldDM ( theInstr ); 15657 IRTemp hi = newTemp(Ity_I64); 15658 IRTemp lo = newTemp(Ity_I64); 15659 15660 if (DM & 0x2) 15661 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 15662 else 15663 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 15664 15665 if (DM & 0x1) 15666 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 15667 else 15668 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 15669 15670 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 15671 15672 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM); 15673 putVSReg( XT, mkexpr( vT ) ); 15674 break; 15675 } 15676 case 0x48: // xxmrghw (VSX Merge High Word) 15677 case 0xc8: // xxmrglw (VSX Merge Low Word) 15678 { 15679 const HChar type = (opc2 == 0x48) ? 'h' : 'l'; 15680 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 15681 IRTemp a64 = newTemp(Ity_I64); 15682 IRTemp ahi32 = newTemp(Ity_I32); 15683 IRTemp alo32 = newTemp(Ity_I32); 15684 IRTemp b64 = newTemp(Ity_I64); 15685 IRTemp bhi32 = newTemp(Ity_I32); 15686 IRTemp blo32 = newTemp(Ity_I32); 15687 15688 assign( a64, unop(word_op, mkexpr(vA)) ); 15689 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 15690 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 15691 15692 assign( b64, unop(word_op, mkexpr(vB)) ); 15693 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 15694 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 15695 15696 assign( vT, binop(Iop_64HLtoV128, 15697 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 15698 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 15699 15700 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB); 15701 putVSReg( XT, mkexpr( vT ) ); 15702 break; 15703 } 15704 case 0x018: // xxsel (VSX Select) 15705 { 15706 UChar XC = ifieldRegXC(theInstr); 15707 IRTemp vC = newTemp( Ity_V128 ); 15708 assign( vC, getVSReg( XC ) ); 15709 DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC); 15710 /* vD = (vA & ~vC) | (vB & vC) */ 15711 putVSReg( XT, binop(Iop_OrV128, 15712 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 15713 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 15714 break; 15715 } 15716 case 0x148: // xxspltw (VSX Splat Word) 15717 { 15718 UChar UIM = ifieldRegA(theInstr) & 3; 15719 UChar sh_uim = (3 - (UIM)) * 32; 15720 DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM); 15721 putVSReg( XT, 15722 unop( Iop_Dup32x4, 15723 unop( Iop_V128to32, 15724 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 15725 break; 15726 } 15727 15728 default: 15729 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 15730 return False; 15731 } 15732 return True; 15733 } 15734 15735 /* 15736 AltiVec Load Instructions 15737 */ 15738 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr ) 15739 { 15740 /* X-Form */ 15741 UChar opc1 = ifieldOPC(theInstr); 15742 UChar vD_addr = ifieldRegDS(theInstr); 15743 UChar rA_addr = ifieldRegA(theInstr); 15744 UChar rB_addr = ifieldRegB(theInstr); 15745 UInt opc2 = ifieldOPClo10(theInstr); 15746 UChar b0 = ifieldBIT0(theInstr); 15747 15748 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15749 IRTemp EA = newTemp(ty); 15750 IRTemp EA_align16 = newTemp(ty); 15751 15752 if (opc1 != 0x1F || b0 != 0) { 15753 vex_printf("dis_av_load(ppc)(instr)\n"); 15754 return False; 15755 } 15756 15757 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15758 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 15759 15760 switch (opc2) { 15761 15762 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 15763 IRDirty* d; 15764 UInt vD_off = vectorGuestRegOffset(vD_addr); 15765 IRExpr** args_be = mkIRExprVec_5( 15766 IRExpr_BBPTR(), 15767 mkU32(vD_off), 15768 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15769 mkU32(0xF)), 15770 mkU32(0)/*left*/, 15771 mkU32(1)/*Big Endian*/); 15772 IRExpr** args_le = mkIRExprVec_5( 15773 IRExpr_BBPTR(), 15774 mkU32(vD_off), 15775 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15776 mkU32(0xF)), 15777 mkU32(0)/*left*/, 15778 mkU32(0)/*Little Endian*/); 15779 if (!mode64) { 15780 d = unsafeIRDirty_0_N ( 15781 0/*regparms*/, 15782 "ppc32g_dirtyhelper_LVS", 15783 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15784 args_be ); 15785 } else { 15786 if (host_endness == VexEndnessBE) 15787 d = unsafeIRDirty_0_N ( 15788 0/*regparms*/, 15789 "ppc64g_dirtyhelper_LVS", 15790 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15791 args_be ); 15792 else 15793 d = unsafeIRDirty_0_N ( 15794 0/*regparms*/, 15795 "ppc64g_dirtyhelper_LVS", 15796 &ppc64g_dirtyhelper_LVS, 15797 args_le ); 15798 } 15799 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15800 /* declare guest state effects */ 15801 d->nFxState = 1; 15802 vex_bzero(&d->fxState, sizeof(d->fxState)); 15803 d->fxState[0].fx = Ifx_Write; 15804 d->fxState[0].offset = vD_off; 15805 d->fxState[0].size = sizeof(U128); 15806 15807 /* execute the dirty call, side-effecting guest state */ 15808 stmt( IRStmt_Dirty(d) ); 15809 break; 15810 } 15811 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 15812 IRDirty* d; 15813 UInt vD_off = vectorGuestRegOffset(vD_addr); 15814 IRExpr** args_be = mkIRExprVec_5( 15815 IRExpr_BBPTR(), 15816 mkU32(vD_off), 15817 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15818 mkU32(0xF)), 15819 mkU32(1)/*right*/, 15820 mkU32(1)/*Big Endian*/); 15821 IRExpr** args_le = mkIRExprVec_5( 15822 IRExpr_BBPTR(), 15823 mkU32(vD_off), 15824 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15825 mkU32(0xF)), 15826 mkU32(1)/*right*/, 15827 mkU32(0)/*Little Endian*/); 15828 15829 if (!mode64) { 15830 d = unsafeIRDirty_0_N ( 15831 0/*regparms*/, 15832 "ppc32g_dirtyhelper_LVS", 15833 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15834 args_be ); 15835 } else { 15836 if (host_endness == VexEndnessBE) 15837 d = unsafeIRDirty_0_N ( 15838 0/*regparms*/, 15839 "ppc64g_dirtyhelper_LVS", 15840 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15841 args_be ); 15842 else 15843 d = unsafeIRDirty_0_N ( 15844 0/*regparms*/, 15845 "ppc64g_dirtyhelper_LVS", 15846 &ppc64g_dirtyhelper_LVS, 15847 args_le ); 15848 } 15849 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15850 /* declare guest state effects */ 15851 d->nFxState = 1; 15852 vex_bzero(&d->fxState, sizeof(d->fxState)); 15853 d->fxState[0].fx = Ifx_Write; 15854 d->fxState[0].offset = vD_off; 15855 d->fxState[0].size = sizeof(U128); 15856 15857 /* execute the dirty call, side-effecting guest state */ 15858 stmt( IRStmt_Dirty(d) ); 15859 break; 15860 } 15861 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 15862 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15863 /* loads addressed byte into vector[EA[0:3] 15864 since all other destination bytes are undefined, 15865 can simply load entire vector from 16-aligned EA */ 15866 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15867 break; 15868 15869 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 15870 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15871 /* see note for lvebx */ 15872 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15873 break; 15874 15875 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 15876 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15877 /* see note for lvebx */ 15878 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15879 break; 15880 15881 case 0x067: // lvx (Load Vector Indexed, AV p127) 15882 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15883 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15884 break; 15885 15886 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 15887 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15888 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) ); 15889 break; 15890 15891 default: 15892 vex_printf("dis_av_load(ppc)(opc2)\n"); 15893 return False; 15894 } 15895 return True; 15896 } 15897 15898 /* 15899 AltiVec Store Instructions 15900 */ 15901 static Bool dis_av_store ( UInt theInstr ) 15902 { 15903 /* X-Form */ 15904 UChar opc1 = ifieldOPC(theInstr); 15905 UChar vS_addr = ifieldRegDS(theInstr); 15906 UChar rA_addr = ifieldRegA(theInstr); 15907 UChar rB_addr = ifieldRegB(theInstr); 15908 UInt opc2 = ifieldOPClo10(theInstr); 15909 UChar b0 = ifieldBIT0(theInstr); 15910 15911 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15912 IRTemp EA = newTemp(ty); 15913 IRTemp addr_aligned = newTemp(ty); 15914 IRTemp vS = newTemp(Ity_V128); 15915 IRTemp eb = newTemp(Ity_I8); 15916 IRTemp idx = newTemp(Ity_I8); 15917 15918 if (opc1 != 0x1F || b0 != 0) { 15919 vex_printf("dis_av_store(ppc)(instr)\n"); 15920 return False; 15921 } 15922 15923 assign( vS, getVReg(vS_addr)); 15924 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15925 15926 switch (opc2) { 15927 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 15928 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15929 assign( eb, binop(Iop_And8, mkU8(0xF), 15930 unop(Iop_32to8, 15931 mkNarrowTo32(ty, mkexpr(EA)) )) ); 15932 if (host_endness == VexEndnessLE) { 15933 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15934 } else { 15935 assign( idx, binop(Iop_Shl8, 15936 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 15937 mkU8(3)) ); 15938 } 15939 store( mkexpr(EA), 15940 unop( Iop_32to8, unop(Iop_V128to32, 15941 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15942 break; 15943 } 15944 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 15945 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15946 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 15947 assign( eb, binop(Iop_And8, mkU8(0xF), 15948 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15949 if (host_endness == VexEndnessLE) { 15950 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15951 } else { 15952 assign( idx, binop(Iop_Shl8, 15953 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 15954 mkU8(3)) ); 15955 } 15956 store( mkexpr(addr_aligned), 15957 unop( Iop_32to16, unop(Iop_V128to32, 15958 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15959 break; 15960 } 15961 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 15962 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15963 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 15964 assign( eb, binop(Iop_And8, mkU8(0xF), 15965 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15966 if (host_endness == VexEndnessLE) { 15967 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) ); 15968 } else { 15969 assign( idx, binop(Iop_Shl8, 15970 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 15971 mkU8(3)) ); 15972 } 15973 store( mkexpr( addr_aligned), 15974 unop( Iop_V128to32, 15975 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 15976 break; 15977 } 15978 15979 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 15980 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15981 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15982 break; 15983 15984 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 15985 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15986 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15987 break; 15988 15989 default: 15990 vex_printf("dis_av_store(ppc)(opc2)\n"); 15991 return False; 15992 } 15993 return True; 15994 } 15995 15996 /* 15997 AltiVec Arithmetic Instructions 15998 */ 15999 static Bool dis_av_arith ( UInt theInstr ) 16000 { 16001 /* VX-Form */ 16002 UChar opc1 = ifieldOPC(theInstr); 16003 UChar vD_addr = ifieldRegDS(theInstr); 16004 UChar vA_addr = ifieldRegA(theInstr); 16005 UChar vB_addr = ifieldRegB(theInstr); 16006 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16007 16008 IRTemp vA = newTemp(Ity_V128); 16009 IRTemp vB = newTemp(Ity_V128); 16010 IRTemp z3 = newTemp(Ity_I64); 16011 IRTemp z2 = newTemp(Ity_I64); 16012 IRTemp z1 = newTemp(Ity_I64); 16013 IRTemp z0 = newTemp(Ity_I64); 16014 IRTemp aEvn, aOdd; 16015 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 16016 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 16017 IRTemp b3, b2, b1, b0; 16018 16019 aEvn = aOdd = IRTemp_INVALID; 16020 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 16021 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 16022 b3 = b2 = b1 = b0 = IRTemp_INVALID; 16023 16024 assign( vA, getVReg(vA_addr)); 16025 assign( vB, getVReg(vB_addr)); 16026 16027 if (opc1 != 0x4) { 16028 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 16029 return False; 16030 } 16031 16032 switch (opc2) { 16033 /* Add */ 16034 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 16035 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16036 /* unsigned_ov(x+y) = (y >u not(x)) */ 16037 putVReg( vD_addr, binop(Iop_ShrN32x4, 16038 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16039 unop(Iop_NotV128, mkexpr(vA))), 16040 mkU8(31)) ); 16041 break; 16042 } 16043 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 16044 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16045 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 16046 break; 16047 16048 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 16049 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16050 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 16051 break; 16052 16053 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 16054 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16055 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 16056 break; 16057 16058 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo) 16059 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16060 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) ); 16061 break; 16062 16063 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 16064 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16065 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 16066 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 16067 break; 16068 16069 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 16070 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16071 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 16072 // TODO: set VSCR[SAT] 16073 break; 16074 16075 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 16076 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16077 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 16078 // TODO: set VSCR[SAT] 16079 break; 16080 16081 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 16082 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16083 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 16084 // TODO: set VSCR[SAT] 16085 break; 16086 16087 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 16088 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16089 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 16090 // TODO: set VSCR[SAT] 16091 break; 16092 16093 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 16094 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16095 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 16096 // TODO: set VSCR[SAT] 16097 break; 16098 16099 16100 /* Subtract */ 16101 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 16102 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16103 /* unsigned_ov(x-y) = (y >u x) */ 16104 putVReg( vD_addr, binop(Iop_ShrN32x4, 16105 unop(Iop_NotV128, 16106 binop(Iop_CmpGT32Ux4, mkexpr(vB), 16107 mkexpr(vA))), 16108 mkU8(31)) ); 16109 break; 16110 } 16111 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 16112 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16113 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 16114 break; 16115 16116 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 16117 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16118 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 16119 break; 16120 16121 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 16122 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16123 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 16124 break; 16125 16126 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo) 16127 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr,