1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_ppc_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2017 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 /* TODO 18/Nov/05: 37 38 Spot rld... cases which are simply left/right shifts and emit 39 Shl64/Shr64 accordingly. 40 41 Altivec 42 - datastream insns 43 - lvxl,stvxl: load/store with 'least recently used' hint 44 - vexptefp, vlogefp 45 46 LIMITATIONS: 47 48 Various, including: 49 50 - Some invalid forms of lswi and lswx are accepted when they should 51 not be. 52 53 - Floating Point: 54 - All exceptions disabled in FPSCR 55 - condition codes not set in FPSCR 56 57 - Altivec floating point: 58 - vmaddfp, vnmsubfp 59 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the 60 system default of Non-Java mode, we get some small errors 61 (lowest bit only). 62 This is because Non-Java mode brutally hacks denormalised results 63 to zero, whereas we keep maximum accuracy. However, using 64 Non-Java mode would give us more inaccuracy, as our intermediate 65 results would then be zeroed, too. 66 67 - AbiHints for the stack red zone are only emitted for 68 unconditional calls and returns (bl, blr). They should also be 69 emitted for conditional calls and returns, but we don't have a 70 way to express that right now. Ah well. 71 72 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c) 73 ignores the rounding mode, and generates code that assumes 74 round-to-nearest. This means V will compute incorrect results 75 for uses of these IROps when the rounding mode (first) arg is 76 not mkU32(Irrm_NEAREST). 77 */ 78 79 /* "Special" instructions. 80 81 This instruction decoder can decode four special instructions 82 which mean nothing natively (are no-ops as far as regs/mem are 83 concerned) but have meaning for supporting Valgrind. A special 84 instruction is flagged by a 16-byte preamble: 85 86 32-bit mode: 5400183E 5400683E 5400E83E 5400983E 87 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31; 88 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31) 89 90 64-bit mode: 78001800 78006800 7800E802 78009802 91 (rotldi 0,0,3; rotldi 0,0,13; 92 rotldi 0,0,61; rotldi 0,0,51) 93 94 Following that, one of the following 3 are allowed 95 (standard interpretation in parentheses): 96 97 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 98 7C421378 (or 2,2,2) %R3 = guest_NRADDR 99 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian 100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian 101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 102 7CA52B78 (or 5,5,5) IR injection 103 104 Any other bytes following the 16-byte preamble are illegal and 105 constitute a failure in instruction decoding. This all assumes 106 that the preamble will never occur except in specific code 107 fragments designed for Valgrind to catch. 108 */ 109 110 /* Little Endian notes */ 111 /* 112 * Vector operations in little Endian mode behave in non-obvious ways at times. 113 * Below is an attempt at explaining this. 114 * 115 * LE/BE vector example 116 * With a vector of unsigned ints declared as follows: 117 * vector unsigned int vec_inA = 118 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; 119 * The '0x11111111' word is word zero in both LE and BE format. But the 120 * loaded vector register will have word zero on the far left in BE mode and 121 * on the far right in LE mode. The lvx and stvx instructions work naturally 122 * for whatever endianness is in effect. For example, in LE mode, the stvx 123 * stores word zero (far right word) of the vector at the lowest memory 124 * address of the EA; in BE mode, stvx still stores word zero at the lowest 125 * memory address, but with word zero interpreted as the one at the far left 126 * of the register. 127 * 128 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode. 129 * When the compiler generates an lxvd2x instruction to load the 130 * above-declared vector of unsigned integers, it loads the vector as two 131 * double words, but they are in BE word-wise format. To put the vector in 132 * the right order for LE, the compiler also generates an xxswapd after the 133 * load, which puts it in proper LE format. Similarly, the stxvd2x 134 * instruction has a BE bias, storing the vector in BE word-wise format. But 135 * the compiler also generates an xxswapd prior to the store, thus ensuring 136 * the vector is stored in memory in the correct LE order. 137 * 138 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts 139 * of a double words and words within a vector. Because of the reverse order 140 * of numbering for LE as described above, the high part refers to word 1 in 141 * LE format. When input data is saved to a guest state vector register 142 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the 143 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction. 144 * The saving of the data to memory must be done in proper LE order. For the 145 * inverse operation of extracting data from a vector register (e.g., 146 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting 147 * in stvx), and then integer registers are loaded from the memory location 148 * from where the vector register was saved. Again, this must be done in 149 * proper LE order. So for these various vector Iops, we have LE-specific 150 * code in host_ppc_isel.c 151 * 152 * Another unique behavior of vectors in LE mode is with the vector scalar 153 * (VSX) operations that operate on "double word 0" of the source register, 154 * storing the result in "double word 0" of the output vector register. For 155 * these operations, "double word 0" is interpreted as "high half of the 156 * register" (i.e, the part on the left side). 157 * 158 */ 159 /* Translates PPC32/64 code to IR. */ 160 161 /* References 162 163 #define PPC32 164 "PowerPC Microprocessor Family: 165 The Programming Environments Manual for 32-Bit Microprocessors" 166 02/21/2000 167 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 168 169 #define PPC64 170 "PowerPC Microprocessor Family: 171 Programming Environments Manual for 64-Bit Microprocessors" 172 06/10/2003 173 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 174 175 #define AV 176 "PowerPC Microprocessor Family: 177 AltiVec(TM) Technology Programming Environments Manual" 178 07/10/2003 179 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 180 */ 181 182 #include "libvex_basictypes.h" 183 #include "libvex_ir.h" 184 #include "libvex.h" 185 #include "libvex_emnote.h" 186 #include "libvex_guest_ppc32.h" 187 #include "libvex_guest_ppc64.h" 188 189 #include "main_util.h" 190 #include "main_globals.h" 191 #include "guest_generic_bb_to_IR.h" 192 #include "guest_ppc_defs.h" 193 194 /*------------------------------------------------------------*/ 195 /*--- Globals ---*/ 196 /*------------------------------------------------------------*/ 197 198 /* These are set at the start of the translation of an insn, right 199 down in disInstr_PPC, so that we don't have to pass them around 200 endlessly. They are all constant during the translation of any 201 given insn. */ 202 203 /* We need to know this to do sub-register accesses correctly. */ 204 static VexEndness host_endness; 205 206 /* Pointer to the guest code area. */ 207 static const UChar* guest_code; 208 209 /* The guest address corresponding to guest_code[0]. */ 210 static Addr64 guest_CIA_bbstart; 211 212 /* The guest address for the instruction currently being 213 translated. */ 214 static Addr64 guest_CIA_curr_instr; 215 216 /* The IRSB* into which we're generating code. */ 217 static IRSB* irsb; 218 219 /* Is our guest binary 32 or 64bit? Set at each call to 220 disInstr_PPC below. */ 221 static Bool mode64 = False; 222 223 // Given a pointer to a function as obtained by "& functionname" in C, 224 // produce a pointer to the actual entry point for the function. For 225 // most platforms it's the identity function. Unfortunately, on 226 // ppc64-linux it isn't (sigh) 227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f ) 228 { 229 if (vbi->host_ppc_calls_use_fndescrs) { 230 /* f is a pointer to a 3-word function descriptor, of which the 231 first word is the entry address. */ 232 /* note, this is correct even with cross-jitting, since this is 233 purely a host issue, not a guest one. */ 234 HWord* fdescr = (HWord*)f; 235 return (void*)(fdescr[0]); 236 } else { 237 /* Simple; "& f" points directly at the code for f. */ 238 return f; 239 } 240 } 241 242 /* The OV32 and CA32 bits were added with ISA3.0 */ 243 static Bool OV32_CA32_supported = False; 244 245 #define SIGN_BIT 0x8000000000000000ULL 246 #define SIGN_MASK 0x7fffffffffffffffULL 247 #define SIGN_BIT32 0x80000000 248 #define SIGN_MASK32 0x7fffffff 249 250 251 /*------------------------------------------------------------*/ 252 /*--- Debugging output ---*/ 253 /*------------------------------------------------------------*/ 254 255 #define DIP(format, args...) \ 256 if (vex_traceflags & VEX_TRACE_FE) \ 257 vex_printf(format, ## args) 258 259 #define DIS(buf, format, args...) \ 260 if (vex_traceflags & VEX_TRACE_FE) \ 261 vex_sprintf(buf, format, ## args) 262 263 264 /*------------------------------------------------------------*/ 265 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 266 /*------------------------------------------------------------*/ 267 268 #define offsetofPPCGuestState(_x) \ 269 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 270 offsetof(VexGuestPPC32State, _x)) 271 272 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 273 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 274 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 275 #define OFFB_LR offsetofPPCGuestState(guest_LR) 276 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 277 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 278 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 279 #define OFFB_XER_OV32 offsetofPPCGuestState(guest_XER_OV32) 280 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 281 #define OFFB_XER_CA32 offsetofPPCGuestState(guest_XER_CA32) 282 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 283 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 284 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 285 #define OFFB_C_FPCC offsetofPPCGuestState(guest_C_FPCC) 286 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 287 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 288 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 289 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 290 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 291 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 292 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 293 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 294 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 295 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU) 296 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 297 #define OFFB_PPR offsetofPPCGuestState(guest_PPR) 298 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB) 299 300 301 /*------------------------------------------------------------*/ 302 /*--- Extract instruction fields --- */ 303 /*------------------------------------------------------------*/ 304 305 /* Extract field from insn, given idx (zero = lsb) and field length */ 306 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 307 308 /* Extract primary opcode, instr[31:26] */ 309 static UChar ifieldOPC( UInt instr ) { 310 return toUChar( IFIELD( instr, 26, 6 ) ); 311 } 312 313 /* Extract 10-bit secondary opcode, instr[10:1] */ 314 static UInt ifieldOPClo10 ( UInt instr) { 315 return IFIELD( instr, 1, 10 ); 316 } 317 318 /* Extract 9-bit secondary opcode, instr[9:1] */ 319 static UInt ifieldOPClo9 ( UInt instr) { 320 return IFIELD( instr, 1, 9 ); 321 } 322 323 /* Extract 8-bit secondary opcode, instr[8:1] */ 324 static UInt ifieldOPClo8 ( UInt instr) { 325 return IFIELD( instr, 1, 8 ); 326 } 327 328 /* Extract 5-bit secondary opcode, instr[5:1] */ 329 static UInt ifieldOPClo5 ( UInt instr) { 330 return IFIELD( instr, 1, 5 ); 331 } 332 333 /* Extract 2-bit secondary opcode, instr[1:0] */ 334 static UInt ifieldOPC0o2 ( UInt instr) { 335 return IFIELD( instr, 0, 2 ); 336 } 337 338 /* Extract RD (destination register) field, instr[25:21] */ 339 static UChar ifieldRegDS( UInt instr ) { 340 return toUChar( IFIELD( instr, 21, 5 ) ); 341 } 342 343 /* Extract XT (destination register) field, instr[0,25:21] */ 344 static UChar ifieldRegXT ( UInt instr ) 345 { 346 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 347 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 348 return (upper_bit << 5) | lower_bits; 349 } 350 351 /* Extract XS (store source register) field, instr[0,25:21] */ 352 static inline UChar ifieldRegXS ( UInt instr ) 353 { 354 return ifieldRegXT ( instr ); 355 } 356 357 /* Extract RA (1st source register) field, instr[20:16] */ 358 static UChar ifieldRegA ( UInt instr ) { 359 return toUChar( IFIELD( instr, 16, 5 ) ); 360 } 361 362 /* Extract XA (1st source register) field, instr[2,20:16] */ 363 static UChar ifieldRegXA ( UInt instr ) 364 { 365 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 366 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 367 return (upper_bit << 5) | lower_bits; 368 } 369 370 /* Extract RB (2nd source register) field, instr[15:11] */ 371 static UChar ifieldRegB ( UInt instr ) { 372 return toUChar( IFIELD( instr, 11, 5 ) ); 373 } 374 375 /* Extract XB (2nd source register) field, instr[1,15:11] */ 376 static UChar ifieldRegXB ( UInt instr ) 377 { 378 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 379 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 380 return (upper_bit << 5) | lower_bits; 381 } 382 383 /* Extract RC (3rd source register) field, instr[10:6] */ 384 static UChar ifieldRegC ( UInt instr ) { 385 return toUChar( IFIELD( instr, 6, 5 ) ); 386 } 387 388 /* Extract XC (3rd source register) field, instr[3,10:6] */ 389 static UChar ifieldRegXC ( UInt instr ) 390 { 391 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 392 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 393 return (upper_bit << 5) | lower_bits; 394 } 395 396 /* Extract bit 10, instr[10] */ 397 static UChar ifieldBIT10 ( UInt instr ) { 398 return toUChar( IFIELD( instr, 10, 1 ) ); 399 } 400 401 /* Extract 2nd lowest bit, instr[1] */ 402 static UChar ifieldBIT1 ( UInt instr ) { 403 return toUChar( IFIELD( instr, 1, 1 ) ); 404 } 405 406 /* Extract lowest bit, instr[0] */ 407 static UChar ifieldBIT0 ( UInt instr ) { 408 return toUChar( instr & 0x1 ); 409 } 410 411 /* Extract unsigned bottom half, instr[15:0] */ 412 static UInt ifieldUIMM16 ( UInt instr ) { 413 return instr & 0xFFFF; 414 } 415 416 /* Extract unsigned bottom 26 bits, instr[25:0] */ 417 static UInt ifieldUIMM26 ( UInt instr ) { 418 return instr & 0x3FFFFFF; 419 } 420 421 /* Extract DM field, instr[9:8] */ 422 static UChar ifieldDM ( UInt instr ) { 423 return toUChar( IFIELD( instr, 8, 2 ) ); 424 } 425 426 /* Extract SHW field, instr[9:8] */ 427 static inline UChar ifieldSHW ( UInt instr ) 428 { 429 return ifieldDM ( instr ); 430 } 431 432 /*------------------------------------------------------------*/ 433 /*--- Guest-state identifiers ---*/ 434 /*------------------------------------------------------------*/ 435 436 typedef enum { 437 PPC_GST_CIA, // Current Instruction Address 438 PPC_GST_LR, // Link Register 439 PPC_GST_CTR, // Count Register 440 PPC_GST_XER, // Overflow, carry flags, byte count 441 PPC_GST_CR, // Condition Register 442 PPC_GST_FPSCR, // Floating Point Status/Control Register 443 PPC_GST_VRSAVE, // Vector Save/Restore Register 444 PPC_GST_VSCR, // Vector Status and Control Register 445 PPC_GST_EMWARN, // Emulation warnings 446 PPC_GST_CMSTART,// For icbi: start of area to invalidate 447 PPC_GST_CMLEN, // For icbi: length of area to invalidate 448 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 449 PPC_GST_SPRG3_RO, // SPRG3 450 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 451 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 452 PPC_GST_TEXASR, // Transactional EXception And Summary Register 453 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 454 PPC_GST_PPR, // Program Priority register 455 PPC_GST_PPR32, // Upper 32-bits of Program Priority register 456 PPC_GST_PSPB, /* Problem State Priority Boost register, Note, the 457 * register is initialized to a non-zero value. Currently 458 * Valgrind is not supporting the register value to 459 * automatically decrement. Could be added later if 460 * needed. 461 */ 462 PPC_GST_MAX 463 } PPC_GST; 464 465 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 466 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 467 #define MASK_FPSCR_C_FPCC 0x1F000ULL // Floating-Point Condition code FPCC 468 469 #define MASK_VSCR_VALID 0x00010001 470 471 472 /*------------------------------------------------------------*/ 473 /*--- FP Helpers ---*/ 474 /*------------------------------------------------------------*/ 475 476 /* Produce the 32-bit pattern corresponding to the supplied 477 float. */ 478 static UInt float_to_bits ( Float f ) 479 { 480 union { UInt i; Float f; } u; 481 vassert(4 == sizeof(UInt)); 482 vassert(4 == sizeof(Float)); 483 vassert(4 == sizeof(u)); 484 u.f = f; 485 return u.i; 486 } 487 488 489 /*------------------------------------------------------------*/ 490 /*--- Misc Helpers ---*/ 491 /*------------------------------------------------------------*/ 492 493 /* Generate mask with 1's from 'begin' through 'end', 494 wrapping if begin > end. 495 begin->end works from right to left, 0=lsb 496 */ 497 static UInt MASK32( UInt begin, UInt end ) 498 { 499 UInt m1, m2, mask; 500 vassert(begin < 32); 501 vassert(end < 32); 502 m1 = ((UInt)(-1)) << begin; 503 m2 = ((UInt)(-1)) << end << 1; 504 mask = m1 ^ m2; 505 if (begin > end) mask = ~mask; // wrap mask 506 return mask; 507 } 508 509 static ULong MASK64( UInt begin, UInt end ) 510 { 511 ULong m1, m2, mask; 512 vassert(begin < 64); 513 vassert(end < 64); 514 m1 = ((ULong)(-1)) << begin; 515 m2 = ((ULong)(-1)) << end << 1; 516 mask = m1 ^ m2; 517 if (begin > end) mask = ~mask; // wrap mask 518 return mask; 519 } 520 521 static Addr64 nextInsnAddr( void ) 522 { 523 return guest_CIA_curr_instr + 4; 524 } 525 526 527 /*------------------------------------------------------------*/ 528 /*--- Helper bits and pieces for deconstructing the ---*/ 529 /*--- ppc32/64 insn stream. ---*/ 530 /*------------------------------------------------------------*/ 531 532 /* Add a statement to the list held by "irsb". */ 533 static void stmt ( IRStmt* st ) 534 { 535 addStmtToIRSB( irsb, st ); 536 } 537 538 /* Generate a new temporary of the given type. */ 539 static IRTemp newTemp ( IRType ty ) 540 { 541 vassert(isPlausibleIRType(ty)); 542 return newIRTemp( irsb->tyenv, ty ); 543 } 544 545 /* Various simple conversions */ 546 547 static UChar extend_s_5to8 ( UChar x ) 548 { 549 return toUChar((((Int)x) << 27) >> 27); 550 } 551 552 static UInt extend_s_8to32( UChar x ) 553 { 554 return (UInt)((((Int)x) << 24) >> 24); 555 } 556 557 static UInt extend_s_16to32 ( UInt x ) 558 { 559 return (UInt)((((Int)x) << 16) >> 16); 560 } 561 562 static ULong extend_s_16to64 ( UInt x ) 563 { 564 return (ULong)((((Long)x) << 48) >> 48); 565 } 566 567 static ULong extend_s_26to64 ( UInt x ) 568 { 569 return (ULong)((((Long)x) << 38) >> 38); 570 } 571 572 static ULong extend_s_32to64 ( UInt x ) 573 { 574 return (ULong)((((Long)x) << 32) >> 32); 575 } 576 577 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 578 of the underlying host. */ 579 static UInt getUIntPPCendianly ( const UChar* p ) 580 { 581 UInt w = 0; 582 if (host_endness == VexEndnessBE) { 583 w = (w << 8) | p[0]; 584 w = (w << 8) | p[1]; 585 w = (w << 8) | p[2]; 586 w = (w << 8) | p[3]; 587 } else { 588 w = (w << 8) | p[3]; 589 w = (w << 8) | p[2]; 590 w = (w << 8) | p[1]; 591 w = (w << 8) | p[0]; 592 } 593 return w; 594 } 595 596 597 /*------------------------------------------------------------*/ 598 /*--- Helpers for constructing IR. ---*/ 599 /*------------------------------------------------------------*/ 600 601 static void assign ( IRTemp dst, IRExpr* e ) 602 { 603 stmt( IRStmt_WrTmp(dst, e) ); 604 } 605 606 /* This generates a normal (non store-conditional) store. */ 607 static void store ( IRExpr* addr, IRExpr* data ) 608 { 609 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 610 vassert(tyA == Ity_I32 || tyA == Ity_I64); 611 612 if (host_endness == VexEndnessBE) 613 stmt( IRStmt_Store(Iend_BE, addr, data) ); 614 else 615 stmt( IRStmt_Store(Iend_LE, addr, data) ); 616 } 617 618 static IRExpr* unop ( IROp op, IRExpr* a ) 619 { 620 return IRExpr_Unop(op, a); 621 } 622 623 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 624 { 625 return IRExpr_Binop(op, a1, a2); 626 } 627 628 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 629 { 630 return IRExpr_Triop(op, a1, a2, a3); 631 } 632 633 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 634 IRExpr* a3, IRExpr* a4 ) 635 { 636 return IRExpr_Qop(op, a1, a2, a3, a4); 637 } 638 639 static IRExpr* mkexpr ( IRTemp tmp ) 640 { 641 return IRExpr_RdTmp(tmp); 642 } 643 644 #define mkU1(_n) IRExpr_Const(IRConst_U1(_n)) 645 646 static IRExpr* mkU8 ( UChar i ) 647 { 648 return IRExpr_Const(IRConst_U8(i)); 649 } 650 651 static IRExpr* mkU16 ( UInt i ) 652 { 653 return IRExpr_Const(IRConst_U16(i)); 654 } 655 656 static IRExpr* mkU32 ( UInt i ) 657 { 658 return IRExpr_Const(IRConst_U32(i)); 659 } 660 661 static IRExpr* mkU64 ( ULong i ) 662 { 663 return IRExpr_Const(IRConst_U64(i)); 664 } 665 666 static IRExpr* mkV128 ( UShort i ) 667 { 668 vassert(i == 0 || i == 0xffff); 669 return IRExpr_Const(IRConst_V128(i)); 670 } 671 672 /* This generates a normal (non load-linked) load. */ 673 static IRExpr* load ( IRType ty, IRExpr* addr ) 674 { 675 if (host_endness == VexEndnessBE) 676 return IRExpr_Load(Iend_BE, ty, addr); 677 else 678 return IRExpr_Load(Iend_LE, ty, addr); 679 } 680 681 static IRStmt* stmt_load ( IRTemp result, 682 IRExpr* addr, IRExpr* storedata ) 683 { 684 if (host_endness == VexEndnessBE) 685 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 686 else 687 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 688 } 689 690 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 691 { 692 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 693 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 694 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 695 unop(Iop_1Uto32, arg2))); 696 } 697 698 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 699 { 700 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 701 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 702 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 703 unop(Iop_1Uto32, arg2))); 704 } 705 706 static inline IRExpr* mkXOr4_32( IRTemp t0, IRTemp t1, IRTemp t2, 707 IRTemp t3 ) 708 { 709 return binop( Iop_Xor32, 710 binop( Iop_Xor32, mkexpr( t0 ), mkexpr( t1 ) ), 711 binop( Iop_Xor32, mkexpr( t2 ), mkexpr( t3 ) ) ); 712 } 713 714 static inline IRExpr* mkOr3_V128( IRTemp t0, IRTemp t1, IRTemp t2 ) 715 { 716 return binop( Iop_OrV128, 717 mkexpr( t0 ), 718 binop( Iop_OrV128, mkexpr( t1 ), mkexpr( t2 ) ) ); 719 } 720 721 static inline IRExpr* mkOr4_V128( IRTemp t0, IRTemp t1, IRTemp t2, 722 IRTemp t3 ) 723 { 724 return binop( Iop_OrV128, 725 binop( Iop_OrV128, mkexpr( t0 ), mkexpr( t1 ) ), 726 binop( Iop_OrV128, mkexpr( t2 ), mkexpr( t3 ) ) ); 727 } 728 729 static inline IRExpr* mkOr4_V128_expr( IRExpr* t0, IRExpr* t1, IRExpr* t2, 730 IRExpr* t3 ) 731 { 732 /* arguments are already expressions */ 733 return binop( Iop_OrV128, 734 binop( Iop_OrV128, ( t0 ), ( t1 ) ), 735 binop( Iop_OrV128, ( t2 ), ( t3 ) ) ); 736 } 737 738 static IRExpr* mkNOT1 ( IRExpr* arg1 ) 739 { 740 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 741 return unop(Iop_32to1, unop(Iop_Not32, unop(Iop_1Uto32, arg1) ) ); 742 } 743 744 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 745 static void expand8Ux16( IRExpr* vIn, 746 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 747 { 748 IRTemp ones8x16 = newTemp(Ity_V128); 749 750 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 751 vassert(vEvn && *vEvn == IRTemp_INVALID); 752 vassert(vOdd && *vOdd == IRTemp_INVALID); 753 *vEvn = newTemp(Ity_V128); 754 *vOdd = newTemp(Ity_V128); 755 756 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 757 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 758 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 759 binop(Iop_ShrV128, vIn, mkU8(8))) ); 760 } 761 762 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 763 static void expand8Sx16( IRExpr* vIn, 764 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 765 { 766 IRTemp ones8x16 = newTemp(Ity_V128); 767 768 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 769 vassert(vEvn && *vEvn == IRTemp_INVALID); 770 vassert(vOdd && *vOdd == IRTemp_INVALID); 771 *vEvn = newTemp(Ity_V128); 772 *vOdd = newTemp(Ity_V128); 773 774 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 775 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 776 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 777 binop(Iop_ShrV128, vIn, mkU8(8))) ); 778 } 779 780 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 781 static void expand16Ux8( IRExpr* vIn, 782 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 783 { 784 IRTemp ones16x8 = newTemp(Ity_V128); 785 786 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 787 vassert(vEvn && *vEvn == IRTemp_INVALID); 788 vassert(vOdd && *vOdd == IRTemp_INVALID); 789 *vEvn = newTemp(Ity_V128); 790 *vOdd = newTemp(Ity_V128); 791 792 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 793 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 794 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 795 binop(Iop_ShrV128, vIn, mkU8(16))) ); 796 } 797 798 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 799 static void expand16Sx8( IRExpr* vIn, 800 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 801 { 802 IRTemp ones16x8 = newTemp(Ity_V128); 803 804 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 805 vassert(vEvn && *vEvn == IRTemp_INVALID); 806 vassert(vOdd && *vOdd == IRTemp_INVALID); 807 *vEvn = newTemp(Ity_V128); 808 *vOdd = newTemp(Ity_V128); 809 810 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 811 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 812 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 813 binop(Iop_ShrV128, vIn, mkU8(16))) ); 814 } 815 816 /* break V128 to 4xF64's*/ 817 static void breakV128to4xF64( IRExpr* t128, 818 /*OUTs*/ 819 IRTemp* t3, IRTemp* t2, 820 IRTemp* t1, IRTemp* t0 ) 821 { 822 IRTemp hi64 = newTemp(Ity_I64); 823 IRTemp lo64 = newTemp(Ity_I64); 824 825 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 826 vassert(t0 && *t0 == IRTemp_INVALID); 827 vassert(t1 && *t1 == IRTemp_INVALID); 828 vassert(t2 && *t2 == IRTemp_INVALID); 829 vassert(t3 && *t3 == IRTemp_INVALID); 830 *t0 = newTemp(Ity_F64); 831 *t1 = newTemp(Ity_F64); 832 *t2 = newTemp(Ity_F64); 833 *t3 = newTemp(Ity_F64); 834 835 assign( hi64, unop(Iop_V128HIto64, t128) ); 836 assign( lo64, unop(Iop_V128to64, t128) ); 837 assign( *t3, 838 unop( Iop_F32toF64, 839 unop( Iop_ReinterpI32asF32, 840 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 841 assign( *t2, 842 unop( Iop_F32toF64, 843 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 844 assign( *t1, 845 unop( Iop_F32toF64, 846 unop( Iop_ReinterpI32asF32, 847 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 848 assign( *t0, 849 unop( Iop_F32toF64, 850 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 851 } 852 853 854 /* break V128 to 4xI32's, then sign-extend to I64's */ 855 static void breakV128to4x64S( IRExpr* t128, 856 /*OUTs*/ 857 IRTemp* t3, IRTemp* t2, 858 IRTemp* t1, IRTemp* t0 ) 859 { 860 IRTemp hi64 = newTemp(Ity_I64); 861 IRTemp lo64 = newTemp(Ity_I64); 862 863 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 864 vassert(t0 && *t0 == IRTemp_INVALID); 865 vassert(t1 && *t1 == IRTemp_INVALID); 866 vassert(t2 && *t2 == IRTemp_INVALID); 867 vassert(t3 && *t3 == IRTemp_INVALID); 868 *t0 = newTemp(Ity_I64); 869 *t1 = newTemp(Ity_I64); 870 *t2 = newTemp(Ity_I64); 871 *t3 = newTemp(Ity_I64); 872 873 assign( hi64, unop(Iop_V128HIto64, t128) ); 874 assign( lo64, unop(Iop_V128to64, t128) ); 875 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 876 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 877 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 878 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 879 } 880 881 /* break V128 to 4xI32's, then zero-extend to I64's */ 882 static void breakV128to4x64U ( IRExpr* t128, 883 /*OUTs*/ 884 IRTemp* t3, IRTemp* t2, 885 IRTemp* t1, IRTemp* t0 ) 886 { 887 IRTemp hi64 = newTemp(Ity_I64); 888 IRTemp lo64 = newTemp(Ity_I64); 889 890 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 891 vassert(t0 && *t0 == IRTemp_INVALID); 892 vassert(t1 && *t1 == IRTemp_INVALID); 893 vassert(t2 && *t2 == IRTemp_INVALID); 894 vassert(t3 && *t3 == IRTemp_INVALID); 895 *t0 = newTemp(Ity_I64); 896 *t1 = newTemp(Ity_I64); 897 *t2 = newTemp(Ity_I64); 898 *t3 = newTemp(Ity_I64); 899 900 assign( hi64, unop(Iop_V128HIto64, t128) ); 901 assign( lo64, unop(Iop_V128to64, t128) ); 902 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 903 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 904 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 905 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 906 } 907 908 static void breakV128to4x32( IRExpr* t128, 909 /*OUTs*/ 910 IRTemp* t3, IRTemp* t2, 911 IRTemp* t1, IRTemp* t0 ) 912 { 913 IRTemp hi64 = newTemp(Ity_I64); 914 IRTemp lo64 = newTemp(Ity_I64); 915 916 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 917 vassert(t0 && *t0 == IRTemp_INVALID); 918 vassert(t1 && *t1 == IRTemp_INVALID); 919 vassert(t2 && *t2 == IRTemp_INVALID); 920 vassert(t3 && *t3 == IRTemp_INVALID); 921 *t0 = newTemp(Ity_I32); 922 *t1 = newTemp(Ity_I32); 923 *t2 = newTemp(Ity_I32); 924 *t3 = newTemp(Ity_I32); 925 926 assign( hi64, unop(Iop_V128HIto64, t128) ); 927 assign( lo64, unop(Iop_V128to64, t128) ); 928 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 929 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 930 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 931 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 932 } 933 934 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 935 IRTemp t1, IRTemp t0 ) 936 { 937 return 938 binop( Iop_64HLtoV128, 939 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 940 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 941 ); 942 } 943 944 static IRExpr* extract_field_from_vector( IRTemp vB, IRExpr* index, UInt mask) 945 { 946 /* vB is a vector, extract bits starting at index to size of mask */ 947 return unop( Iop_V128to64, 948 binop( Iop_AndV128, 949 binop( Iop_ShrV128, 950 mkexpr( vB ), 951 unop( Iop_64to8, 952 binop( Iop_Mul64, index, 953 mkU64( 8 ) ) ) ), 954 binop( Iop_64HLtoV128, 955 mkU64( 0x0 ), 956 mkU64( mask ) ) ) ); 957 } 958 959 /* Signed saturating narrow 64S to 32 */ 960 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 961 { 962 IRTemp hi32 = newTemp(Ity_I32); 963 IRTemp lo32 = newTemp(Ity_I32); 964 965 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 966 967 assign( hi32, unop(Iop_64HIto32, t64)); 968 assign( lo32, unop(Iop_64to32, t64)); 969 970 return IRExpr_ITE( 971 /* if (hi32 == (lo32 >>s 31)) */ 972 binop(Iop_CmpEQ32, mkexpr(hi32), 973 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 974 /* then: within signed-32 range: lo half good enough */ 975 mkexpr(lo32), 976 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 977 binop(Iop_Add32, mkU32(0x7FFFFFFF), 978 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 979 } 980 981 /* Unsigned saturating narrow 64S to 32 */ 982 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 983 { 984 IRTemp hi32 = newTemp(Ity_I32); 985 IRTemp lo32 = newTemp(Ity_I32); 986 987 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 988 989 assign( hi32, unop(Iop_64HIto32, t64)); 990 assign( lo32, unop(Iop_64to32, t64)); 991 992 return IRExpr_ITE( 993 /* if (top 32 bits of t64 are 0) */ 994 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 995 /* then: within unsigned-32 range: lo half good enough */ 996 mkexpr(lo32), 997 /* else: positive saturate -> 0xFFFFFFFF */ 998 mkU32(0xFFFFFFFF)); 999 } 1000 1001 /* Signed saturate narrow 64->32, combining to V128 */ 1002 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 1003 IRExpr* t1, IRExpr* t0 ) 1004 { 1005 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 1006 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 1007 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 1008 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 1009 return binop(Iop_64HLtoV128, 1010 binop(Iop_32HLto64, 1011 mkQNarrow64Sto32( t3 ), 1012 mkQNarrow64Sto32( t2 )), 1013 binop(Iop_32HLto64, 1014 mkQNarrow64Sto32( t1 ), 1015 mkQNarrow64Sto32( t0 ))); 1016 } 1017 1018 /* Unsigned saturate narrow 64->32, combining to V128 */ 1019 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 1020 IRExpr* t1, IRExpr* t0 ) 1021 { 1022 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 1023 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 1024 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 1025 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 1026 return binop(Iop_64HLtoV128, 1027 binop(Iop_32HLto64, 1028 mkQNarrow64Uto32( t3 ), 1029 mkQNarrow64Uto32( t2 )), 1030 binop(Iop_32HLto64, 1031 mkQNarrow64Uto32( t1 ), 1032 mkQNarrow64Uto32( t0 ))); 1033 } 1034 1035 /* Simulate irops Iop_MullOdd*, since we don't have them */ 1036 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 1037 binop(Iop_MullEven8Ux16, \ 1038 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 1039 binop(Iop_ShrV128, expr_vB, mkU8(8))) 1040 1041 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 1042 binop(Iop_MullEven8Sx16, \ 1043 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 1044 binop(Iop_ShrV128, expr_vB, mkU8(8))) 1045 1046 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 1047 binop(Iop_MullEven16Ux8, \ 1048 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 1049 binop(Iop_ShrV128, expr_vB, mkU8(16))) 1050 1051 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 1052 binop(Iop_MullEven32Ux4, \ 1053 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 1054 binop(Iop_ShrV128, expr_vB, mkU8(32))) 1055 1056 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 1057 binop(Iop_MullEven16Sx8, \ 1058 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 1059 binop(Iop_ShrV128, expr_vB, mkU8(16))) 1060 1061 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 1062 binop(Iop_MullEven32Sx4, \ 1063 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 1064 binop(Iop_ShrV128, expr_vB, mkU8(32))) 1065 1066 1067 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 1068 { 1069 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1070 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 1071 } 1072 1073 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 1074 { 1075 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1076 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1077 } 1078 1079 static IROp mkSzOp ( IRType ty, IROp op8 ) 1080 { 1081 Int adj; 1082 vassert(ty == Ity_I8 || ty == Ity_I16 || 1083 ty == Ity_I32 || ty == Ity_I64); 1084 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1085 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1086 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1087 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1088 op8 == Iop_Not8 ); 1089 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1090 return adj + op8; 1091 } 1092 1093 /* Make sure we get valid 32 and 64bit addresses */ 1094 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1095 { 1096 vassert(ty == Ity_I32 || ty == Ity_I64); 1097 return ( ty == Ity_I64 ? 1098 (Addr64)addr : 1099 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1100 } 1101 1102 /* sz, ULong -> IRExpr */ 1103 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1104 { 1105 vassert(ty == Ity_I32 || ty == Ity_I64); 1106 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1107 } 1108 1109 /* sz, ULong -> IRConst */ 1110 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1111 { 1112 vassert(ty == Ity_I32 || ty == Ity_I64); 1113 return ( ty == Ity_I64 ? 1114 IRConst_U64(imm64) : 1115 IRConst_U32((UInt)imm64) ); 1116 } 1117 1118 /* Sign extend imm16 -> IRExpr* */ 1119 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1120 { 1121 vassert(ty == Ity_I32 || ty == Ity_I64); 1122 return ( ty == Ity_I64 ? 1123 mkU64(extend_s_16to64(imm16)) : 1124 mkU32(extend_s_16to32(imm16)) ); 1125 } 1126 1127 /* Sign extend imm32 -> IRExpr* */ 1128 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1129 { 1130 vassert(ty == Ity_I32 || ty == Ity_I64); 1131 return ( ty == Ity_I64 ? 1132 mkU64(extend_s_32to64(imm32)) : 1133 mkU32(imm32) ); 1134 } 1135 1136 /* IR narrows I32/I64 -> I8/I16/I32 */ 1137 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1138 { 1139 vassert(ty == Ity_I32 || ty == Ity_I64); 1140 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1141 } 1142 1143 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1144 { 1145 vassert(ty == Ity_I32 || ty == Ity_I64); 1146 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1147 } 1148 1149 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1150 { 1151 vassert(ty == Ity_I32 || ty == Ity_I64); 1152 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1153 } 1154 1155 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1156 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1157 { 1158 IROp op; 1159 vassert(ty == Ity_I32 || ty == Ity_I64); 1160 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1161 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1162 return unop(op, src); 1163 } 1164 1165 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1166 { 1167 IROp op; 1168 vassert(ty == Ity_I32 || ty == Ity_I64); 1169 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1170 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1171 return unop(op, src); 1172 } 1173 1174 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1175 { 1176 vassert(ty == Ity_I32 || ty == Ity_I64); 1177 if (ty == Ity_I32) 1178 return src; 1179 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1180 } 1181 1182 1183 static Int integerGuestRegOffset ( UInt archreg ) 1184 { 1185 vassert(archreg < 32); 1186 1187 // jrs: probably not necessary; only matters if we reference sub-parts 1188 // of the ppc registers, but that isn't the case 1189 // later: this might affect Altivec though? 1190 1191 switch (archreg) { 1192 case 0: return offsetofPPCGuestState(guest_GPR0); 1193 case 1: return offsetofPPCGuestState(guest_GPR1); 1194 case 2: return offsetofPPCGuestState(guest_GPR2); 1195 case 3: return offsetofPPCGuestState(guest_GPR3); 1196 case 4: return offsetofPPCGuestState(guest_GPR4); 1197 case 5: return offsetofPPCGuestState(guest_GPR5); 1198 case 6: return offsetofPPCGuestState(guest_GPR6); 1199 case 7: return offsetofPPCGuestState(guest_GPR7); 1200 case 8: return offsetofPPCGuestState(guest_GPR8); 1201 case 9: return offsetofPPCGuestState(guest_GPR9); 1202 case 10: return offsetofPPCGuestState(guest_GPR10); 1203 case 11: return offsetofPPCGuestState(guest_GPR11); 1204 case 12: return offsetofPPCGuestState(guest_GPR12); 1205 case 13: return offsetofPPCGuestState(guest_GPR13); 1206 case 14: return offsetofPPCGuestState(guest_GPR14); 1207 case 15: return offsetofPPCGuestState(guest_GPR15); 1208 case 16: return offsetofPPCGuestState(guest_GPR16); 1209 case 17: return offsetofPPCGuestState(guest_GPR17); 1210 case 18: return offsetofPPCGuestState(guest_GPR18); 1211 case 19: return offsetofPPCGuestState(guest_GPR19); 1212 case 20: return offsetofPPCGuestState(guest_GPR20); 1213 case 21: return offsetofPPCGuestState(guest_GPR21); 1214 case 22: return offsetofPPCGuestState(guest_GPR22); 1215 case 23: return offsetofPPCGuestState(guest_GPR23); 1216 case 24: return offsetofPPCGuestState(guest_GPR24); 1217 case 25: return offsetofPPCGuestState(guest_GPR25); 1218 case 26: return offsetofPPCGuestState(guest_GPR26); 1219 case 27: return offsetofPPCGuestState(guest_GPR27); 1220 case 28: return offsetofPPCGuestState(guest_GPR28); 1221 case 29: return offsetofPPCGuestState(guest_GPR29); 1222 case 30: return offsetofPPCGuestState(guest_GPR30); 1223 case 31: return offsetofPPCGuestState(guest_GPR31); 1224 default: break; 1225 } 1226 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1227 } 1228 1229 static IRExpr* getIReg ( UInt archreg ) 1230 { 1231 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1232 vassert(archreg < 32); 1233 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1234 } 1235 1236 /* Ditto, but write to a reg instead. */ 1237 static void putIReg ( UInt archreg, IRExpr* e ) 1238 { 1239 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1240 vassert(archreg < 32); 1241 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1242 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1243 } 1244 1245 1246 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1247 static Int floatGuestRegOffset ( UInt archreg ) 1248 { 1249 vassert(archreg < 32); 1250 1251 if (host_endness == VexEndnessLE) { 1252 switch (archreg) { 1253 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1254 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1255 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1256 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1257 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1258 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1259 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1260 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1261 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1262 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1263 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1264 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1265 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1266 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1267 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1268 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1269 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1270 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1271 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1272 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1273 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1274 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1275 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1276 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1277 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1278 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1279 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1280 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1281 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1282 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1283 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1284 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1285 default: break; 1286 } 1287 } else { 1288 switch (archreg) { 1289 case 0: return offsetofPPCGuestState(guest_VSR0); 1290 case 1: return offsetofPPCGuestState(guest_VSR1); 1291 case 2: return offsetofPPCGuestState(guest_VSR2); 1292 case 3: return offsetofPPCGuestState(guest_VSR3); 1293 case 4: return offsetofPPCGuestState(guest_VSR4); 1294 case 5: return offsetofPPCGuestState(guest_VSR5); 1295 case 6: return offsetofPPCGuestState(guest_VSR6); 1296 case 7: return offsetofPPCGuestState(guest_VSR7); 1297 case 8: return offsetofPPCGuestState(guest_VSR8); 1298 case 9: return offsetofPPCGuestState(guest_VSR9); 1299 case 10: return offsetofPPCGuestState(guest_VSR10); 1300 case 11: return offsetofPPCGuestState(guest_VSR11); 1301 case 12: return offsetofPPCGuestState(guest_VSR12); 1302 case 13: return offsetofPPCGuestState(guest_VSR13); 1303 case 14: return offsetofPPCGuestState(guest_VSR14); 1304 case 15: return offsetofPPCGuestState(guest_VSR15); 1305 case 16: return offsetofPPCGuestState(guest_VSR16); 1306 case 17: return offsetofPPCGuestState(guest_VSR17); 1307 case 18: return offsetofPPCGuestState(guest_VSR18); 1308 case 19: return offsetofPPCGuestState(guest_VSR19); 1309 case 20: return offsetofPPCGuestState(guest_VSR20); 1310 case 21: return offsetofPPCGuestState(guest_VSR21); 1311 case 22: return offsetofPPCGuestState(guest_VSR22); 1312 case 23: return offsetofPPCGuestState(guest_VSR23); 1313 case 24: return offsetofPPCGuestState(guest_VSR24); 1314 case 25: return offsetofPPCGuestState(guest_VSR25); 1315 case 26: return offsetofPPCGuestState(guest_VSR26); 1316 case 27: return offsetofPPCGuestState(guest_VSR27); 1317 case 28: return offsetofPPCGuestState(guest_VSR28); 1318 case 29: return offsetofPPCGuestState(guest_VSR29); 1319 case 30: return offsetofPPCGuestState(guest_VSR30); 1320 case 31: return offsetofPPCGuestState(guest_VSR31); 1321 default: break; 1322 } 1323 } 1324 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1325 } 1326 1327 static IRExpr* getFReg ( UInt archreg ) 1328 { 1329 vassert(archreg < 32); 1330 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1331 } 1332 1333 /* Ditto, but write to a reg instead. */ 1334 static void putFReg ( UInt archreg, IRExpr* e ) 1335 { 1336 vassert(archreg < 32); 1337 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1338 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1339 } 1340 1341 /* get Decimal float value. Note, they share floating point register file. */ 1342 static IRExpr* getDReg(UInt archreg) { 1343 IRExpr *e; 1344 vassert( archreg < 32 ); 1345 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1346 return e; 1347 } 1348 static IRExpr* getDReg32(UInt archreg) { 1349 IRExpr *e; 1350 vassert( archreg < 32 ); 1351 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1352 return e; 1353 } 1354 1355 /* Read a floating point register pair and combine their contents into a 1356 128-bit value */ 1357 static IRExpr *getDReg_pair(UInt archreg) { 1358 IRExpr *high = getDReg( archreg ); 1359 IRExpr *low = getDReg( archreg + 1 ); 1360 1361 return binop( Iop_D64HLtoD128, high, low ); 1362 } 1363 1364 /* Ditto, but write to a reg instead. */ 1365 static void putDReg32(UInt archreg, IRExpr* e) { 1366 vassert( archreg < 32 ); 1367 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1368 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1369 } 1370 1371 static void putDReg(UInt archreg, IRExpr* e) { 1372 vassert( archreg < 32 ); 1373 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1374 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1375 } 1376 1377 /* Write a 128-bit floating point value into a register pair. */ 1378 static void putDReg_pair(UInt archreg, IRExpr *e) { 1379 IRTemp low = newTemp( Ity_D64 ); 1380 IRTemp high = newTemp( Ity_D64 ); 1381 1382 vassert( archreg < 32 ); 1383 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1384 1385 assign( low, unop( Iop_D128LOtoD64, e ) ); 1386 assign( high, unop( Iop_D128HItoD64, e ) ); 1387 1388 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1389 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1390 } 1391 1392 static Int vsxGuestRegOffset ( UInt archreg ) 1393 { 1394 vassert(archreg < 64); 1395 switch (archreg) { 1396 case 0: return offsetofPPCGuestState(guest_VSR0); 1397 case 1: return offsetofPPCGuestState(guest_VSR1); 1398 case 2: return offsetofPPCGuestState(guest_VSR2); 1399 case 3: return offsetofPPCGuestState(guest_VSR3); 1400 case 4: return offsetofPPCGuestState(guest_VSR4); 1401 case 5: return offsetofPPCGuestState(guest_VSR5); 1402 case 6: return offsetofPPCGuestState(guest_VSR6); 1403 case 7: return offsetofPPCGuestState(guest_VSR7); 1404 case 8: return offsetofPPCGuestState(guest_VSR8); 1405 case 9: return offsetofPPCGuestState(guest_VSR9); 1406 case 10: return offsetofPPCGuestState(guest_VSR10); 1407 case 11: return offsetofPPCGuestState(guest_VSR11); 1408 case 12: return offsetofPPCGuestState(guest_VSR12); 1409 case 13: return offsetofPPCGuestState(guest_VSR13); 1410 case 14: return offsetofPPCGuestState(guest_VSR14); 1411 case 15: return offsetofPPCGuestState(guest_VSR15); 1412 case 16: return offsetofPPCGuestState(guest_VSR16); 1413 case 17: return offsetofPPCGuestState(guest_VSR17); 1414 case 18: return offsetofPPCGuestState(guest_VSR18); 1415 case 19: return offsetofPPCGuestState(guest_VSR19); 1416 case 20: return offsetofPPCGuestState(guest_VSR20); 1417 case 21: return offsetofPPCGuestState(guest_VSR21); 1418 case 22: return offsetofPPCGuestState(guest_VSR22); 1419 case 23: return offsetofPPCGuestState(guest_VSR23); 1420 case 24: return offsetofPPCGuestState(guest_VSR24); 1421 case 25: return offsetofPPCGuestState(guest_VSR25); 1422 case 26: return offsetofPPCGuestState(guest_VSR26); 1423 case 27: return offsetofPPCGuestState(guest_VSR27); 1424 case 28: return offsetofPPCGuestState(guest_VSR28); 1425 case 29: return offsetofPPCGuestState(guest_VSR29); 1426 case 30: return offsetofPPCGuestState(guest_VSR30); 1427 case 31: return offsetofPPCGuestState(guest_VSR31); 1428 case 32: return offsetofPPCGuestState(guest_VSR32); 1429 case 33: return offsetofPPCGuestState(guest_VSR33); 1430 case 34: return offsetofPPCGuestState(guest_VSR34); 1431 case 35: return offsetofPPCGuestState(guest_VSR35); 1432 case 36: return offsetofPPCGuestState(guest_VSR36); 1433 case 37: return offsetofPPCGuestState(guest_VSR37); 1434 case 38: return offsetofPPCGuestState(guest_VSR38); 1435 case 39: return offsetofPPCGuestState(guest_VSR39); 1436 case 40: return offsetofPPCGuestState(guest_VSR40); 1437 case 41: return offsetofPPCGuestState(guest_VSR41); 1438 case 42: return offsetofPPCGuestState(guest_VSR42); 1439 case 43: return offsetofPPCGuestState(guest_VSR43); 1440 case 44: return offsetofPPCGuestState(guest_VSR44); 1441 case 45: return offsetofPPCGuestState(guest_VSR45); 1442 case 46: return offsetofPPCGuestState(guest_VSR46); 1443 case 47: return offsetofPPCGuestState(guest_VSR47); 1444 case 48: return offsetofPPCGuestState(guest_VSR48); 1445 case 49: return offsetofPPCGuestState(guest_VSR49); 1446 case 50: return offsetofPPCGuestState(guest_VSR50); 1447 case 51: return offsetofPPCGuestState(guest_VSR51); 1448 case 52: return offsetofPPCGuestState(guest_VSR52); 1449 case 53: return offsetofPPCGuestState(guest_VSR53); 1450 case 54: return offsetofPPCGuestState(guest_VSR54); 1451 case 55: return offsetofPPCGuestState(guest_VSR55); 1452 case 56: return offsetofPPCGuestState(guest_VSR56); 1453 case 57: return offsetofPPCGuestState(guest_VSR57); 1454 case 58: return offsetofPPCGuestState(guest_VSR58); 1455 case 59: return offsetofPPCGuestState(guest_VSR59); 1456 case 60: return offsetofPPCGuestState(guest_VSR60); 1457 case 61: return offsetofPPCGuestState(guest_VSR61); 1458 case 62: return offsetofPPCGuestState(guest_VSR62); 1459 case 63: return offsetofPPCGuestState(guest_VSR63); 1460 default: break; 1461 } 1462 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1463 } 1464 1465 /* Vector registers are mapped to VSX registers[32..63]. */ 1466 static Int vectorGuestRegOffset ( UInt archreg ) 1467 { 1468 vassert(archreg < 32); 1469 1470 switch (archreg) { 1471 case 0: return offsetofPPCGuestState(guest_VSR32); 1472 case 1: return offsetofPPCGuestState(guest_VSR33); 1473 case 2: return offsetofPPCGuestState(guest_VSR34); 1474 case 3: return offsetofPPCGuestState(guest_VSR35); 1475 case 4: return offsetofPPCGuestState(guest_VSR36); 1476 case 5: return offsetofPPCGuestState(guest_VSR37); 1477 case 6: return offsetofPPCGuestState(guest_VSR38); 1478 case 7: return offsetofPPCGuestState(guest_VSR39); 1479 case 8: return offsetofPPCGuestState(guest_VSR40); 1480 case 9: return offsetofPPCGuestState(guest_VSR41); 1481 case 10: return offsetofPPCGuestState(guest_VSR42); 1482 case 11: return offsetofPPCGuestState(guest_VSR43); 1483 case 12: return offsetofPPCGuestState(guest_VSR44); 1484 case 13: return offsetofPPCGuestState(guest_VSR45); 1485 case 14: return offsetofPPCGuestState(guest_VSR46); 1486 case 15: return offsetofPPCGuestState(guest_VSR47); 1487 case 16: return offsetofPPCGuestState(guest_VSR48); 1488 case 17: return offsetofPPCGuestState(guest_VSR49); 1489 case 18: return offsetofPPCGuestState(guest_VSR50); 1490 case 19: return offsetofPPCGuestState(guest_VSR51); 1491 case 20: return offsetofPPCGuestState(guest_VSR52); 1492 case 21: return offsetofPPCGuestState(guest_VSR53); 1493 case 22: return offsetofPPCGuestState(guest_VSR54); 1494 case 23: return offsetofPPCGuestState(guest_VSR55); 1495 case 24: return offsetofPPCGuestState(guest_VSR56); 1496 case 25: return offsetofPPCGuestState(guest_VSR57); 1497 case 26: return offsetofPPCGuestState(guest_VSR58); 1498 case 27: return offsetofPPCGuestState(guest_VSR59); 1499 case 28: return offsetofPPCGuestState(guest_VSR60); 1500 case 29: return offsetofPPCGuestState(guest_VSR61); 1501 case 30: return offsetofPPCGuestState(guest_VSR62); 1502 case 31: return offsetofPPCGuestState(guest_VSR63); 1503 default: break; 1504 } 1505 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1506 } 1507 1508 static IRExpr* getVReg ( UInt archreg ) 1509 { 1510 vassert(archreg < 32); 1511 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1512 } 1513 1514 /* Get contents of 128-bit reg guest register */ 1515 static IRExpr* getF128Reg ( UInt archreg ) 1516 { 1517 vassert(archreg < 64); 1518 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_F128 ); 1519 } 1520 1521 /* Ditto, but write to a reg instead. */ 1522 static void putF128Reg ( UInt archreg, IRExpr* e ) 1523 { 1524 vassert(archreg < 64); 1525 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F128); 1526 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1527 } 1528 1529 /* Ditto, but write to a reg instead. */ 1530 static void putVReg ( UInt archreg, IRExpr* e ) 1531 { 1532 vassert(archreg < 32); 1533 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1534 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1535 } 1536 1537 /* Get contents of VSX guest register */ 1538 static IRExpr* getVSReg ( UInt archreg ) 1539 { 1540 vassert(archreg < 64); 1541 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1542 } 1543 1544 /* Ditto, but write to a VSX reg instead. */ 1545 static void putVSReg ( UInt archreg, IRExpr* e ) 1546 { 1547 vassert(archreg < 64); 1548 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1549 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1550 } 1551 1552 1553 static Int guestCR321offset ( UInt cr ) 1554 { 1555 switch (cr) { 1556 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1557 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1558 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1559 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1560 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1561 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1562 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1563 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1564 default: vpanic("guestCR321offset(ppc)"); 1565 } 1566 } 1567 1568 static Int guestCR0offset ( UInt cr ) 1569 { 1570 switch (cr) { 1571 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1572 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1573 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1574 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1575 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1576 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1577 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1578 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1579 default: vpanic("guestCR3offset(ppc)"); 1580 } 1581 } 1582 1583 typedef enum { 1584 _placeholder0, 1585 _placeholder1, 1586 _placeholder2, 1587 BYTE, 1588 HWORD, 1589 WORD, 1590 DWORD 1591 } _popcount_data_type; 1592 1593 /* Generate an IR sequence to do a popcount operation on the supplied 1594 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1595 Ity_I32 or Ity_I64 only. */ 1596 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1597 { 1598 /* Do count across 2^data_type bits, 1599 byte: data_type = 3 1600 half word: data_type = 4 1601 word: data_type = 5 1602 double word: data_type = 6 (not supported for 32-bit type) 1603 */ 1604 Int shift[6]; 1605 _popcount_data_type idx, i; 1606 IRTemp mask[6]; 1607 IRTemp old = IRTemp_INVALID; 1608 IRTemp nyu = IRTemp_INVALID; 1609 1610 vassert(ty == Ity_I64 || ty == Ity_I32); 1611 1612 if (ty == Ity_I32) { 1613 1614 for (idx = 0; idx < WORD; idx++) { 1615 mask[idx] = newTemp(ty); 1616 shift[idx] = 1 << idx; 1617 } 1618 assign(mask[0], mkU32(0x55555555)); 1619 assign(mask[1], mkU32(0x33333333)); 1620 assign(mask[2], mkU32(0x0F0F0F0F)); 1621 assign(mask[3], mkU32(0x00FF00FF)); 1622 assign(mask[4], mkU32(0x0000FFFF)); 1623 old = src; 1624 for (i = 0; i < data_type; i++) { 1625 nyu = newTemp(ty); 1626 assign(nyu, 1627 binop(Iop_Add32, 1628 binop(Iop_And32, 1629 mkexpr(old), 1630 mkexpr(mask[i])), 1631 binop(Iop_And32, 1632 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1633 mkexpr(mask[i])))); 1634 old = nyu; 1635 } 1636 return nyu; 1637 } 1638 1639 // else, ty == Ity_I64 1640 vassert(mode64); 1641 1642 for (i = 0; i < DWORD; i++) { 1643 mask[i] = newTemp( Ity_I64 ); 1644 shift[i] = 1 << i; 1645 } 1646 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1647 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1648 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1649 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1650 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1651 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1652 old = src; 1653 for (i = 0; i < data_type; i++) { 1654 nyu = newTemp( Ity_I64 ); 1655 assign( nyu, 1656 binop( Iop_Add64, 1657 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1658 binop( Iop_And64, 1659 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1660 mkexpr( mask[i] ) ) ) ); 1661 old = nyu; 1662 } 1663 return nyu; 1664 } 1665 1666 /* Special purpose population count function for 1667 * vpopcntd in 32-bit mode. 1668 */ 1669 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1670 { 1671 Int i, shift[6]; 1672 IRTemp mask[6]; 1673 IRTemp old = IRTemp_INVALID; 1674 IRTemp nyu1 = IRTemp_INVALID; 1675 IRTemp nyu2 = IRTemp_INVALID; 1676 IRTemp retval = newTemp(Ity_I64); 1677 1678 vassert(!mode64); 1679 1680 for (i = 0; i < WORD; i++) { 1681 mask[i] = newTemp(Ity_I32); 1682 shift[i] = 1 << i; 1683 } 1684 assign(mask[0], mkU32(0x55555555)); 1685 assign(mask[1], mkU32(0x33333333)); 1686 assign(mask[2], mkU32(0x0F0F0F0F)); 1687 assign(mask[3], mkU32(0x00FF00FF)); 1688 assign(mask[4], mkU32(0x0000FFFF)); 1689 old = src1; 1690 for (i = 0; i < WORD; i++) { 1691 nyu1 = newTemp(Ity_I32); 1692 assign(nyu1, 1693 binop(Iop_Add32, 1694 binop(Iop_And32, 1695 mkexpr(old), 1696 mkexpr(mask[i])), 1697 binop(Iop_And32, 1698 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1699 mkexpr(mask[i])))); 1700 old = nyu1; 1701 } 1702 1703 old = src2; 1704 for (i = 0; i < WORD; i++) { 1705 nyu2 = newTemp(Ity_I32); 1706 assign(nyu2, 1707 binop(Iop_Add32, 1708 binop(Iop_And32, 1709 mkexpr(old), 1710 mkexpr(mask[i])), 1711 binop(Iop_And32, 1712 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1713 mkexpr(mask[i])))); 1714 old = nyu2; 1715 } 1716 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1717 return retval; 1718 } 1719 1720 1721 // ROTL(src32/64, rot_amt5/6) 1722 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1723 IRExpr* rot_amt ) 1724 { 1725 IRExpr *mask, *rot; 1726 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1727 1728 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1729 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1730 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1731 rot = binop(Iop_Or64, 1732 binop(Iop_Shl64, src, mask), 1733 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1734 } else { 1735 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1736 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1737 rot = binop(Iop_Or32, 1738 binop(Iop_Shl32, src, mask), 1739 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1740 } 1741 /* Note: the ITE not merely an optimisation; it's needed 1742 because otherwise the Shr is a shift by the word size when 1743 mask denotes zero. For rotates by immediates, a lot of 1744 this junk gets folded out. */ 1745 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1746 /* non-zero rotate */ rot, 1747 /* zero rotate */ src); 1748 } 1749 1750 /* Standard effective address calc: (rA + rB) */ 1751 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1752 { 1753 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1754 vassert(rA < 32); 1755 vassert(rB < 32); 1756 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1757 } 1758 1759 /* Standard effective address calc: (rA + simm) */ 1760 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1761 { 1762 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1763 vassert(rA < 32); 1764 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1765 mkSzExtendS16(ty, simm16)); 1766 } 1767 1768 /* Standard effective address calc: (rA|0) */ 1769 static IRExpr* ea_rAor0 ( UInt rA ) 1770 { 1771 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1772 vassert(rA < 32); 1773 if (rA == 0) { 1774 return mkSzImm(ty, 0); 1775 } else { 1776 return getIReg(rA); 1777 } 1778 } 1779 1780 /* Standard effective address calc: (rA|0) + rB */ 1781 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1782 { 1783 vassert(rA < 32); 1784 vassert(rB < 32); 1785 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1786 } 1787 1788 /* Standard effective address calc: (rA|0) + simm16 */ 1789 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1790 { 1791 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1792 vassert(rA < 32); 1793 if (rA == 0) { 1794 return mkSzExtendS16(ty, simm16); 1795 } else { 1796 return ea_rA_simm( rA, simm16 ); 1797 } 1798 } 1799 1800 1801 /* Align effective address */ 1802 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1803 { 1804 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1805 ULong mask; 1806 switch (align) { 1807 case 1: return addr; // byte aligned 1808 case 2: mask = ~0ULL << 1; break; // half-word aligned 1809 case 4: mask = ~0ULL << 2; break; // word aligned 1810 case 16: mask = ~0ULL << 4; break; // quad-word aligned 1811 default: 1812 vex_printf("addr_align: align = %u\n", align); 1813 vpanic("addr_align(ppc)"); 1814 } 1815 1816 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1817 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1818 } 1819 1820 1821 /* Exit the trace if ADDR (intended to be a guest memory address) is 1822 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1823 restart of the current insn. */ 1824 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1825 { 1826 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1827 if (mode64) { 1828 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1829 stmt( 1830 IRStmt_Exit( 1831 binop(Iop_CmpNE64, 1832 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1833 mkU64(0)), 1834 Ijk_SigBUS, 1835 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1836 ) 1837 ); 1838 } else { 1839 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1840 stmt( 1841 IRStmt_Exit( 1842 binop(Iop_CmpNE32, 1843 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1844 mkU32(0)), 1845 Ijk_SigBUS, 1846 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1847 ) 1848 ); 1849 } 1850 } 1851 1852 1853 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1854 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1855 N) becomes undefined. That is at function calls and returns. ELF 1856 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1857 the address of the next instruction to be executed. 1858 */ 1859 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1860 IRTemp nia, const HChar* who ) 1861 { 1862 Int szB = vbi->guest_stack_redzone_size; 1863 if (0) vex_printf("AbiHint: %s\n", who); 1864 vassert(szB >= 0); 1865 if (szB > 0) { 1866 if (mode64) { 1867 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1868 stmt( IRStmt_AbiHint( 1869 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1870 szB, 1871 mkexpr(nia) 1872 )); 1873 } else { 1874 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1875 stmt( IRStmt_AbiHint( 1876 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1877 szB, 1878 mkexpr(nia) 1879 )); 1880 } 1881 } 1882 } 1883 1884 1885 /*------------------------------------------------------------*/ 1886 /*--- Helpers for condition codes. ---*/ 1887 /*------------------------------------------------------------*/ 1888 1889 /* Condition register layout. 1890 1891 In the hardware, CR is laid out like this. The leftmost end is the 1892 most significant bit in the register; however the IBM documentation 1893 numbers the bits backwards for some reason. 1894 1895 CR0 CR1 .......... CR6 CR7 1896 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1897 31 28 3 0 (normal bit numbering) 1898 1899 Each CR field is 4 bits: [<,>,==,SO] 1900 1901 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1902 1903 Indexing from BI to guest state: 1904 1905 let n = BI / 4 1906 off = BI % 4 1907 this references CR n: 1908 1909 off==0 -> guest_CRn_321 >> 3 1910 off==1 -> guest_CRn_321 >> 2 1911 off==2 -> guest_CRn_321 >> 1 1912 off==3 -> guest_CRn_SO 1913 1914 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1915 (normal notation) and in guest_CRn_321 the significant bits are 1916 3, 2 and 1 (normal notation). 1917 */ 1918 1919 static void putCR321 ( UInt cr, IRExpr* e ) 1920 { 1921 vassert(cr < 8); 1922 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1923 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1924 } 1925 1926 static void putCR0 ( UInt cr, IRExpr* e ) 1927 { 1928 vassert(cr < 8); 1929 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1930 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1931 } 1932 1933 static void putC ( IRExpr* e ) 1934 { 1935 /* The assumption is that the value of the Floating-Point Result 1936 * Class Descriptor bit (C) is passed in the lower four bits of a 1937 * 32 bit value. 1938 * 1939 * Note, the C and FPCC bits which are fields in the FPSCR 1940 * register are stored in their own memory location of 1941 * memory. The FPCC bits are in the lower 4 bits. The C bit needs 1942 * to be shifted to bit 4 in the memory location that holds C and FPCC. 1943 * Note not all of the FPSCR register bits are supported. We are 1944 * only writing C bit. 1945 */ 1946 IRExpr* tmp; 1947 1948 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32); 1949 1950 /* Get the FPCC bit field */ 1951 tmp = binop( Iop_And32, 1952 mkU32( 0xF ), 1953 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) ); 1954 1955 stmt( IRStmt_Put( OFFB_C_FPCC, 1956 unop( Iop_32to8, 1957 binop( Iop_Or32, tmp, 1958 binop( Iop_Shl32, 1959 binop( Iop_And32, mkU32( 0x1 ), e ), 1960 mkU8( 4 ) ) ) ) ) ); 1961 } 1962 1963 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1964 { 1965 vassert(cr < 8); 1966 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1967 } 1968 1969 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1970 { 1971 vassert(cr < 8); 1972 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1973 } 1974 1975 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1976 return it at the bottom of an I32; the top 31 bits are guaranteed 1977 to be zero. */ 1978 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1979 { 1980 UInt n = bi / 4; 1981 UInt off = bi % 4; 1982 vassert(bi < 32); 1983 if (off == 3) { 1984 /* Fetch the SO bit for this CR field */ 1985 /* Note: And32 is redundant paranoia iff guest state only has 0 1986 or 1 in that slot. */ 1987 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1988 } else { 1989 /* Fetch the <, > or == bit for this CR field */ 1990 return binop( Iop_And32, 1991 binop( Iop_Shr32, 1992 unop(Iop_8Uto32, getCR321(n)), 1993 mkU8(toUChar(3-off)) ), 1994 mkU32(1) ); 1995 } 1996 } 1997 1998 /* Dually, write the least significant bit of BIT to the specified CR 1999 bit. Indexing as per getCRbit. */ 2000 static void putCRbit ( UInt bi, IRExpr* bit ) 2001 { 2002 UInt n, off; 2003 IRExpr* safe; 2004 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 2005 safe = binop(Iop_And32, bit, mkU32(1)); 2006 n = bi / 4; 2007 off = bi % 4; 2008 vassert(bi < 32); 2009 if (off == 3) { 2010 /* This is the SO bit for this CR field */ 2011 putCR0(n, unop(Iop_32to8, safe)); 2012 } else { 2013 off = 3 - off; 2014 vassert(off == 1 || off == 2 || off == 3); 2015 putCR321( 2016 n, 2017 unop( Iop_32to8, 2018 binop( Iop_Or32, 2019 /* old value with field masked out */ 2020 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 2021 mkU32(~(1 << off))), 2022 /* new value in the right place */ 2023 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 2024 ) 2025 ) 2026 ); 2027 } 2028 } 2029 2030 /* Fetch the specified CR bit (as per IBM/hardware notation) and 2031 return it somewhere in an I32; it does not matter where, but 2032 whichever bit it is, all other bits are guaranteed to be zero. In 2033 other words, the I32-typed expression will be zero if the bit is 2034 zero and nonzero if the bit is 1. Write into *where the index 2035 of where the bit will be. */ 2036 2037 static 2038 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 2039 { 2040 UInt n = bi / 4; 2041 UInt off = bi % 4; 2042 vassert(bi < 32); 2043 if (off == 3) { 2044 /* Fetch the SO bit for this CR field */ 2045 /* Note: And32 is redundant paranoia iff guest state only has 0 2046 or 1 in that slot. */ 2047 *where = 0; 2048 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 2049 } else { 2050 /* Fetch the <, > or == bit for this CR field */ 2051 *where = 3-off; 2052 return binop( Iop_And32, 2053 unop(Iop_8Uto32, getCR321(n)), 2054 mkU32(1 << (3-off)) ); 2055 } 2056 } 2057 2058 /* Set the CR0 flags following an arithmetic operation. 2059 (Condition Register CR0 Field Definition, PPC32 p60) 2060 */ 2061 static IRExpr* getXER_SO ( void ); 2062 static void set_CR0 ( IRExpr* result ) 2063 { 2064 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 2065 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 2066 if (mode64) { 2067 putCR321( 0, unop(Iop_64to8, 2068 binop(Iop_CmpORD64S, result, mkU64(0))) ); 2069 } else { 2070 putCR321( 0, unop(Iop_32to8, 2071 binop(Iop_CmpORD32S, result, mkU32(0))) ); 2072 } 2073 putCR0( 0, getXER_SO() ); 2074 } 2075 2076 2077 /* Set the CR6 flags following an AltiVec compare operation. 2078 * NOTE: This also works for VSX single-precision compares. 2079 * */ 2080 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 2081 { 2082 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 2083 all_ones = (v[0] && v[1] && v[2] && v[3]) 2084 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 2085 */ 2086 IRTemp v0 = newTemp(Ity_V128); 2087 IRTemp v1 = newTemp(Ity_V128); 2088 IRTemp v2 = newTemp(Ity_V128); 2089 IRTemp v3 = newTemp(Ity_V128); 2090 IRTemp rOnes = newTemp(Ity_I8); 2091 IRTemp rZeros = newTemp(Ity_I8); 2092 2093 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 2094 2095 assign( v0, result ); 2096 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 2097 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 2098 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 2099 2100 assign( rZeros, unop(Iop_1Uto8, 2101 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2102 unop(Iop_Not32, 2103 unop(Iop_V128to32, 2104 binop(Iop_OrV128, 2105 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 2106 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 2107 ))) ); 2108 2109 if (test_all_ones) { 2110 assign( rOnes, unop(Iop_1Uto8, 2111 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2112 unop(Iop_V128to32, 2113 binop(Iop_AndV128, 2114 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 2115 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 2116 ))) ); 2117 putCR321( 6, binop(Iop_Or8, 2118 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 2119 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 2120 } else { 2121 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2122 } 2123 putCR0( 6, mkU8(0) ); 2124 } 2125 2126 2127 static IRExpr * create_DCM ( IRType size, IRTemp NaN, IRTemp inf, IRTemp zero, 2128 IRTemp dnorm, IRTemp pos) 2129 { 2130 /* This is a general function for creating the DCM for a 32-bit or 2131 64-bit expression based on the passes size. 2132 */ 2133 IRTemp neg; 2134 IROp opAND, opOR, opSHL, opXto1, op1UtoX; 2135 2136 vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) ); 2137 2138 if ( size == Ity_I32 ) { 2139 opSHL = Iop_Shl32; 2140 opAND = Iop_And32; 2141 opOR = Iop_Or32; 2142 opXto1 = Iop_32to1; 2143 op1UtoX = Iop_1Uto32; 2144 neg = newTemp( Ity_I32 ); 2145 2146 } else { 2147 opSHL = Iop_Shl64; 2148 opAND = Iop_And64; 2149 opOR = Iop_Or64; 2150 opXto1 = Iop_64to1; 2151 op1UtoX = Iop_1Uto64; 2152 neg = newTemp( Ity_I64 ); 2153 } 2154 2155 assign( neg, unop( op1UtoX, mkNOT1( unop( opXto1, 2156 mkexpr ( pos ) ) ) ) ); 2157 2158 return binop( opOR, 2159 binop( opSHL, mkexpr( NaN ), mkU8( 6 ) ), 2160 binop( opOR, 2161 binop( opOR, 2162 binop( opOR, 2163 binop( opSHL, 2164 binop( opAND, 2165 mkexpr( pos ), 2166 mkexpr( inf ) ), 2167 mkU8( 5 ) ), 2168 binop( opSHL, 2169 binop( opAND, 2170 mkexpr( neg ), 2171 mkexpr( inf ) ), 2172 mkU8( 4 ) ) ), 2173 binop( opOR, 2174 binop( opSHL, 2175 binop( opAND, 2176 mkexpr( pos ), 2177 mkexpr( zero ) ), 2178 mkU8( 3 ) ), 2179 binop( opSHL, 2180 binop( opAND, 2181 mkexpr( neg ), 2182 mkexpr( zero ) ), 2183 mkU8( 2 ) ) ) ), 2184 binop( opOR, 2185 binop( opSHL, 2186 binop( opAND, 2187 mkexpr( pos ), 2188 mkexpr( dnorm ) ), 2189 mkU8( 1 ) ), 2190 binop( opAND, 2191 mkexpr( neg ), 2192 mkexpr( dnorm ) ) ) ) ); 2193 } 2194 2195 /*------------------------------------------------------------*/ 2196 /*--- Helpers for XER flags. ---*/ 2197 /*------------------------------------------------------------*/ 2198 2199 static void putXER_SO ( IRExpr* e ) 2200 { 2201 IRExpr* so; 2202 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2203 so = binop(Iop_And8, e, mkU8(1)); 2204 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2205 } 2206 2207 static void putXER_OV ( IRExpr* e ) 2208 { 2209 /* Interface to write XER[OV] */ 2210 IRExpr* ov; 2211 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2212 ov = binop(Iop_And8, e, mkU8(1)); 2213 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2214 } 2215 2216 static void putXER_OV32 ( IRExpr* e ) 2217 { 2218 /*Interface to write XER[OV32] */ 2219 IRExpr* ov; 2220 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2221 ov = binop(Iop_And8, e, mkU8(1)); 2222 2223 /* The OV32 bit was added to XER in ISA 3.0. Do not write unless we 2224 * ISA 3.0 or beyond is supported. */ 2225 if( OV32_CA32_supported ) 2226 stmt( IRStmt_Put( OFFB_XER_OV32, ov ) ); 2227 } 2228 2229 static void putXER_CA ( IRExpr* e ) 2230 { 2231 /* Interface to write XER[CA] */ 2232 IRExpr* ca; 2233 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2234 ca = binop(Iop_And8, e, mkU8(1)); 2235 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2236 } 2237 2238 static void putXER_CA32 ( IRExpr* e ) 2239 { 2240 /* Interface to write XER[CA32] */ 2241 IRExpr* ca; 2242 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2243 ca = binop(Iop_And8, e, mkU8(1)); 2244 2245 /* The CA32 bit was added to XER in ISA 3.0. Do not write unless we 2246 * ISA 3.0 or beyond is supported. */ 2247 if( OV32_CA32_supported ) 2248 stmt( IRStmt_Put( OFFB_XER_CA32, ca ) ); 2249 } 2250 2251 static void putXER_BC ( IRExpr* e ) 2252 { 2253 IRExpr* bc; 2254 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2255 bc = binop(Iop_And8, e, mkU8(0x7F)); 2256 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2257 } 2258 2259 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2260 { 2261 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2262 } 2263 2264 static IRExpr* /* :: Ity_I32 */ getXER_SO_32 ( void ) 2265 { 2266 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2267 } 2268 2269 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2270 { 2271 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2272 } 2273 2274 static IRExpr* /* :: Ity_I8 */ getXER_OV32 ( void ) 2275 { 2276 return IRExpr_Get( OFFB_XER_OV32, Ity_I8 ); 2277 } 2278 2279 static IRExpr* /* :: Ity_I32 */ getXER_OV_32 ( void ) 2280 { 2281 /* get XER[OV], 32-bit interface */ 2282 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2283 } 2284 2285 static IRExpr* /* :: Ity_I32 */ getXER_OV32_32 ( void ) 2286 { 2287 /* get XER[OV32], 32-bit interface */ 2288 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV32()), mkU32(1) ); 2289 } 2290 2291 static IRExpr* /* :: Ity_I32 */ getXER_CA_32 ( void ) 2292 { 2293 /* get XER[CA], 32-bit interface */ 2294 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2295 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2296 } 2297 2298 static IRExpr* /* :: Ity_I32 */ getXER_CA32_32 ( void ) 2299 { 2300 /* get XER[CA32], 32-bit interface */ 2301 IRExpr* ca = IRExpr_Get( OFFB_XER_CA32, Ity_I8 ); 2302 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2303 } 2304 2305 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2306 { 2307 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2308 } 2309 2310 static IRExpr* /* :: Ity_I32 */ getXER_BC_32 ( void ) 2311 { 2312 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2313 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2314 } 2315 2316 2317 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2318 %XER.SO accordingly. */ 2319 2320 static IRExpr* calculate_XER_OV_32( UInt op, IRExpr* res, 2321 IRExpr* argL, IRExpr* argR ) 2322 { 2323 IRTemp t64; 2324 IRExpr* xer_ov; 2325 2326 # define INT32_MIN 0x80000000 2327 2328 # define XOR2(_aa,_bb) \ 2329 binop(Iop_Xor32,(_aa),(_bb)) 2330 2331 # define XOR3(_cc,_dd,_ee) \ 2332 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2333 2334 # define AND3(_ff,_gg,_hh) \ 2335 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2336 2337 #define NOT(_jj) \ 2338 unop(Iop_Not32, (_jj)) 2339 2340 switch (op) { 2341 case /* 0 */ PPCG_FLAG_OP_ADD: 2342 case /* 1 */ PPCG_FLAG_OP_ADDE: 2343 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2344 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2345 xer_ov 2346 = AND3( XOR3(argL,argR,mkU32(-1)), 2347 XOR2(argL,res), 2348 mkU32(INT32_MIN) ); 2349 /* xer_ov can only be 0 or 1<<31 */ 2350 xer_ov 2351 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2352 break; 2353 2354 case /* 2 */ PPCG_FLAG_OP_DIVW: 2355 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2356 xer_ov 2357 = mkOR1( 2358 mkAND1( 2359 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2360 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2361 ), 2362 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2363 ); 2364 xer_ov 2365 = unop(Iop_1Uto32, xer_ov); 2366 break; 2367 2368 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2369 /* argR == 0 */ 2370 xer_ov 2371 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2372 break; 2373 2374 case /* 4 */ PPCG_FLAG_OP_MULLW: 2375 /* OV true if result can't be represented in 32 bits 2376 i.e sHi != sign extension of sLo */ 2377 t64 = newTemp(Ity_I64); 2378 assign( t64, binop(Iop_MullS32, argL, argR) ); 2379 xer_ov 2380 = binop( Iop_CmpNE32, 2381 unop(Iop_64HIto32, mkexpr(t64)), 2382 binop( Iop_Sar32, 2383 unop(Iop_64to32, mkexpr(t64)), 2384 mkU8(31)) 2385 ); 2386 xer_ov 2387 = unop(Iop_1Uto32, xer_ov); 2388 break; 2389 2390 case /* 5 */ PPCG_FLAG_OP_NEG: 2391 /* argL == INT32_MIN */ 2392 xer_ov 2393 = unop( Iop_1Uto32, 2394 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2395 break; 2396 2397 case /* 6 */ PPCG_FLAG_OP_SUBF: 2398 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2399 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2400 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2401 xer_ov 2402 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2403 XOR2(NOT(argL),res), 2404 mkU32(INT32_MIN) ); 2405 /* xer_ov can only be 0 or 1<<31 */ 2406 xer_ov 2407 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2408 break; 2409 2410 case PPCG_FLAG_OP_DIVWEU: 2411 xer_ov 2412 = binop( Iop_Or32, 2413 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2414 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2415 break; 2416 2417 case PPCG_FLAG_OP_DIVWE: 2418 2419 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2420 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2421 * an overflow is implied. 2422 */ 2423 xer_ov = binop( Iop_Or32, 2424 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2425 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2426 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2427 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2428 break; 2429 2430 2431 2432 default: 2433 vex_printf("calculate_XER_OV_32: op = %u\n", op); 2434 vpanic("calculate_XER_OV_32(ppc)"); 2435 } 2436 2437 return xer_ov; 2438 2439 # undef INT32_MIN 2440 # undef AND3 2441 # undef XOR3 2442 # undef XOR2 2443 # undef NOT 2444 } 2445 2446 static void set_XER_OV_OV32_32( UInt op, IRExpr* res, 2447 IRExpr* argL, IRExpr* argR ) 2448 { 2449 IRExpr* xer_ov; 2450 2451 vassert(op < PPCG_FLAG_OP_NUMBER); 2452 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2453 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2454 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2455 2456 xer_ov = calculate_XER_OV_32( op, res, argL, argR ); 2457 2458 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2459 putXER_OV( unop(Iop_32to8, xer_ov) ); 2460 putXER_OV32( unop(Iop_32to8, xer_ov) ); 2461 } 2462 2463 static IRExpr* calculate_XER_OV_64( UInt op, IRExpr* res, 2464 IRExpr* argL, IRExpr* argR ) 2465 { 2466 IRExpr* xer_ov; 2467 2468 # define INT64_MIN 0x8000000000000000ULL 2469 2470 # define XOR2(_aa,_bb) \ 2471 binop(Iop_Xor64,(_aa),(_bb)) 2472 2473 # define XOR3(_cc,_dd,_ee) \ 2474 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2475 2476 # define AND3(_ff,_gg,_hh) \ 2477 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2478 2479 #define NOT(_jj) \ 2480 unop(Iop_Not64, (_jj)) 2481 2482 switch (op) { 2483 case /* 0 */ PPCG_FLAG_OP_ADD: 2484 case /* 1 */ PPCG_FLAG_OP_ADDE: 2485 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2486 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2487 xer_ov 2488 = AND3( XOR3(argL,argR,mkU64(-1)), 2489 XOR2(argL,res), 2490 mkU64(INT64_MIN) ); 2491 /* xer_ov can only be 0 or 1<<63 */ 2492 xer_ov 2493 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2494 break; 2495 2496 case /* 2 */ PPCG_FLAG_OP_DIVW: 2497 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2498 xer_ov 2499 = mkOR1( 2500 mkAND1( 2501 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2502 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2503 ), 2504 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2505 ); 2506 break; 2507 2508 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2509 /* argR == 0 */ 2510 xer_ov 2511 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2512 break; 2513 2514 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2515 /* OV true if result can't be represented in 64 bits 2516 i.e sHi != sign extension of sLo */ 2517 xer_ov 2518 = binop( Iop_CmpNE32, 2519 unop(Iop_64HIto32, res), 2520 binop( Iop_Sar32, 2521 unop(Iop_64to32, res), 2522 mkU8(31)) 2523 ); 2524 break; 2525 } 2526 2527 case /* 5 */ PPCG_FLAG_OP_NEG: 2528 /* argL == INT64_MIN */ 2529 xer_ov 2530 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2531 break; 2532 2533 case /* 6 */ PPCG_FLAG_OP_SUBF: 2534 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2535 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2536 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2537 xer_ov 2538 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2539 XOR2(NOT(argL),res), 2540 mkU64(INT64_MIN) ); 2541 /* xer_ov can only be 0 or 1<<63 */ 2542 xer_ov 2543 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2544 break; 2545 2546 case /* 14 */ PPCG_FLAG_OP_DIVDE: 2547 2548 /* If argR == 0, we must set the OV bit. But there's another condition 2549 * where we can get overflow set for divde . . . when the 2550 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2551 * both dividend and divisor are non-zero, it implies an overflow. 2552 */ 2553 xer_ov 2554 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2555 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2556 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2557 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2558 break; 2559 2560 case /* 17 */ PPCG_FLAG_OP_DIVDEU: 2561 /* If argR == 0 or if argL >= argR, set OV. */ 2562 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2563 binop( Iop_CmpLE64U, argR, argL ) ); 2564 break; 2565 2566 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2567 IRTemp t128; 2568 /* OV true if result can't be represented in 64 bits 2569 i.e sHi != sign extension of sLo */ 2570 t128 = newTemp(Ity_I128); 2571 assign( t128, binop(Iop_MullS64, argL, argR) ); 2572 xer_ov 2573 = binop( Iop_CmpNE64, 2574 unop(Iop_128HIto64, mkexpr(t128)), 2575 binop( Iop_Sar64, 2576 unop(Iop_128to64, mkexpr(t128)), 2577 mkU8(63)) 2578 ); 2579 break; 2580 } 2581 2582 default: 2583 vex_printf("calculate_XER_OV_64: op = %u\n", op); 2584 vpanic("calculate_XER_OV_64(ppc64)"); 2585 } 2586 2587 return xer_ov; 2588 2589 # undef INT64_MIN 2590 # undef AND3 2591 # undef XOR3 2592 # undef XOR2 2593 # undef NOT 2594 } 2595 2596 static void set_XER_OV_64( UInt op, IRExpr* res, 2597 IRExpr* argL, IRExpr* argR ) 2598 { 2599 IRExpr* xer_ov; 2600 vassert(op < PPCG_FLAG_OP_NUMBER); 2601 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2602 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2603 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2604 2605 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2606 xer_ov = calculate_XER_OV_64( op, res, argL, argR); 2607 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2608 2609 /* Update the summary overflow */ 2610 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2611 } 2612 2613 static void update_SO( void ) { 2614 /* Update the summary overflow bit */ 2615 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2616 } 2617 2618 static void copy_OV_to_OV32( void ) { 2619 /* Update the OV32 to match OV */ 2620 putXER_OV32( getXER_OV() ); 2621 } 2622 2623 static void set_XER_OV_OV32 ( IRType ty, UInt op, IRExpr* res, 2624 IRExpr* argL, IRExpr* argR ) 2625 { 2626 if (ty == Ity_I32) { 2627 set_XER_OV_OV32_32( op, res, argL, argR ); 2628 } else { 2629 IRExpr* xer_ov_32; 2630 set_XER_OV_64( op, res, argL, argR ); 2631 xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res), 2632 unop(Iop_64to32, argL), 2633 unop(Iop_64to32, argR)); 2634 putXER_OV32( unop(Iop_32to8, xer_ov_32) ); 2635 } 2636 } 2637 2638 static void set_XER_OV_OV32_SO ( IRType ty, UInt op, IRExpr* res, 2639 IRExpr* argL, IRExpr* argR ) 2640 { 2641 if (ty == Ity_I32) { 2642 set_XER_OV_OV32_32( op, res, argL, argR ); 2643 } else { 2644 IRExpr* xer_ov_32; 2645 set_XER_OV_64( op, res, argL, argR ); 2646 xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res), 2647 unop(Iop_64to32, argL), 2648 unop(Iop_64to32, argR)); 2649 putXER_OV32( unop(Iop_32to8, xer_ov_32) ); 2650 } 2651 update_SO(); 2652 } 2653 2654 2655 2656 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2657 value being OLDCA. Set %XER.CA accordingly. */ 2658 2659 static IRExpr* calculate_XER_CA_32 ( UInt op, IRExpr* res, 2660 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2661 { 2662 IRExpr* xer_ca; 2663 2664 switch (op) { 2665 case /* 0 */ PPCG_FLAG_OP_ADD: 2666 /* res <u argL */ 2667 xer_ca 2668 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2669 break; 2670 2671 case /* 1 */ PPCG_FLAG_OP_ADDE: 2672 /* res <u argL || (old_ca==1 && res==argL) */ 2673 xer_ca 2674 = mkOR1( 2675 binop(Iop_CmpLT32U, res, argL), 2676 mkAND1( 2677 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2678 binop(Iop_CmpEQ32, res, argL) 2679 ) 2680 ); 2681 xer_ca 2682 = unop(Iop_1Uto32, xer_ca); 2683 break; 2684 2685 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2686 /* res <u argR || (old_ca==1 && res==argR) */ 2687 xer_ca 2688 = mkOR1( 2689 binop(Iop_CmpLT32U, res, argR), 2690 mkAND1( 2691 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2692 binop(Iop_CmpEQ32, res, argR) 2693 ) 2694 ); 2695 xer_ca 2696 = unop(Iop_1Uto32, xer_ca); 2697 break; 2698 2699 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2700 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2701 /* res <=u argR */ 2702 xer_ca 2703 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2704 break; 2705 2706 case /* 10 */ PPCG_FLAG_OP_SRAW: 2707 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2708 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2709 bit of argL. */ 2710 /* This term valid for shift amount < 32 only */ 2711 xer_ca 2712 = binop( 2713 Iop_And32, 2714 binop(Iop_Sar32, argL, mkU8(31)), 2715 binop( Iop_And32, 2716 argL, 2717 binop( Iop_Sub32, 2718 binop(Iop_Shl32, mkU32(1), 2719 unop(Iop_32to8,argR)), 2720 mkU32(1) ) 2721 ) 2722 ); 2723 xer_ca 2724 = IRExpr_ITE( 2725 /* shift amt > 31 ? */ 2726 binop(Iop_CmpLT32U, mkU32(31), argR), 2727 /* yes -- get sign bit of argL */ 2728 binop(Iop_Shr32, argL, mkU8(31)), 2729 /* no -- be like srawi */ 2730 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2731 ); 2732 break; 2733 2734 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2735 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2736 0. Since the shift amount is known to be in the range 2737 0 .. 31 inclusive the following seems viable: 2738 xer.ca == 1 iff the following is nonzero: 2739 (argL >>s 31) -- either all 0s or all 1s 2740 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2741 xer_ca 2742 = binop( 2743 Iop_And32, 2744 binop(Iop_Sar32, argL, mkU8(31)), 2745 binop( Iop_And32, 2746 argL, 2747 binop( Iop_Sub32, 2748 binop(Iop_Shl32, mkU32(1), 2749 unop(Iop_32to8,argR)), 2750 mkU32(1) ) 2751 ) 2752 ); 2753 xer_ca 2754 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2755 break; 2756 2757 default: 2758 vex_printf("set_XER_CA: op = %u\n", op); 2759 vpanic("set_XER_CA(ppc)"); 2760 } 2761 2762 return xer_ca; 2763 } 2764 2765 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2766 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2767 { 2768 IRExpr* xer_ca; 2769 vassert(op < PPCG_FLAG_OP_NUMBER); 2770 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2771 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2772 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2773 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2774 2775 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2776 seems reasonable given that it's always generated by 2777 getXER_CA_32(), which masks it accordingly. In any case it being 2778 0 or 1 is an invariant of the ppc guest state representation; 2779 if it has any other value, that invariant has been violated. */ 2780 2781 xer_ca = calculate_XER_CA_32( op, res, argL, argR, oldca); 2782 2783 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2784 putXER_CA( unop(Iop_32to8, xer_ca) ); 2785 } 2786 2787 static IRExpr* calculate_XER_CA_64 ( UInt op, IRExpr* res, 2788 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2789 { 2790 IRExpr* xer_ca; 2791 2792 switch (op) { 2793 case /* 0 */ PPCG_FLAG_OP_ADD: 2794 /* res <u argL */ 2795 xer_ca 2796 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2797 break; 2798 2799 case /* 1 */ PPCG_FLAG_OP_ADDE: 2800 /* res <u argL || (old_ca==1 && res==argL) */ 2801 xer_ca 2802 = mkOR1( 2803 binop(Iop_CmpLT64U, res, argL), 2804 mkAND1( 2805 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2806 binop(Iop_CmpEQ64, res, argL) 2807 ) 2808 ); 2809 xer_ca 2810 = unop(Iop_1Uto32, xer_ca); 2811 break; 2812 2813 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2814 /* res <u argR || (old_ca==1 && res==argR) */ 2815 xer_ca 2816 = mkOR1( 2817 binop(Iop_CmpLT64U, res, argR), 2818 mkAND1( 2819 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2820 binop(Iop_CmpEQ64, res, argR) 2821 ) 2822 ); 2823 xer_ca 2824 = unop(Iop_1Uto32, xer_ca); 2825 break; 2826 2827 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2828 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2829 /* res <=u argR */ 2830 xer_ca 2831 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2832 break; 2833 2834 2835 case /* 10 */ PPCG_FLAG_OP_SRAW: 2836 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2837 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2838 bit of argL. */ 2839 /* This term valid for shift amount < 31 only */ 2840 2841 xer_ca 2842 = binop( 2843 Iop_And64, 2844 binop(Iop_Sar64, argL, mkU8(31)), 2845 binop( Iop_And64, 2846 argL, 2847 binop( Iop_Sub64, 2848 binop(Iop_Shl64, mkU64(1), 2849 unop(Iop_64to8,argR)), 2850 mkU64(1) ) 2851 ) 2852 ); 2853 xer_ca 2854 = IRExpr_ITE( 2855 /* shift amt > 31 ? */ 2856 binop(Iop_CmpLT64U, mkU64(31), argR), 2857 /* yes -- get sign bit of argL */ 2858 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2859 /* no -- be like srawi */ 2860 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2861 ); 2862 break; 2863 2864 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2865 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2866 Since the shift amount is known to be in the range 0 .. 31 2867 inclusive the following seems viable: 2868 xer.ca == 1 iff the following is nonzero: 2869 (argL >>s 31) -- either all 0s or all 1s 2870 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2871 2872 xer_ca 2873 = binop( 2874 Iop_And64, 2875 binop(Iop_Sar64, argL, mkU8(31)), 2876 binop( Iop_And64, 2877 argL, 2878 binop( Iop_Sub64, 2879 binop(Iop_Shl64, mkU64(1), 2880 unop(Iop_64to8,argR)), 2881 mkU64(1) ) 2882 ) 2883 ); 2884 xer_ca 2885 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2886 break; 2887 2888 2889 case /* 12 */ PPCG_FLAG_OP_SRAD: 2890 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2891 If it is <= 63, behave like SRADI; else XER.CA is the sign 2892 bit of argL. */ 2893 /* This term valid for shift amount < 63 only */ 2894 2895 xer_ca 2896 = binop( 2897 Iop_And64, 2898 binop(Iop_Sar64, argL, mkU8(63)), 2899 binop( Iop_And64, 2900 argL, 2901 binop( Iop_Sub64, 2902 binop(Iop_Shl64, mkU64(1), 2903 unop(Iop_64to8,argR)), 2904 mkU64(1) ) 2905 ) 2906 ); 2907 xer_ca 2908 = IRExpr_ITE( 2909 /* shift amt > 63 ? */ 2910 binop(Iop_CmpLT64U, mkU64(63), argR), 2911 /* yes -- get sign bit of argL */ 2912 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2913 /* no -- be like sradi */ 2914 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2915 ); 2916 break; 2917 2918 2919 case /* 13 */ PPCG_FLAG_OP_SRADI: 2920 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2921 Since the shift amount is known to be in the range 0 .. 63 2922 inclusive, the following seems viable: 2923 xer.ca == 1 iff the following is nonzero: 2924 (argL >>s 63) -- either all 0s or all 1s 2925 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2926 2927 xer_ca 2928 = binop( 2929 Iop_And64, 2930 binop(Iop_Sar64, argL, mkU8(63)), 2931 binop( Iop_And64, 2932 argL, 2933 binop( Iop_Sub64, 2934 binop(Iop_Shl64, mkU64(1), 2935 unop(Iop_64to8,argR)), 2936 mkU64(1) ) 2937 ) 2938 ); 2939 xer_ca 2940 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2941 break; 2942 2943 default: 2944 vex_printf("set_XER_CA: op = %u\n", op); 2945 vpanic("set_XER_CA(ppc64)"); 2946 } 2947 2948 return xer_ca; 2949 } 2950 2951 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2952 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2953 { 2954 IRExpr* xer_ca; 2955 vassert(op < PPCG_FLAG_OP_NUMBER); 2956 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2957 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2958 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2959 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2960 2961 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2962 seems reasonable given that it's always generated by 2963 getXER_CA_32(), which masks it accordingly. In any case it being 2964 0 or 1 is an invariant of the ppc guest state representation; 2965 if it has any other value, that invariant has been violated. */ 2966 2967 xer_ca = calculate_XER_CA_64( op, res, argL, argR, oldca ); 2968 2969 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2970 putXER_CA( unop(Iop_32to8, xer_ca) ); 2971 } 2972 2973 static void set_XER_CA_CA32 ( IRType ty, UInt op, IRExpr* res, 2974 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2975 { 2976 if (ty == Ity_I32) { 2977 set_XER_CA_32( op, res, argL, argR, oldca ); 2978 } else { 2979 set_XER_CA_64( op, res, argL, argR, oldca ); 2980 } 2981 } 2982 2983 2984 2985 /*------------------------------------------------------------*/ 2986 /*--- Read/write to guest-state --- */ 2987 /*------------------------------------------------------------*/ 2988 2989 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2990 { 2991 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2992 switch (reg) { 2993 case PPC_GST_SPRG3_RO: 2994 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2995 2996 case PPC_GST_CIA: 2997 return IRExpr_Get( OFFB_CIA, ty ); 2998 2999 case PPC_GST_LR: 3000 return IRExpr_Get( OFFB_LR, ty ); 3001 3002 case PPC_GST_CTR: 3003 return IRExpr_Get( OFFB_CTR, ty ); 3004 3005 case PPC_GST_VRSAVE: 3006 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 3007 3008 case PPC_GST_VSCR: 3009 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 3010 mkU32(MASK_VSCR_VALID)); 3011 3012 case PPC_GST_CR: { 3013 /* Synthesise the entire CR into a single word. Expensive. */ 3014 # define FIELD(_n) \ 3015 binop(Iop_Shl32, \ 3016 unop(Iop_8Uto32, \ 3017 binop(Iop_Or8, \ 3018 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 3019 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 3020 ) \ 3021 ), \ 3022 mkU8(4 * (7-(_n))) \ 3023 ) 3024 return binop(Iop_Or32, 3025 binop(Iop_Or32, 3026 binop(Iop_Or32, FIELD(0), FIELD(1)), 3027 binop(Iop_Or32, FIELD(2), FIELD(3)) 3028 ), 3029 binop(Iop_Or32, 3030 binop(Iop_Or32, FIELD(4), FIELD(5)), 3031 binop(Iop_Or32, FIELD(6), FIELD(7)) 3032 ) 3033 ); 3034 # undef FIELD 3035 } 3036 3037 case PPC_GST_XER: 3038 return binop(Iop_Or32, 3039 binop(Iop_Or32, 3040 binop(Iop_Or32, 3041 binop( Iop_Shl32, getXER_SO_32(), mkU8(31)), 3042 binop( Iop_Shl32, getXER_OV_32(), mkU8(30))), 3043 binop(Iop_Or32, 3044 binop( Iop_Shl32, getXER_CA_32(), mkU8(29)), 3045 getXER_BC_32())), 3046 binop(Iop_Or32, 3047 binop( Iop_Shl32, getXER_OV32_32(), mkU8(19)), 3048 binop( Iop_Shl32, getXER_CA32_32(), mkU8(18)))); 3049 3050 case PPC_GST_TFHAR: 3051 return IRExpr_Get( OFFB_TFHAR, ty ); 3052 3053 case PPC_GST_TEXASR: 3054 return IRExpr_Get( OFFB_TEXASR, ty ); 3055 3056 case PPC_GST_TEXASRU: 3057 return IRExpr_Get( OFFB_TEXASRU, ty ); 3058 3059 case PPC_GST_TFIAR: 3060 return IRExpr_Get( OFFB_TFIAR, ty ); 3061 3062 case PPC_GST_PPR: 3063 return IRExpr_Get( OFFB_PPR, ty ); 3064 3065 case PPC_GST_PPR32: 3066 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) ); 3067 3068 case PPC_GST_PSPB: 3069 return IRExpr_Get( OFFB_PSPB, ty ); 3070 3071 default: 3072 vex_printf("getGST(ppc): reg = %u", reg); 3073 vpanic("getGST(ppc)"); 3074 } 3075 } 3076 3077 /* Get a masked word from the given reg */ 3078 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, ULong mask ) 3079 { 3080 IRTemp val = newTemp(Ity_I32); 3081 vassert( reg < PPC_GST_MAX ); 3082 3083 switch (reg) { 3084 3085 case PPC_GST_FPSCR: { 3086 /* Vex-generated code expects the FPSCR to be set as follows: 3087 all exceptions masked, round-to-nearest. 3088 This corresponds to a FPSCR value of 0x0. */ 3089 3090 /* In the lower 32 bits of FPSCR, we're keeping track of the binary 3091 * floating point rounding mode and Floating-point Condition code, so 3092 * if the mask isn't asking for either of these, just return 0x0. 3093 */ 3094 if ( mask & ( MASK_FPSCR_C_FPCC | MASK_FPSCR_RN ) ) { 3095 assign( val, binop( Iop_Or32, 3096 unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ), 3097 binop( Iop_Shl32, 3098 unop( Iop_8Uto32, 3099 IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3100 mkU8( 12 ) ) ) ); 3101 } else { 3102 assign( val, mkU32(0x0) ); 3103 } 3104 3105 break; 3106 } 3107 3108 default: 3109 vex_printf("getGST_masked(ppc): reg = %u", reg); 3110 vpanic("getGST_masked(ppc)"); 3111 } 3112 3113 if ( mask != 0xFFFFFFFF ) { 3114 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 3115 } else { 3116 return mkexpr(val); 3117 } 3118 } 3119 3120 /* Get a masked word from the given reg */ 3121 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 3122 IRExpr * val; 3123 vassert( reg < PPC_GST_MAX ); 3124 3125 switch (reg) { 3126 3127 case PPC_GST_FPSCR: { 3128 /* In the upper 32 bits of FPSCR, we're only keeping track 3129 * of the decimal floating point rounding mode, so if the mask 3130 * isn't asking for this, just return 0x0. 3131 */ 3132 if (mask & MASK_FPSCR_DRN) { 3133 val = binop( Iop_And32, 3134 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 3135 unop( Iop_64HIto32, mkU64( mask ) ) ); 3136 } else { 3137 val = mkU32( 0x0ULL ); 3138 } 3139 break; 3140 } 3141 3142 default: 3143 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 3144 vpanic( "getGST_masked_upper(ppc)" ); 3145 } 3146 return val; 3147 } 3148 3149 3150 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 3151 and return it at the bottom of an I32; the top 27 bits are 3152 guaranteed to be zero. */ 3153 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 3154 { 3155 UInt shft, mask; 3156 3157 vassert( fld < 8 ); 3158 vassert( reg < PPC_GST_MAX ); 3159 3160 shft = 4*(7-fld); 3161 mask = 0xF<<shft; 3162 3163 switch (reg) { 3164 case PPC_GST_XER: 3165 vassert(fld ==7); 3166 return binop(Iop_Or32, 3167 binop(Iop_Or32, 3168 binop(Iop_Shl32, getXER_SO_32(), mkU8(3)), 3169 binop(Iop_Shl32, getXER_OV_32(), mkU8(2))), 3170 binop( Iop_Shl32, getXER_CA_32(), mkU8(1))); 3171 break; 3172 3173 default: 3174 if (shft == 0) 3175 return getGST_masked( reg, mask ); 3176 else 3177 return binop(Iop_Shr32, 3178 getGST_masked( reg, mask ), 3179 mkU8(toUChar( shft ))); 3180 } 3181 } 3182 3183 static void putGST ( PPC_GST reg, IRExpr* src ) 3184 { 3185 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3186 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 3187 vassert( reg < PPC_GST_MAX ); 3188 switch (reg) { 3189 case PPC_GST_IP_AT_SYSCALL: 3190 vassert( ty_src == ty ); 3191 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 3192 break; 3193 case PPC_GST_CIA: 3194 vassert( ty_src == ty ); 3195 stmt( IRStmt_Put( OFFB_CIA, src ) ); 3196 break; 3197 case PPC_GST_LR: 3198 vassert( ty_src == ty ); 3199 stmt( IRStmt_Put( OFFB_LR, src ) ); 3200 break; 3201 case PPC_GST_CTR: 3202 vassert( ty_src == ty ); 3203 stmt( IRStmt_Put( OFFB_CTR, src ) ); 3204 break; 3205 case PPC_GST_VRSAVE: 3206 vassert( ty_src == Ity_I32 ); 3207 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 3208 break; 3209 case PPC_GST_VSCR: 3210 vassert( ty_src == Ity_I32 ); 3211 stmt( IRStmt_Put( OFFB_VSCR, 3212 binop(Iop_And32, src, 3213 mkU32(MASK_VSCR_VALID)) ) ); 3214 break; 3215 case PPC_GST_XER: 3216 vassert( ty_src == Ity_I32 ); 3217 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 3218 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 3219 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 3220 putXER_OV32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(19))) ); 3221 putXER_CA32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(18))) ); 3222 putXER_BC( unop(Iop_32to8, src) ); 3223 break; 3224 3225 case PPC_GST_EMWARN: 3226 vassert( ty_src == Ity_I32 ); 3227 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 3228 break; 3229 3230 case PPC_GST_CMSTART: 3231 vassert( ty_src == ty ); 3232 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 3233 break; 3234 3235 case PPC_GST_CMLEN: 3236 vassert( ty_src == ty ); 3237 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 3238 break; 3239 3240 case PPC_GST_TEXASR: 3241 vassert( ty_src == Ity_I64 ); 3242 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 3243 break; 3244 3245 case PPC_GST_TEXASRU: 3246 vassert( ty_src == Ity_I32 ); 3247 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 3248 break; 3249 3250 case PPC_GST_TFIAR: 3251 vassert( ty_src == Ity_I64 ); 3252 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 3253 break; 3254 case PPC_GST_TFHAR: 3255 vassert( ty_src == Ity_I64 ); 3256 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 3257 break; 3258 3259 case PPC_GST_PPR32: 3260 case PPC_GST_PPR: 3261 { 3262 /* The Program Priority Register (PPR) stores the priority in 3263 * bits [52:50]. The user setable priorities are: 3264 * 3265 * 001 very low 3266 * 010 low 3267 * 011 medium low 3268 * 100 medium 3269 * 101 medium high 3270 * 3271 * If the argument is not between 0b001 and 0b100 the priority is set 3272 * to 0b100. The priority can only be set to 0b101 if the the Problem 3273 * State Boost Register is non-zero. The value of the PPR is not 3274 * changed if the input is not valid. 3275 */ 3276 3277 IRTemp not_valid = newTemp(Ity_I64); 3278 IRTemp has_perm = newTemp(Ity_I64); 3279 IRTemp new_src = newTemp(Ity_I64); 3280 IRTemp PSPB_val = newTemp(Ity_I64); 3281 IRTemp value = newTemp(Ity_I64); 3282 3283 vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 )); 3284 assign( PSPB_val, binop( Iop_32HLto64, 3285 mkU32( 0 ), 3286 IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) ); 3287 if( reg == PPC_GST_PPR32 ) { 3288 vassert( ty_src == Ity_I32 ); 3289 assign( value, binop( Iop_32HLto64, 3290 mkU32(0), 3291 binop( Iop_And32, 3292 binop( Iop_Shr32, src, mkU8( 18 ) ), 3293 mkU32( 0x7 ) ) ) ); 3294 } else { 3295 vassert( ty_src == Ity_I64 ); 3296 assign( value, binop( Iop_And64, 3297 binop( Iop_Shr64, src, mkU8( 50 ) ), 3298 mkU64( 0x7 ) ) ); 3299 } 3300 assign( has_perm, 3301 binop( Iop_And64, 3302 unop( Iop_1Sto64, 3303 binop( Iop_CmpEQ64, 3304 mkexpr( PSPB_val ), 3305 mkU64( 0 ) ) ), 3306 unop( Iop_1Sto64, 3307 binop( Iop_CmpEQ64, 3308 mkU64( 0x5 ), 3309 mkexpr( value ) ) ) ) ); 3310 assign( not_valid, 3311 binop( Iop_Or64, 3312 unop( Iop_1Sto64, 3313 binop( Iop_CmpEQ64, 3314 mkexpr( value ), 3315 mkU64( 0 ) ) ), 3316 unop( Iop_1Sto64, 3317 binop( Iop_CmpLT64U, 3318 mkU64( 0x5 ), 3319 mkexpr( value ) ) ) ) ); 3320 assign( new_src, 3321 binop( Iop_Or64, 3322 binop( Iop_And64, 3323 unop( Iop_Not64, 3324 mkexpr( not_valid ) ), 3325 src ), 3326 binop( Iop_And64, 3327 mkexpr( not_valid ), 3328 binop( Iop_Or64, 3329 binop( Iop_And64, 3330 mkexpr( has_perm), 3331 binop( Iop_Shl64, 3332 mkexpr( value ), 3333 mkU8( 50 ) ) ), 3334 binop( Iop_And64, 3335 IRExpr_Get( OFFB_PPR, ty ), 3336 unop( Iop_Not64, 3337 mkexpr( has_perm ) 3338 ) ) ) ) ) ); 3339 3340 /* make sure we only set the valid bit field [52:50] */ 3341 stmt( IRStmt_Put( OFFB_PPR, 3342 binop( Iop_And64, 3343 mkexpr( new_src ), 3344 mkU64( 0x1C000000000000) ) ) ); 3345 break; 3346 } 3347 default: 3348 vex_printf("putGST(ppc): reg = %u", reg); 3349 vpanic("putGST(ppc)"); 3350 } 3351 } 3352 3353 /* Write masked src to the given reg */ 3354 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 3355 { 3356 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3357 vassert( reg < PPC_GST_MAX ); 3358 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 3359 3360 switch (reg) { 3361 case PPC_GST_FPSCR: { 3362 /* Allow writes to either binary or decimal floating point 3363 Rounding Mode. 3364 */ 3365 /* If any part of |mask| covers FPSCR.RN, update the bits of 3366 FPSCR.RN by copying in |src| for locations where the 3367 corresponding bit in |mask| is 1, and leaving it unchanged 3368 for corresponding |mask| zero bits. */ 3369 if (mask & MASK_FPSCR_RN) { 3370 stmt( 3371 IRStmt_Put( 3372 OFFB_FPROUND, 3373 unop( 3374 Iop_32to8, 3375 binop( 3376 Iop_Or32, 3377 binop( 3378 Iop_And32, 3379 unop(Iop_64to32, src), 3380 mkU32(MASK_FPSCR_RN & mask) 3381 ), 3382 binop( 3383 Iop_And32, 3384 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 3385 mkU32(MASK_FPSCR_RN & ~mask) 3386 ) 3387 ) 3388 ) 3389 ) 3390 ); 3391 } 3392 3393 if (mask & MASK_FPSCR_C_FPCC) { 3394 /* FPCC bits are in [47:51] */ 3395 stmt( 3396 IRStmt_Put( 3397 OFFB_C_FPCC, 3398 unop( 3399 Iop_32to8, 3400 binop(Iop_Shr32, 3401 binop( 3402 Iop_Or32, 3403 binop( 3404 Iop_And32, 3405 unop(Iop_64to32, src), 3406 mkU32(MASK_FPSCR_C_FPCC & mask) ), 3407 binop( 3408 Iop_And32, 3409 unop(Iop_8Uto32, 3410 IRExpr_Get(OFFB_C_FPCC,Ity_I8)), 3411 mkU32(MASK_FPSCR_C_FPCC & ~mask) 3412 ) ), 3413 mkU8( 12 ) ) 3414 ) ) ); 3415 } 3416 3417 /* Similarly, update FPSCR.DRN if any bits of |mask| 3418 corresponding to FPSCR.DRN are set. */ 3419 if (mask & MASK_FPSCR_DRN) { 3420 stmt( 3421 IRStmt_Put( 3422 OFFB_DFPROUND, 3423 unop( 3424 Iop_32to8, 3425 binop( 3426 Iop_Or32, 3427 binop( 3428 Iop_And32, 3429 unop(Iop_64HIto32, src), 3430 mkU32((MASK_FPSCR_DRN & mask) >> 32) 3431 ), 3432 binop( 3433 Iop_And32, 3434 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 3435 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 3436 ) 3437 ) 3438 ) 3439 ) 3440 ); 3441 } 3442 3443 /* Give EmNote for attempted writes to: 3444 - Exception Controls 3445 - Non-IEEE Mode 3446 */ 3447 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3448 VexEmNote ew = EmWarn_PPCexns; 3449 3450 /* If any of the src::exception_control bits are actually set, 3451 side-exit to the next insn, reporting the warning, 3452 so that Valgrind's dispatcher sees the warning. */ 3453 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3454 stmt( 3455 IRStmt_Exit( 3456 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3457 Ijk_EmWarn, 3458 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3459 } 3460 3461 /* Ignore all other writes */ 3462 break; 3463 } 3464 3465 default: 3466 vex_printf("putGST_masked(ppc): reg = %u", reg); 3467 vpanic("putGST_masked(ppc)"); 3468 } 3469 } 3470 3471 /* Write the least significant nibble of src to the specified 3472 REG[FLD] (as per IBM/hardware notation). */ 3473 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3474 { 3475 UInt shft; 3476 ULong mask; 3477 3478 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3479 vassert( fld < 16 ); 3480 vassert( reg < PPC_GST_MAX ); 3481 3482 if (fld < 8) 3483 shft = 4*(7-fld); 3484 else 3485 shft = 4*(15-fld); 3486 mask = 0xF; 3487 mask = mask << shft; 3488 3489 switch (reg) { 3490 case PPC_GST_CR: 3491 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3492 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3493 break; 3494 3495 default: 3496 { 3497 IRExpr * src64 = unop( Iop_32Uto64, src ); 3498 3499 if (shft == 0) { 3500 putGST_masked( reg, src64, mask ); 3501 } else { 3502 putGST_masked( reg, 3503 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3504 mask ); 3505 } 3506 } 3507 } 3508 } 3509 3510 static void putFPCC ( IRExpr* e ) 3511 { 3512 /* The assumption is that the value of the FPCC are passed in the lower 3513 * four bits of a 32 bit value. 3514 * 3515 * Note, the C and FPCC bits which are a field of the FPSCR 3516 * register are stored in their own "register" in 3517 * memory. The FPCC bits are in the lower 4 bits. We don't need to 3518 * shift it to the bits to their location in the FPSCR register. Note, 3519 * not all of the FPSCR register bits are supported. We are writing all 3520 * of the bits in the FPCC field but not the C field. 3521 */ 3522 IRExpr* tmp; 3523 3524 vassert( typeOfIRExpr( irsb->tyenv, e ) == Ity_I32 ); 3525 /* Get the C bit field */ 3526 tmp = binop( Iop_And32, 3527 mkU32( 0x10 ), 3528 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) ); 3529 3530 stmt( IRStmt_Put( OFFB_C_FPCC, 3531 unop( Iop_32to8, 3532 binop( Iop_Or32, tmp, 3533 binop( Iop_And32, mkU32( 0xF ), e ) ) ) ) ); 3534 3535 } 3536 3537 static IRExpr* /* ::Ity_I32 */ getC ( void ) 3538 { 3539 /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of 3540 * the FPSCR registered are stored in its own "register" in guest state 3541 * with the FPCC bit field. C | FPCC 3542 */ 3543 IRTemp val = newTemp(Ity_I32); 3544 3545 assign( val, binop( Iop_Shr32, 3546 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3547 mkU8( 4 ) ) ); 3548 return mkexpr(val); 3549 } 3550 3551 static IRExpr* /* ::Ity_I32 */ getFPCC ( void ) 3552 { 3553 /* Note, the FPCC bits are a field of the FPSCR 3554 * register are stored in their own "register" in 3555 * guest state with the C bit field. C | FPCC 3556 */ 3557 IRTemp val = newTemp( Ity_I32 ); 3558 3559 assign( val, binop( Iop_And32, unop( Iop_8Uto32, 3560 IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ), 3561 mkU32( 0xF ) )); 3562 return mkexpr(val); 3563 } 3564 3565 /*------------------------------------------------------------*/ 3566 /* Helpers for VSX instructions that do floating point 3567 * operations and need to determine if a src contains a 3568 * special FP value. 3569 * 3570 *------------------------------------------------------------*/ 3571 3572 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3573 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3574 mkexpr( x ), \ 3575 mkU64( NONZERO_FRAC_MASK ) ) 3576 3577 #define NONZERO_FRAC_MASK32 0x007fffffULL 3578 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3579 mkexpr( x ), \ 3580 mkU32( NONZERO_FRAC_MASK32 ) ) 3581 3582 // Returns exponent part of floating point src as I32 3583 static IRExpr * fp_exp_part( IRType size, IRTemp src ) 3584 { 3585 IRExpr *shift_by, *mask, *tsrc; 3586 3587 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3588 || ( size == Ity_I64 ) ); 3589 3590 if( size == Ity_I16 ) { 3591 /* The 16-bit floating point value is in the lower 16-bits 3592 * of the 32-bit input value. 3593 */ 3594 tsrc = mkexpr( src ); 3595 mask = mkU32( 0x1F ); 3596 shift_by = mkU8( 10 ); 3597 3598 } else if( size == Ity_I32 ) { 3599 tsrc = mkexpr( src ); 3600 mask = mkU32( 0xFF ); 3601 shift_by = mkU8( 23 ); 3602 3603 } else if( size == Ity_I64 ) { 3604 tsrc = unop( Iop_64HIto32, mkexpr( src ) ); 3605 mask = mkU32( 0x7FF ); 3606 shift_by = mkU8( 52 - 32 ); 3607 3608 } else { 3609 /*NOTREACHED*/ 3610 vassert(0); // Stops gcc complaining at "-Og" 3611 } 3612 3613 return binop( Iop_And32, binop( Iop_Shr32, tsrc, shift_by ), mask ); 3614 } 3615 3616 /* The following functions check the floating point value to see if it 3617 is zero, infinity, NaN, Normalized, Denormalized. 3618 */ 3619 /* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */ 3620 #define I16_EXP_MASK 0x7C00 3621 #define I16_FRACTION_MASK 0x03FF 3622 #define I32_EXP_MASK 0x7F800000 3623 #define I32_FRACTION_MASK 0x007FFFFF 3624 #define I64_EXP_MASK 0x7FF0000000000000ULL 3625 #define I64_FRACTION_MASK 0x000FFFFFFFFFFFFFULL 3626 #define V128_EXP_MASK 0x7FFF000000000000ULL 3627 #define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL /* upper 64-bit fractional mask */ 3628 3629 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask, 3630 IRTemp *zero ); 3631 3632 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask, 3633 IRTemp *zero ) { 3634 3635 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3636 || ( size == Ity_I64 ) || ( size == Ity_V128 ) ); 3637 3638 if( size == Ity_I16 ) { 3639 /* The 16-bit floating point value is in the lower 16-bits of 3640 the 32-bit input value */ 3641 *frac_mask = newTemp( Ity_I32 ); 3642 *exp_mask = newTemp( Ity_I32 ); 3643 *zero = newTemp( Ity_I32 ); 3644 assign( *exp_mask, mkU32( I16_EXP_MASK ) ); 3645 assign( *frac_mask, mkU32( I16_FRACTION_MASK ) ); 3646 assign( *zero, mkU32( 0 ) ); 3647 3648 } else if( size == Ity_I32 ) { 3649 *frac_mask = newTemp( Ity_I32 ); 3650 *exp_mask = newTemp( Ity_I32 ); 3651 *zero = newTemp( Ity_I32 ); 3652 assign( *exp_mask, mkU32( I32_EXP_MASK ) ); 3653 assign( *frac_mask, mkU32( I32_FRACTION_MASK ) ); 3654 assign( *zero, mkU32( 0 ) ); 3655 3656 } else if( size == Ity_I64 ) { 3657 *frac_mask = newTemp( Ity_I64 ); 3658 *exp_mask = newTemp( Ity_I64 ); 3659 *zero = newTemp( Ity_I64 ); 3660 assign( *exp_mask, mkU64( I64_EXP_MASK ) ); 3661 assign( *frac_mask, mkU64( I64_FRACTION_MASK ) ); 3662 assign( *zero, mkU64( 0 ) ); 3663 3664 } else { 3665 /* V128 is converted to upper and lower 64 bit values, */ 3666 /* uses 64-bit operators and temps */ 3667 *frac_mask = newTemp( Ity_I64 ); 3668 *exp_mask = newTemp( Ity_I64 ); 3669 *zero = newTemp( Ity_I64 ); 3670 assign( *exp_mask, mkU64( V128_EXP_MASK ) ); 3671 /* upper 64-bit fractional mask */ 3672 assign( *frac_mask, mkU64( V128_FRACTION_MASK ) ); 3673 assign( *zero, mkU64( 0 ) ); 3674 } 3675 } 3676 3677 /* Helper function for the various function which check the value of 3678 the floating point value. 3679 */ 3680 static IRExpr * exponent_compare( IRType size, IRTemp src, 3681 IRTemp exp_mask, IRExpr *exp_val ) 3682 { 3683 IROp opAND, opCmpEQ; 3684 3685 if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3686 /* The 16-bit floating point value is in the lower 16-bits of 3687 the 32-bit input value */ 3688 opAND = Iop_And32; 3689 opCmpEQ = Iop_CmpEQ32; 3690 3691 } else { 3692 opAND = Iop_And64; 3693 opCmpEQ = Iop_CmpEQ64; 3694 } 3695 3696 if( size == Ity_V128 ) { 3697 return binop( opCmpEQ, 3698 binop ( opAND, 3699 unop( Iop_V128HIto64, mkexpr( src ) ), 3700 mkexpr( exp_mask ) ), 3701 exp_val ); 3702 3703 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3704 return binop( opCmpEQ, 3705 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ), 3706 exp_val ); 3707 } else { 3708 /* 64-bit operands */ 3709 3710 if (mode64) { 3711 return binop( opCmpEQ, 3712 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ), 3713 exp_val ); 3714 } else { 3715 /* No support for 64-bit compares in 32-bit mode, need to do upper 3716 * and lower parts using 32-bit compare operators. 3717 */ 3718 return 3719 mkAND1( binop( Iop_CmpEQ32, 3720 binop ( Iop_And32, 3721 unop(Iop_64HIto32, mkexpr( src ) ), 3722 unop(Iop_64HIto32, mkexpr( exp_mask ) ) ), 3723 unop(Iop_64HIto32, exp_val ) ), 3724 binop( Iop_CmpEQ32, 3725 binop ( Iop_And32, 3726 unop(Iop_64to32, mkexpr( src ) ), 3727 unop(Iop_64to32, mkexpr( exp_mask ) ) ), 3728 unop(Iop_64to32, exp_val ) ) ); 3729 } 3730 } 3731 } 3732 3733 static IRExpr *fractional_part_compare( IRType size, IRTemp src, 3734 IRTemp frac_mask, IRExpr *zero ) 3735 { 3736 IROp opAND, opCmpEQ; 3737 3738 if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3739 /*The 16-bit floating point value is in the lower 16-bits of 3740 the 32-bit input value */ 3741 opAND = Iop_And32; 3742 opCmpEQ = Iop_CmpEQ32; 3743 3744 } else { 3745 opAND = Iop_And64; 3746 opCmpEQ = Iop_CmpEQ64; 3747 } 3748 3749 if( size == Ity_V128 ) { 3750 /* 128-bit, note we only care if the fractional part is zero so take upper 3751 52-bits of fractional part and lower 64-bits and OR them together and test 3752 for zero. This keeps the temp variables and operators all 64-bit. 3753 */ 3754 return binop( opCmpEQ, 3755 binop( Iop_Or64, 3756 binop( opAND, 3757 unop( Iop_V128HIto64, mkexpr( src ) ), 3758 mkexpr( frac_mask ) ), 3759 unop( Iop_V128to64, mkexpr( src ) ) ), 3760 zero ); 3761 3762 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) { 3763 return binop( opCmpEQ, 3764 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ), 3765 zero ); 3766 } else { 3767 if (mode64) { 3768 return binop( opCmpEQ, 3769 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ), 3770 zero ); 3771 } else { 3772 /* No support for 64-bit compares in 32-bit mode, need to do upper 3773 * and lower parts using 32-bit compare operators. 3774 */ 3775 return 3776 mkAND1( binop( Iop_CmpEQ32, 3777 binop ( Iop_And32, 3778 unop(Iop_64HIto32, mkexpr( src ) ), 3779 unop(Iop_64HIto32, mkexpr( frac_mask ) ) ), 3780 mkU32 ( 0 ) ), 3781 binop( Iop_CmpEQ32, 3782 binop ( Iop_And32, 3783 unop(Iop_64to32, mkexpr( src ) ), 3784 unop(Iop_64to32, mkexpr( frac_mask ) ) ), 3785 mkU32 ( 0 ) ) ); 3786 } 3787 } 3788 } 3789 3790 // Infinity: exp has all bits set, and fraction is zero; s = 0/1 3791 static IRExpr * is_Inf( IRType size, IRTemp src ) 3792 { 3793 IRExpr *max_exp, *zero_frac; 3794 IRTemp exp_mask, frac_mask, zero; 3795 3796 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3797 3798 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3799 max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) ); 3800 3801 /* check fractional part is all zeros */ 3802 zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) ); 3803 3804 return mkAND1( max_exp, zero_frac ); 3805 } 3806 3807 // Zero: exp is zero and fraction is zero; s = 0/1 3808 static IRExpr * is_Zero( IRType size, IRTemp src ) 3809 { 3810 IRExpr *zero_exp, *zero_frac; 3811 IRTemp exp_mask, frac_mask, zero; 3812 3813 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3814 3815 /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */ 3816 zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) ); 3817 3818 /* check fractional part is all zeros */ 3819 zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) ); 3820 3821 return mkAND1( zero_exp, zero_frac ); 3822 } 3823 3824 /* SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1' 3825 * QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0' 3826 */ 3827 static IRExpr * is_NaN( IRType size, IRTemp src ) 3828 { 3829 IRExpr *max_exp, *not_zero_frac; 3830 IRTemp exp_mask, frac_mask, zero; 3831 3832 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3833 3834 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3835 max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) ); 3836 3837 /* check fractional part is not zero */ 3838 not_zero_frac = unop( Iop_Not1, 3839 fractional_part_compare( size, src, frac_mask, 3840 mkexpr( zero ) ) ); 3841 3842 return mkAND1( max_exp, not_zero_frac ); 3843 } 3844 3845 /* Denormalized number has a zero exponent and non zero fraction. */ 3846 static IRExpr * is_Denorm( IRType size, IRTemp src ) 3847 { 3848 IRExpr *zero_exp, *not_zero_frac; 3849 IRTemp exp_mask, frac_mask, zero; 3850 3851 setup_value_check_args( size, &exp_mask, &frac_mask, &zero ); 3852 3853 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */ 3854 zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) ); 3855 3856 /* check fractional part is not zero */ 3857 not_zero_frac = unop( Iop_Not1, 3858 fractional_part_compare( size, src, frac_mask, 3859 mkexpr( zero ) ) ); 3860 3861 return mkAND1( zero_exp, not_zero_frac ); 3862 } 3863 3864 /* Normalized number has exponent between 1 and max_exp -1, or in other words 3865 the exponent is not zero and not equal to the max exponent value. */ 3866 static IRExpr * is_Norm( IRType size, IRTemp src ) 3867 { 3868 IRExpr *not_zero_exp, *not_max_exp; 3869 IRTemp exp_mask, zero; 3870 3871 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3872 || ( size == Ity_I64 ) || ( size == Ity_V128 ) ); 3873 3874 if( size == Ity_I16 ) { 3875 /* The 16-bit floating point value is in the lower 16-bits of 3876 the 32-bit input value */ 3877 exp_mask = newTemp( Ity_I32 ); 3878 zero = newTemp( Ity_I32 ); 3879 assign( exp_mask, mkU32( I16_EXP_MASK ) ); 3880 assign( zero, mkU32( 0 ) ); 3881 3882 } else if( size == Ity_I32 ) { 3883 exp_mask = newTemp( Ity_I32 ); 3884 zero = newTemp( Ity_I32 ); 3885 assign( exp_mask, mkU32( I32_EXP_MASK ) ); 3886 assign( zero, mkU32( 0 ) ); 3887 3888 } else if( size == Ity_I64 ) { 3889 exp_mask = newTemp( Ity_I64 ); 3890 zero = newTemp( Ity_I64 ); 3891 assign( exp_mask, mkU64( I64_EXP_MASK ) ); 3892 assign( zero, mkU64( 0 ) ); 3893 3894 } else { 3895 /* V128 is converted to upper and lower 64 bit values, */ 3896 /* uses 64-bit operators and temps */ 3897 exp_mask = newTemp( Ity_I64 ); 3898 zero = newTemp( Ity_I64 ); 3899 assign( exp_mask, mkU64( V128_EXP_MASK ) ); 3900 assign( zero, mkU64( 0 ) ); 3901 } 3902 3903 not_zero_exp = unop( Iop_Not1, 3904 exponent_compare( size, src, 3905 exp_mask, mkexpr( zero ) ) ); 3906 not_max_exp = unop( Iop_Not1, 3907 exponent_compare( size, src, 3908 exp_mask, mkexpr( exp_mask ) ) ); 3909 3910 return mkAND1( not_zero_exp, not_max_exp ); 3911 } 3912 3913 3914 static IRExpr * create_FPCC( IRTemp NaN, IRTemp inf, 3915 IRTemp zero, IRTemp norm, 3916 IRTemp dnorm, IRTemp pos, 3917 IRTemp neg ) { 3918 IRExpr *bit0, *bit1, *bit2, *bit3; 3919 3920 /* If the result is NaN then must force bits 1, 2 and 3 to zero 3921 * to get correct result. 3922 */ 3923 bit0 = unop( Iop_1Uto32, mkOR1( mkexpr( NaN ), mkexpr( inf ) ) ); 3924 bit1 = unop( Iop_1Uto32, mkAND1( mkNOT1( mkexpr( NaN ) ), mkexpr( zero ) ) ); 3925 bit2 = unop( Iop_1Uto32, 3926 mkAND1( mkNOT1( mkexpr( NaN ) ), 3927 mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( pos ), 3928 mkexpr( dnorm ) ), 3929 mkAND1( mkexpr( pos ), 3930 mkexpr( norm ) ) ), 3931 mkAND1( mkexpr( pos ), 3932 mkexpr( inf ) ) ), 3933 mkAND1( mkNOT1 ( mkexpr( zero ) ), 3934 mkNOT1( mkexpr( NaN ) ) ) ) ) ); 3935 bit3 = unop( Iop_1Uto32, 3936 mkAND1( mkNOT1( mkexpr( NaN ) ), 3937 mkAND1( mkOR1( mkOR1( mkAND1( mkexpr( neg ), 3938 mkexpr( dnorm ) ), 3939 mkAND1( mkexpr( neg ), 3940 mkexpr( norm ) ) ), 3941 mkAND1( mkexpr( neg ), 3942 mkexpr( inf ) ) ), 3943 mkAND1( mkNOT1 ( mkexpr( zero ) ), 3944 mkNOT1( mkexpr( NaN ) ) ) ) ) ); 3945 3946 return binop( Iop_Or32, 3947 binop( Iop_Or32, 3948 bit0, 3949 binop( Iop_Shl32, bit1, mkU8( 1 ) ) ), 3950 binop( Iop_Or32, 3951 binop( Iop_Shl32, bit2, mkU8( 2 ) ), 3952 binop( Iop_Shl32, bit3, mkU8( 3 ) ) ) ); 3953 } 3954 3955 static IRExpr * create_C( IRTemp NaN, IRTemp zero, 3956 IRTemp dnorm, IRTemp pos, 3957 IRTemp neg ) 3958 { 3959 3960 return unop( Iop_1Uto32, 3961 mkOR1( mkOR1( mkexpr( NaN ), 3962 mkAND1( mkexpr( neg ), mkexpr( dnorm ) ) ), 3963 mkOR1( mkAND1( mkexpr( neg ), mkexpr( zero ) ), 3964 mkAND1( mkexpr( pos ), mkexpr( dnorm ) ) ) ) ); 3965 } 3966 3967 static void generate_store_FPRF( IRType size, IRTemp src ) 3968 { 3969 IRExpr *FPCC, *C; 3970 IRTemp NaN = newTemp( Ity_I1 ), inf = newTemp( Ity_I1 ); 3971 IRTemp dnorm = newTemp( Ity_I1 ), norm = newTemp( Ity_I1 ); 3972 IRTemp pos = newTemp( Ity_I1 ), neg = newTemp( Ity_I1 ); 3973 IRTemp zero = newTemp( Ity_I1 ); 3974 3975 IRTemp sign_bit = newTemp( Ity_I1 ); 3976 IRTemp value; 3977 3978 vassert( ( size == Ity_I16 ) || ( size == Ity_I32 ) 3979 || ( size == Ity_I64 ) || ( size == Ity_F128 ) ); 3980 3981 vassert( ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I32 ) 3982 || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I64 ) 3983 || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_F128 ) ); 3984 3985 if( size == Ity_I16 ) { 3986 /* The 16-bit floating point value is in the lower 16-bits of 3987 the 32-bit input value */ 3988 value = newTemp( Ity_I32 ); 3989 assign( value, mkexpr( src ) ); 3990 assign( sign_bit, 3991 unop ( Iop_32to1, 3992 binop( Iop_And32, 3993 binop( Iop_Shr32, mkexpr( value ), mkU8( 15 ) ), 3994 mkU32( 0x1 ) ) ) ); 3995 3996 } else if( size == Ity_I32 ) { 3997 value = newTemp( size ); 3998 assign( value, mkexpr( src ) ); 3999 assign( sign_bit, 4000 unop ( Iop_32to1, 4001 binop( Iop_And32, 4002 binop( Iop_Shr32, mkexpr( value ), mkU8( 31 ) ), 4003 mkU32( 0x1 ) ) ) ); 4004 4005 } else if( size == Ity_I64 ) { 4006 value = newTemp( size ); 4007 assign( value, mkexpr( src ) ); 4008 assign( sign_bit, 4009 unop ( Iop_64to1, 4010 binop( Iop_And64, 4011 binop( Iop_Shr64, mkexpr( value ), mkU8( 63 ) ), 4012 mkU64( 0x1 ) ) ) ); 4013 4014 } else { 4015 /* Move the F128 bit pattern to an integer V128 bit pattern */ 4016 value = newTemp( Ity_V128 ); 4017 assign( value, 4018 binop( Iop_64HLtoV128, 4019 unop( Iop_ReinterpF64asI64, 4020 unop( Iop_F128HItoF64, mkexpr( src ) ) ), 4021 unop( Iop_ReinterpF64asI64, 4022 unop( Iop_F128LOtoF64, mkexpr( src ) ) ) ) ); 4023 4024 size = Ity_V128; 4025 assign( sign_bit, 4026 unop ( Iop_64to1, 4027 binop( Iop_And64, 4028 binop( Iop_Shr64, 4029 unop( Iop_V128HIto64, mkexpr( value ) ), 4030 mkU8( 63 ) ), 4031 mkU64( 0x1 ) ) ) ); 4032 } 4033 4034 /* Calculate the floating point result field FPRF */ 4035 assign( NaN, is_NaN( size, value ) ); 4036 assign( inf, is_Inf( size, value ) ); 4037 assign( zero, is_Zero( size, value ) ); 4038 assign( norm, is_Norm( size, value ) ); 4039 assign( dnorm, is_Denorm( size, value ) ); 4040 assign( pos, mkAND1( mkNOT1( mkexpr( sign_bit ) ), mkU1( 1 ) ) ); 4041 assign( neg, mkAND1( mkexpr( sign_bit ), mkU1( 1 ) ) ); 4042 4043 /* create the FPRF bit field 4044 * 4045 * FPRF field[4:0] type of value 4046 * 10001 QNaN 4047 * 01001 - infininity 4048 * 01000 - Normalized 4049 * 11000 - Denormalized 4050 * 10010 - zero 4051 * 00010 + zero 4052 * 10100 + Denormalized 4053 * 00100 + Normalized 4054 * 00101 + infinity 4055 */ 4056 FPCC = create_FPCC( NaN, inf, zero, norm, dnorm, pos, neg ); 4057 C = create_C( NaN, zero, dnorm, pos, neg ); 4058 4059 /* Write the C and FPCC fields of the FPRF field */ 4060 putC( C ); 4061 putFPCC( FPCC ); 4062 } 4063 4064 /* This function takes an Ity_I32 input argument interpreted 4065 as a single-precision floating point value. If src is a 4066 SNaN, it is changed to a QNaN and returned; otherwise, 4067 the original value is returned. */ 4068 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 4069 { 4070 #define SNAN_MASK32 0x00400000 4071 IRTemp tmp = newTemp(Ity_I32); 4072 IRTemp mask = newTemp(Ity_I32); 4073 IRTemp is_SNAN = newTemp(Ity_I1); 4074 4075 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 4076 assign(tmp, src); 4077 4078 /* check if input is SNaN, if it is convert to QNaN */ 4079 assign( is_SNAN, 4080 mkAND1( is_NaN( Ity_I32, tmp ), 4081 binop( Iop_CmpEQ32, 4082 binop( Iop_And32, mkexpr( tmp ), 4083 mkU32( SNAN_MASK32 ) ), 4084 mkU32( 0 ) ) ) ); 4085 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 4086 assign ( mask, binop( Iop_And32, 4087 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 4088 mkU32( SNAN_MASK32 ) ) ); 4089 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 4090 } 4091 4092 4093 /* This helper function performs the negation part of operations of the form: 4094 * "Negate Multiply-<op>" 4095 * where "<op>" is either "Add" or "Sub". 4096 * 4097 * This function takes one argument -- the floating point intermediate result (converted to 4098 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 4099 * the operation described above. 4100 */ 4101 static IRTemp getNegatedResult(IRTemp intermediateResult) 4102 { 4103 ULong signbit_mask = 0x8000000000000000ULL; 4104 IRTemp signbit_32 = newTemp(Ity_I32); 4105 IRTemp resultantSignbit = newTemp(Ity_I1); 4106 IRTemp negatedResult = newTemp(Ity_I64); 4107 assign( signbit_32, binop( Iop_Shr32, 4108 unop( Iop_64HIto32, 4109 binop( Iop_And64, mkexpr( intermediateResult ), 4110 mkU64( signbit_mask ) ) ), 4111 mkU8( 31 ) ) ); 4112 /* We negate the signbit if and only if the intermediate result from the 4113 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 4114 */ 4115 assign( resultantSignbit, 4116 unop( Iop_Not1, 4117 binop( Iop_CmpEQ32, 4118 binop( Iop_Xor32, 4119 mkexpr( signbit_32 ), 4120 unop( Iop_1Uto32, is_NaN( Ity_I64, 4121 intermediateResult ) ) ), 4122 mkU32( 1 ) ) ) ); 4123 4124 assign( negatedResult, 4125 binop( Iop_Or64, 4126 binop( Iop_And64, 4127 mkexpr( intermediateResult ), 4128 mkU64( ~signbit_mask ) ), 4129 binop( Iop_32HLto64, 4130 binop( Iop_Shl32, 4131 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 4132 mkU8( 31 ) ), 4133 mkU32( 0 ) ) ) ); 4134 4135 return negatedResult; 4136 } 4137 4138 /* This helper function performs the negation part of operations of the form: 4139 * "Negate Multiply-<op>" 4140 * where "<op>" is either "Add" or "Sub". 4141 * 4142 * This function takes one argument -- the floating point intermediate result (converted to 4143 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 4144 * the operation described above. 4145 */ 4146 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 4147 { 4148 UInt signbit_mask = 0x80000000; 4149 IRTemp signbit_32 = newTemp(Ity_I32); 4150 IRTemp resultantSignbit = newTemp(Ity_I1); 4151 IRTemp negatedResult = newTemp(Ity_I32); 4152 assign( signbit_32, binop( Iop_Shr32, 4153 binop( Iop_And32, mkexpr( intermediateResult ), 4154 mkU32( signbit_mask ) ), 4155 mkU8( 31 ) ) ); 4156 /* We negate the signbit if and only if the intermediate result from the 4157 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 4158 */ 4159 assign( resultantSignbit, 4160 unop( Iop_Not1, 4161 binop( Iop_CmpEQ32, 4162 binop( Iop_Xor32, 4163 mkexpr( signbit_32 ), 4164 unop( Iop_1Uto32, is_NaN( Ity_I32, 4165 intermediateResult ) ) ), 4166 mkU32( 1 ) ) ) ); 4167 4168 assign( negatedResult, 4169 binop( Iop_Or32, 4170 binop( Iop_And32, 4171 mkexpr( intermediateResult ), 4172 mkU32( ~signbit_mask ) ), 4173 binop( Iop_Shl32, 4174 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 4175 mkU8( 31 ) ) ) ); 4176 4177 return negatedResult; 4178 } 4179 4180 /* This function takes two quad_precision floating point numbers of type 4181 V128 and return 1 if src_A > src_B, 0 otherwise. */ 4182 static IRExpr * Quad_precision_gt ( IRTemp src_A, IRTemp src_B ) 4183 { 4184 #define FRAC_MASK64Hi 0x0000ffffffffffffULL 4185 #define MASK 0x7FFFFFFFFFFFFFFFULL /* exclude sign bit in upper 64 bits */ 4186 #define EXP_MASK 0x7fff 4187 4188 IRType ty = Ity_I64; 4189 IRTemp sign_A = newTemp( ty ); 4190 IRTemp sign_B = newTemp( ty ); 4191 IRTemp exp_A = newTemp( ty ); 4192 IRTemp exp_B = newTemp( ty ); 4193 IRTemp frac_A_hi = newTemp( ty ); 4194 IRTemp frac_B_hi = newTemp( ty ); 4195 IRTemp frac_A_lo = newTemp( ty ); 4196 IRTemp frac_B_lo = newTemp( ty ); 4197 4198 4199 /* extract exponents, and fractional parts so they can be compared */ 4200 assign( sign_A, binop( Iop_Shr64, 4201 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4202 mkU8( 63 ) ) ); 4203 assign( sign_B, binop( Iop_Shr64, 4204 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4205 mkU8( 63 ) ) ); 4206 assign( exp_A, binop( Iop_And64, 4207 binop( Iop_Shr64, 4208 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4209 mkU8( 48 ) ), 4210 mkU64( EXP_MASK ) ) ); 4211 assign( exp_B, binop( Iop_And64, 4212 binop( Iop_Shr64, 4213 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4214 mkU8( 48 ) ), 4215 mkU64( EXP_MASK ) ) ); 4216 assign( frac_A_hi, binop( Iop_And64, 4217 unop( Iop_V128HIto64, mkexpr( src_A ) ), 4218 mkU64( FRAC_MASK64Hi ) ) ); 4219 assign( frac_B_hi, binop( Iop_And64, 4220 unop( Iop_V128HIto64, mkexpr( src_B ) ), 4221 mkU64( FRAC_MASK64Hi ) ) ); 4222 assign( frac_A_lo, unop( Iop_V128to64, mkexpr( src_A ) ) ); 4223 assign( frac_B_lo, unop( Iop_V128to64, mkexpr( src_B ) ) ); 4224 4225 IRExpr * A_zero = mkAND1( binop( Iop_CmpEQ64, 4226 binop( Iop_And64, 4227 unop( Iop_V128HIto64, 4228 mkexpr( src_A ) ), 4229 mkU64( MASK ) ), 4230 mkU64( 0 ) ), 4231 binop( Iop_CmpEQ64, 4232 unop( Iop_V128to64, mkexpr( src_A ) ), 4233 mkU64( 0 ) ) ); 4234 IRExpr * B_zero = mkAND1( binop( Iop_CmpEQ64, 4235 binop( Iop_And64, 4236 unop( Iop_V128HIto64, 4237 mkexpr( src_B ) ), 4238 mkU64( MASK ) ), 4239 mkU64( 0 ) ), 4240 binop( Iop_CmpEQ64, 4241 unop( Iop_V128to64, mkexpr( src_B ) ), 4242 mkU64( 0 ) ) ); 4243 IRExpr * A_B_zero = mkAND1( A_zero, B_zero ); 4244 4245 /* Compare numbers */ 4246 IRExpr * both_pos = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ), 4247 mkU64( 0 ) ), 4248 binop( Iop_CmpEQ64, mkexpr( sign_B ), 4249 mkU64( 0 ) ) ); 4250 IRExpr * both_neg = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ), 4251 mkU64( 1 ) ), 4252 binop( Iop_CmpEQ64, mkexpr( sign_B ), 4253 mkU64( 1 ) ) ); 4254 IRExpr * sign_eq = binop( Iop_CmpEQ64, mkexpr( sign_A ), mkexpr( sign_B ) ); 4255 IRExpr * sign_gt = binop( Iop_CmpLT64U, mkexpr( sign_A ), 4256 mkexpr( sign_B ) ); /* A pos, B neg */ 4257 4258 IRExpr * exp_eq = binop( Iop_CmpEQ64, mkexpr( exp_A ), mkexpr( exp_B ) ); 4259 IRExpr * exp_gt = binop( Iop_CmpLT64U, mkexpr( exp_B ), mkexpr( exp_A ) ); 4260 IRExpr * exp_lt = binop( Iop_CmpLT64U, mkexpr( exp_A ), mkexpr( exp_B ) ); 4261 4262 IRExpr * frac_hi_eq = binop( Iop_CmpEQ64, mkexpr( frac_A_hi), 4263 mkexpr( frac_B_hi ) ); 4264 IRExpr * frac_hi_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_hi ), 4265 mkexpr( frac_A_hi ) ); 4266 IRExpr * frac_hi_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_hi ), 4267 mkexpr( frac_B_hi ) ); 4268 4269 IRExpr * frac_lo_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_lo ), 4270 mkexpr( frac_A_lo ) ); 4271 IRExpr * frac_lo_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_lo ), 4272 mkexpr( frac_B_lo ) ); 4273 4274 /* src_A and src_B both positive */ 4275 IRExpr *pos_cmp = mkOR1( exp_gt, 4276 mkAND1( exp_eq, 4277 mkOR1( frac_hi_gt, 4278 mkAND1( frac_hi_eq, frac_lo_gt ) ) 4279 ) ); 4280 4281 /* src_A and src_B both negative */ 4282 IRExpr *neg_cmp = mkOR1( exp_lt, 4283 mkAND1( exp_eq, 4284 mkOR1( frac_hi_lt, 4285 mkAND1( frac_hi_eq, frac_lo_lt ) ) 4286 ) ); 4287 4288 /* Need to check the case where one value is a positive 4289 * zero and the other value is a negative zero 4290 */ 4291 return mkAND1( mkNOT1( A_B_zero ), 4292 mkOR1( sign_gt, 4293 mkAND1( sign_eq, 4294 mkOR1( mkAND1( both_pos, pos_cmp ), 4295 mkAND1( both_neg, neg_cmp ) ) ) ) ); 4296 } 4297 4298 /*----------------------------------------------------------- 4299 * Helpers for VX instructions that work on National decimal values, 4300 * Zoned decimal values and BCD values. 4301 * 4302 *------------------------------------------------------------*/ 4303 static IRExpr * is_National_decimal (IRTemp src) 4304 { 4305 /* The src is a 128-bit value containing a sign code in half word 7 4306 * and seven digits in halfwords 0 to 6 (IBM numbering). A valid 4307 * national decimal value has the following: 4308 * - the sign code must be 0x002B (positive) or 0x002D (negative) 4309 * - the digits must be in the range 0x0030 to 0x0039 4310 */ 4311 Int i; 4312 IRExpr * valid_pos_sign; 4313 IRExpr * valid_neg_sign; 4314 IRTemp valid_num[8]; 4315 IRTemp digit[7]; 4316 4317 valid_pos_sign = binop( Iop_CmpEQ64, 4318 binop( Iop_And64, 4319 mkU64( 0xFFFF ), 4320 unop( Iop_V128to64, mkexpr( src ) ) ), 4321 mkU64( 0x002B ) ); 4322 4323 valid_neg_sign = binop( Iop_CmpEQ64, 4324 binop( Iop_And64, 4325 mkU64( 0xFFFF ), 4326 unop( Iop_V128to64, mkexpr( src ) ) ), 4327 mkU64( 0x002D ) ); 4328 4329 valid_num[0] = newTemp( Ity_I1 ); 4330 digit[0] = newTemp( Ity_I64 ); 4331 assign( valid_num[0], mkU1( 1 ) ); // Assume true to start 4332 4333 for(i = 0; i < 7; i++) { 4334 valid_num[i+1] = newTemp( Ity_I1 ); 4335 digit[i] = newTemp( Ity_I64 ); 4336 assign( digit[i], binop( Iop_And64, 4337 unop( Iop_V128to64, 4338 binop( Iop_ShrV128, 4339 mkexpr( src ), 4340 mkU8( (7-i)*16 ) ) ), 4341 mkU64( 0xFFFF ) ) ); 4342 4343 assign( valid_num[i+1], 4344 mkAND1( mkexpr( valid_num[i] ), 4345 mkAND1( binop( Iop_CmpLE64U, 4346 mkexpr( digit[i] ), 4347 mkU64( 0x39 ) ), 4348 binop( Iop_CmpLE64U, 4349 mkU64( 0x30 ), 4350 mkexpr( digit[i] ) ) ) ) ); 4351 } 4352 4353 return mkAND1( mkOR1( valid_pos_sign, valid_neg_sign), 4354 mkexpr( valid_num[7] ) ); 4355 } 4356 4357 static IRExpr * is_Zoned_decimal (IRTemp src, UChar ps) 4358 { 4359 /* The src is a 128-bit value containing a sign code the least significant 4360 * two bytes. The upper pairs of bytes contain digits. A valid Zoned 4361 * decimal value has the following: 4362 * - the sign code must be between 0x0X to 0xFX inclusive (X - don't care) 4363 * - bits [0:3] of each digit must be equal to 0x3 4364 * - bits [4:7] of each digit must be between 0x0 and 0x9 4365 * 4366 * If ps = 0 4367 * Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB 4368 * (note 0bX0XX XXXX is positive) 4369 * 4370 * Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF 4371 * (note 0bX1XX XXXX is negative) 4372 * 4373 * If ps = 1, then the sign code must be in the range 0xA to 0xF 4374 * Positive sign codes are: 0xA, 0xC, 0xE, 0xF 4375 * 4376 * Negative sign codes are 0xB, 0xD 4377 */ 4378 Int i, mask_hi, mask_lo; 4379 IRExpr *valid_range; 4380 IRTemp valid_num[16]; 4381 IRTemp digit[15]; 4382 4383 /* check the range of the sign value based on the value of ps */ 4384 valid_range = mkOR1( 4385 mkAND1( binop( Iop_CmpEQ64, 4386 mkU64( 1 ), 4387 mkU64( ps ) ), 4388 mkAND1( binop( Iop_CmpLE64U, 4389 binop( Iop_And64, 4390 mkU64( 0xF0 ), 4391 unop( Iop_V128to64, 4392 mkexpr( src ) ) ), 4393 4394 mkU64( 0xF0 ) ), 4395 binop( Iop_CmpLE64U, 4396 mkU64( 0xA0 ), 4397 binop( Iop_And64, 4398 mkU64( 0xF0 ), 4399 unop( Iop_V128to64, 4400 mkexpr( src ) ))))), 4401 binop( Iop_CmpEQ64, 4402 mkU64( 0 ), 4403 mkU64( ps ) ) ); 4404 4405 valid_num[0] = newTemp( Ity_I1 ); 4406 assign( valid_num[0], mkU1( 1) ); // Assume true to start 4407 4408 if (ps == 0) { 4409 mask_hi = 0x39; 4410 mask_lo = 0x30; 4411 } else { 4412 mask_hi = 0xF9; 4413 mask_lo = 0xF0; 4414 } 4415 4416 for(i = 0; i < 15; i++) { 4417 valid_num[i+1] = newTemp( Ity_I1 ); 4418 digit[i] = newTemp( Ity_I64 ); 4419 assign( digit[i], binop( Iop_And64, 4420 unop( Iop_V128to64, 4421 binop( Iop_ShrV128, 4422 mkexpr( src ), 4423 mkU8( (15-i)*8 ) ) ), 4424 mkU64( 0xFF ) ) ); 4425 4426 assign( valid_num[i+1], 4427 mkAND1( mkexpr( valid_num[i] ), 4428 mkAND1( binop( Iop_CmpLE64U, 4429 mkexpr( digit[i] ), 4430 mkU64( mask_hi ) ), 4431 binop( Iop_CmpLE64U, 4432 mkU64( mask_lo ), 4433 mkexpr( digit[i] ) ) ) ) ); 4434 } 4435 4436 return mkAND1( valid_range, mkexpr( valid_num[15] ) ); 4437 } 4438 4439 static IRExpr * CmpGT128U ( IRExpr *src1, IRExpr *src2 ) 4440 { 4441 /* Unsigend compare of two 128-bit values */ 4442 IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt; 4443 4444 pos_upper_gt = binop( Iop_CmpLT64U, 4445 unop( Iop_V128HIto64, src2 ), 4446 unop( Iop_V128HIto64, src1 ) ); 4447 pos_upper_eq = binop( Iop_CmpEQ64, 4448 unop( Iop_V128HIto64, src1 ), 4449 unop( Iop_V128HIto64, src2 ) ); 4450 pos_lower_gt = binop( Iop_CmpLT64U, 4451 unop( Iop_V128to64, src2), 4452 unop( Iop_V128to64, src1) ); 4453 return mkOR1( pos_upper_gt, 4454 mkAND1( pos_upper_eq, 4455 pos_lower_gt ) ); 4456 } 4457 4458 4459 static IRExpr * is_BCDstring128 ( const VexAbiInfo* vbi, 4460 UInt Signed, IRExpr *src ) 4461 { 4462 4463 IRTemp valid = newTemp( Ity_I64 ); 4464 4465 /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and 4466 * a sign. The upper bytes are BCD values between 0x0 and 0x9. The sign 4467 * byte is the least significant byte. This function returns 64-bit 1 4468 * value if sign and digits are valid, 0 otherwise. 4469 * 4470 * This function was originally written using IR code. It has been 4471 * replaced with a clean helper due to the large amount of IR code 4472 * needed by this function. 4473 */ 4474 assign( valid, 4475 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4476 "is_BCDstring128_helper", 4477 fnptr_to_fnentry( vbi, &is_BCDstring128_helper ), 4478 mkIRExprVec_3( mkU64( Signed ), 4479 unop( Iop_V128HIto64, src ), 4480 unop( Iop_V128to64, src ) ) ) ); 4481 return mkexpr( valid ); 4482 } 4483 4484 static IRExpr * BCDstring_zero (IRExpr *src) 4485 { 4486 /* The src is a 128-bit value containing a BCD string. The function 4487 * returns a 1 if the BCD string values are all zero, 0 otherwise. 4488 */ 4489 IRTemp tsrc = newTemp( Ity_V128 ); 4490 assign( tsrc, src); 4491 4492 if ( mode64 ) { 4493 return mkAND1( binop( Iop_CmpEQ64, 4494 mkU64( 0 ), 4495 unop( Iop_V128HIto64, 4496 mkexpr( tsrc ) ) ), 4497 binop( Iop_CmpEQ64, 4498 mkU64( 0 ), 4499 unop( Iop_V128to64, 4500 mkexpr( tsrc ) ) ) ); 4501 } else { 4502 /* make this work in 32-bit mode */ 4503 return mkAND1( 4504 mkAND1( binop( Iop_CmpEQ32, 4505 mkU32( 0 ), 4506 unop( Iop_64HIto32, 4507 unop( Iop_V128HIto64, 4508 mkexpr( tsrc ) ) ) ), 4509 binop( Iop_CmpEQ32, 4510 mkU32( 0 ), 4511 unop( Iop_64to32, 4512 unop( Iop_V128HIto64, 4513 mkexpr( tsrc ) ) ) ) ), 4514 mkAND1( binop( Iop_CmpEQ32, 4515 mkU32( 0 ), 4516 unop( Iop_64HIto32, 4517 unop( Iop_V128to64, 4518 mkexpr( tsrc ) ) ) ), 4519 binop( Iop_CmpEQ32, 4520 mkU32( 0 ), 4521 unop( Iop_64to32, 4522 unop( Iop_V128to64, 4523 mkexpr( tsrc ) ) ) ) ) ); 4524 } 4525 } 4526 4527 static IRExpr * check_BCD_round (IRExpr *src, IRTemp shift) 4528 { 4529 /* The src is a 128-bit value containing 31 BCD digits with the sign in 4530 * the least significant byte. The bytes are BCD values between 0x0 and 0x9. 4531 * This routine checks the BCD digit in position shift (counting from 4532 * the least significant digit). If the digit is greater then five, 4533 * a 1 is returned indicating the string needs to be rounded up, 4534 * otherwise, 0 is returned. The value of shift (I64) is the index of 4535 * the BCD digit times four bits. 4536 */ 4537 return binop( Iop_CmpLE64U, 4538 mkU64( 6 ), 4539 binop( Iop_And64, 4540 unop( Iop_V128to64, 4541 binop( Iop_ShrV128, 4542 src, 4543 unop( Iop_64to8, mkexpr( shift ) ) ) ), 4544 mkU64( 0xF ) ) ); 4545 } 4546 4547 static IRTemp increment_BCDstring ( const VexAbiInfo* vbi, 4548 IRExpr *src, IRExpr *carry_in ) 4549 { 4550 /* The src is a 128-bit value containing 31 BCD digits with the sign in 4551 * the least significant byte. The bytes are BCD values between 0x0 and 0x9. 4552 * This function returns the BCD string incremented by 1. 4553 * 4554 * Call a clean helper to do the computation as it requires a lot of 4555 * IR code to do this. 4556 * 4557 * The helper function takes a 32-bit BCD string, in a 64-bit value, and 4558 * increments the string by the 32-bi carry in value. 4559 * 4560 * The incremented value is returned in the lower 32-bits of the result. 4561 * The carry out is returned in bits [35:32] of the result. The 4562 * helper function will be called for each of the four 32-bit strings 4563 * that make up the src string passing the returned carry out to the 4564 * next call. 4565 */ 4566 IRTemp bcd_result = newTemp( Ity_V128 ); 4567 IRTemp bcd_result0 = newTemp( Ity_I64 ); 4568 IRTemp bcd_result1 = newTemp( Ity_I64 ); 4569 IRTemp bcd_result2 = newTemp( Ity_I64 ); 4570 IRTemp bcd_result3 = newTemp( Ity_I64 ); 4571 IRExpr *bcd_string0, *bcd_string1, *bcd_string2, *bcd_string3; 4572 4573 bcd_string0 = binop( Iop_And64, 4574 mkU64( 0xFFFFFFFF ), unop( Iop_V128to64, src ) ); 4575 bcd_string1 = binop( Iop_Shr64, unop( Iop_V128to64, src ), mkU8( 32 ) ); 4576 bcd_string2 = binop( Iop_And64, 4577 mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64, src ) ); 4578 bcd_string3 = binop( Iop_Shr64, unop( Iop_V128HIto64, src ), mkU8( 32 ) ); 4579 4580 assign( bcd_result0, 4581 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4582 "increment_BCDstring32_helper", 4583 fnptr_to_fnentry( vbi, 4584 &increment_BCDstring32_helper ), 4585 mkIRExprVec_3( mkU64( True /*Signed*/ ), 4586 bcd_string0, 4587 binop( Iop_32HLto64, mkU32( 0 ), 4588 carry_in ) ) ) ); 4589 4590 assign( bcd_result1, 4591 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4592 "increment_BCDstring32_helper", 4593 fnptr_to_fnentry( vbi, 4594 &increment_BCDstring32_helper ), 4595 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4596 bcd_string1, 4597 binop( Iop_Shr64, 4598 mkexpr( bcd_result0 ), 4599 mkU8( 32 ) ) ) ) ); 4600 assign( bcd_result2, 4601 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4602 "increment_BCDstring32_helper", 4603 fnptr_to_fnentry( vbi, 4604 &increment_BCDstring32_helper ), 4605 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4606 bcd_string2, 4607 binop( Iop_Shr64, 4608 mkexpr( bcd_result1 ), 4609 mkU8( 32 ) ) ) ) ); 4610 assign( bcd_result3, 4611 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4612 "increment_BCDstring32_helper", 4613 fnptr_to_fnentry( vbi, 4614 &increment_BCDstring32_helper ), 4615 mkIRExprVec_3( mkU64( False /*Unsigned*/ ), 4616 bcd_string3, 4617 binop( Iop_Shr64, 4618 mkexpr( bcd_result2 ), 4619 mkU8( 32 ) ) ) ) ); 4620 4621 /* Put the 128-bit result together from the intermediate results. Remember 4622 * to mask out the carry out from the upper 32 bits of the results. 4623 */ 4624 assign( bcd_result, 4625 binop( Iop_64HLtoV128, 4626 binop( Iop_Or64, 4627 binop( Iop_And64, 4628 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2 ) ), 4629 binop( Iop_Shl64, 4630 mkexpr (bcd_result3 ), mkU8( 32 ) ) ), 4631 binop( Iop_Or64, 4632 binop( Iop_And64, 4633 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0 ) ), 4634 binop( Iop_Shl64, 4635 mkexpr (bcd_result1 ), mkU8( 32 ) ) ) ) ); 4636 return bcd_result; 4637 } 4638 4639 static IRExpr * convert_to_zoned ( const VexAbiInfo* vbi, 4640 IRExpr *src, IRExpr *upper_byte ) 4641 { 4642 /* The function takes a V128 packed decimal value and returns 4643 * the value in zoned format. Note, the sign of the value is ignored. 4644 */ 4645 IRTemp result_low = newTemp( Ity_I64 ); 4646 IRTemp result_hi = newTemp( Ity_I64 ); 4647 IRTemp result = newTemp( Ity_V128 ); 4648 4649 /* Since we can only return 64-bits from a clean helper, we will 4650 * have to get the lower and upper 64-bits separately. 4651 */ 4652 4653 assign( result_low, 4654 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4655 "convert_to_zoned_helper", 4656 fnptr_to_fnentry( vbi, &convert_to_zoned_helper ), 4657 mkIRExprVec_4( unop( Iop_V128HIto64, src ), 4658 unop( Iop_V128to64, src ), 4659 upper_byte, 4660 mkU64( 0 ) ) ) ); 4661 4662 assign( result_hi, 4663 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4664 "convert_to_zoned_helper", 4665 fnptr_to_fnentry( vbi, &convert_to_zoned_helper ), 4666 mkIRExprVec_4( unop( Iop_V128HIto64, src ), 4667 unop( Iop_V128to64, src ), 4668 upper_byte, 4669 mkU64( 1 ) ) ) ); 4670 4671 4672 assign( result, 4673 binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) ); 4674 4675 return mkexpr( result ); 4676 } 4677 4678 static IRExpr * convert_to_national ( const VexAbiInfo* vbi, IRExpr *src ) { 4679 /* The function takes 128-bit value which has a 64-bit packed decimal 4680 * value in the lower 64-bits of the source. The packed decimal is 4681 * converted to the national format via a clean helper. The clean 4682 * helper is used to to the large amount of IR code needed to do the 4683 * conversion. The helper returns the upper 64-bits of the 128-bit 4684 * result if return_upper != 0. Otherwise, the lower 64-bits of the 4685 * result is returned. 4686 */ 4687 IRTemp result_low = newTemp( Ity_I64 ); 4688 IRTemp result_hi = newTemp( Ity_I64 ); 4689 IRTemp result = newTemp( Ity_V128 ); 4690 4691 /* Since we can only return 64-bits from a clean helper, we will 4692 * have to get the lower and upper 64-bits separately. 4693 */ 4694 4695 assign( result_low, 4696 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4697 "convert_to_national_helper", 4698 fnptr_to_fnentry( vbi, &convert_to_national_helper ), 4699 mkIRExprVec_2( unop( Iop_V128to64, src ), 4700 mkU64( 0 ) ) ) ); 4701 4702 assign( result_hi, 4703 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4704 "convert_to_national_helper", 4705 fnptr_to_fnentry( vbi, &convert_to_national_helper ), 4706 mkIRExprVec_2( unop( Iop_V128to64, src ), 4707 mkU64( 1 ) ) ) ); 4708 4709 assign( result, 4710 binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) ); 4711 4712 return mkexpr( result ); 4713 } 4714 4715 static IRExpr * convert_from_zoned ( const VexAbiInfo* vbi, IRExpr *src ) { 4716 /* The function takes 128-bit zoned value and returns a signless 64-bit 4717 * packed decimal value in the lower 64-bits of the 128-bit result. 4718 */ 4719 IRTemp result = newTemp( Ity_V128 ); 4720 4721 assign( result, 4722 binop( Iop_ShlV128, 4723 binop( Iop_64HLtoV128, 4724 mkU64( 0 ), 4725 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4726 "convert_from_zoned_helper", 4727 fnptr_to_fnentry( vbi, 4728 &convert_from_zoned_helper ), 4729 mkIRExprVec_2( unop( Iop_V128HIto64, 4730 src ), 4731 unop( Iop_V128to64, 4732 src ) ) ) ), 4733 mkU8( 4 ) ) ); 4734 4735 return mkexpr( result ); 4736 } 4737 4738 static IRExpr * convert_from_national ( const VexAbiInfo* vbi, IRExpr *src ) { 4739 /* The function takes 128-bit national value and returns a 64-bit 4740 * packed decimal value. 4741 */ 4742 IRTemp result = newTemp( Ity_I64); 4743 4744 assign( result, 4745 mkIRExprCCall( Ity_I64, 0 /*regparms*/, 4746 "convert_from_national_helper", 4747 fnptr_to_fnentry( vbi, 4748 &convert_from_national_helper ), 4749 mkIRExprVec_2( unop( Iop_V128HIto64, 4750 src ), 4751 unop( Iop_V128to64, 4752 src ) ) ) ); 4753 4754 return mkexpr( result ); 4755 } 4756 4757 static IRExpr * UNSIGNED_CMP_GT_V128 ( IRExpr *vA, IRExpr *vB ) { 4758 /* This function does an unsigned compare of two V128 values. The 4759 * function is for use in 32-bit mode only as it is expensive. The 4760 * issue is that compares (GT, LT, EQ) are not supported for operands 4761 * larger then 32-bits when running in 32-bit mode. The function returns 4762 * a 1-bit expression, 1 for TRUE and 0 for FALSE. 4763 */ 4764 IRTemp vA_word0 = newTemp( Ity_I32); 4765 IRTemp vA_word1 = newTemp( Ity_I32); 4766 IRTemp vA_word2 = newTemp( Ity_I32); 4767 IRTemp vA_word3 = newTemp( Ity_I32); 4768 IRTemp vB_word0 = newTemp( Ity_I32); 4769 IRTemp vB_word1 = newTemp( Ity_I32); 4770 IRTemp vB_word2 = newTemp( Ity_I32); 4771 IRTemp vB_word3 = newTemp( Ity_I32); 4772 4773 IRTemp eq_word1 = newTemp( Ity_I1); 4774 IRTemp eq_word2 = newTemp( Ity_I1); 4775 IRTemp eq_word3 = newTemp( Ity_I1); 4776 4777 4778 IRExpr *gt_word0, *gt_word1, *gt_word2, *gt_word3; 4779 IRExpr *eq_word3_2, *eq_word3_2_1; 4780 IRTemp result = newTemp( Ity_I1 ); 4781 4782 assign( vA_word0, unop( Iop_64to32, unop( Iop_V128to64, vA ) ) ); 4783 assign( vA_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vA ) ) ); 4784 assign( vA_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vA ) ) ); 4785 assign( vA_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vA ) ) ); 4786 4787 assign( vB_word0, unop( Iop_64to32, unop( Iop_V128to64, vB ) ) ); 4788 assign( vB_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vB ) ) ); 4789 assign( vB_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vB ) ) ); 4790 assign( vB_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vB ) ) ); 4791 4792 assign( eq_word3, binop( Iop_CmpEQ32, mkexpr( vA_word3 ), 4793 mkexpr( vB_word3 ) ) ); 4794 assign( eq_word2, binop( Iop_CmpEQ32, mkexpr( vA_word2 ), 4795 mkexpr( vB_word2 ) ) ); 4796 assign( eq_word1, binop( Iop_CmpEQ32, mkexpr( vA_word1 ), 4797 mkexpr( vB_word1 ) ) ); 4798 4799 gt_word3 = binop( Iop_CmpLT32U, mkexpr( vB_word3 ), mkexpr( vA_word3 ) ); 4800 gt_word2 = binop( Iop_CmpLT32U, mkexpr( vB_word2 ), mkexpr( vA_word2 ) ); 4801 gt_word1 = binop( Iop_CmpLT32U, mkexpr( vB_word1 ), mkexpr( vA_word1 ) ); 4802 gt_word0 = binop( Iop_CmpLT32U, mkexpr( vB_word0 ), mkexpr( vA_word0 ) ); 4803 4804 eq_word3_2 = mkAND1( mkexpr( eq_word3 ), mkexpr( eq_word2 ) ); 4805 eq_word3_2_1 = mkAND1( mkexpr( eq_word1 ), eq_word3_2 ); 4806 4807 assign( result, mkOR1( 4808 mkOR1( gt_word3, 4809 mkAND1( mkexpr( eq_word3 ), gt_word2 ) ), 4810 mkOR1( mkAND1( eq_word3_2, gt_word1 ), 4811 mkAND1( eq_word3_2_1, gt_word0 ) ) ) ); 4812 return mkexpr( result ); 4813 } 4814 4815 /*------------------------------------------------------------*/ 4816 /* Transactional memory helpers 4817 * 4818 *------------------------------------------------------------*/ 4819 4820 static ULong generate_TMreason( UInt failure_code, 4821 UInt persistant, 4822 UInt nest_overflow, 4823 UInt tm_exact ) 4824 { 4825 ULong tm_err_code = 4826 ( (ULong) 0) << (63-6) /* Failure code */ 4827 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 4828 | ( (ULong) 0) << (63-8) /* Disallowed */ 4829 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 4830 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 4831 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 4832 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 4833 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 4834 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 4835 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 4836 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 4837 | ( (ULong) 0) << (63-30) /* Reserved */ 4838 | ( (ULong) 0) << (63-31) /* Abort */ 4839 | ( (ULong) 0) << (63-32) /* Suspend */ 4840 | ( (ULong) 0) << (63-33) /* Reserved */ 4841 | ( (ULong) 0) << (63-35) /* Privilege */ 4842 | ( (ULong) 0) << (63-36) /* Failure Summary */ 4843 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 4844 | ( (ULong) 0) << (63-38) /* ROT */ 4845 | ( (ULong) 0) << (63-51) /* Reserved */ 4846 | ( (ULong) 0) << (63-63); /* Transaction Level */ 4847 4848 return tm_err_code; 4849 } 4850 4851 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 4852 Addr64 handler_address ) 4853 { 4854 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 4855 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 4856 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 4857 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 4858 } 4859 4860 /*------------------------------------------------------------*/ 4861 /*--- Integer Instruction Translation --- */ 4862 /*------------------------------------------------------------*/ 4863 4864 /* 4865 Integer Arithmetic Instructions 4866 */ 4867 static Bool dis_int_mult_add ( UInt theInstr ) 4868 { 4869 /* VA-Form */ 4870 UChar rD_addr = ifieldRegDS( theInstr ); 4871 UChar rA_addr = ifieldRegA( theInstr ); 4872 UChar rB_addr = ifieldRegB( theInstr ); 4873 UChar rC_addr = ifieldRegC( theInstr ); 4874 UInt opc2 = IFIELD( theInstr, 0, 6 ); 4875 IRType ty = Ity_I64; 4876 IRTemp rA = newTemp( ty ); 4877 IRTemp rB = newTemp( ty ); 4878 IRTemp rC = newTemp( ty ); 4879 IRTemp rD = newTemp( ty ); 4880 IRTemp tmpLo = newTemp( Ity_I64 ); 4881 IRTemp tmpHi = newTemp( Ity_I64 ); 4882 IRTemp tmp2Hi = newTemp( Ity_I64 ); 4883 IRTemp result = newTemp( Ity_I128 ); 4884 IRTemp resultLo = newTemp( Ity_I64 ); 4885 IRExpr* carryout; 4886 4887 assign( rA, getIReg( rA_addr ) ); 4888 assign( rB, getIReg( rB_addr ) ); 4889 assign( rC, getIReg( rC_addr ) ); 4890 4891 switch (opc2) { 4892 case 0x30: // maddhd multiply-add High doubleword signed 4893 DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4894 4895 assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) ); 4896 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4897 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4898 4899 /* Multiply rA and rB then add rC. If the lower 32-bits of the result 4900 * is less then rC and the result rA * rB, a carry out of the lower 32 4901 * bits occurred and the upper 32 bits must be incremented by 1. Sign 4902 * extend rC and do the add to the upper 64 bits to handle the 4903 * negative case for rC. 4904 */ 4905 assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4906 assign( tmp2Hi, binop( Iop_Add64, 4907 mkexpr( tmpHi ), 4908 unop( Iop_1Sto64, 4909 unop( Iop_64to1, 4910 binop( Iop_Shr64, 4911 mkexpr( rC ), 4912 mkU8( 63 ) ) ) ) ) ); 4913 4914 /* need to do calculation for the upper 32 bit result */ 4915 carryout = mkAND1( binop( Iop_CmpLT64U, 4916 mkexpr( resultLo ), mkexpr( rC ) ), 4917 binop( Iop_CmpLT64U, 4918 mkexpr( resultLo ), mkexpr( tmpLo ) ) ); 4919 assign( rD, binop( Iop_Add64, 4920 mkexpr( tmp2Hi ), 4921 unop( Iop_1Uto64, carryout ) ) ); 4922 break; 4923 4924 case 0x31: // maddhdu multiply-add High doubleword unsigned 4925 DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4926 4927 assign( result, binop( Iop_MullU64, mkexpr( rA ), mkexpr( rB ) ) ); 4928 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4929 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4930 4931 /* Add rC, if the lower 32-bits of the result is less then rC and 4932 * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits 4933 * must be incremented by 1. 4934 */ 4935 assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4936 4937 /* need to do calculation for the upper 32 bit result */ 4938 carryout = mkAND1( binop( Iop_CmpLT64U, 4939 mkexpr(resultLo), mkexpr( rC ) ), 4940 binop( Iop_CmpLT64U, 4941 mkexpr(resultLo), mkexpr( tmpLo ) ) ); 4942 assign( rD, binop( Iop_Add64, 4943 mkexpr( tmpHi ), 4944 unop( Iop_1Uto64, carryout ) ) ); 4945 break; 4946 4947 case 0x33: // maddld multiply-add Low doubleword 4948 DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr); 4949 4950 assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) ); 4951 assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) ); 4952 assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) ); 4953 4954 assign( rD, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) ); 4955 break; 4956 4957 default: 4958 vex_printf("dis_int_mult(ppc): unrecognized instruction\n"); 4959 return False; 4960 } 4961 4962 putIReg( rD_addr, mkexpr(rD) ); 4963 4964 return True; 4965 } 4966 4967 static Bool dis_int_arith ( UInt theInstr ) 4968 { 4969 /* D-Form, XO-Form */ 4970 UChar opc1 = ifieldOPC(theInstr); 4971 UChar rD_addr = ifieldRegDS(theInstr); 4972 UChar rA_addr = ifieldRegA(theInstr); 4973 UInt uimm16 = ifieldUIMM16(theInstr); 4974 UChar rB_addr = ifieldRegB(theInstr); 4975 UChar flag_OE = ifieldBIT10(theInstr); 4976 UInt opc2 = ifieldOPClo9(theInstr); 4977 UChar flag_rC = ifieldBIT0(theInstr); 4978 4979 Long simm16 = extend_s_16to64(uimm16); 4980 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4981 IRTemp rA = newTemp(ty); 4982 IRTemp rB = newTemp(ty); 4983 IRTemp rD = newTemp(ty); 4984 4985 Bool do_rc = False; 4986 4987 assign( rA, getIReg(rA_addr) ); 4988 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 4989 4990 switch (opc1) { 4991 /* D-Form */ 4992 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 4993 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 4994 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 4995 mkSzExtendS16(ty, uimm16) ) ); 4996 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 4997 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 4998 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 4999 break; 5000 5001 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 5002 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5003 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5004 mkSzExtendS16(ty, uimm16) ) ); 5005 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 5006 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 5007 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5008 do_rc = True; // Always record to CR 5009 flag_rC = 1; 5010 break; 5011 5012 case 0x0E: // addi (Add Immediate, PPC32 p350) 5013 // li rD,val == addi rD,0,val 5014 // la disp(rA) == addi rD,rA,disp 5015 if ( rA_addr == 0 ) { 5016 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 5017 assign( rD, mkSzExtendS16(ty, uimm16) ); 5018 } else { 5019 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5020 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5021 mkSzExtendS16(ty, uimm16) ) ); 5022 } 5023 break; 5024 5025 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 5026 // lis rD,val == addis rD,0,val 5027 if ( rA_addr == 0 ) { 5028 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 5029 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 5030 } else { 5031 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16); 5032 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5033 mkSzExtendS32(ty, uimm16 << 16) ) ); 5034 } 5035 break; 5036 5037 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 5038 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5039 if (mode64) 5040 assign( rD, unop(Iop_128to64, 5041 binop(Iop_MullS64, mkexpr(rA), 5042 mkSzExtendS16(ty, uimm16))) ); 5043 else 5044 assign( rD, unop(Iop_64to32, 5045 binop(Iop_MullS32, mkexpr(rA), 5046 mkSzExtendS16(ty, uimm16))) ); 5047 break; 5048 5049 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 5050 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 5051 // rD = simm16 - rA 5052 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5053 mkSzExtendS16(ty, uimm16), 5054 mkexpr(rA)) ); 5055 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFI, 5056 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 5057 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5058 break; 5059 5060 /* XO-Form */ 5061 case 0x1F: 5062 do_rc = True; // All below record to CR 5063 5064 switch (opc2) { 5065 case 0x10A: // add (Add, PPC32 p347) 5066 DIP("add%s%s r%u,r%u,r%u\n", 5067 flag_OE ? "o" : "", flag_rC ? ".":"", 5068 rD_addr, rA_addr, rB_addr); 5069 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5070 mkexpr(rA), mkexpr(rB) ) ); 5071 if (flag_OE) { 5072 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD, 5073 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5074 } 5075 break; 5076 5077 case 0x00A: // addc (Add Carrying, PPC32 p348) 5078 DIP("addc%s%s r%u,r%u,r%u\n", 5079 flag_OE ? "o" : "", flag_rC ? ".":"", 5080 rD_addr, rA_addr, rB_addr); 5081 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5082 mkexpr(rA), mkexpr(rB)) ); 5083 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD, 5084 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5085 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5086 if (flag_OE) { 5087 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD, 5088 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5089 } 5090 break; 5091 5092 case 0x08A: { // adde (Add Extended, PPC32 p349) 5093 IRTemp old_xer_ca = newTemp(ty); 5094 DIP("adde%s%s r%u,r%u,r%u\n", 5095 flag_OE ? "o" : "", flag_rC ? ".":"", 5096 rD_addr, rA_addr, rB_addr); 5097 // rD = rA + rB + XER[CA] 5098 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5099 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5100 binop( mkSzOp(ty, Iop_Add8), 5101 mkexpr(rB), mkexpr(old_xer_ca))) ); 5102 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5103 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5104 mkexpr(old_xer_ca) ); 5105 if (flag_OE) { 5106 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5107 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5108 } 5109 break; 5110 } 5111 5112 case 0xAA: {// addex (Add Extended alternate carry bit Z23-form) 5113 DIP("addex r%u,r%u,r%u,%d\n", rD_addr, rA_addr, rB_addr, (Int)flag_OE); 5114 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5115 binop( mkSzOp(ty, Iop_Add8), mkexpr(rB), 5116 mkWidenFrom8( ty, getXER_OV(), False ) ) ) ); 5117 5118 /* CY bit is same as OE bit */ 5119 if (flag_OE == 0) { 5120 /* Exception, do not set SO bit */ 5121 set_XER_OV_OV32( ty, PPCG_FLAG_OP_ADDE, 5122 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5123 } else { 5124 /* CY=1, 2 and 3 (AKA flag_OE) are reserved */ 5125 vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE); 5126 vpanic("addex instruction\n"); 5127 } 5128 break; 5129 } 5130 5131 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 5132 IRTemp old_xer_ca = newTemp(ty); 5133 IRExpr *min_one; 5134 if (rB_addr != 0) { 5135 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 5136 return False; 5137 } 5138 DIP("addme%s%s r%u,r%u,r%u\n", 5139 flag_OE ? "o" : "", flag_rC ? ".":"", 5140 rD_addr, rA_addr, rB_addr); 5141 // rD = rA + (-1) + XER[CA] 5142 // => Just another form of adde 5143 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5144 min_one = mkSzImm(ty, (Long)-1); 5145 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 5146 binop( mkSzOp(ty, Iop_Add8), 5147 min_one, mkexpr(old_xer_ca)) )); 5148 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5149 mkexpr(rD), mkexpr(rA), min_one, 5150 mkexpr(old_xer_ca) ); 5151 if (flag_OE) { 5152 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5153 mkexpr(rD), mkexpr(rA), min_one ); 5154 } 5155 break; 5156 } 5157 5158 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 5159 IRTemp old_xer_ca = newTemp(ty); 5160 if (rB_addr != 0) { 5161 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 5162 return False; 5163 } 5164 DIP("addze%s%s r%u,r%u,r%u\n", 5165 flag_OE ? "o" : "", flag_rC ? ".":"", 5166 rD_addr, rA_addr, rB_addr); 5167 // rD = rA + (0) + XER[CA] 5168 // => Just another form of adde 5169 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5170 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5171 mkexpr(rA), mkexpr(old_xer_ca)) ); 5172 set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE, 5173 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 5174 mkexpr(old_xer_ca) ); 5175 if (flag_OE) { 5176 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE, 5177 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 5178 } 5179 break; 5180 } 5181 5182 case 0x1EB: // divw (Divide Word, PPC32 p388) 5183 DIP("divw%s%s r%u,r%u,r%u\n", 5184 flag_OE ? "o" : "", flag_rC ? ".":"", 5185 rD_addr, rA_addr, rB_addr); 5186 if (mode64) { 5187 /* Note: 5188 XER settings are mode independent, and reflect the 5189 overflow of the low-order 32bit result 5190 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 5191 */ 5192 /* rD[hi32] are undefined: setting them to sign of lo32 5193 - makes set_CR0 happy */ 5194 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 5195 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 5196 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 5197 divisor) ) ); 5198 if (flag_OE) { 5199 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5200 mkexpr(rD), dividend, divisor ); 5201 } 5202 } else { 5203 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 5204 if (flag_OE) { 5205 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5206 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5207 } 5208 } 5209 /* Note: 5210 if (0x8000_0000 / -1) or (x / 0) 5211 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 5212 => But _no_ exception raised. */ 5213 break; 5214 5215 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 5216 DIP("divwu%s%s r%u,r%u,r%u\n", 5217 flag_OE ? "o" : "", flag_rC ? ".":"", 5218 rD_addr, rA_addr, rB_addr); 5219 if (mode64) { 5220 /* Note: 5221 XER settings are mode independent, and reflect the 5222 overflow of the low-order 32bit result 5223 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 5224 */ 5225 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 5226 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 5227 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 5228 divisor) ) ); 5229 if (flag_OE) { 5230 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5231 mkexpr(rD), dividend, divisor ); 5232 } 5233 } else { 5234 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 5235 if (flag_OE) { 5236 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5237 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5238 } 5239 } 5240 /* Note: ditto comment divw, for (x / 0) */ 5241 break; 5242 5243 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 5244 if (flag_OE != 0) { 5245 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 5246 return False; 5247 } 5248 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5249 rD_addr, rA_addr, rB_addr); 5250 if (mode64) { 5251 /* rD[hi32] are undefined: setting them to sign of lo32 5252 - makes set_CR0 happy */ 5253 assign( rD, binop(Iop_Sar64, 5254 binop(Iop_Mul64, 5255 mk64lo32Sto64( mkexpr(rA) ), 5256 mk64lo32Sto64( mkexpr(rB) )), 5257 mkU8(32)) ); 5258 } else { 5259 assign( rD, unop(Iop_64HIto32, 5260 binop(Iop_MullS32, 5261 mkexpr(rA), mkexpr(rB))) ); 5262 } 5263 break; 5264 5265 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 5266 if (flag_OE != 0) { 5267 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 5268 return False; 5269 } 5270 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5271 rD_addr, rA_addr, rB_addr); 5272 if (mode64) { 5273 /* rD[hi32] are undefined: setting them to sign of lo32 5274 - makes set_CR0 happy */ 5275 assign( rD, binop(Iop_Sar64, 5276 binop(Iop_Mul64, 5277 mk64lo32Uto64( mkexpr(rA) ), 5278 mk64lo32Uto64( mkexpr(rB) ) ), 5279 mkU8(32)) ); 5280 } else { 5281 assign( rD, unop(Iop_64HIto32, 5282 binop(Iop_MullU32, 5283 mkexpr(rA), mkexpr(rB))) ); 5284 } 5285 break; 5286 5287 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 5288 DIP("mullw%s%s r%u,r%u,r%u\n", 5289 flag_OE ? "o" : "", flag_rC ? ".":"", 5290 rD_addr, rA_addr, rB_addr); 5291 if (mode64) { 5292 /* rD[hi32] are undefined: setting them to sign of lo32 5293 - set_XER_OV() and set_CR0() depend on this */ 5294 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 5295 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 5296 assign( rD, binop(Iop_MullS32, a, b) ); 5297 if (flag_OE) { 5298 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW, 5299 mkexpr(rD), 5300 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 5301 } 5302 } else { 5303 assign( rD, unop(Iop_64to32, 5304 binop(Iop_MullU32, 5305 mkexpr(rA), mkexpr(rB))) ); 5306 if (flag_OE) { 5307 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW, 5308 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5309 } 5310 } 5311 break; 5312 5313 case 0x068: // neg (Negate, PPC32 p493) 5314 if (rB_addr != 0) { 5315 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 5316 return False; 5317 } 5318 DIP("neg%s%s r%u,r%u\n", 5319 flag_OE ? "o" : "", flag_rC ? ".":"", 5320 rD_addr, rA_addr); 5321 // rD = (~rA) + 1 5322 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5323 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 5324 mkSzImm(ty, 1)) ); 5325 if (flag_OE) { 5326 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_NEG, 5327 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5328 } 5329 break; 5330 5331 case 0x028: // subf (Subtract From, PPC32 p537) 5332 DIP("subf%s%s r%u,r%u,r%u\n", 5333 flag_OE ? "o" : "", flag_rC ? ".":"", 5334 rD_addr, rA_addr, rB_addr); 5335 // rD = rB - rA 5336 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5337 mkexpr(rB), mkexpr(rA)) ); 5338 if (flag_OE) { 5339 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBF, 5340 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5341 } 5342 break; 5343 5344 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 5345 DIP("subfc%s%s r%u,r%u,r%u\n", 5346 flag_OE ? "o" : "", flag_rC ? ".":"", 5347 rD_addr, rA_addr, rB_addr); 5348 // rD = rB - rA 5349 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 5350 mkexpr(rB), mkexpr(rA)) ); 5351 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFC, 5352 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5353 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 5354 if (flag_OE) { 5355 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFC, 5356 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5357 } 5358 break; 5359 5360 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 5361 IRTemp old_xer_ca = newTemp(ty); 5362 DIP("subfe%s%s r%u,r%u,r%u\n", 5363 flag_OE ? "o" : "", flag_rC ? ".":"", 5364 rD_addr, rA_addr, rB_addr); 5365 // rD = (log not)rA + rB + XER[CA] 5366 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5367 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5368 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 5369 binop( mkSzOp(ty, Iop_Add8), 5370 mkexpr(rB), mkexpr(old_xer_ca))) ); 5371 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5372 mkexpr(rD), mkexpr(rA), mkexpr(rB), 5373 mkexpr(old_xer_ca) ); 5374 if (flag_OE) { 5375 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5376 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5377 } 5378 break; 5379 } 5380 5381 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 5382 IRTemp old_xer_ca = newTemp(ty); 5383 IRExpr *min_one; 5384 if (rB_addr != 0) { 5385 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 5386 return False; 5387 } 5388 DIP("subfme%s%s r%u,r%u\n", 5389 flag_OE ? "o" : "", flag_rC ? ".":"", 5390 rD_addr, rA_addr); 5391 // rD = (log not)rA + (-1) + XER[CA] 5392 // => Just another form of subfe 5393 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5394 min_one = mkSzImm(ty, (Long)-1); 5395 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5396 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 5397 binop( mkSzOp(ty, Iop_Add8), 5398 min_one, mkexpr(old_xer_ca))) ); 5399 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5400 mkexpr(rD), mkexpr(rA), min_one, 5401 mkexpr(old_xer_ca) ); 5402 if (flag_OE) { 5403 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5404 mkexpr(rD), mkexpr(rA), min_one ); 5405 } 5406 break; 5407 } 5408 5409 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 5410 IRTemp old_xer_ca = newTemp(ty); 5411 if (rB_addr != 0) { 5412 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 5413 return False; 5414 } 5415 DIP("subfze%s%s r%u,r%u\n", 5416 flag_OE ? "o" : "", flag_rC ? ".":"", 5417 rD_addr, rA_addr); 5418 // rD = (log not)rA + (0) + XER[CA] 5419 // => Just another form of subfe 5420 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) ); 5421 assign( rD, binop( mkSzOp(ty, Iop_Add8), 5422 unop( mkSzOp(ty, Iop_Not8), 5423 mkexpr(rA)), mkexpr(old_xer_ca)) ); 5424 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE, 5425 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 5426 mkexpr(old_xer_ca) ); 5427 if (flag_OE) { 5428 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE, 5429 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 5430 } 5431 break; 5432 } 5433 5434 5435 /* 64bit Arithmetic */ 5436 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 5437 if (flag_OE != 0) { 5438 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 5439 return False; 5440 } 5441 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5442 rD_addr, rA_addr, rB_addr); 5443 assign( rD, unop(Iop_128HIto64, 5444 binop(Iop_MullS64, 5445 mkexpr(rA), mkexpr(rB))) ); 5446 5447 break; 5448 5449 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 5450 if (flag_OE != 0) { 5451 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 5452 return False; 5453 } 5454 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5455 rD_addr, rA_addr, rB_addr); 5456 assign( rD, unop(Iop_128HIto64, 5457 binop(Iop_MullU64, 5458 mkexpr(rA), mkexpr(rB))) ); 5459 break; 5460 5461 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 5462 DIP("mulld%s%s r%u,r%u,r%u\n", 5463 flag_OE ? "o" : "", flag_rC ? ".":"", 5464 rD_addr, rA_addr, rB_addr); 5465 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 5466 if (flag_OE) { 5467 set_XER_OV_64( PPCG_FLAG_OP_MULLD, 5468 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5469 /* OV is set to 1 if product isn't representable. 5470 * In this case also need to set OV32 and SO to 1, 5471 * i.e. copy OV to OV32 and SO. 5472 */ 5473 copy_OV_to_OV32(); 5474 update_SO(); 5475 } 5476 break; 5477 5478 case 0x1E9: // divd (Divide DWord, PPC64 p419) 5479 DIP("divd%s%s r%u,r%u,r%u\n", 5480 flag_OE ? "o" : "", flag_rC ? ".":"", 5481 rD_addr, rA_addr, rB_addr); 5482 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 5483 if (flag_OE) { 5484 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW, 5485 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5486 } 5487 break; 5488 /* Note: 5489 if (0x8000_0000_0000_0000 / -1) or (x / 0) 5490 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 5491 => But _no_ exception raised. */ 5492 5493 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 5494 DIP("divdu%s%s r%u,r%u,r%u\n", 5495 flag_OE ? "o" : "", flag_rC ? ".":"", 5496 rD_addr, rA_addr, rB_addr); 5497 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 5498 if (flag_OE) { 5499 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU, 5500 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 5501 } 5502 break; 5503 /* Note: ditto comment divd, for (x / 0) */ 5504 5505 case 0x18B: // divweu (Divide Word Extended Unsigned) 5506 { 5507 /* 5508 * If (RA) >= (RB), or if an attempt is made to perform the division 5509 * <anything> / 0 5510 * then the contents of register RD are undefined as are (if Rc=1) the contents of 5511 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 5512 * to 1. 5513 */ 5514 IRTemp res = newTemp(Ity_I32); 5515 IRExpr * dividend, * divisor; 5516 DIP("divweu%s%s r%u,r%u,r%u\n", 5517 flag_OE ? "o" : "", flag_rC ? ".":"", 5518 rD_addr, rA_addr, rB_addr); 5519 if (mode64) { 5520 dividend = unop( Iop_64to32, mkexpr( rA ) ); 5521 divisor = unop( Iop_64to32, mkexpr( rB ) ); 5522 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 5523 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 5524 } else { 5525 dividend = mkexpr( rA ); 5526 divisor = mkexpr( rB ); 5527 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 5528 assign( rD, mkexpr( res) ); 5529 } 5530 5531 if (flag_OE) { 5532 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU, 5533 mkexpr(res), dividend, divisor ); 5534 update_SO( ); 5535 } 5536 break; 5537 } 5538 5539 case 0x1AB: // divwe (Divide Word Extended) 5540 { 5541 /* 5542 * If the quotient cannot be represented in 32 bits, or if an 5543 * attempt is made to perform the division 5544 * <anything> / 0 5545 * then the contents of register RD are undefined as are (if 5546 * Rc=1) the contents of the LT, GT, and EQ bits of CR 5547 * Field 0. In these cases, if OE=1 then OV is set to 1. 5548 */ 5549 5550 IRTemp res = newTemp(Ity_I32); 5551 IRExpr * dividend, * divisor; 5552 DIP("divwe%s%s r%u,r%u,r%u\n", 5553 flag_OE ? "o" : "", flag_rC ? ".":"", 5554 rD_addr, rA_addr, rB_addr); 5555 if (mode64) { 5556 dividend = unop( Iop_64to32, mkexpr( rA ) ); 5557 divisor = unop( Iop_64to32, mkexpr( rB ) ); 5558 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 5559 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 5560 } else { 5561 dividend = mkexpr( rA ); 5562 divisor = mkexpr( rB ); 5563 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 5564 assign( rD, mkexpr( res) ); 5565 } 5566 5567 if (flag_OE) { 5568 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE, 5569 mkexpr(res), dividend, divisor ); 5570 update_SO( ); 5571 } 5572 break; 5573 } 5574 5575 5576 case 0x1A9: // divde (Divide Doubleword Extended) 5577 /* 5578 * If the quotient cannot be represented in 64 bits, or if an 5579 * attempt is made to perform the division 5580 * <anything> / 0 5581 * then the contents of register RD are undefined as are (if 5582 * Rc=1) the contents of the LT, GT, and EQ bits of CR 5583 * Field 0. In these cases, if OE=1 then OV is set to 1. 5584 */ 5585 DIP("divde%s%s r%u,r%u,r%u\n", 5586 flag_OE ? "o" : "", flag_rC ? ".":"", 5587 rD_addr, rA_addr, rB_addr); 5588 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 5589 if (flag_OE) { 5590 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 5591 mkexpr( rA ), mkexpr( rB ) ); 5592 copy_OV_to_OV32(); 5593 update_SO(); 5594 } 5595 break; 5596 5597 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 5598 // Same CR and OV rules as given for divweu above 5599 DIP("divdeu%s%s r%u,r%u,r%u\n", 5600 flag_OE ? "o" : "", flag_rC ? ".":"", 5601 rD_addr, rA_addr, rB_addr); 5602 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 5603 if (flag_OE) { 5604 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 5605 mkexpr( rA ), mkexpr( rB ) ); 5606 copy_OV_to_OV32(); 5607 update_SO(); 5608 } 5609 break; 5610 5611 default: 5612 vex_printf("dis_int_arith(ppc)(opc2)\n"); 5613 return False; 5614 } 5615 break; 5616 5617 default: 5618 vex_printf("dis_int_arith(ppc)(opc1)\n"); 5619 return False; 5620 } 5621 5622 putIReg( rD_addr, mkexpr(rD) ); 5623 5624 if (do_rc && flag_rC) { 5625 set_CR0( mkexpr(rD) ); 5626 } 5627 return True; 5628 } 5629 5630 static Bool dis_modulo_int ( UInt theInstr ) 5631 { 5632 /* X-Form */ 5633 UChar opc1 = ifieldOPC( theInstr ); 5634 UInt opc2 = ifieldOPClo10( theInstr ); 5635 UChar rA_addr = ifieldRegA( theInstr ); 5636 UChar rB_addr = ifieldRegB( theInstr ); 5637 UChar rD_addr = ifieldRegDS( theInstr ); 5638 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5639 IRTemp rD = newTemp( ty ); 5640 5641 switch (opc1) { 5642 /* X-Form */ 5643 case 0x1F: 5644 switch (opc2) { 5645 case 0x109: // modud Modulo Unsigned Double Word 5646 { 5647 IRTemp rA = newTemp( Ity_I64 ); 5648 IRTemp rB = newTemp( Ity_I64 ); 5649 IRTemp quotient = newTemp( Ity_I64 ); 5650 IRTemp quotientTimesDivisor = newTemp( Ity_I64 ); 5651 IRTemp remainder = newTemp( Ity_I64 ); 5652 IRTemp rB_0 = newTemp( Ity_I64 ); /* all 1's if rB = 0 */ 5653 5654 DIP("modud r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5655 5656 assign( rA, getIReg( rA_addr ) ); 5657 assign( rB, getIReg( rB_addr ) ); 5658 5659 assign( quotient, 5660 binop( Iop_DivU64, mkexpr( rA ), mkexpr( rB ) ) ); 5661 5662 assign( quotientTimesDivisor, 5663 binop( Iop_Mul64, 5664 mkexpr( quotient ), 5665 mkexpr( rB ) ) ); 5666 5667 assign( remainder, 5668 binop( Iop_Sub64, 5669 mkexpr( rA ), 5670 mkexpr( quotientTimesDivisor ) ) ); 5671 5672 /* Need to match the HW for these special cases 5673 * rB = 0 result all zeros 5674 */ 5675 assign( rB_0, unop( Iop_1Sto64, 5676 binop( Iop_CmpEQ64, 5677 mkexpr( rB ), 5678 mkU64( 0x0 ) ) ) ); 5679 5680 assign (rD, binop( Iop_And64, 5681 unop( Iop_Not64, mkexpr( rB_0 ) ), 5682 mkexpr( remainder ) ) ); 5683 break; 5684 } 5685 5686 case 0x10B: // moduw Modulo Unsigned Word 5687 { 5688 IRTemp quotient = newTemp( Ity_I32 ); 5689 IRTemp quotientTimesDivisor = newTemp( Ity_I32 ); 5690 IRTemp remainder = newTemp( Ity_I32 ); 5691 5692 IRTemp rA = newTemp( Ity_I32 ); 5693 IRTemp rB = newTemp( Ity_I32 ); 5694 IRTemp rB_0 = newTemp( Ity_I32 ); /* all 1's if rB = 0 */ 5695 5696 DIP("moduw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5697 5698 if ( ty == Ity_I64 ) { 5699 /* rA and rB are 32 bit values in bits 32:63 of the 5700 * 64-bit register. 5701 */ 5702 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 5703 assign( rB, unop( Iop_64to32, getIReg( rB_addr ) ) ); 5704 5705 } else { 5706 assign( rA, getIReg( rA_addr ) ); 5707 assign( rB, getIReg( rB_addr ) ); 5708 } 5709 5710 assign( quotient, 5711 binop( Iop_DivU32, mkexpr( rA ), mkexpr( rB ) ) ); 5712 5713 assign( quotientTimesDivisor, 5714 unop( Iop_64to32, 5715 binop( Iop_MullU32, 5716 mkexpr( quotient ), 5717 mkexpr( rB ) ) ) ); 5718 5719 assign( remainder, 5720 binop( Iop_Sub32, 5721 mkexpr( rA ), 5722 mkexpr( quotientTimesDivisor ) ) ); 5723 5724 /* Need to match the HW for these special cases 5725 * rB = 0 result all zeros 5726 */ 5727 assign( rB_0, unop( Iop_1Sto32, 5728 binop( Iop_CmpEQ32, 5729 mkexpr( rB ), 5730 mkU32( 0x0 ) ) ) ); 5731 5732 assign (rD, binop( Iop_32HLto64, 5733 mkU32( 0 ), 5734 binop( Iop_And32, 5735 unop( Iop_Not32, mkexpr( rB_0 ) ), 5736 mkexpr( remainder ) ) ) ); 5737 break; 5738 } 5739 5740 case 0x21A: // cnttzw, cnttzw. Count Trailing Zero Word 5741 { 5742 /* Note cnttzw RA, RS - RA is dest, RS is source. But the 5743 * order of the operands in theInst is opc1 RS RA opc2 which has 5744 * the operand fields backwards to what the standard order. 5745 */ 5746 UChar rA_address = ifieldRegA(theInstr); 5747 UChar rS_address = ifieldRegDS(theInstr); 5748 IRTemp rA = newTemp(Ity_I64); 5749 IRTemp rS = newTemp(Ity_I64); 5750 UChar flag_rC = ifieldBIT0(theInstr); 5751 IRTemp result = newTemp(Ity_I32); 5752 5753 DIP("cnttzw%s r%u,r%u\n", flag_rC ? "." : "", 5754 rA_address, rS_address); 5755 5756 assign( rS, getIReg( rS_address ) ); 5757 assign( result, unop( Iop_Ctz32, 5758 unop( Iop_64to32, mkexpr( rS ) ) ) ); 5759 assign( rA, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( result ) ) ); 5760 5761 if ( flag_rC ) 5762 set_CR0( mkexpr( rA ) ); 5763 5764 putIReg( rA_address, mkexpr( rA ) ); 5765 5766 return True; /* Return here since this inst is not consistent 5767 * with the other instructions 5768 */ 5769 } 5770 break; 5771 5772 case 0x23A: // cnttzd, cnttzd. Count Trailing Zero Double word 5773 { 5774 /* Note cnttzd RA, RS - RA is dest, RS is source. But the 5775 * order of the operands in theInst is opc1 RS RA opc2 which has 5776 * the operand order listed backwards to what is standard. 5777 */ 5778 UChar rA_address = ifieldRegA(theInstr); 5779 UChar rS_address = ifieldRegDS(theInstr); 5780 IRTemp rA = newTemp(Ity_I64); 5781 IRTemp rS = newTemp(Ity_I64); 5782 UChar flag_rC = ifieldBIT0(theInstr); 5783 5784 DIP("cnttzd%s r%u,r%u\n", flag_rC ? "." : "", 5785 rA_address, rS_address); 5786 5787 assign( rS, getIReg( rS_address ) ); 5788 assign( rA, unop( Iop_Ctz64, mkexpr( rS ) ) ); 5789 5790 if ( flag_rC == 1 ) 5791 set_CR0( mkexpr( rA ) ); 5792 5793 putIReg( rA_address, mkexpr( rA ) ); 5794 5795 return True; /* Return here since this inst is not consistent 5796 * with the other instructions 5797 */ 5798 } 5799 break; 5800 5801 case 0x309: // modsd Modulo Signed Double Word 5802 { 5803 IRTemp rA = newTemp( Ity_I64 ); 5804 IRTemp rB = newTemp( Ity_I64 ); 5805 IRTemp rA2_63 = newTemp( Ity_I64 ); /* all 1's if rA != -2^63 */ 5806 IRTemp rB_0 = newTemp( Ity_I1 ); /* 1 if rB = 0 */ 5807 IRTemp rB_1 = newTemp( Ity_I1 ); /* 1 if rB = -1 */ 5808 IRTemp rA_1 = newTemp( Ity_I1 ); /* 1 if rA = -1 */ 5809 IRTemp resultis0 = newTemp( Ity_I64 ); 5810 IRTemp resultisF = newTemp( Ity_I64 ); 5811 IRTemp quotient = newTemp( Ity_I64 ); 5812 IRTemp quotientTimesDivisor = newTemp( Ity_I64 ); 5813 IRTemp remainder = newTemp( Ity_I64 ); 5814 IRTemp tmp = newTemp( Ity_I64 ); 5815 5816 DIP("modsd r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5817 5818 assign( rA, getIReg( rA_addr ) ); 5819 assign( rB, getIReg( rB_addr ) ); 5820 5821 assign( rA2_63, unop ( Iop_1Sto64, 5822 binop( Iop_CmpNE64, 5823 mkexpr( rA ), 5824 mkU64( 0x8000000000000000 ) ) ) ); 5825 assign( rB_0, binop( Iop_CmpEQ64, 5826 mkexpr( rB ), 5827 mkU64( 0x0 ) ) ); 5828 5829 assign( rB_1, binop( Iop_CmpEQ64, 5830 mkexpr( rB ), 5831 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ); 5832 5833 assign( rA_1, binop( Iop_CmpEQ64, 5834 mkexpr( rA ), 5835 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ); 5836 5837 /* Need to match the HW for these special cases 5838 * rA = -2^31 and rB = -1 result all zeros 5839 * rA = -1 and rB = -1 result all zeros 5840 * rA = -1 and (rB != -1 AND rB != 0) result all 1's 5841 */ 5842 assign( resultis0, 5843 binop( Iop_Or64, 5844 mkexpr( rA2_63 ), 5845 unop ( Iop_1Sto64, mkexpr( rB_1 ) ) ) ); 5846 assign( resultisF, 5847 binop( Iop_And64, 5848 unop( Iop_1Sto64, mkexpr( rA_1 ) ), 5849 binop( Iop_And64, 5850 unop( Iop_Not64, 5851 unop( Iop_1Sto64, mkexpr( rB_0 ) ) ), 5852 unop( Iop_Not64, 5853 unop( Iop_1Sto64, mkexpr( rB_1 ) ) ) 5854 ) ) ); 5855 5856 /* The following remainder computation works as long as 5857 * rA != -2^63 and rB != -1. 5858 */ 5859 assign( quotient, 5860 binop( Iop_DivS64, mkexpr( rA ), mkexpr( rB ) ) ); 5861 5862 assign( quotientTimesDivisor, 5863 binop( Iop_Mul64, 5864 mkexpr( quotient ), 5865 mkexpr( rB ) ) ); 5866 5867 assign( remainder, 5868 binop( Iop_Sub64, 5869 mkexpr( rA ), 5870 mkexpr( quotientTimesDivisor ) ) ); 5871 5872 assign( tmp, binop( Iop_And64, 5873 mkexpr( remainder ), 5874 unop( Iop_Not64, 5875 mkexpr( resultis0 ) ) ) ); 5876 5877 assign( rD, binop( Iop_Or64, 5878 binop( Iop_And64, 5879 unop (Iop_Not64, 5880 mkexpr( resultisF ) ), 5881 mkexpr( tmp ) ), 5882 mkexpr( resultisF ) ) ); 5883 break; 5884 } 5885 case 0x30B: // modsw Modulo Signed Word 5886 { 5887 IRTemp rA = newTemp( Ity_I32 ); 5888 IRTemp rB = newTemp( Ity_I32 ); 5889 IRTemp rA2_32 = newTemp( Ity_I32 ); /* all 1's if rA = -2^32 */ 5890 IRTemp rB_0 = newTemp( Ity_I1 ); /* 1 if rB = 0 */ 5891 IRTemp rB_1 = newTemp( Ity_I1 ); /* 1 if rB = -1 */ 5892 IRTemp rA_1 = newTemp( Ity_I1 ); /* 1 if rA = -1 */ 5893 IRTemp resultis0 = newTemp( Ity_I32 ); 5894 IRTemp resultisF = newTemp( Ity_I64 ); 5895 IRTemp quotient = newTemp( Ity_I32 ); 5896 IRTemp quotientTimesDivisor = newTemp( Ity_I32 ); 5897 IRTemp remainder = newTemp( Ity_I32 ); 5898 IRTemp tmp = newTemp( Ity_I64 ); 5899 5900 DIP("modsw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5901 5902 if ( ty == Ity_I64 ) { 5903 /* rA and rB are 32 bit values in bits 32:63 of the 5904 * 64-bit register. 5905 */ 5906 assign( rA, unop(Iop_64to32, getIReg(rA_addr) ) ); 5907 assign( rB, unop(Iop_64to32, getIReg(rB_addr) ) ); 5908 5909 } else { 5910 assign( rA, getIReg(rA_addr) ); 5911 assign( rB, getIReg(rB_addr) ); 5912 } 5913 5914 assign( rA2_32, unop( Iop_1Sto32, 5915 binop( Iop_CmpEQ32, 5916 mkexpr( rA ), 5917 mkU32( 0x80000000 ) ) ) ); 5918 /* If the divisor is zero, then the result is undefined. 5919 * However, we will make the result be zero to match what 5920 * the hardware does. 5921 */ 5922 assign( rB_0, binop( Iop_CmpEQ32, 5923 mkexpr( rB ), 5924 mkU32( 0x0 ) ) ); 5925 5926 assign( rB_1, binop( Iop_CmpEQ32, 5927 mkexpr( rB ), 5928 mkU32( 0xFFFFFFFF ) ) ); 5929 5930 assign( rA_1, binop( Iop_CmpEQ32, 5931 mkexpr( rA ), 5932 mkU32( 0xFFFFFFFF ) ) ); 5933 5934 /* Need to match the HW for these special cases 5935 * rA = -2^31 and rB = -1 result all zeros 5936 * rA = -1 and rB = -1 result all zeros 5937 * rA = -1 and (rB != -1 AND rB != 0) result all 1's 5938 */ 5939 assign( resultis0, 5940 binop( Iop_Or32, 5941 unop( Iop_Not32, 5942 binop( Iop_And32, 5943 mkexpr( rA2_32 ), 5944 unop( Iop_1Sto32, 5945 mkexpr( rB_1 ) ) ) ), 5946 binop( Iop_And32, 5947 unop( Iop_1Sto32, mkexpr( rA_1 ) ), 5948 unop( Iop_1Sto32, mkexpr( rB_1 ) ) ) ) ); 5949 assign( resultisF, 5950 binop( Iop_And64, 5951 unop( Iop_1Sto64, mkexpr( rA_1 ) ), 5952 binop( Iop_And64, 5953 unop( Iop_Not64, 5954 unop( Iop_1Sto64, mkexpr( rB_0 ) ) ), 5955 unop( Iop_Not64, 5956 unop( Iop_1Sto64, mkexpr( rB_1 ) ) ) 5957 ) ) ); 5958 5959 /* The following remainder computation works as long as 5960 * rA != -2^31 and rB != -1. 5961 */ 5962 assign( quotient, 5963 binop( Iop_DivS32, mkexpr( rA ), mkexpr( rB ) ) ); 5964 5965 assign( quotientTimesDivisor, 5966 unop( Iop_64to32, 5967 binop( Iop_MullS32, 5968 mkexpr( quotient ), 5969 mkexpr( rB ) ) ) ); 5970 5971 assign( remainder, 5972 binop( Iop_Sub32, 5973 mkexpr( rA ), 5974 mkexpr( quotientTimesDivisor ) ) ); 5975 5976 assign( tmp, binop( Iop_32HLto64, 5977 mkU32( 0 ), 5978 binop( Iop_And32, 5979 mkexpr( remainder ), 5980 unop( Iop_Not32, 5981 mkexpr( resultis0 ) ) ) ) ); 5982 5983 assign( rD, binop( Iop_Or64, 5984 binop( Iop_And64, 5985 unop ( Iop_Not64, 5986 mkexpr( resultisF ) ), 5987 mkexpr( tmp ) ), 5988 mkexpr( resultisF ) ) ); 5989 break; 5990 } 5991 5992 default: 5993 vex_printf("dis_modulo_int(ppc)(opc2)\n"); 5994 return False; 5995 } 5996 break; 5997 5998 default: 5999 vex_printf("dis_modulo_int(ppc)(opc1)\n"); 6000 return False; 6001 } 6002 6003 putIReg( rD_addr, mkexpr( rD ) ); 6004 6005 return True; 6006 } 6007 6008 6009 /* 6010 Byte Compare Instructions 6011 */ 6012 static Bool dis_byte_cmp ( UInt theInstr ) 6013 { 6014 /* X-Form */ 6015 UChar opc1 = ifieldOPC(theInstr); 6016 UInt opc2 = ifieldOPClo10(theInstr); 6017 UChar rA_addr = ifieldRegA(theInstr); 6018 UChar rB_addr = ifieldRegB(theInstr); 6019 IRTemp rA = newTemp(Ity_I64); 6020 IRTemp rB = newTemp(Ity_I64); 6021 UChar L = toUChar( IFIELD( theInstr, 21, 1 ) ); 6022 UChar BF = toUChar( IFIELD( theInstr, 23, 3 ) ); 6023 6024 assign( rA, getIReg(rA_addr) ); 6025 assign( rB, getIReg(rB_addr) ); 6026 6027 if (opc1 != 0x1F) { 6028 vex_printf("dis_byte_cmp(ppc)(opc1)\n"); 6029 return False; 6030 } 6031 6032 switch (opc2) { 6033 case 0xc0: // cmprb (Compare Ranged Byte) 6034 { 6035 IRExpr *value; 6036 IRExpr *hi_1, *lo_1, *hi_2, *lo_2; 6037 IRExpr *inrange_1, *inrange_2; 6038 6039 DIP("cmprb %u,%u,r%u,r%u\n", BF, L, rA_addr, rB_addr); 6040 6041 hi_1 = binop( Iop_Shr64, 6042 binop( Iop_And64, 6043 mkexpr( rB ), 6044 mkU64( 0xFF000000 ) ), 6045 mkU8( 24 ) ); 6046 lo_1 = binop( Iop_Shr64, 6047 binop( Iop_And64, 6048 mkexpr( rB ), 6049 mkU64( 0xFF0000 ) ) , 6050 mkU8( 16 ) ); 6051 hi_2 = binop( Iop_Shr64, 6052 binop( Iop_And64, 6053 mkexpr( rB ), 6054 mkU64( 0xFF00 ) ), 6055 mkU8( 8 ) ); 6056 lo_2 = binop( Iop_And64, 6057 mkexpr( rB ), 6058 mkU64( 0xFF ) ); 6059 value = binop( Iop_And64, 6060 mkexpr( rA ), 6061 mkU64( 0xFF ) ); 6062 6063 inrange_1 = mkAND1( binop( Iop_CmpLE64U, value, hi_1 ), 6064 mkNOT1( binop( Iop_CmpLT64U, value, lo_1 ) ) ); 6065 inrange_2 = mkAND1( binop( Iop_CmpLE64U, value, hi_2 ), 6066 mkNOT1( binop( Iop_CmpLT64U, value, lo_2 ) ) ); 6067 6068 putGST_field( PPC_GST_CR, 6069 binop( Iop_Shl32, 6070 binop( Iop_Or32, 6071 unop( Iop_1Uto32, inrange_2 ), 6072 binop( Iop_And32, 6073 mkU32 ( L ), 6074 unop( Iop_1Uto32, inrange_1 ) ) ), 6075 mkU8( 2 ) ), 6076 BF ); 6077 } 6078 break; 6079 6080 case 0xE0: // cmpeqb (Compare Equal Byte) 6081 { 6082 Int i; 6083 IRTemp tmp[9]; 6084 IRExpr *value; 6085 6086 DIP("cmpeqb %u,r%u,r%u\n", BF, rA_addr, rB_addr); 6087 6088 value = binop( Iop_And64, 6089 mkexpr( rA ), 6090 mkU64( 0xFF ) ); 6091 6092 tmp[0] = newTemp(Ity_I32); 6093 assign( tmp[0], mkU32( 0 ) ); 6094 6095 for(i = 0; i < 8; i++) { 6096 tmp[i+1] = newTemp(Ity_I32); 6097 assign( tmp[i+1], binop( Iop_Or32, 6098 unop( Iop_1Uto32, 6099 binop( Iop_CmpEQ64, 6100 value, 6101 binop( Iop_And64, 6102 binop( Iop_Shr64, 6103 mkexpr( rB ), 6104 mkU8( i*8 ) ), 6105 mkU64( 0xFF ) ) ) ), 6106 mkexpr( tmp[i] ) ) ); 6107 } 6108 6109 putGST_field( PPC_GST_CR, 6110 binop( Iop_Shl32, 6111 unop( Iop_1Uto32, 6112 mkNOT1( binop( Iop_CmpEQ32, 6113 mkexpr( tmp[8] ), 6114 mkU32( 0 ) ) ) ), 6115 mkU8( 2 ) ), 6116 BF ); 6117 } 6118 break; 6119 6120 default: 6121 vex_printf("dis_byte_cmp(ppc)(opc2)\n"); 6122 return False; 6123 } 6124 return True; 6125 } 6126 6127 /* 6128 * Integer Miscellaneous instructions 6129 */ 6130 static Bool dis_int_misc ( UInt theInstr ) 6131 { 6132 Int wc = IFIELD(theInstr, 21, 2); 6133 UChar opc1 = ifieldOPC(theInstr); 6134 UInt opc2 = ifieldOPClo10(theInstr); 6135 6136 if ( opc1 != 0x1F ) { 6137 vex_printf("dis_modulo_int(ppc)(opc1)\n"); 6138 return False; 6139 } 6140 6141 switch (opc2) { 6142 case 0x01E: // wait, (X-from) 6143 DIP("wait %u\n", wc); 6144 6145 /* The wait instruction causes instruction fetching and execution 6146 * to be suspended. Instruction fetching and execution are resumed 6147 * when the events specified by the WC field occur. 6148 * 6149 * 0b00 Resume instruction fetching and execution when an 6150 * exception or an event-based branch exception occurs, 6151 * or a resume signal from the platform is recieved. 6152 * 6153 * 0b01 Reserved. 6154 * 6155 * For our purposes, we will just assume the contition is always 6156 * immediately satisfied. 6157 */ 6158 break; 6159 default: 6160 vex_printf("dis_int_misc(ppc)(opc2)\n"); 6161 return False; 6162 } 6163 6164 return True; 6165 } 6166 6167 /* 6168 Integer Compare Instructions 6169 */ 6170 static Bool dis_int_cmp ( UInt theInstr ) 6171 { 6172 /* D-Form, X-Form */ 6173 UChar opc1 = ifieldOPC(theInstr); 6174 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6175 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 6176 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 6177 UChar rA_addr = ifieldRegA(theInstr); 6178 UInt uimm16 = ifieldUIMM16(theInstr); 6179 UChar rB_addr = ifieldRegB(theInstr); 6180 UInt opc2 = ifieldOPClo10(theInstr); 6181 UChar b0 = ifieldBIT0(theInstr); 6182 6183 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6184 IRExpr *a = getIReg(rA_addr); 6185 IRExpr *b; 6186 6187 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 6188 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 6189 return False; 6190 } 6191 6192 if (( b22 != 0 ) && ( opc2 != 0x080 ) ) { // setb case exception 6193 vex_printf("dis_int_cmp(ppc)(b22)\n"); 6194 return False; 6195 } 6196 6197 switch (opc1) { 6198 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 6199 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 6200 (Int)extend_s_16to32(uimm16)); 6201 b = mkSzExtendS16( ty, uimm16 ); 6202 if (flag_L == 1) { 6203 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 6204 } else { 6205 a = mkNarrowTo32( ty, a ); 6206 b = mkNarrowTo32( ty, b ); 6207 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 6208 } 6209 putCR0( crfD, getXER_SO() ); 6210 break; 6211 6212 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 6213 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 6214 b = mkSzImm( ty, uimm16 ); 6215 if (flag_L == 1) { 6216 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 6217 } else { 6218 a = mkNarrowTo32( ty, a ); 6219 b = mkNarrowTo32( ty, b ); 6220 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 6221 } 6222 putCR0( crfD, getXER_SO() ); 6223 break; 6224 6225 /* X Form */ 6226 case 0x1F: 6227 if (b0 != 0) { 6228 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 6229 return False; 6230 } 6231 b = getIReg(rB_addr); 6232 6233 switch (opc2) { 6234 case 0x000: // cmp (Compare, PPC32 p367) 6235 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 6236 /* Comparing a reg with itself produces a result which 6237 doesn't depend on the contents of the reg. Therefore 6238 remove the false dependency, which has been known to cause 6239 memcheck to produce false errors. */ 6240 if (rA_addr == rB_addr) 6241 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 6242 ? mkU64(0) : mkU32(0); 6243 if (flag_L == 1) { 6244 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 6245 } else { 6246 a = mkNarrowTo32( ty, a ); 6247 b = mkNarrowTo32( ty, b ); 6248 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 6249 } 6250 putCR0( crfD, getXER_SO() ); 6251 break; 6252 6253 case 0x020: // cmpl (Compare Logical, PPC32 p369) 6254 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 6255 /* Comparing a reg with itself produces a result which 6256 doesn't depend on the contents of the reg. Therefore 6257 remove the false dependency, which has been known to cause 6258 memcheck to produce false errors. */ 6259 if (rA_addr == rB_addr) 6260 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 6261 ? mkU64(0) : mkU32(0); 6262 if (flag_L == 1) { 6263 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 6264 } else { 6265 a = mkNarrowTo32( ty, a ); 6266 b = mkNarrowTo32( ty, b ); 6267 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 6268 } 6269 putCR0( crfD, getXER_SO() ); 6270 break; 6271 6272 case 0x080: // setb (Set Boolean) 6273 { 6274 UChar rT_addr = ifieldRegDS(theInstr); 6275 Int bfa = IFIELD(theInstr, 18, 3); 6276 IRTemp cr = newTemp(Ity_I32); 6277 IRTemp cr0 = newTemp(Ity_I32); 6278 IRTemp cr1 = newTemp(Ity_I32); 6279 IRTemp result = newTemp(Ity_I64); 6280 6281 DIP("setb r%u,%d\n", rT_addr, bfa); 6282 6283 /* Fetch the entire condition code value */ 6284 assign( cr, getGST( PPC_GST_CR ) ); 6285 6286 /* Get bit zero (IBM numbering) of the CR field specified 6287 * by bfa. 6288 */ 6289 assign( cr0, binop( Iop_And32, 6290 binop( Iop_Shr32, 6291 mkexpr( cr ), 6292 mkU8( (7-bfa)*4 ) ), 6293 mkU32( 0x8 ) ) ); 6294 assign( cr1, binop( Iop_And32, 6295 binop( Iop_Shr32, 6296 mkexpr( cr ), 6297 mkU8( (7-bfa)*4 ) ), 6298 mkU32( 0x4 ) ) ); 6299 assign( result, binop( Iop_Or64, 6300 unop( Iop_1Sto64, 6301 binop( Iop_CmpEQ32, 6302 mkexpr( cr0 ), 6303 mkU32( 0x8 ) ) ), 6304 binop( Iop_32HLto64, 6305 mkU32( 0 ), 6306 unop( Iop_1Uto32, 6307 binop( Iop_CmpEQ32, 6308 mkexpr( cr1 ), 6309 mkU32( 0x4 ) ) ) ) ) ); 6310 if ( ty == Ity_I64 ) 6311 putIReg( rT_addr, mkexpr( result ) ); 6312 else 6313 putIReg( rT_addr, unop( Iop_64to32, mkexpr(result ) ) ); 6314 } 6315 break; 6316 default: 6317 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 6318 return False; 6319 } 6320 break; 6321 6322 default: 6323 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 6324 return False; 6325 } 6326 6327 return True; 6328 } 6329 6330 6331 /* 6332 Integer Logical Instructions 6333 */ 6334 static Bool dis_int_logic ( UInt theInstr ) 6335 { 6336 /* D-Form, X-Form */ 6337 UChar opc1 = ifieldOPC(theInstr); 6338 UChar rS_addr = ifieldRegDS(theInstr); 6339 UChar rA_addr = ifieldRegA(theInstr); 6340 UInt uimm16 = ifieldUIMM16(theInstr); 6341 UChar rB_addr = ifieldRegB(theInstr); 6342 UInt opc2 = ifieldOPClo10(theInstr); 6343 UChar flag_rC = ifieldBIT0(theInstr); 6344 6345 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6346 IRTemp rS = newTemp(ty); 6347 IRTemp rA = newTemp(ty); 6348 IRTemp rB = newTemp(ty); 6349 IRExpr* irx; 6350 Bool do_rc = False; 6351 6352 assign( rS, getIReg(rS_addr) ); 6353 assign( rB, getIReg(rB_addr) ); 6354 6355 switch (opc1) { 6356 case 0x1C: // andi. (AND Immediate, PPC32 p358) 6357 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6358 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6359 mkSzImm(ty, uimm16)) ); 6360 do_rc = True; // Always record to CR 6361 flag_rC = 1; 6362 break; 6363 6364 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 6365 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6366 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6367 mkSzImm(ty, uimm16 << 16)) ); 6368 do_rc = True; // Always record to CR 6369 flag_rC = 1; 6370 break; 6371 6372 case 0x18: // ori (OR Immediate, PPC32 p497) 6373 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6374 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6375 mkSzImm(ty, uimm16)) ); 6376 break; 6377 6378 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 6379 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6380 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6381 mkSzImm(ty, uimm16 << 16)) ); 6382 break; 6383 6384 case 0x1A: // xori (XOR Immediate, PPC32 p550) 6385 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6386 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 6387 mkSzImm(ty, uimm16)) ); 6388 break; 6389 6390 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 6391 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 6392 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 6393 mkSzImm(ty, uimm16 << 16)) ); 6394 break; 6395 6396 /* X Form */ 6397 case 0x1F: 6398 6399 opc2 = IFIELD( theInstr, 2, 9 ); 6400 6401 switch ( opc2 ) { 6402 case 0x1BD: // extswsli (Extend Sign Word shift left) 6403 { 6404 /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */ 6405 UChar sh = IFIELD( theInstr, 11, 5 ) | (IFIELD(theInstr, 1, 1) << 5); 6406 IRTemp temp = newTemp( ty ); 6407 6408 DIP("extswsli%s r%u,r%u,%u\n", flag_rC ? ".":"", 6409 rA_addr, rS_addr, sh); 6410 6411 assign( temp, unop( Iop_32Sto64, 6412 unop( Iop_64to32, mkexpr( rS ) ) ) ); 6413 assign( rA, binop( Iop_Shl64, mkexpr( temp ), mkU8( sh ) ) ); 6414 putIReg( rA_addr, mkexpr( rA ) ); 6415 6416 if ( flag_rC ) { 6417 set_CR0( mkexpr( rA ) ); 6418 } 6419 return True; 6420 } 6421 default: 6422 break; // drop to next opc2 check 6423 } 6424 6425 do_rc = True; // All below record to CR, except for where we return at case end. 6426 6427 opc2 = ifieldOPClo10( theInstr ); 6428 6429 switch (opc2) { 6430 case 0x01C: // and (AND, PPC32 p356) 6431 DIP("and%s r%u,r%u,r%u\n", 6432 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6433 assign(rA, binop( mkSzOp(ty, Iop_And8), 6434 mkexpr(rS), mkexpr(rB))); 6435 break; 6436 6437 case 0x03C: // andc (AND with Complement, PPC32 p357) 6438 DIP("andc%s r%u,r%u,r%u\n", 6439 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6440 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 6441 unop( mkSzOp(ty, Iop_Not8), 6442 mkexpr(rB)))); 6443 break; 6444 6445 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 6446 IRExpr* lo32; 6447 if (rB_addr!=0) { 6448 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 6449 return False; 6450 } 6451 DIP("cntlzw%s r%u,r%u\n", 6452 flag_rC ? ".":"", rA_addr, rS_addr); 6453 6454 // mode64: count in low word only 6455 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 6456 6457 // Iop_Clz32 undefined for arg==0, so deal with that case: 6458 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 6459 assign(rA, mkWidenFrom32(ty, 6460 IRExpr_ITE( irx, 6461 unop(Iop_Clz32, lo32), 6462 mkU32(32)), 6463 False)); 6464 6465 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 6466 break; 6467 } 6468 6469 case 0x11C: // eqv (Equivalent, PPC32 p396) 6470 DIP("eqv%s r%u,r%u,r%u\n", 6471 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6472 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6473 binop( mkSzOp(ty, Iop_Xor8), 6474 mkexpr(rS), mkexpr(rB))) ); 6475 break; 6476 6477 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 6478 if (rB_addr!=0) { 6479 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 6480 return False; 6481 } 6482 DIP("extsb%s r%u,r%u\n", 6483 flag_rC ? ".":"", rA_addr, rS_addr); 6484 if (mode64) 6485 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 6486 else 6487 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 6488 break; 6489 6490 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 6491 if (rB_addr!=0) { 6492 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 6493 return False; 6494 } 6495 DIP("extsh%s r%u,r%u\n", 6496 flag_rC ? ".":"", rA_addr, rS_addr); 6497 if (mode64) 6498 assign( rA, unop(Iop_16Sto64, 6499 unop(Iop_64to16, mkexpr(rS))) ); 6500 else 6501 assign( rA, unop(Iop_16Sto32, 6502 unop(Iop_32to16, mkexpr(rS))) ); 6503 break; 6504 6505 case 0x1DC: // nand (NAND, PPC32 p492) 6506 DIP("nand%s r%u,r%u,r%u\n", 6507 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6508 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6509 binop( mkSzOp(ty, Iop_And8), 6510 mkexpr(rS), mkexpr(rB))) ); 6511 break; 6512 6513 case 0x07C: // nor (NOR, PPC32 p494) 6514 DIP("nor%s r%u,r%u,r%u\n", 6515 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6516 assign( rA, unop( mkSzOp(ty, Iop_Not8), 6517 binop( mkSzOp(ty, Iop_Or8), 6518 mkexpr(rS), mkexpr(rB))) ); 6519 break; 6520 6521 case 0x1BC: // or (OR, PPC32 p495) 6522 if ((!flag_rC) && rS_addr == rB_addr) { 6523 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 6524 assign( rA, mkexpr(rS) ); 6525 } else { 6526 DIP("or%s r%u,r%u,r%u\n", 6527 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6528 assign( rA, binop( mkSzOp(ty, Iop_Or8), 6529 mkexpr(rS), mkexpr(rB)) ); 6530 } 6531 break; 6532 6533 case 0x19C: // orc (OR with Complement, PPC32 p496) 6534 DIP("orc%s r%u,r%u,r%u\n", 6535 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6536 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 6537 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 6538 break; 6539 6540 case 0x13C: // xor (XOR, PPC32 p549) 6541 DIP("xor%s r%u,r%u,r%u\n", 6542 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6543 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 6544 mkexpr(rS), mkexpr(rB)) ); 6545 break; 6546 6547 6548 /* 64bit Integer Logical Instructions */ 6549 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 6550 if (rB_addr!=0) { 6551 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 6552 return False; 6553 } 6554 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 6555 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 6556 break; 6557 6558 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 6559 if (rB_addr!=0) { 6560 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 6561 return False; 6562 } 6563 DIP("cntlzd%s r%u,r%u\n", 6564 flag_rC ? ".":"", rA_addr, rS_addr); 6565 // Iop_Clz64 undefined for arg==0, so deal with that case: 6566 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 6567 assign(rA, IRExpr_ITE( irx, 6568 unop(Iop_Clz64, mkexpr(rS)), 6569 mkU64(64) )); 6570 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 6571 break; 6572 6573 case 0x1FC: // cmpb (Power6: compare bytes) 6574 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 6575 6576 if (mode64) 6577 assign( rA, unop( Iop_V128to64, 6578 binop( Iop_CmpEQ8x16, 6579 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 6580 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 6581 )) ); 6582 else 6583 assign( rA, unop( Iop_V128to32, 6584 binop( Iop_CmpEQ8x16, 6585 unop( Iop_32UtoV128, mkexpr(rS) ), 6586 unop( Iop_32UtoV128, mkexpr(rB) ) 6587 )) ); 6588 break; 6589 6590 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 6591 IRTemp frB = newTemp(Ity_F64); 6592 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 6593 6594 assign( frB, getFReg(rB_addr)); // always F64 6595 if (mode64) 6596 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 6597 else 6598 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 6599 6600 putIReg( rS_addr, mkexpr(rA)); 6601 return True; 6602 } 6603 6604 case 0x25F: { // mffgpr (move floating-point from general purpose register) 6605 IRTemp frA = newTemp(Ity_F64); 6606 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 6607 6608 if (mode64) 6609 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 6610 else 6611 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 6612 6613 putFReg( rS_addr, mkexpr(frA)); 6614 return True; 6615 } 6616 case 0x1FA: // popcntd (population count doubleword 6617 { 6618 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 6619 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 6620 putIReg( rA_addr, mkexpr(result) ); 6621 return True; 6622 } 6623 case 0x17A: // popcntw (Population Count Words) 6624 { 6625 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 6626 if (mode64) { 6627 IRTemp resultHi, resultLo; 6628 IRTemp argLo = newTemp(Ity_I32); 6629 IRTemp argHi = newTemp(Ity_I32); 6630 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 6631 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 6632 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 6633 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 6634 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 6635 } else { 6636 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 6637 putIReg( rA_addr, mkexpr(result) ); 6638 } 6639 return True; 6640 } 6641 case 0x7A: // popcntb (Population Count Byte) 6642 { 6643 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 6644 6645 if (mode64) { 6646 IRTemp resultHi, resultLo; 6647 IRTemp argLo = newTemp(Ity_I32); 6648 IRTemp argHi = newTemp(Ity_I32); 6649 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 6650 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 6651 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 6652 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 6653 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 6654 mkexpr(resultLo))); 6655 } else { 6656 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 6657 putIReg( rA_addr, mkexpr(result) ); 6658 } 6659 return True; 6660 } 6661 case 0x0FC: // bpermd (Bit Permute Doubleword) 6662 { 6663 /* This is a lot of rigmarole to emulate bpermd like this, as it 6664 * could be done much faster by implementing a call to the native 6665 * instruction. However, where possible I want to avoid using new 6666 * native instructions so that we can use valgrind to emulate those 6667 * instructions on older PPC64 hardware. 6668 */ 6669 #define BPERMD_IDX_MASK 0x00000000000000FFULL 6670 #define BPERMD_BIT_MASK 0x8000000000000000ULL 6671 int i; 6672 IRExpr * rS_expr = mkexpr(rS); 6673 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 6674 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 6675 for (i = 0; i < 8; i++) { 6676 IRTemp idx_tmp = newTemp( Ity_I64 ); 6677 IRTemp perm_bit = newTemp( Ity_I64 ); 6678 IRTemp idx = newTemp( Ity_I8 ); 6679 IRTemp idx_LT64 = newTemp( Ity_I1 ); 6680 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 6681 6682 assign( idx_tmp, 6683 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 6684 assign( idx_LT64, 6685 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 6686 assign( idx, 6687 binop( Iop_And8, 6688 unop( Iop_1Sto8, 6689 mkexpr(idx_LT64) ), 6690 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 6691 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 6692 * to determine which bit of rB to use for the perm bit, and then we shift 6693 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 6694 * to set the final perm bit. 6695 */ 6696 assign( idx_LT64_ity64, 6697 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 6698 assign( perm_bit, 6699 binop( Iop_And64, 6700 mkexpr( idx_LT64_ity64 ), 6701 binop( Iop_Shr64, 6702 binop( Iop_And64, 6703 mkU64( BPERMD_BIT_MASK ), 6704 binop( Iop_Shl64, 6705 mkexpr( rB ), 6706 mkexpr( idx ) ) ), 6707 mkU8( 63 ) ) ) ); 6708 res = binop( Iop_Or64, 6709 res, 6710 binop( Iop_Shl64, 6711 mkexpr( perm_bit ), 6712 mkU8( i ) ) ); 6713 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 6714 } 6715 putIReg(rA_addr, res); 6716 return True; 6717 } 6718 6719 default: 6720 vex_printf("dis_int_logic(ppc)(opc2)\n"); 6721 return False; 6722 } 6723 break; 6724 6725 default: 6726 vex_printf("dis_int_logic(ppc)(opc1)\n"); 6727 return False; 6728 } 6729 6730 putIReg( rA_addr, mkexpr(rA) ); 6731 6732 if (do_rc && flag_rC) { 6733 set_CR0( mkexpr(rA) ); 6734 } 6735 return True; 6736 } 6737 6738 /* 6739 Integer Parity Instructions 6740 */ 6741 static Bool dis_int_parity ( UInt theInstr ) 6742 { 6743 /* X-Form */ 6744 UChar opc1 = ifieldOPC(theInstr); 6745 UChar rS_addr = ifieldRegDS(theInstr); 6746 UChar rA_addr = ifieldRegA(theInstr); 6747 UChar rB_addr = ifieldRegB(theInstr); 6748 UInt opc2 = ifieldOPClo10(theInstr); 6749 UChar b0 = ifieldBIT0(theInstr); 6750 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6751 6752 IRTemp rS = newTemp(ty); 6753 IRTemp rA = newTemp(ty); 6754 IRTemp iTot1 = newTemp(Ity_I32); 6755 IRTemp iTot2 = newTemp(Ity_I32); 6756 IRTemp iTot3 = newTemp(Ity_I32); 6757 IRTemp iTot4 = newTemp(Ity_I32); 6758 IRTemp iTot5 = newTemp(Ity_I32); 6759 IRTemp iTot6 = newTemp(Ity_I32); 6760 IRTemp iTot7 = newTemp(Ity_I32); 6761 IRTemp iTot8 = newTemp(Ity_I32); 6762 IRTemp rS1 = newTemp(ty); 6763 IRTemp rS2 = newTemp(ty); 6764 IRTemp rS3 = newTemp(ty); 6765 IRTemp rS4 = newTemp(ty); 6766 IRTemp rS5 = newTemp(ty); 6767 IRTemp rS6 = newTemp(ty); 6768 IRTemp rS7 = newTemp(ty); 6769 IRTemp iHi = newTemp(Ity_I32); 6770 IRTemp iLo = newTemp(Ity_I32); 6771 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 6772 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 6773 6774 if (opc1 != 0x1f || rB_addr || b0) { 6775 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 6776 return False; 6777 } 6778 6779 assign( rS, getIReg(rS_addr) ); 6780 6781 switch (opc2) { 6782 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 6783 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 6784 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 6785 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 6786 assign( iTot2, binop(Iop_Add32, 6787 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 6788 mkexpr(iTot1)) ); 6789 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 6790 assign( iTot3, binop(Iop_Add32, 6791 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 6792 mkexpr(iTot2)) ); 6793 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 6794 assign( iTot4, binop(Iop_Add32, 6795 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 6796 mkexpr(iTot3)) ); 6797 if (mode64) { 6798 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 6799 assign( iTot5, binop(Iop_Add32, 6800 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 6801 mkexpr(iTot4)) ); 6802 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 6803 assign( iTot6, binop(Iop_Add32, 6804 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 6805 mkexpr(iTot5)) ); 6806 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 6807 assign( iTot7, binop(Iop_Add32, 6808 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 6809 mkexpr(iTot6)) ); 6810 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 6811 assign( iTot8, binop(Iop_Add32, 6812 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 6813 mkexpr(iTot7)) ); 6814 assign( rA, unop(Iop_32Uto64, 6815 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 6816 } else 6817 assign( rA, mkexpr(iTot4) ); 6818 6819 break; 6820 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 6821 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 6822 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 6823 assign( iTot2, binop(Iop_Add32, 6824 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 6825 mkexpr(iTot1)) ); 6826 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 6827 assign( iTot3, binop(Iop_Add32, 6828 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 6829 mkexpr(iTot2)) ); 6830 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 6831 assign( iTot4, binop(Iop_Add32, 6832 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 6833 mkexpr(iTot3)) ); 6834 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 6835 6836 if (mode64) { 6837 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 6838 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 6839 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 6840 assign( iTot6, binop(Iop_Add32, 6841 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 6842 mkexpr(iTot5)) ); 6843 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 6844 assign( iTot7, binop(Iop_Add32, 6845 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 6846 mkexpr(iTot6)) ); 6847 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 6848 assign( iTot8, binop(Iop_Add32, 6849 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 6850 mkexpr(iTot7)) ); 6851 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 6852 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 6853 } else 6854 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 6855 break; 6856 default: 6857 vex_printf("dis_int_parity(ppc)(opc2)\n"); 6858 return False; 6859 } 6860 6861 putIReg( rA_addr, mkexpr(rA) ); 6862 6863 return True; 6864 } 6865 6866 6867 /* 6868 Integer Rotate Instructions 6869 */ 6870 static Bool dis_int_rot ( UInt theInstr ) 6871 { 6872 /* M-Form, MDS-Form */ 6873 UChar opc1 = ifieldOPC(theInstr); 6874 UChar rS_addr = ifieldRegDS(theInstr); 6875 UChar rA_addr = ifieldRegA(theInstr); 6876 UChar rB_addr = ifieldRegB(theInstr); 6877 UChar sh_imm = rB_addr; 6878 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 6879 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 6880 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 6881 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 6882 UChar b1 = ifieldBIT1(theInstr); 6883 UChar flag_rC = ifieldBIT0(theInstr); 6884 6885 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6886 IRTemp rS = newTemp(ty); 6887 IRTemp rA = newTemp(ty); 6888 IRTemp rB = newTemp(ty); 6889 IRTemp rot = newTemp(ty); 6890 IRExpr *r; 6891 UInt mask32; 6892 ULong mask64; 6893 6894 assign( rS, getIReg(rS_addr) ); 6895 assign( rB, getIReg(rB_addr) ); 6896 6897 switch (opc1) { 6898 case 0x14: { 6899 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 6900 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6901 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6902 if (mode64) { 6903 // tmp32 = (ROTL(rS_Lo32, Imm) 6904 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 6905 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6906 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 6907 r = unop(Iop_32Uto64, r); 6908 assign( rot, binop(Iop_Or64, r, 6909 binop(Iop_Shl64, r, mkU8(32))) ); 6910 assign( rA, 6911 binop(Iop_Or64, 6912 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 6913 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 6914 } 6915 else { 6916 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 6917 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6918 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 6919 assign( rA, 6920 binop(Iop_Or32, 6921 binop(Iop_And32, mkU32(mask32), r), 6922 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 6923 } 6924 break; 6925 } 6926 6927 case 0x15: { 6928 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 6929 vassert(MaskBeg < 32); 6930 vassert(MaskEnd < 32); 6931 vassert(sh_imm < 32); 6932 6933 if (mode64) { 6934 IRTemp rTmp = newTemp(Ity_I64); 6935 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6936 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6937 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6938 // tmp32 = (ROTL(rS_Lo32, Imm) 6939 // rA = ((tmp32 || tmp32) & mask64) 6940 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 6941 r = unop(Iop_32Uto64, r); 6942 assign( rTmp, r ); 6943 r = NULL; 6944 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 6945 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 6946 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 6947 } 6948 else { 6949 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 6950 /* Special-case the ,n,0,31-n form as that is just n-bit 6951 shift left, PPC32 p501 */ 6952 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6953 rA_addr, rS_addr, sh_imm); 6954 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 6955 } 6956 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 6957 /* Special-case the ,32-n,n,31 form as that is just n-bit 6958 unsigned shift right, PPC32 p501 */ 6959 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6960 rA_addr, rS_addr, MaskBeg); 6961 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 6962 } 6963 else { 6964 /* General case. */ 6965 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6966 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 6967 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 6968 // rA = ROTL(rS, Imm) & mask 6969 assign( rA, binop(Iop_And32, 6970 ROTL(mkexpr(rS), mkU8(sh_imm)), 6971 mkU32(mask32)) ); 6972 } 6973 } 6974 break; 6975 } 6976 6977 case 0x17: { 6978 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 6979 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 6980 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 6981 if (mode64) { 6982 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 6983 /* weird insn alert! 6984 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 6985 rA = ((tmp32 || tmp32) & mask64) 6986 */ 6987 // note, ROTL does the masking, so we don't do it here 6988 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 6989 unop(Iop_64to8, mkexpr(rB)) ); 6990 r = unop(Iop_32Uto64, r); 6991 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 6992 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 6993 } else { 6994 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 6995 // rA = ROTL(rS, rB[0-4]) & mask 6996 // note, ROTL does the masking, so we don't do it here 6997 assign( rA, binop(Iop_And32, 6998 ROTL(mkexpr(rS), 6999 unop(Iop_32to8, mkexpr(rB))), 7000 mkU32(mask32)) ); 7001 } 7002 break; 7003 } 7004 7005 /* 64bit Integer Rotates */ 7006 case 0x1E: { 7007 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 7008 sh_imm |= b1 << 5; 7009 7010 vassert( msk_imm < 64 ); 7011 vassert( sh_imm < 64 ); 7012 7013 switch (opc2) { 7014 case 0x4: { 7015 /* r = ROTL64( rS, rB_lo6) */ 7016 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 7017 7018 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 7019 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 7020 rA_addr, rS_addr, rB_addr, msk_imm); 7021 // note, ROTL does the masking, so we don't do it here 7022 mask64 = MASK64(0, 63-msk_imm); 7023 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7024 break; 7025 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 7026 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 7027 rA_addr, rS_addr, rB_addr, msk_imm); 7028 mask64 = MASK64(63-msk_imm, 63); 7029 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7030 break; 7031 } 7032 break; 7033 } 7034 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 7035 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7036 rA_addr, rS_addr, sh_imm, msk_imm); 7037 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7038 mask64 = MASK64(sh_imm, 63-msk_imm); 7039 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7040 break; 7041 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 7042 /* 7043 Hmm... looks like this'll do the job more simply: 7044 r = SHL(rS, sh_imm) 7045 m = ~(1 << (63-msk_imm)) 7046 assign(rA, r & m); 7047 */ 7048 7049 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 7050 if (mode64 7051 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 7052 /* special-case the ,64-n,n form as that is just 7053 unsigned shift-right by n */ 7054 DIP("srdi%s r%u,r%u,%u\n", 7055 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 7056 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 7057 } else { 7058 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7059 rA_addr, rS_addr, sh_imm, msk_imm); 7060 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7061 mask64 = MASK64(0, 63-msk_imm); 7062 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7063 } 7064 break; 7065 7066 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 7067 if (mode64 7068 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 7069 /* special-case the ,n,63-n form as that is just 7070 shift-left by n */ 7071 DIP("sldi%s r%u,r%u,%u\n", 7072 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 7073 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 7074 } else { 7075 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7076 rA_addr, rS_addr, sh_imm, msk_imm); 7077 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7078 mask64 = MASK64(63-msk_imm, 63); 7079 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 7080 } 7081 break; 7082 7083 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 7084 IRTemp rA_orig = newTemp(ty); 7085 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 7086 rA_addr, rS_addr, sh_imm, msk_imm); 7087 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 7088 mask64 = MASK64(sh_imm, 63-msk_imm); 7089 assign( rA_orig, getIReg(rA_addr) ); 7090 assign( rA, binop(Iop_Or64, 7091 binop(Iop_And64, mkU64(mask64), r), 7092 binop(Iop_And64, mkU64(~mask64), 7093 mkexpr(rA_orig))) ); 7094 break; 7095 } 7096 default: 7097 vex_printf("dis_int_rot(ppc)(opc2)\n"); 7098 return False; 7099 } 7100 break; 7101 } 7102 7103 default: 7104 vex_printf("dis_int_rot(ppc)(opc1)\n"); 7105 return False; 7106 } 7107 7108 putIReg( rA_addr, mkexpr(rA) ); 7109 7110 if (flag_rC) { 7111 set_CR0( mkexpr(rA) ); 7112 } 7113 return True; 7114 } 7115 7116 7117 /* 7118 Integer Load Instructions 7119 */ 7120 static Bool dis_int_load ( UInt theInstr ) 7121 { 7122 /* D-Form, X-Form, DS-Form */ 7123 UChar opc1 = ifieldOPC(theInstr); 7124 UChar rD_addr = ifieldRegDS(theInstr); 7125 UChar rA_addr = ifieldRegA(theInstr); 7126 UInt uimm16 = ifieldUIMM16(theInstr); 7127 UChar rB_addr = ifieldRegB(theInstr); 7128 UInt opc2 = ifieldOPClo10(theInstr); 7129 UChar b1 = ifieldBIT1(theInstr); 7130 UChar b0 = ifieldBIT0(theInstr); 7131 7132 Int simm16 = extend_s_16to32(uimm16); 7133 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7134 IRTemp EA = newTemp(ty); 7135 IRExpr* val; 7136 7137 switch (opc1) { 7138 case 0x1F: // register offset 7139 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7140 break; 7141 case 0x38: // immediate offset: 64bit: lq: maskoff 7142 // lowest 4 bits of immediate before forming EA 7143 simm16 = simm16 & 0xFFFFFFF0; 7144 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7145 break; 7146 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 7147 // lowest 2 bits of immediate before forming EA 7148 simm16 = simm16 & 0xFFFFFFFC; 7149 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7150 break; 7151 default: // immediate offset 7152 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7153 break; 7154 } 7155 7156 switch (opc1) { 7157 case 0x22: // lbz (Load B & Zero, PPC32 p433) 7158 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7159 val = load(Ity_I8, mkexpr(EA)); 7160 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7161 break; 7162 7163 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 7164 if (rA_addr == 0 || rA_addr == rD_addr) { 7165 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 7166 return False; 7167 } 7168 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7169 val = load(Ity_I8, mkexpr(EA)); 7170 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7171 putIReg( rA_addr, mkexpr(EA) ); 7172 break; 7173 7174 case 0x2A: // lha (Load HW Alg, PPC32 p445) 7175 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7176 val = load(Ity_I16, mkexpr(EA)); 7177 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7178 break; 7179 7180 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 7181 if (rA_addr == 0 || rA_addr == rD_addr) { 7182 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 7183 return False; 7184 } 7185 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7186 val = load(Ity_I16, mkexpr(EA)); 7187 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7188 putIReg( rA_addr, mkexpr(EA) ); 7189 break; 7190 7191 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 7192 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7193 val = load(Ity_I16, mkexpr(EA)); 7194 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7195 break; 7196 7197 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 7198 if (rA_addr == 0 || rA_addr == rD_addr) { 7199 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 7200 return False; 7201 } 7202 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7203 val = load(Ity_I16, mkexpr(EA)); 7204 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7205 putIReg( rA_addr, mkexpr(EA) ); 7206 break; 7207 7208 case 0x20: // lwz (Load W & Zero, PPC32 p460) 7209 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7210 val = load(Ity_I32, mkexpr(EA)); 7211 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7212 break; 7213 7214 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 7215 if (rA_addr == 0 || rA_addr == rD_addr) { 7216 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 7217 return False; 7218 } 7219 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 7220 val = load(Ity_I32, mkexpr(EA)); 7221 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7222 putIReg( rA_addr, mkexpr(EA) ); 7223 break; 7224 7225 /* X Form */ 7226 case 0x1F: 7227 if (b0 != 0) { 7228 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 7229 return False; 7230 } 7231 7232 switch (opc2) { 7233 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 7234 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7235 if (rA_addr == 0 || rA_addr == rD_addr) { 7236 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 7237 return False; 7238 } 7239 val = load(Ity_I8, mkexpr(EA)); 7240 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7241 putIReg( rA_addr, mkexpr(EA) ); 7242 break; 7243 7244 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 7245 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7246 val = load(Ity_I8, mkexpr(EA)); 7247 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 7248 break; 7249 7250 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 7251 if (rA_addr == 0 || rA_addr == rD_addr) { 7252 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 7253 return False; 7254 } 7255 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7256 val = load(Ity_I16, mkexpr(EA)); 7257 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7258 putIReg( rA_addr, mkexpr(EA) ); 7259 break; 7260 7261 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 7262 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7263 val = load(Ity_I16, mkexpr(EA)); 7264 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 7265 break; 7266 7267 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 7268 if (rA_addr == 0 || rA_addr == rD_addr) { 7269 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 7270 return False; 7271 } 7272 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7273 val = load(Ity_I16, mkexpr(EA)); 7274 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7275 putIReg( rA_addr, mkexpr(EA) ); 7276 break; 7277 7278 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 7279 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7280 val = load(Ity_I16, mkexpr(EA)); 7281 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 7282 break; 7283 7284 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 7285 if (rA_addr == 0 || rA_addr == rD_addr) { 7286 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 7287 return False; 7288 } 7289 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7290 val = load(Ity_I32, mkexpr(EA)); 7291 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7292 putIReg( rA_addr, mkexpr(EA) ); 7293 break; 7294 7295 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 7296 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7297 val = load(Ity_I32, mkexpr(EA)); 7298 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 7299 break; 7300 7301 7302 /* 64bit Loads */ 7303 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 7304 if (rA_addr == 0 || rA_addr == rD_addr) { 7305 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 7306 return False; 7307 } 7308 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7309 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7310 putIReg( rA_addr, mkexpr(EA) ); 7311 break; 7312 7313 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 7314 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7315 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7316 break; 7317 7318 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 7319 if (rA_addr == 0 || rA_addr == rD_addr) { 7320 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 7321 return False; 7322 } 7323 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7324 putIReg( rD_addr, 7325 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7326 putIReg( rA_addr, mkexpr(EA) ); 7327 break; 7328 7329 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 7330 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7331 putIReg( rD_addr, 7332 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7333 break; 7334 7335 default: 7336 vex_printf("dis_int_load(ppc)(opc2)\n"); 7337 return False; 7338 } 7339 break; 7340 7341 /* DS Form - 64bit Loads. In each case EA will have been formed 7342 with the lowest 2 bits masked off the immediate offset. */ 7343 case 0x3A: 7344 switch ((b1<<1) | b0) { 7345 case 0x0: // ld (Load DWord, PPC64 p472) 7346 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7347 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7348 break; 7349 7350 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 7351 if (rA_addr == 0 || rA_addr == rD_addr) { 7352 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 7353 return False; 7354 } 7355 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7356 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 7357 putIReg( rA_addr, mkexpr(EA) ); 7358 break; 7359 7360 case 0x2: // lwa (Load Word Alg, PPC64 p499) 7361 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7362 putIReg( rD_addr, 7363 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 7364 break; 7365 7366 default: 7367 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 7368 return False; 7369 } 7370 break; 7371 7372 case 0x38: { 7373 IRTemp high = newTemp(ty); 7374 IRTemp low = newTemp(ty); 7375 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 7376 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7377 /* NOTE: there are some changes to XER[41:42] that have not been 7378 * implemented. 7379 */ 7380 // trap if EA misaligned on 16 byte address 7381 if (mode64) { 7382 if (host_endness == VexEndnessBE) { 7383 assign(high, load(ty, mkexpr( EA ) ) ); 7384 assign(low, load(ty, binop( Iop_Add64, 7385 mkexpr( EA ), 7386 mkU64( 8 ) ) ) ); 7387 } else { 7388 assign(low, load(ty, mkexpr( EA ) ) ); 7389 assign(high, load(ty, binop( Iop_Add64, 7390 mkexpr( EA ), 7391 mkU64( 8 ) ) ) ); 7392 } 7393 } else { 7394 assign(high, load(ty, binop( Iop_Add32, 7395 mkexpr( EA ), 7396 mkU32( 4 ) ) ) ); 7397 assign(low, load(ty, binop( Iop_Add32, 7398 mkexpr( EA ), 7399 mkU32( 12 ) ) ) ); 7400 } 7401 gen_SIGBUS_if_misaligned( EA, 16 ); 7402 putIReg( rD_addr, mkexpr( high) ); 7403 putIReg( rD_addr+1, mkexpr( low) ); 7404 break; 7405 } 7406 default: 7407 vex_printf("dis_int_load(ppc)(opc1)\n"); 7408 return False; 7409 } 7410 return True; 7411 } 7412 7413 7414 7415 /* 7416 Integer Store Instructions 7417 */ 7418 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 7419 { 7420 /* D-Form, X-Form, DS-Form */ 7421 UChar opc1 = ifieldOPC(theInstr); 7422 UInt rS_addr = ifieldRegDS(theInstr); 7423 UInt rA_addr = ifieldRegA(theInstr); 7424 UInt uimm16 = ifieldUIMM16(theInstr); 7425 UInt rB_addr = ifieldRegB(theInstr); 7426 UInt opc2 = ifieldOPClo10(theInstr); 7427 UChar b1 = ifieldBIT1(theInstr); 7428 UChar b0 = ifieldBIT0(theInstr); 7429 7430 Int simm16 = extend_s_16to32(uimm16); 7431 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7432 IRTemp rS = newTemp(ty); 7433 IRTemp rB = newTemp(ty); 7434 IRTemp EA = newTemp(ty); 7435 7436 assign( rB, getIReg(rB_addr) ); 7437 assign( rS, getIReg(rS_addr) ); 7438 7439 switch (opc1) { 7440 case 0x1F: // register offset 7441 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7442 break; 7443 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 7444 // lowest 2 bits of immediate before forming EA 7445 simm16 = simm16 & 0xFFFFFFFC; 7446 default: // immediate offset 7447 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7448 break; 7449 } 7450 7451 switch (opc1) { 7452 case 0x26: // stb (Store B, PPC32 p509) 7453 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7454 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7455 break; 7456 7457 case 0x27: // stbu (Store B, Update, PPC32 p510) 7458 if (rA_addr == 0 ) { 7459 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 7460 return False; 7461 } 7462 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7463 putIReg( rA_addr, mkexpr(EA) ); 7464 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7465 break; 7466 7467 case 0x2C: // sth (Store HW, PPC32 p522) 7468 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7469 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7470 break; 7471 7472 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 7473 if (rA_addr == 0) { 7474 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 7475 return False; 7476 } 7477 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7478 putIReg( rA_addr, mkexpr(EA) ); 7479 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7480 break; 7481 7482 case 0x24: // stw (Store W, PPC32 p530) 7483 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7484 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7485 break; 7486 7487 case 0x25: // stwu (Store W, Update, PPC32 p534) 7488 if (rA_addr == 0) { 7489 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 7490 return False; 7491 } 7492 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7493 putIReg( rA_addr, mkexpr(EA) ); 7494 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7495 break; 7496 7497 /* X Form : all these use EA_indexed */ 7498 case 0x1F: 7499 if (b0 != 0) { 7500 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 7501 return False; 7502 } 7503 7504 switch (opc2) { 7505 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 7506 if (rA_addr == 0) { 7507 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 7508 return False; 7509 } 7510 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7511 putIReg( rA_addr, mkexpr(EA) ); 7512 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7513 break; 7514 7515 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 7516 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7517 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 7518 break; 7519 7520 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 7521 if (rA_addr == 0) { 7522 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 7523 return False; 7524 } 7525 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7526 putIReg( rA_addr, mkexpr(EA) ); 7527 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7528 break; 7529 7530 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 7531 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7532 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 7533 break; 7534 7535 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 7536 if (rA_addr == 0) { 7537 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 7538 return False; 7539 } 7540 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7541 putIReg( rA_addr, mkexpr(EA) ); 7542 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7543 break; 7544 7545 case 0x097: // stwx (Store W Indexed, PPC32 p536) 7546 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7547 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 7548 break; 7549 7550 7551 /* 64bit Stores */ 7552 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 7553 if (rA_addr == 0) { 7554 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 7555 return False; 7556 } 7557 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7558 putIReg( rA_addr, mkexpr(EA) ); 7559 store( mkexpr(EA), mkexpr(rS) ); 7560 break; 7561 7562 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 7563 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7564 store( mkexpr(EA), mkexpr(rS) ); 7565 break; 7566 7567 default: 7568 vex_printf("dis_int_store(ppc)(opc2)\n"); 7569 return False; 7570 } 7571 break; 7572 7573 /* DS Form - 64bit Stores. In each case EA will have been formed 7574 with the lowest 2 bits masked off the immediate offset. */ 7575 case 0x3E: 7576 switch ((b1<<1) | b0) { 7577 case 0x0: // std (Store DWord, PPC64 p580) 7578 if (!mode64) 7579 return False; 7580 7581 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7582 store( mkexpr(EA), mkexpr(rS) ); 7583 break; 7584 7585 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 7586 if (!mode64) 7587 return False; 7588 7589 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7590 putIReg( rA_addr, mkexpr(EA) ); 7591 store( mkexpr(EA), mkexpr(rS) ); 7592 break; 7593 7594 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 7595 IRTemp EA_hi = newTemp(ty); 7596 IRTemp EA_lo = newTemp(ty); 7597 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7598 7599 if (mode64) { 7600 if (host_endness == VexEndnessBE) { 7601 7602 /* upper 64-bits */ 7603 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 7604 7605 /* lower 64-bits */ 7606 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 7607 } else { 7608 /* upper 64-bits */ 7609 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 7610 7611 /* lower 64-bits */ 7612 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 7613 } 7614 } else { 7615 /* upper half of upper 64-bits */ 7616 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 7617 7618 /* lower half of upper 64-bits */ 7619 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 7620 } 7621 store( mkexpr(EA_hi), mkexpr(rS) ); 7622 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 7623 break; 7624 } 7625 default: 7626 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 7627 return False; 7628 } 7629 break; 7630 7631 default: 7632 vex_printf("dis_int_store(ppc)(opc1)\n"); 7633 return False; 7634 } 7635 return True; 7636 } 7637 7638 7639 7640 /* 7641 Integer Load/Store Multiple Instructions 7642 */ 7643 static Bool dis_int_ldst_mult ( UInt theInstr ) 7644 { 7645 /* D-Form */ 7646 UChar opc1 = ifieldOPC(theInstr); 7647 UChar rD_addr = ifieldRegDS(theInstr); 7648 UChar rS_addr = rD_addr; 7649 UChar rA_addr = ifieldRegA(theInstr); 7650 UInt uimm16 = ifieldUIMM16(theInstr); 7651 7652 Int simm16 = extend_s_16to32(uimm16); 7653 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7654 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 7655 IRTemp EA = newTemp(ty); 7656 UInt r = 0; 7657 UInt ea_off = 0; 7658 IRExpr* irx_addr; 7659 7660 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 7661 7662 switch (opc1) { 7663 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 7664 if (rA_addr >= rD_addr) { 7665 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 7666 return False; 7667 } 7668 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 7669 for (r = rD_addr; r <= 31; r++) { 7670 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 7671 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 7672 False) ); 7673 ea_off += 4; 7674 } 7675 break; 7676 7677 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 7678 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 7679 for (r = rS_addr; r <= 31; r++) { 7680 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 7681 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 7682 ea_off += 4; 7683 } 7684 break; 7685 7686 default: 7687 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 7688 return False; 7689 } 7690 return True; 7691 } 7692 7693 7694 7695 /* 7696 Integer Load/Store String Instructions 7697 */ 7698 static 7699 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 7700 IRTemp EA, // EA 7701 Int rD, // first dst register 7702 Int maxBytes ) // 32 or 128 7703 { 7704 Int i, shift = 24; 7705 IRExpr* e_nbytes = mkexpr(tNBytes); 7706 IRExpr* e_EA = mkexpr(EA); 7707 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7708 7709 vassert(rD >= 0 && rD < 32); 7710 rD--; if (rD < 0) rD = 31; 7711 7712 for (i = 0; i < maxBytes; i++) { 7713 /* if (nBytes < (i+1)) goto NIA; */ 7714 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 7715 Ijk_Boring, 7716 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 7717 /* when crossing into a new dest register, set it to zero. */ 7718 if ((i % 4) == 0) { 7719 rD++; if (rD == 32) rD = 0; 7720 putIReg(rD, mkSzImm(ty, 0)); 7721 shift = 24; 7722 } 7723 /* rD |= (8Uto32(*(EA+i))) << shift */ 7724 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 7725 putIReg( 7726 rD, 7727 mkWidenFrom32( 7728 ty, 7729 binop( 7730 Iop_Or32, 7731 mkNarrowTo32(ty, getIReg(rD)), 7732 binop( 7733 Iop_Shl32, 7734 unop( 7735 Iop_8Uto32, 7736 load( Ity_I8, 7737 binop( mkSzOp(ty,Iop_Add8), 7738 e_EA, mkSzImm(ty,i))) 7739 ), 7740 mkU8(toUChar(shift)) 7741 ) 7742 ), 7743 /*Signed*/False 7744 ) 7745 ); 7746 shift -= 8; 7747 } 7748 } 7749 7750 static 7751 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 7752 IRTemp EA, // EA 7753 Int rS, // first src register 7754 Int maxBytes ) // 32 or 128 7755 { 7756 Int i, shift = 24; 7757 IRExpr* e_nbytes = mkexpr(tNBytes); 7758 IRExpr* e_EA = mkexpr(EA); 7759 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7760 7761 vassert(rS >= 0 && rS < 32); 7762 rS--; if (rS < 0) rS = 31; 7763 7764 for (i = 0; i < maxBytes; i++) { 7765 /* if (nBytes < (i+1)) goto NIA; */ 7766 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 7767 Ijk_Boring, 7768 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 7769 /* check for crossing into a new src register. */ 7770 if ((i % 4) == 0) { 7771 rS++; if (rS == 32) rS = 0; 7772 shift = 24; 7773 } 7774 /* *(EA+i) = 32to8(rS >> shift) */ 7775 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 7776 store( 7777 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 7778 unop( Iop_32to8, 7779 binop( Iop_Shr32, 7780 mkNarrowTo32( ty, getIReg(rS) ), 7781 mkU8( toUChar(shift) ))) 7782 ); 7783 shift -= 8; 7784 } 7785 } 7786 7787 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 7788 { 7789 /* X-Form */ 7790 UChar opc1 = ifieldOPC(theInstr); 7791 UChar rD_addr = ifieldRegDS(theInstr); 7792 UChar rS_addr = rD_addr; 7793 UChar rA_addr = ifieldRegA(theInstr); 7794 UChar rB_addr = ifieldRegB(theInstr); 7795 UChar NumBytes = rB_addr; 7796 UInt opc2 = ifieldOPClo10(theInstr); 7797 UChar b0 = ifieldBIT0(theInstr); 7798 7799 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7800 IRTemp t_EA = newTemp(ty); 7801 IRTemp t_nbytes = IRTemp_INVALID; 7802 7803 *stopHere = False; 7804 7805 if (opc1 != 0x1F || b0 != 0) { 7806 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 7807 return False; 7808 } 7809 7810 switch (opc2) { 7811 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 7812 /* NB: does not reject the case where RA is in the range of 7813 registers to be loaded. It should. */ 7814 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 7815 assign( t_EA, ea_rAor0(rA_addr) ); 7816 if (NumBytes == 8 && !mode64) { 7817 /* Special case hack */ 7818 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 7819 putIReg( rD_addr, 7820 load(Ity_I32, mkexpr(t_EA)) ); 7821 putIReg( (rD_addr+1) % 32, 7822 load(Ity_I32, 7823 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 7824 } else { 7825 t_nbytes = newTemp(Ity_I32); 7826 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 7827 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 7828 *stopHere = True; 7829 } 7830 return True; 7831 7832 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 7833 /* NB: does not reject the case where RA is in the range of 7834 registers to be loaded. It should. Although considering 7835 that that can only be detected at run time, it's not easy to 7836 do so. */ 7837 if (rD_addr == rA_addr || rD_addr == rB_addr) 7838 return False; 7839 if (rD_addr == 0 && rA_addr == 0) 7840 return False; 7841 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7842 t_nbytes = newTemp(Ity_I32); 7843 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 7844 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 7845 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 7846 *stopHere = True; 7847 return True; 7848 7849 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 7850 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 7851 assign( t_EA, ea_rAor0(rA_addr) ); 7852 if (NumBytes == 8 && !mode64) { 7853 /* Special case hack */ 7854 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 7855 store( mkexpr(t_EA), 7856 getIReg(rD_addr) ); 7857 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 7858 getIReg((rD_addr+1) % 32) ); 7859 } else { 7860 t_nbytes = newTemp(Ity_I32); 7861 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 7862 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 7863 *stopHere = True; 7864 } 7865 return True; 7866 7867 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 7868 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7869 t_nbytes = newTemp(Ity_I32); 7870 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 7871 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 7872 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 7873 *stopHere = True; 7874 return True; 7875 7876 default: 7877 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 7878 return False; 7879 } 7880 return True; 7881 } 7882 7883 7884 /* ------------------------------------------------------------------ 7885 Integer Branch Instructions 7886 ------------------------------------------------------------------ */ 7887 7888 /* 7889 Branch helper function 7890 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 7891 Returns an I32 which is 0x00000000 if the ctr condition failed 7892 and 0xFFFFFFFF otherwise. 7893 */ 7894 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 7895 { 7896 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7897 IRTemp ok = newTemp(Ity_I32); 7898 7899 if ((BO >> 2) & 1) { // independent of ctr 7900 assign( ok, mkU32(0xFFFFFFFF) ); 7901 } else { 7902 if ((BO >> 1) & 1) { // ctr == 0 ? 7903 assign( ok, unop( Iop_1Sto32, 7904 binop( mkSzOp(ty, Iop_CmpEQ8), 7905 getGST( PPC_GST_CTR ), 7906 mkSzImm(ty,0))) ); 7907 } else { // ctr != 0 ? 7908 assign( ok, unop( Iop_1Sto32, 7909 binop( mkSzOp(ty, Iop_CmpNE8), 7910 getGST( PPC_GST_CTR ), 7911 mkSzImm(ty,0))) ); 7912 } 7913 } 7914 return mkexpr(ok); 7915 } 7916 7917 7918 /* 7919 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 7920 Returns an I32 which is either 0 if the condition failed or 7921 some arbitrary nonzero value otherwise. */ 7922 7923 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 7924 { 7925 Int where; 7926 IRTemp res = newTemp(Ity_I32); 7927 IRTemp cr_bi = newTemp(Ity_I32); 7928 7929 if ((BO >> 4) & 1) { 7930 assign( res, mkU32(1) ); 7931 } else { 7932 // ok = (CR[BI] == BO[3]) Note, the following relies on 7933 // getCRbit_anywhere returning a value which 7934 // is either zero or has exactly 1 bit set. 7935 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 7936 7937 if ((BO >> 3) & 1) { 7938 /* We can use cr_bi as-is. */ 7939 assign( res, mkexpr(cr_bi) ); 7940 } else { 7941 /* We have to invert the sense of the information held in 7942 cr_bi. For that we need to know which bit 7943 getCRbit_anywhere regards as significant. */ 7944 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 7945 mkU32(1<<where)) ); 7946 } 7947 } 7948 return mkexpr(res); 7949 } 7950 7951 7952 /* 7953 Integer Branch Instructions 7954 */ 7955 static Bool dis_branch ( UInt theInstr, 7956 const VexAbiInfo* vbi, 7957 /*OUT*/DisResult* dres, 7958 Bool (*resteerOkFn)(void*,Addr), 7959 void* callback_opaque ) 7960 { 7961 UChar opc1 = ifieldOPC(theInstr); 7962 UChar BO = ifieldRegDS(theInstr); 7963 UChar BI = ifieldRegA(theInstr); 7964 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 7965 UChar b11to15 = ifieldRegB(theInstr); 7966 UInt opc2 = ifieldOPClo10(theInstr); 7967 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 7968 UChar flag_AA = ifieldBIT1(theInstr); 7969 UChar flag_LK = ifieldBIT0(theInstr); 7970 7971 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7972 Addr64 tgt = 0; 7973 UInt BD = extend_s_16to32(BD_u16); 7974 IRTemp do_branch = newTemp(Ity_I32); 7975 IRTemp ctr_ok = newTemp(Ity_I32); 7976 IRTemp cond_ok = newTemp(Ity_I32); 7977 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 7978 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 7979 IRTemp lr_old = newTemp(ty); 7980 7981 /* Hack to pass through code that just wants to read the PC */ 7982 if (theInstr == 0x429F0005) { 7983 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 7984 putGST( PPC_GST_LR, e_nia ); 7985 return True; 7986 } 7987 7988 /* The default what-next. Individual cases can override it. */ 7989 dres->whatNext = Dis_StopHere; 7990 vassert(dres->jk_StopHere == Ijk_INVALID); 7991 7992 switch (opc1) { 7993 case 0x12: // b (Branch, PPC32 p360) 7994 if (flag_AA) { 7995 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 7996 } else { 7997 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 7998 (Long)extend_s_26to64(LI_u26) ); 7999 } 8000 if (mode64) { 8001 DIP("b%s%s 0x%llx\n", 8002 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 8003 } else { 8004 DIP("b%s%s 0x%x\n", 8005 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 8006 } 8007 8008 if (flag_LK) { 8009 putGST( PPC_GST_LR, e_nia ); 8010 if (vbi->guest_ppc_zap_RZ_at_bl 8011 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 8012 IRTemp t_tgt = newTemp(ty); 8013 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 8014 make_redzone_AbiHint( vbi, t_tgt, 8015 "branch-and-link (unconditional call)" ); 8016 } 8017 } 8018 8019 if (resteerOkFn( callback_opaque, tgt )) { 8020 dres->whatNext = Dis_ResteerU; 8021 dres->continueAt = tgt; 8022 } else { 8023 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 8024 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 8025 } 8026 break; 8027 8028 case 0x10: // bc (Branch Conditional, PPC32 p361) 8029 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 8030 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 8031 8032 if (!(BO & 0x4)) { 8033 putGST( PPC_GST_CTR, 8034 binop(mkSzOp(ty, Iop_Sub8), 8035 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 8036 } 8037 8038 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 8039 cond_ok is either zero or nonzero, since that's the cheapest 8040 way to compute it. Anding them together gives a value which 8041 is either zero or non zero and so that's what we must test 8042 for in the IRStmt_Exit. */ 8043 assign( ctr_ok, branch_ctr_ok( BO ) ); 8044 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8045 assign( do_branch, 8046 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 8047 8048 if (flag_AA) { 8049 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 8050 } else { 8051 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 8052 (Long)extend_s_16to64(BD_u16)); 8053 } 8054 if (flag_LK) 8055 putGST( PPC_GST_LR, e_nia ); 8056 8057 stmt( IRStmt_Exit( 8058 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 8059 flag_LK ? Ijk_Call : Ijk_Boring, 8060 mkSzConst(ty, tgt), OFFB_CIA ) ); 8061 8062 dres->jk_StopHere = Ijk_Boring; 8063 putGST( PPC_GST_CIA, e_nia ); 8064 break; 8065 8066 case 0x13: 8067 /* For bclr and bcctr, it appears that the lowest two bits of 8068 b11to15 are a branch hint, and so we only need to ensure it's 8069 of the form 000XX. */ 8070 if ((b11to15 & ~3) != 0) { 8071 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15); 8072 return False; 8073 } 8074 8075 switch (opc2) { 8076 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 8077 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 8078 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 8079 return False; 8080 } 8081 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 8082 8083 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8084 8085 /* FIXME: this is confusing. lr_old holds the old value 8086 of ctr, not lr :-) */ 8087 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 8088 8089 if (flag_LK) 8090 putGST( PPC_GST_LR, e_nia ); 8091 8092 stmt( IRStmt_Exit( 8093 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 8094 Ijk_Boring, 8095 c_nia, OFFB_CIA )); 8096 8097 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 8098 make_redzone_AbiHint( vbi, lr_old, 8099 "b-ctr-l (indirect call)" ); 8100 } 8101 8102 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 8103 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 8104 break; 8105 8106 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 8107 Bool vanilla_return = False; 8108 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 8109 DIP("blr\n"); 8110 vanilla_return = True; 8111 } else { 8112 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 8113 } 8114 8115 if (!(BO & 0x4)) { 8116 putGST( PPC_GST_CTR, 8117 binop(mkSzOp(ty, Iop_Sub8), 8118 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 8119 } 8120 8121 /* See comments above for 'bc' about this */ 8122 assign( ctr_ok, branch_ctr_ok( BO ) ); 8123 assign( cond_ok, branch_cond_ok( BO, BI ) ); 8124 assign( do_branch, 8125 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 8126 8127 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 8128 8129 if (flag_LK) 8130 putGST( PPC_GST_LR, e_nia ); 8131 8132 stmt( IRStmt_Exit( 8133 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 8134 Ijk_Boring, 8135 c_nia, OFFB_CIA )); 8136 8137 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 8138 make_redzone_AbiHint( vbi, lr_old, 8139 "branch-to-lr (unconditional return)" ); 8140 } 8141 8142 /* blrl is pretty strange; it's like a return that sets the 8143 return address of its caller to the insn following this 8144 one. Mark it as a return. */ 8145 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 8146 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 8147 break; 8148 } 8149 default: 8150 vex_printf("dis_int_branch(ppc)(opc2)\n"); 8151 return False; 8152 } 8153 break; 8154 8155 default: 8156 vex_printf("dis_int_branch(ppc)(opc1)\n"); 8157 return False; 8158 } 8159 8160 return True; 8161 } 8162 8163 /* 8164 * PC relative instruction 8165 */ 8166 static Bool dis_pc_relative ( UInt theInstr ) 8167 { 8168 /* DX-Form */ 8169 UChar opc1 = ifieldOPC(theInstr); 8170 unsigned long long D; 8171 UInt d0 = IFIELD(theInstr, 6, 10); 8172 UInt d1 = IFIELD(theInstr, 16, 5); 8173 UInt d2 = IFIELD(theInstr, 0, 1); 8174 UChar rT_addr = ifieldRegDS(theInstr); 8175 UInt opc2 = ifieldOPClo5(theInstr); 8176 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8177 8178 if ( opc1 != 0x13) { 8179 vex_printf("dis_pc_relative(ppc)(opc1)\n"); 8180 return False; 8181 } 8182 8183 switch (opc2) { 8184 case 0x002: // addpcis (Add PC immediate Shifted DX-form) 8185 { 8186 IRExpr* nia = mkSzImm(ty, nextInsnAddr()); 8187 IRExpr* result; 8188 8189 D = (d0 << 6) | (d1 << 1) | d2; 8190 DIP("addpcis %u,%llu\n", rT_addr, D); 8191 8192 if ( (D & 0x8000) == 0x8000 ) 8193 D = 0xFFFFFFFFFFFF0000UL | D; // sign extend 8194 8195 if ( ty == Ity_I32 ) { 8196 result = binop( Iop_Add32, nia, mkU32( D << 16 ) ); 8197 } else { 8198 vassert( ty == Ity_I64 ); 8199 result = binop( Iop_Add64, nia, mkU64( D << 16 ) ); 8200 } 8201 8202 putIReg( rT_addr, result); 8203 } 8204 break; 8205 8206 default: 8207 vex_printf("dis_pc_relative(ppc)(opc2)\n"); 8208 return False; 8209 } 8210 8211 return True; 8212 } 8213 8214 /* 8215 Condition Register Logical Instructions 8216 */ 8217 static Bool dis_cond_logic ( UInt theInstr ) 8218 { 8219 /* XL-Form */ 8220 UChar opc1 = ifieldOPC(theInstr); 8221 UChar crbD_addr = ifieldRegDS(theInstr); 8222 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 8223 UChar crbA_addr = ifieldRegA(theInstr); 8224 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 8225 UChar crbB_addr = ifieldRegB(theInstr); 8226 UInt opc2 = ifieldOPClo10(theInstr); 8227 UChar b0 = ifieldBIT0(theInstr); 8228 8229 IRTemp crbD = newTemp(Ity_I32); 8230 IRTemp crbA = newTemp(Ity_I32); 8231 IRTemp crbB = newTemp(Ity_I32); 8232 8233 if (opc1 != 19 || b0 != 0) { 8234 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 8235 return False; 8236 } 8237 8238 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 8239 if (((crbD_addr & 0x3) != 0) || 8240 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 8241 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 8242 return False; 8243 } 8244 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 8245 putCR0( crfD_addr, getCR0( crfS_addr) ); 8246 putCR321( crfD_addr, getCR321(crfS_addr) ); 8247 } else { 8248 assign( crbA, getCRbit(crbA_addr) ); 8249 if (crbA_addr == crbB_addr) 8250 crbB = crbA; 8251 else 8252 assign( crbB, getCRbit(crbB_addr) ); 8253 8254 switch (opc2) { 8255 case 0x101: // crand (Cond Reg AND, PPC32 p372) 8256 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8257 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 8258 break; 8259 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 8260 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8261 assign( crbD, binop(Iop_And32, 8262 mkexpr(crbA), 8263 unop(Iop_Not32, mkexpr(crbB))) ); 8264 break; 8265 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 8266 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8267 assign( crbD, unop(Iop_Not32, 8268 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 8269 break; 8270 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 8271 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8272 assign( crbD, unop(Iop_Not32, 8273 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 8274 break; 8275 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 8276 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8277 assign( crbD, unop(Iop_Not32, 8278 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 8279 break; 8280 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 8281 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8282 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 8283 break; 8284 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 8285 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8286 assign( crbD, binop(Iop_Or32, 8287 mkexpr(crbA), 8288 unop(Iop_Not32, mkexpr(crbB))) ); 8289 break; 8290 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 8291 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 8292 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 8293 break; 8294 default: 8295 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 8296 return False; 8297 } 8298 8299 putCRbit( crbD_addr, mkexpr(crbD) ); 8300 } 8301 return True; 8302 } 8303 8304 8305 /* 8306 Trap instructions 8307 */ 8308 8309 /* Do the code generation for a trap. Returned Bool is true iff 8310 this is an unconditional trap. If the two arg IRExpr*s are 8311 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 8312 then they are 64-bit, and we must be disassembling 64-bit 8313 instructions. */ 8314 static Bool do_trap ( UChar TO, 8315 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 8316 { 8317 IRTemp argL, argR; 8318 IRExpr *argLe, *argRe, *cond, *tmp; 8319 8320 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 8321 8322 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 8323 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 8324 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 8325 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 8326 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 8327 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 8328 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 8329 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 8330 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 8331 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 8332 8333 const UChar b11100 = 0x1C; 8334 const UChar b00111 = 0x07; 8335 8336 if (is32bit) { 8337 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 8338 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 8339 } else { 8340 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 8341 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 8342 vassert( mode64 ); 8343 } 8344 8345 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 8346 /* Unconditional trap. Just do the exit without 8347 testing the arguments. */ 8348 stmt( IRStmt_Exit( 8349 binop(opCMPEQ, const0, const0), 8350 Ijk_SigTRAP, 8351 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 8352 OFFB_CIA 8353 )); 8354 return True; /* unconditional trap */ 8355 } 8356 8357 if (is32bit) { 8358 argL = newTemp(Ity_I32); 8359 argR = newTemp(Ity_I32); 8360 } else { 8361 argL = newTemp(Ity_I64); 8362 argR = newTemp(Ity_I64); 8363 } 8364 8365 assign( argL, argL0 ); 8366 assign( argR, argR0 ); 8367 8368 argLe = mkexpr(argL); 8369 argRe = mkexpr(argR); 8370 8371 cond = const0; 8372 if (TO & 16) { // L <s R 8373 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 8374 cond = binop(opOR, tmp, cond); 8375 } 8376 if (TO & 8) { // L >s R 8377 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 8378 cond = binop(opOR, tmp, cond); 8379 } 8380 if (TO & 4) { // L == R 8381 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 8382 cond = binop(opOR, tmp, cond); 8383 } 8384 if (TO & 2) { // L <u R 8385 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 8386 cond = binop(opOR, tmp, cond); 8387 } 8388 if (TO & 1) { // L >u R 8389 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 8390 cond = binop(opOR, tmp, cond); 8391 } 8392 stmt( IRStmt_Exit( 8393 binop(opCMPNE, cond, const0), 8394 Ijk_SigTRAP, 8395 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 8396 OFFB_CIA 8397 )); 8398 return False; /* not an unconditional trap */ 8399 } 8400 8401 static Bool dis_trapi ( UInt theInstr, 8402 /*OUT*/DisResult* dres ) 8403 { 8404 /* D-Form */ 8405 UChar opc1 = ifieldOPC(theInstr); 8406 UChar TO = ifieldRegDS(theInstr); 8407 UChar rA_addr = ifieldRegA(theInstr); 8408 UInt uimm16 = ifieldUIMM16(theInstr); 8409 ULong simm16 = extend_s_16to64(uimm16); 8410 Addr64 cia = guest_CIA_curr_instr; 8411 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8412 Bool uncond = False; 8413 8414 switch (opc1) { 8415 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 8416 uncond = do_trap( TO, 8417 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 8418 : getIReg(rA_addr), 8419 mkU32( (UInt)simm16 ), 8420 cia ); 8421 if (TO == 4) { 8422 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16); 8423 } else { 8424 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16); 8425 } 8426 break; 8427 case 0x02: // tdi 8428 if (!mode64) 8429 return False; 8430 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 8431 if (TO == 4) { 8432 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16); 8433 } else { 8434 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16); 8435 } 8436 break; 8437 default: 8438 return False; 8439 } 8440 8441 if (uncond) { 8442 /* If the trap shows signs of being unconditional, don't 8443 continue decoding past it. */ 8444 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8445 dres->jk_StopHere = Ijk_Boring; 8446 dres->whatNext = Dis_StopHere; 8447 } 8448 8449 return True; 8450 } 8451 8452 static Bool dis_trap ( UInt theInstr, 8453 /*OUT*/DisResult* dres ) 8454 { 8455 /* X-Form */ 8456 UInt opc2 = ifieldOPClo10(theInstr); 8457 UChar TO = ifieldRegDS(theInstr); 8458 UChar rA_addr = ifieldRegA(theInstr); 8459 UChar rB_addr = ifieldRegB(theInstr); 8460 Addr64 cia = guest_CIA_curr_instr; 8461 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8462 Bool uncond = False; 8463 8464 if (ifieldBIT0(theInstr) != 0) 8465 return False; 8466 8467 switch (opc2) { 8468 case 0x004: // tw (Trap Word, PPC64 p540) 8469 uncond = do_trap( TO, 8470 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 8471 : getIReg(rA_addr), 8472 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 8473 : getIReg(rB_addr), 8474 cia ); 8475 if (TO == 4) { 8476 DIP("tweq r%u,r%u\n", rA_addr, rB_addr); 8477 } else { 8478 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr); 8479 } 8480 break; 8481 case 0x044: // td (Trap Doubleword, PPC64 p534) 8482 if (!mode64) 8483 return False; 8484 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 8485 if (TO == 4) { 8486 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr); 8487 } else { 8488 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr); 8489 } 8490 break; 8491 default: 8492 return False; 8493 } 8494 8495 if (uncond) { 8496 /* If the trap shows signs of being unconditional, don't 8497 continue decoding past it. */ 8498 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8499 dres->jk_StopHere = Ijk_Boring; 8500 dres->whatNext = Dis_StopHere; 8501 } 8502 8503 return True; 8504 } 8505 8506 8507 /* 8508 System Linkage Instructions 8509 */ 8510 static Bool dis_syslink ( UInt theInstr, 8511 const VexAbiInfo* abiinfo, DisResult* dres ) 8512 { 8513 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8514 8515 if (theInstr != 0x44000002) { 8516 vex_printf("dis_syslink(ppc)(theInstr)\n"); 8517 return False; 8518 } 8519 8520 // sc (System Call, PPC32 p504) 8521 DIP("sc\n"); 8522 8523 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 8524 Valgrind can back the guest up to this instruction if it needs 8525 to restart the syscall. */ 8526 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 8527 8528 /* It's important that all ArchRegs carry their up-to-date value 8529 at this point. So we declare an end-of-block here, which 8530 forces any TempRegs caching ArchRegs to be flushed. */ 8531 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 8532 8533 dres->whatNext = Dis_StopHere; 8534 dres->jk_StopHere = Ijk_Sys_syscall; 8535 return True; 8536 } 8537 8538 8539 /* 8540 Memory Synchronization Instructions 8541 8542 Note on Reservations: 8543 We rely on the assumption that V will in fact only allow one thread at 8544 once to run. In effect, a thread can make a reservation, but we don't 8545 check any stores it does. Instead, the reservation is cancelled when 8546 the scheduler switches to another thread (run_thread_for_a_while()). 8547 */ 8548 static Bool dis_memsync ( UInt theInstr ) 8549 { 8550 /* X-Form, XL-Form */ 8551 UChar opc1 = ifieldOPC(theInstr); 8552 UInt b11to25 = IFIELD(theInstr, 11, 15); 8553 UChar flag_L = ifieldRegDS(theInstr); 8554 UInt b11to20 = IFIELD(theInstr, 11, 10); 8555 UInt M0 = IFIELD(theInstr, 11, 5); 8556 UChar rD_addr = ifieldRegDS(theInstr); 8557 UChar rS_addr = rD_addr; 8558 UChar rA_addr = ifieldRegA(theInstr); 8559 UChar rB_addr = ifieldRegB(theInstr); 8560 UInt opc2 = ifieldOPClo10(theInstr); 8561 UChar b0 = ifieldBIT0(theInstr); 8562 8563 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8564 IRTemp EA = newTemp(ty); 8565 8566 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 8567 8568 switch (opc1) { 8569 /* XL-Form */ 8570 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 8571 if (opc2 != 0x096) { 8572 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 8573 return False; 8574 } 8575 if (b11to25 != 0 || b0 != 0) { 8576 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 8577 return False; 8578 } 8579 DIP("isync\n"); 8580 stmt( IRStmt_MBE(Imbe_Fence) ); 8581 break; 8582 8583 /* X-Form */ 8584 case 0x1F: 8585 switch (opc2) { 8586 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394) 8587 if (M0 == 0) { 8588 if (b11to20 != 0 || b0 != 0) { 8589 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n"); 8590 return False; 8591 } 8592 DIP("eieio\n"); 8593 } else { 8594 if (b11to20 != 0 || b0 != 0) { 8595 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n"); 8596 return False; 8597 } 8598 DIP("mbar %d\n", M0); 8599 } 8600 /* Insert a memory fence, just to be on the safe side. */ 8601 stmt( IRStmt_MBE(Imbe_Fence) ); 8602 break; 8603 8604 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 8605 IRTemp res; 8606 /* According to the PowerPC ISA version 2.05, b0 (called EH 8607 in the documentation) is merely a hint bit to the 8608 hardware, I think as to whether or not contention is 8609 likely. So we can just ignore it. */ 8610 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8611 8612 // trap if misaligned 8613 gen_SIGBUS_if_misaligned( EA, 4 ); 8614 8615 // and actually do the load 8616 res = newTemp(Ity_I32); 8617 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8618 8619 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 8620 break; 8621 } 8622 8623 case 0x034: { // lbarx (Load Word and Reserve Indexed) 8624 IRTemp res; 8625 /* According to the PowerPC ISA version 2.05, b0 (called EH 8626 in the documentation) is merely a hint bit to the 8627 hardware, I think as to whether or not contention is 8628 likely. So we can just ignore it. */ 8629 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8630 8631 // and actually do the load 8632 res = newTemp(Ity_I8); 8633 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8634 8635 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 8636 break; 8637 } 8638 8639 case 0x074: { // lharx (Load Word and Reserve Indexed) 8640 IRTemp res; 8641 /* According to the PowerPC ISA version 2.05, b0 (called EH 8642 in the documentation) is merely a hint bit to the 8643 hardware, I think as to whether or not contention is 8644 likely. So we can just ignore it. */ 8645 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8646 8647 // trap if misaligned 8648 gen_SIGBUS_if_misaligned( EA, 2 ); 8649 8650 // and actually do the load 8651 res = newTemp(Ity_I16); 8652 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 8653 8654 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 8655 break; 8656 } 8657 8658 case 0x096: { 8659 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 8660 // Note this has to handle stwcx. in both 32- and 64-bit modes, 8661 // so isn't quite as straightforward as it might otherwise be. 8662 IRTemp rS = newTemp(Ity_I32); 8663 IRTemp resSC; 8664 if (b0 != 1) { 8665 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 8666 return False; 8667 } 8668 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8669 8670 // trap if misaligned 8671 gen_SIGBUS_if_misaligned( EA, 4 ); 8672 8673 // Get the data to be stored, and narrow to 32 bits if necessary 8674 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 8675 8676 // Do the store, and get success/failure bit into resSC 8677 resSC = newTemp(Ity_I1); 8678 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8679 8680 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8681 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8682 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8683 putCR0(0, getXER_SO()); 8684 8685 /* Note: 8686 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 8687 whether rS is stored is dependent on that value. */ 8688 /* So I guess we can just ignore this case? */ 8689 break; 8690 } 8691 8692 case 0x2B6: { 8693 // stbcx. (Store Byte Conditional Indexed) 8694 // Note this has to handle stbcx. in both 32- and 64-bit modes, 8695 // so isn't quite as straightforward as it might otherwise be. 8696 IRTemp rS = newTemp(Ity_I8); 8697 IRTemp resSC; 8698 if (b0 != 1) { 8699 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 8700 return False; 8701 } 8702 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8703 8704 // Get the data to be stored, and narrow to 32 bits if necessary 8705 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 8706 8707 // Do the store, and get success/failure bit into resSC 8708 resSC = newTemp(Ity_I1); 8709 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8710 8711 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8712 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8713 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8714 putCR0(0, getXER_SO()); 8715 8716 /* Note: 8717 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 8718 whether rS is stored is dependent on that value. */ 8719 /* So I guess we can just ignore this case? */ 8720 break; 8721 } 8722 8723 case 0x2D6: { 8724 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 8725 // Note this has to handle sthcx. in both 32- and 64-bit modes, 8726 // so isn't quite as straightforward as it might otherwise be. 8727 IRTemp rS = newTemp(Ity_I16); 8728 IRTemp resSC; 8729 if (b0 != 1) { 8730 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 8731 return False; 8732 } 8733 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8734 8735 // trap if misaligned 8736 gen_SIGBUS_if_misaligned( EA, 2 ); 8737 8738 // Get the data to be stored, and narrow to 16 bits if necessary 8739 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 8740 8741 // Do the store, and get success/failure bit into resSC 8742 resSC = newTemp(Ity_I1); 8743 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8744 8745 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8746 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8747 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8748 putCR0(0, getXER_SO()); 8749 8750 /* Note: 8751 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 8752 whether rS is stored is dependent on that value. */ 8753 /* So I guess we can just ignore this case? */ 8754 break; 8755 } 8756 8757 case 0x256: // sync (Synchronize, PPC32 p543), 8758 // also lwsync (L==1), ptesync (L==2) 8759 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 8760 8761 The PowerPC architecture used in IBM chips has expanded 8762 the sync instruction into two variants: lightweight sync 8763 and heavyweight sync. The original sync instruction is 8764 the new heavyweight sync and lightweight sync is a strict 8765 subset of the heavyweight sync functionality. This allows 8766 the programmer to specify a less expensive operation on 8767 high-end systems when the full sync functionality is not 8768 necessary. 8769 8770 The basic "sync" mnemonic now utilizes an operand. "sync" 8771 without an operand now becomes a extended mnemonic for 8772 heavyweight sync. Processors without the lwsync 8773 instruction will not decode the L field and will perform a 8774 heavyweight sync. Everything is backward compatible. 8775 8776 sync = sync 0 8777 lwsync = sync 1 8778 ptesync = sync 2 *** TODO - not implemented *** 8779 */ 8780 if (b11to20 != 0 || b0 != 0) { 8781 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 8782 return False; 8783 } 8784 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 8785 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 8786 return False; 8787 } 8788 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 8789 /* Insert a memory fence. It's sometimes important that these 8790 are carried through to the generated code. */ 8791 stmt( IRStmt_MBE(Imbe_Fence) ); 8792 break; 8793 8794 /* 64bit Memsync */ 8795 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 8796 IRTemp res; 8797 /* According to the PowerPC ISA version 2.05, b0 (called EH 8798 in the documentation) is merely a hint bit to the 8799 hardware, I think as to whether or not contention is 8800 likely. So we can just ignore it. */ 8801 if (!mode64) 8802 return False; 8803 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8804 8805 // trap if misaligned 8806 gen_SIGBUS_if_misaligned( EA, 8 ); 8807 8808 // and actually do the load 8809 res = newTemp(Ity_I64); 8810 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 8811 8812 putIReg( rD_addr, mkexpr(res) ); 8813 break; 8814 } 8815 8816 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 8817 // A marginally simplified version of the stwcx. case 8818 IRTemp rS = newTemp(Ity_I64); 8819 IRTemp resSC; 8820 if (b0 != 1) { 8821 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 8822 return False; 8823 } 8824 if (!mode64) 8825 return False; 8826 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8827 8828 // trap if misaligned 8829 gen_SIGBUS_if_misaligned( EA, 8 ); 8830 8831 // Get the data to be stored 8832 assign( rS, getIReg(rS_addr) ); 8833 8834 // Do the store, and get success/failure bit into resSC 8835 resSC = newTemp(Ity_I1); 8836 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 8837 8838 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8839 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8840 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 8841 putCR0(0, getXER_SO()); 8842 8843 /* Note: 8844 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 8845 whether rS is stored is dependent on that value. */ 8846 /* So I guess we can just ignore this case? */ 8847 break; 8848 } 8849 8850 /* 128bit Memsync */ 8851 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 8852 IRTemp res_hi = newTemp(ty); 8853 IRTemp res_lo = newTemp(ty); 8854 8855 /* According to the PowerPC ISA version 2.07, b0 (called EH 8856 in the documentation) is merely a hint bit to the 8857 hardware, I think as to whether or not contention is 8858 likely. So we can just ignore it. */ 8859 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 8860 8861 // trap if misaligned 8862 gen_SIGBUS_if_misaligned( EA, 16 ); 8863 8864 // and actually do the load 8865 if (mode64) { 8866 if (host_endness == VexEndnessBE) { 8867 stmt( stmt_load( res_hi, 8868 mkexpr(EA), NULL/*this is a load*/) ); 8869 stmt( stmt_load( res_lo, 8870 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 8871 NULL/*this is a load*/) ); 8872 } else { 8873 stmt( stmt_load( res_lo, 8874 mkexpr(EA), NULL/*this is a load*/) ); 8875 stmt( stmt_load( res_hi, 8876 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 8877 NULL/*this is a load*/) ); 8878 } 8879 } else { 8880 stmt( stmt_load( res_hi, 8881 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 8882 NULL/*this is a load*/) ); 8883 stmt( stmt_load( res_lo, 8884 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 8885 NULL/*this is a load*/) ); 8886 } 8887 putIReg( rD_addr, mkexpr(res_hi) ); 8888 putIReg( rD_addr+1, mkexpr(res_lo) ); 8889 break; 8890 } 8891 8892 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 8893 // A marginally simplified version of the stwcx. case 8894 IRTemp rS_hi = newTemp(ty); 8895 IRTemp rS_lo = newTemp(ty); 8896 IRTemp resSC; 8897 if (b0 != 1) { 8898 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 8899 return False; 8900 } 8901 8902 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 8903 8904 // trap if misaligned 8905 gen_SIGBUS_if_misaligned( EA, 16 ); 8906 // Get the data to be stored 8907 assign( rS_hi, getIReg(rS_addr) ); 8908 assign( rS_lo, getIReg(rS_addr+1) ); 8909 8910 // Do the store, and get success/failure bit into resSC 8911 resSC = newTemp(Ity_I1); 8912 8913 if (mode64) { 8914 if (host_endness == VexEndnessBE) { 8915 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 8916 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 8917 mkexpr(rS_lo) ); 8918 } else { 8919 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 8920 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 8921 mkexpr(rS_hi) ); 8922 } 8923 } else { 8924 stmt( stmt_load( resSC, binop( Iop_Add32, 8925 mkexpr(EA), 8926 mkU32(4) ), 8927 mkexpr(rS_hi) ) ); 8928 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 8929 } 8930 8931 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 8932 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 8933 putCR321(0, binop( Iop_Shl8, 8934 unop(Iop_1Uto8, mkexpr(resSC) ), 8935 mkU8(1))); 8936 putCR0(0, getXER_SO()); 8937 break; 8938 } 8939 8940 default: 8941 vex_printf("dis_memsync(ppc)(opc2)\n"); 8942 return False; 8943 } 8944 break; 8945 8946 default: 8947 vex_printf("dis_memsync(ppc)(opc1)\n"); 8948 return False; 8949 } 8950 return True; 8951 } 8952 8953 8954 8955 /* 8956 Integer Shift Instructions 8957 */ 8958 static Bool dis_int_shift ( UInt theInstr ) 8959 { 8960 /* X-Form, XS-Form */ 8961 UChar opc1 = ifieldOPC(theInstr); 8962 UChar rS_addr = ifieldRegDS(theInstr); 8963 UChar rA_addr = ifieldRegA(theInstr); 8964 UChar rB_addr = ifieldRegB(theInstr); 8965 UChar sh_imm = rB_addr; 8966 UInt opc2 = ifieldOPClo10(theInstr); 8967 UChar b1 = ifieldBIT1(theInstr); 8968 UChar flag_rC = ifieldBIT0(theInstr); 8969 8970 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8971 IRTemp rA = newTemp(ty); 8972 IRTemp rS = newTemp(ty); 8973 IRTemp rB = newTemp(ty); 8974 IRTemp outofrange = newTemp(Ity_I1); 8975 IRTemp rS_lo32 = newTemp(Ity_I32); 8976 IRTemp rB_lo32 = newTemp(Ity_I32); 8977 IRExpr* e_tmp; 8978 8979 assign( rS, getIReg(rS_addr) ); 8980 assign( rB, getIReg(rB_addr) ); 8981 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 8982 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 8983 8984 if (opc1 == 0x1F) { 8985 switch (opc2) { 8986 case 0x018: { // slw (Shift Left Word, PPC32 p505) 8987 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 8988 rA_addr, rS_addr, rB_addr); 8989 /* rA = rS << rB */ 8990 /* ppc32 semantics are: 8991 slw(x,y) = (x << (y & 31)) -- primary result 8992 & ~((y << 26) >>s 31) -- make result 0 8993 for y in 32 .. 63 8994 */ 8995 e_tmp = 8996 binop( Iop_And32, 8997 binop( Iop_Shl32, 8998 mkexpr(rS_lo32), 8999 unop( Iop_32to8, 9000 binop(Iop_And32, 9001 mkexpr(rB_lo32), mkU32(31)))), 9002 unop( Iop_Not32, 9003 binop( Iop_Sar32, 9004 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 9005 mkU8(31))) ); 9006 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 9007 break; 9008 } 9009 9010 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 9011 IRTemp sh_amt = newTemp(Ity_I32); 9012 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 9013 rA_addr, rS_addr, rB_addr); 9014 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 9015 amt = rB & 63 9016 rA = Sar32( rS, amt > 31 ? 31 : amt ) 9017 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 9018 */ 9019 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 9020 mkexpr(rB_lo32)) ); 9021 assign( outofrange, 9022 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 9023 e_tmp = binop( Iop_Sar32, 9024 mkexpr(rS_lo32), 9025 unop( Iop_32to8, 9026 IRExpr_ITE( mkexpr(outofrange), 9027 mkU32(31), 9028 mkexpr(sh_amt)) ) ); 9029 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 9030 9031 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAW, 9032 mkexpr(rA), 9033 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 9034 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 9035 mkWidenFrom32(ty, getXER_CA_32(), True) ); 9036 break; 9037 } 9038 9039 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 9040 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 9041 rA_addr, rS_addr, sh_imm); 9042 vassert(sh_imm < 32); 9043 if (mode64) { 9044 assign( rA, binop(Iop_Sar64, 9045 binop(Iop_Shl64, getIReg(rS_addr), 9046 mkU8(32)), 9047 mkU8(32 + sh_imm)) ); 9048 } else { 9049 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 9050 mkU8(sh_imm)) ); 9051 } 9052 9053 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAWI, 9054 mkexpr(rA), 9055 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 9056 mkSzImm(ty, sh_imm), 9057 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9058 break; 9059 9060 case 0x218: // srw (Shift Right Word, PPC32 p508) 9061 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 9062 rA_addr, rS_addr, rB_addr); 9063 /* rA = rS >>u rB */ 9064 /* ppc32 semantics are: 9065 srw(x,y) = (x >>u (y & 31)) -- primary result 9066 & ~((y << 26) >>s 31) -- make result 0 9067 for y in 32 .. 63 9068 */ 9069 e_tmp = 9070 binop( 9071 Iop_And32, 9072 binop( Iop_Shr32, 9073 mkexpr(rS_lo32), 9074 unop( Iop_32to8, 9075 binop(Iop_And32, mkexpr(rB_lo32), 9076 mkU32(31)))), 9077 unop( Iop_Not32, 9078 binop( Iop_Sar32, 9079 binop(Iop_Shl32, mkexpr(rB_lo32), 9080 mkU8(26)), 9081 mkU8(31)))); 9082 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 9083 break; 9084 9085 9086 /* 64bit Shifts */ 9087 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 9088 DIP("sld%s r%u,r%u,r%u\n", 9089 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9090 /* rA = rS << rB */ 9091 /* ppc64 semantics are: 9092 slw(x,y) = (x << (y & 63)) -- primary result 9093 & ~((y << 57) >>s 63) -- make result 0 9094 for y in 64 .. 9095 */ 9096 assign( rA, 9097 binop( 9098 Iop_And64, 9099 binop( Iop_Shl64, 9100 mkexpr(rS), 9101 unop( Iop_64to8, 9102 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 9103 unop( Iop_Not64, 9104 binop( Iop_Sar64, 9105 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 9106 mkU8(63)))) ); 9107 break; 9108 9109 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 9110 IRTemp sh_amt = newTemp(Ity_I64); 9111 DIP("srad%s r%u,r%u,r%u\n", 9112 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9113 /* amt = rB & 127 9114 rA = Sar64( rS, amt > 63 ? 63 : amt ) 9115 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 9116 */ 9117 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 9118 assign( outofrange, 9119 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 9120 assign( rA, 9121 binop( Iop_Sar64, 9122 mkexpr(rS), 9123 unop( Iop_64to8, 9124 IRExpr_ITE( mkexpr(outofrange), 9125 mkU64(63), 9126 mkexpr(sh_amt)) )) 9127 ); 9128 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAD, 9129 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 9130 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9131 break; 9132 } 9133 9134 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 9135 sh_imm |= b1<<5; 9136 vassert(sh_imm < 64); 9137 DIP("sradi%s r%u,r%u,%u\n", 9138 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 9139 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 9140 9141 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRADI, 9142 mkexpr(rA), 9143 getIReg(rS_addr), 9144 mkU64(sh_imm), 9145 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) ); 9146 break; 9147 9148 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 9149 DIP("srd%s r%u,r%u,r%u\n", 9150 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 9151 /* rA = rS >>u rB */ 9152 /* ppc semantics are: 9153 srw(x,y) = (x >>u (y & 63)) -- primary result 9154 & ~((y << 57) >>s 63) -- make result 0 9155 for y in 64 .. 127 9156 */ 9157 assign( rA, 9158 binop( 9159 Iop_And64, 9160 binop( Iop_Shr64, 9161 mkexpr(rS), 9162 unop( Iop_64to8, 9163 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 9164 unop( Iop_Not64, 9165 binop( Iop_Sar64, 9166 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 9167 mkU8(63)))) ); 9168 break; 9169 9170 default: 9171 vex_printf("dis_int_shift(ppc)(opc2)\n"); 9172 return False; 9173 } 9174 } else { 9175 vex_printf("dis_int_shift(ppc)(opc1)\n"); 9176 return False; 9177 } 9178 9179 putIReg( rA_addr, mkexpr(rA) ); 9180 9181 if (flag_rC) { 9182 set_CR0( mkexpr(rA) ); 9183 } 9184 return True; 9185 } 9186 9187 9188 9189 /* 9190 Integer Load/Store Reverse Instructions 9191 */ 9192 /* Generates code to swap the byte order in an Ity_I32. */ 9193 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 9194 { 9195 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 9196 return 9197 binop(Iop_Or32, 9198 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 9199 binop(Iop_Or32, 9200 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 9201 mkU32(0x00FF0000)), 9202 binop(Iop_Or32, 9203 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 9204 mkU32(0x0000FF00)), 9205 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 9206 mkU32(0x000000FF) ) 9207 ))); 9208 } 9209 9210 /* Generates code to swap the byte order in the lower half of an Ity_I32, 9211 and zeroes the upper half. */ 9212 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 9213 { 9214 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 9215 return 9216 binop(Iop_Or32, 9217 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 9218 mkU32(0x0000FF00)), 9219 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 9220 mkU32(0x000000FF)) 9221 ); 9222 } 9223 9224 static Bool dis_int_ldst_rev ( UInt theInstr ) 9225 { 9226 /* X-Form */ 9227 UChar opc1 = ifieldOPC(theInstr); 9228 UChar rD_addr = ifieldRegDS(theInstr); 9229 UChar rS_addr = rD_addr; 9230 UChar rA_addr = ifieldRegA(theInstr); 9231 UChar rB_addr = ifieldRegB(theInstr); 9232 UInt opc2 = ifieldOPClo10(theInstr); 9233 UChar b0 = ifieldBIT0(theInstr); 9234 9235 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9236 IRTemp EA = newTemp(ty); 9237 IRTemp w1 = newTemp(Ity_I32); 9238 IRTemp w2 = newTemp(Ity_I32); 9239 9240 if (opc1 != 0x1F || b0 != 0) { 9241 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 9242 return False; 9243 } 9244 9245 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 9246 9247 switch (opc2) { 9248 9249 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 9250 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9251 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 9252 assign( w2, gen_byterev16(w1) ); 9253 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 9254 /* Signed */False) ); 9255 break; 9256 9257 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 9258 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9259 assign( w1, load(Ity_I32, mkexpr(EA)) ); 9260 assign( w2, gen_byterev32(w1) ); 9261 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 9262 /* Signed */False) ); 9263 break; 9264 9265 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 9266 { 9267 IRExpr * nextAddr; 9268 IRTemp w3 = newTemp( Ity_I32 ); 9269 IRTemp w4 = newTemp( Ity_I32 ); 9270 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 9271 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 9272 assign( w2, gen_byterev32( w1 ) ); 9273 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 9274 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 9275 assign( w3, load( Ity_I32, nextAddr ) ); 9276 assign( w4, gen_byterev32( w3 ) ); 9277 if (host_endness == VexEndnessLE) 9278 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 9279 else 9280 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 9281 break; 9282 } 9283 9284 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 9285 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9286 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 9287 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 9288 break; 9289 9290 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 9291 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9292 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 9293 store( mkexpr(EA), gen_byterev32(w1) ); 9294 break; 9295 9296 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 9297 { 9298 IRTemp lo = newTemp(Ity_I32); 9299 IRTemp hi = newTemp(Ity_I32); 9300 IRTemp rS = newTemp(Ity_I64); 9301 assign( rS, getIReg( rS_addr ) ); 9302 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 9303 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 9304 assign(hi, unop(Iop_64to32, mkexpr(rS))); 9305 store( mkexpr( EA ), 9306 binop( Iop_32HLto64, gen_byterev32( hi ), 9307 gen_byterev32( lo ) ) ); 9308 break; 9309 } 9310 9311 default: 9312 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 9313 return False; 9314 } 9315 return True; 9316 } 9317 9318 9319 9320 /* 9321 Processor Control Instructions 9322 */ 9323 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 9324 { 9325 UChar opc1 = ifieldOPC(theInstr); 9326 9327 /* X-Form */ 9328 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9329 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9330 UChar rD_addr = ifieldRegDS(theInstr); 9331 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 9332 9333 /* XFX-Form */ 9334 UChar rS_addr = rD_addr; 9335 UInt SPR = b11to20; 9336 UInt TBR = b11to20; 9337 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 9338 UInt CRM = IFIELD( theInstr, 12, 8 ); 9339 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9340 9341 UInt opc2 = ifieldOPClo10(theInstr); 9342 UChar b0 = ifieldBIT0(theInstr); 9343 9344 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9345 IRTemp rS = newTemp(ty); 9346 assign( rS, getIReg(rS_addr) ); 9347 9348 /* Reorder SPR field as per PPC32 p470 */ 9349 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 9350 /* Reorder TBR field as per PPC32 p475 */ 9351 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 9352 9353 /* b0 = 0, inst is treated as floating point inst for reservation purposes 9354 * b0 = 1, inst is treated as vector inst for reservation purposes 9355 */ 9356 if (opc1 != 0x1F) { 9357 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 9358 return False; 9359 } 9360 9361 switch (opc2) { 9362 /* X-Form */ 9363 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 9364 if (b21to22 != 0 || b11to20 != 0) { 9365 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 9366 return False; 9367 } 9368 DIP("mcrxr crf%d\n", crfD); 9369 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 9370 putGST_field( PPC_GST_CR, 9371 getGST_field( PPC_GST_XER, 7 ), 9372 crfD ); 9373 9374 // Clear XER[0-3] 9375 putXER_SO( mkU8(0) ); 9376 putXER_OV( mkU8(0) ); 9377 putXER_CA( mkU8(0) ); 9378 break; 9379 } 9380 9381 case 0x013: 9382 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 9383 // b20==1 & b11==0: mfocrf (Move from One CR Field) 9384 // However it seems that the 'mfcr' behaviour is an acceptable 9385 // implementation of mfocr (from the 2.02 arch spec) 9386 if (b11to20 == 0) { 9387 DIP("mfcr r%u\n", rD_addr); 9388 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 9389 /* Signed */False) ); 9390 break; 9391 } 9392 if (b20 == 1 && b11 == 0) { 9393 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 9394 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 9395 /* Signed */False) ); 9396 break; 9397 } 9398 /* not decodable */ 9399 return False; 9400 9401 /* XFX-Form */ 9402 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 9403 9404 switch (SPR) { // Choose a register... 9405 case 0x1: 9406 DIP("mfxer r%u\n", rD_addr); 9407 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 9408 /* Signed */False) ); 9409 break; 9410 case 0x8: 9411 DIP("mflr r%u\n", rD_addr); 9412 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 9413 break; 9414 case 0x9: 9415 DIP("mfctr r%u\n", rD_addr); 9416 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 9417 break; 9418 case 0x80: // 128 9419 DIP("mfspr r%u (TFHAR)\n", rD_addr); 9420 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 9421 break; 9422 case 0x81: // 129 9423 DIP("mfspr r%u (TFIAR)\n", rD_addr); 9424 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 9425 break; 9426 case 0x82: // 130 9427 DIP("mfspr r%u (TEXASR)\n", rD_addr); 9428 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 9429 break; 9430 case 0x83: // 131 9431 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 9432 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 9433 break; 9434 case 0x9F: // 159 9435 DIP("mfspr r%u (PSPB)\n", rD_addr); 9436 putIReg( rD_addr, getGST( PPC_GST_PSPB) ); 9437 break; 9438 case 0x380: // 896 9439 DIP("mfspr r%u (PPR)\n", rD_addr); 9440 putIReg( rD_addr, getGST( PPC_GST_PPR) ); 9441 break; 9442 case 0x382: // 898 9443 DIP("mfspr r%u (PPR)32\n", rD_addr); 9444 putIReg( rD_addr, getGST( PPC_GST_PPR32) ); 9445 break; 9446 case 0x100: 9447 DIP("mfvrsave r%u\n", rD_addr); 9448 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 9449 /* Signed */False) ); 9450 break; 9451 9452 case 0x103: 9453 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 9454 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 9455 break; 9456 9457 /* Even a lowly PPC7400 can run the associated helper, so no 9458 obvious need for feature testing at this point. */ 9459 case 268 /* 0x10C */: 9460 case 269 /* 0x10D */: { 9461 UInt arg = SPR==268 ? 0 : 1; 9462 IRTemp val = newTemp(Ity_I32); 9463 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 9464 IRDirty* d = unsafeIRDirty_1_N( 9465 val, 9466 0/*regparms*/, 9467 "ppc32g_dirtyhelper_MFSPR_268_269", 9468 fnptr_to_fnentry 9469 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 9470 args 9471 ); 9472 /* execute the dirty call, dumping the result in val. */ 9473 stmt( IRStmt_Dirty(d) ); 9474 putIReg( rD_addr, 9475 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 9476 DIP("mfspr r%u,%u", rD_addr, SPR); 9477 break; 9478 } 9479 9480 /* Again, runs natively on PPC7400 (7447, really). Not 9481 bothering with a feature test. */ 9482 case 287: /* 0x11F */ { 9483 IRTemp val = newTemp(Ity_I32); 9484 IRExpr** args = mkIRExprVec_0(); 9485 IRDirty* d = unsafeIRDirty_1_N( 9486 val, 9487 0/*regparms*/, 9488 "ppc32g_dirtyhelper_MFSPR_287", 9489 fnptr_to_fnentry 9490 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 9491 args 9492 ); 9493 /* execute the dirty call, dumping the result in val. */ 9494 stmt( IRStmt_Dirty(d) ); 9495 putIReg( rD_addr, 9496 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 9497 DIP("mfspr r%u,%u", rD_addr, SPR); 9498 break; 9499 } 9500 9501 default: 9502 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 9503 return False; 9504 } 9505 break; 9506 9507 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 9508 IRTemp val = newTemp(Ity_I64); 9509 IRExpr** args = mkIRExprVec_0(); 9510 IRDirty* d = unsafeIRDirty_1_N( 9511 val, 9512 0/*regparms*/, 9513 "ppcg_dirtyhelper_MFTB", 9514 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 9515 args ); 9516 /* execute the dirty call, dumping the result in val. */ 9517 stmt( IRStmt_Dirty(d) ); 9518 9519 switch (TBR) { 9520 case 269: 9521 DIP("mftbu r%u", rD_addr); 9522 putIReg( rD_addr, 9523 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 9524 /* Signed */False) ); 9525 break; 9526 case 268: 9527 DIP("mftb r%u", rD_addr); 9528 putIReg( rD_addr, (mode64) ? mkexpr(val) : 9529 unop(Iop_64to32, mkexpr(val)) ); 9530 break; 9531 default: 9532 return False; /* illegal instruction */ 9533 } 9534 break; 9535 } 9536 9537 case 0x090: { 9538 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 9539 // b20==1: mtocrf (Move to One Cond Reg Field) 9540 Int cr; 9541 UChar shft; 9542 if (b11 != 0) 9543 return False; 9544 if (b20 == 1) { 9545 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 9546 1 field is written. It seems more robust to decline to 9547 decode the insn if so. */ 9548 switch (CRM) { 9549 case 0x01: case 0x02: case 0x04: case 0x08: 9550 case 0x10: case 0x20: case 0x40: case 0x80: 9551 break; 9552 default: 9553 return False; 9554 } 9555 } 9556 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 9557 CRM, rS_addr); 9558 /* Write to each field specified by CRM */ 9559 for (cr = 0; cr < 8; cr++) { 9560 if ((CRM & (1 << (7-cr))) == 0) 9561 continue; 9562 shft = 4*(7-cr); 9563 putGST_field( PPC_GST_CR, 9564 binop(Iop_Shr32, 9565 mkNarrowTo32(ty, mkexpr(rS)), 9566 mkU8(shft)), cr ); 9567 } 9568 break; 9569 } 9570 9571 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 9572 9573 switch (SPR) { // Choose a register... 9574 case 0x1: 9575 DIP("mtxer r%u\n", rS_addr); 9576 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 9577 break; 9578 case 0x8: 9579 DIP("mtlr r%u\n", rS_addr); 9580 putGST( PPC_GST_LR, mkexpr(rS) ); 9581 break; 9582 case 0x9: 9583 DIP("mtctr r%u\n", rS_addr); 9584 putGST( PPC_GST_CTR, mkexpr(rS) ); 9585 break; 9586 case 0x100: 9587 DIP("mtvrsave r%u\n", rS_addr); 9588 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 9589 break; 9590 case 0x80: // 128 9591 DIP("mtspr r%u (TFHAR)\n", rS_addr); 9592 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 9593 break; 9594 case 0x81: // 129 9595 DIP("mtspr r%u (TFIAR)\n", rS_addr); 9596 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 9597 break; 9598 case 0x82: // 130 9599 DIP("mtspr r%u (TEXASR)\n", rS_addr); 9600 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 9601 break; 9602 case 0x9F: // 159 9603 DIP("mtspr r%u (PSPB)\n", rS_addr); 9604 putGST( PPC_GST_PSPB, mkexpr(rS) ); 9605 break; 9606 case 0x380: // 896 9607 DIP("mtspr r%u (PPR)\n", rS_addr); 9608 putGST( PPC_GST_PPR, mkexpr(rS) ); 9609 break; 9610 case 0x382: // 898 9611 DIP("mtspr r%u (PPR32)\n", rS_addr); 9612 putGST( PPC_GST_PPR32, mkexpr(rS) ); 9613 break; 9614 default: 9615 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 9616 return False; 9617 } 9618 break; 9619 9620 case 0x33: // mfvsrd 9621 { 9622 UChar XS = ifieldRegXS( theInstr ); 9623 UChar rA_addr = ifieldRegA(theInstr); 9624 IRExpr * high64; 9625 IRTemp vS = newTemp( Ity_V128 ); 9626 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS); 9627 9628 /* XS = SX || S 9629 * For SX=0, mfvsrd is treated as a Floating-Point 9630 * instruction in terms of resource availability. 9631 * For SX=1, mfvsrd is treated as a Vector instruction in 9632 * terms of resource availability. 9633 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9634 */ 9635 assign( vS, getVSReg( XS ) ); 9636 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 9637 putIReg( rA_addr, (mode64) ? high64 : 9638 unop( Iop_64to32, high64 ) ); 9639 break; 9640 } 9641 9642 case 0x73: // mfvsrwz 9643 { 9644 UChar XS = ifieldRegXS( theInstr ); 9645 UChar rA_addr = ifieldRegA(theInstr); 9646 IRExpr * high64; 9647 IRTemp vS = newTemp( Ity_V128 ); 9648 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS); 9649 /* XS = SX || S 9650 * For SX=0, mfvsrwz is treated as a Floating-Point 9651 * instruction in terms of resource availability. 9652 * For SX=1, mfvsrwz is treated as a Vector instruction in 9653 * terms of resource availability. 9654 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9655 */ 9656 9657 assign( vS, getVSReg( XS ) ); 9658 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 9659 /* move value to the destination setting the upper 32-bits to zero */ 9660 putIReg( rA_addr, (mode64) ? 9661 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 9662 unop( Iop_64to32, 9663 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 9664 break; 9665 } 9666 9667 case 0xB3: // mtvsrd 9668 { 9669 UChar XT = ifieldRegXT( theInstr ); 9670 UChar rA_addr = ifieldRegA(theInstr); 9671 IRTemp rA = newTemp(ty); 9672 DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr); 9673 /* XS = SX || S 9674 * For SX=0, mfvsrd is treated as a Floating-Point 9675 * instruction in terms of resource availability. 9676 * For SX=1, mfvsrd is treated as a Vector instruction in 9677 * terms of resource availability. 9678 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9679 */ 9680 assign( rA, getIReg(rA_addr) ); 9681 9682 if (mode64) 9683 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 9684 else 9685 putVSReg( XT, binop( Iop_64HLtoV128, 9686 binop( Iop_32HLto64, 9687 mkU32( 0 ), 9688 mkexpr( rA ) ), 9689 mkU64( 0 ) ) ); 9690 break; 9691 } 9692 9693 case 0xD3: // mtvsrwa 9694 { 9695 UChar XT = ifieldRegXT( theInstr ); 9696 UChar rA_addr = ifieldRegA(theInstr); 9697 IRTemp rA = newTemp( Ity_I32 ); 9698 DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr); 9699 /* XS = SX || S 9700 * For SX=0, mtvsrwa is treated as a Floating-Point 9701 * instruction in terms of resource availability. 9702 * For SX=1, mtvsrwa is treated as a Vector instruction in 9703 * terms of resource availability. 9704 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9705 */ 9706 if (mode64) 9707 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 9708 else 9709 assign( rA, getIReg(rA_addr) ); 9710 9711 putVSReg( XT, binop( Iop_64HLtoV128, 9712 unop( Iop_32Sto64, mkexpr( rA ) ), 9713 mkU64( 0 ) ) ); 9714 break; 9715 } 9716 9717 case 0xF3: // mtvsrwz 9718 { 9719 UChar XT = ifieldRegXT( theInstr ); 9720 UChar rA_addr = ifieldRegA(theInstr); 9721 IRTemp rA = newTemp( Ity_I32 ); 9722 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT); 9723 /* XS = SX || S 9724 * For SX=0, mtvsrwz is treated as a Floating-Point 9725 * instruction in terms of resource availability. 9726 * For SX=1, mtvsrwz is treated as a Vector instruction in 9727 * terms of resource availability. 9728 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 9729 */ 9730 if (mode64) 9731 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 9732 else 9733 assign( rA, getIReg(rA_addr) ); 9734 9735 putVSReg( XT, binop( Iop_64HLtoV128, 9736 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 9737 mkU64( 0 ) ) ); 9738 break; 9739 } 9740 9741 default: 9742 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 9743 return False; 9744 } 9745 return True; 9746 } 9747 9748 9749 /* 9750 Cache Management Instructions 9751 */ 9752 static Bool dis_cache_manage ( UInt theInstr, 9753 DisResult* dres, 9754 const VexArchInfo* guest_archinfo ) 9755 { 9756 /* X-Form */ 9757 UChar opc1 = ifieldOPC(theInstr); 9758 UChar b21to25 = ifieldRegDS(theInstr); 9759 UChar rA_addr = ifieldRegA(theInstr); 9760 UChar rB_addr = ifieldRegB(theInstr); 9761 UInt opc2 = ifieldOPClo10(theInstr); 9762 UChar b0 = ifieldBIT0(theInstr); 9763 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 9764 Bool is_dcbzl = False; 9765 9766 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9767 9768 // Check for valid hint values for dcbt and dcbtst as currently described in 9769 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 9770 // means of modeling the hint anyway. 9771 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 9772 if (b21to25 == 0x10 || b21to25 < 0x10) 9773 b21to25 = 0; 9774 } 9775 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 9776 b21to25 = 0; 9777 9778 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 9779 if (b21to25 == 1) { 9780 is_dcbzl = True; 9781 b21to25 = 0; 9782 if (!(guest_archinfo->ppc_dcbzl_szB)) { 9783 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 9784 return False; 9785 } 9786 } 9787 } 9788 9789 if (opc1 != 0x1F || b0 != 0) { 9790 if (0) vex_printf("dis_cache_manage %d %d\n", 9791 opc1, b0); 9792 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n"); 9793 return False; 9794 } 9795 9796 /* stay sane .. */ 9797 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 9798 9799 switch (opc2) { 9800 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 9801 //zz vassert(0); /* AWAITING TEST CASE */ 9802 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 9803 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 9804 //zz break; 9805 9806 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 9807 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 9808 /* nop as far as vex is concerned */ 9809 break; 9810 9811 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 9812 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 9813 /* nop as far as vex is concerned */ 9814 break; 9815 9816 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 9817 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 9818 /* nop as far as vex is concerned */ 9819 break; 9820 9821 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 9822 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 9823 /* nop as far as vex is concerned */ 9824 break; 9825 9826 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 9827 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 9828 /* Clear all bytes in cache block at (rA|0) + rB. */ 9829 IRTemp EA = newTemp(ty); 9830 IRTemp addr = newTemp(ty); 9831 IRExpr* irx_addr; 9832 UInt i; 9833 UInt clearszB; 9834 if (is_dcbzl) { 9835 clearszB = guest_archinfo->ppc_dcbzl_szB; 9836 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 9837 } 9838 else { 9839 clearszB = guest_archinfo->ppc_dcbz_szB; 9840 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 9841 } 9842 9843 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 9844 9845 if (mode64) { 9846 /* Round EA down to the start of the containing block. */ 9847 assign( addr, binop( Iop_And64, 9848 mkexpr(EA), 9849 mkU64( ~((ULong)clearszB-1) )) ); 9850 9851 for (i = 0; i < clearszB / 8; i++) { 9852 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 9853 store( irx_addr, mkU64(0) ); 9854 } 9855 } else { 9856 /* Round EA down to the start of the containing block. */ 9857 assign( addr, binop( Iop_And32, 9858 mkexpr(EA), 9859 mkU32( ~(clearszB-1) )) ); 9860 9861 for (i = 0; i < clearszB / 4; i++) { 9862 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 9863 store( irx_addr, mkU32(0) ); 9864 } 9865 } 9866 break; 9867 } 9868 9869 case 0x3D6: { 9870 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 9871 /* Invalidate all translations containing code from the cache 9872 block at (rA|0) + rB. */ 9873 IRTemp EA = newTemp(ty); 9874 IRTemp addr = newTemp(ty); 9875 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 9876 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 9877 9878 /* Round EA down to the start of the containing block. */ 9879 assign( addr, binop( mkSzOp(ty, Iop_And8), 9880 mkexpr(EA), 9881 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 9882 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 9883 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 9884 9885 /* be paranoid ... */ 9886 stmt( IRStmt_MBE(Imbe_Fence) ); 9887 9888 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 9889 dres->jk_StopHere = Ijk_InvalICache; 9890 dres->whatNext = Dis_StopHere; 9891 break; 9892 } 9893 9894 default: 9895 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 9896 return False; 9897 } 9898 return True; 9899 } 9900 9901 9902 /*------------------------------------------------------------*/ 9903 /*--- Floating Point Helpers ---*/ 9904 /*------------------------------------------------------------*/ 9905 9906 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 9907 /* Produces a value in 0 .. 3, which is encoded as per the type 9908 IRRoundingMode. PPCRoundingMode encoding is different to 9909 IRRoundingMode, so need to map it. 9910 */ 9911 9912 static IRExpr* /* :: Ity_I32 */ set_round_to_Oddmode ( void ) 9913 { 9914 /* PPC/ valgrind have two-bits to designate the rounding mode. 9915 ISA 3.0 adds instructions than can use a round to odd mode 9916 but did not change the number of bits for the rm. Basically, 9917 they added two instructions that only differ by the rounding 9918 mode the operation uses. In essesce, they encoded the rm 9919 in the name. In order to avoid having to create Iops, that 9920 encode the rm in th name, we will "expand" the definition of 9921 the rounding mode bits. We will just pass the rm and then 9922 map the to odd mode to the appropriate PPCFpOp name that 9923 will tell us which instruction to map to. 9924 9925 rounding mode | PPC | IR 9926 ------------------------ 9927 to nearest | 000 | 00 9928 to zero | 001 | 11 9929 to +infinity | 010 | 10 9930 to -infinity | 011 | 01 9931 to odd | 1xx | xx 9932 */ 9933 return mkU32(8); 9934 } 9935 9936 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 9937 { 9938 /* 9939 rounding mode | PPC | IR 9940 ------------------------ 9941 to nearest | 00 | 00 9942 to zero | 01 | 11 9943 to +infinity | 10 | 10 9944 to -infinity | 11 | 01 9945 */ 9946 IRTemp rm_PPC32 = newTemp(Ity_I32); 9947 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 9948 9949 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 9950 return binop( Iop_Xor32, 9951 mkexpr(rm_PPC32), 9952 binop( Iop_And32, 9953 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 9954 mkU32(2) )); 9955 } 9956 9957 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 9958 * mapping would still work with the extended three bit DFP rounding 9959 * mode designator. 9960 9961 * rounding mode | PPC | IR 9962 * ----------------------------------------------- 9963 * to nearest, ties to even | 000 | 000 9964 * to zero | 001 | 011 9965 * to +infinity | 010 | 010 9966 * to -infinity | 011 | 001 9967 * to nearest, ties away from 0 | 100 | 100 9968 * to nearest, ties toward 0 | 101 | 111 9969 * to away from 0 | 110 | 110 9970 * to prepare for shorter precision | 111 | 101 9971 */ 9972 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 9973 { 9974 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 9975 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 9976 9977 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 9978 return binop( Iop_Xor32, 9979 mkexpr( rm_PPC32 ), 9980 binop( Iop_And32, 9981 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 9982 mkU32( 2 ) ) ); 9983 } 9984 9985 #define NANmaskSingle 0x7F800000 9986 #define NANmaskDouble 0x7FF00000 9987 9988 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 9989 { 9990 IRTemp exp_zero = newTemp(Ity_I8); 9991 IRTemp frac_mask = newTemp(Ity_I32); 9992 IRTemp frac_not_zero = newTemp(Ity_I8); 9993 9994 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 9995 * The input value is always 64-bits, for single precision values, the 9996 * lower 32 bits must be zero. 9997 * 9998 * Single Pricision 9999 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 10000 * [53:32] fraction field is zero for Infinity and non-zero for NAN 10001 * [31:0] unused for single precision representation 10002 * 10003 * Double Pricision 10004 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 10005 * [50:0] fraction field is zero for Infinity and non-zero for NAN 10006 * 10007 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 10008 */ 10009 assign( frac_mask, unop( Iop_Not32, 10010 binop( Iop_Or32, 10011 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 10012 10013 assign( exp_zero, 10014 unop( Iop_1Sto8, 10015 binop( Iop_CmpEQ32, 10016 binop( Iop_And32, 10017 unop( Iop_64HIto32, 10018 unop( Iop_ReinterpF64asI64, 10019 value ) ), 10020 Hi32Mask ), 10021 Hi32Mask ) ) ); 10022 assign( frac_not_zero, 10023 binop( Iop_Or8, 10024 unop( Iop_1Sto8, 10025 binop( Iop_CmpNE32, 10026 binop( Iop_And32, 10027 unop( Iop_64HIto32, 10028 unop( Iop_ReinterpF64asI64, 10029 value ) ), 10030 mkexpr( frac_mask ) ), 10031 mkU32( 0x0 ) ) ), 10032 unop( Iop_1Sto8, 10033 binop( Iop_CmpNE32, 10034 binop( Iop_And32, 10035 unop( Iop_64to32, 10036 unop( Iop_ReinterpF64asI64, 10037 value ) ), 10038 mkU32( 0xFFFFFFFF ) ), 10039 mkU32( 0x0 ) ) ) ) ); 10040 return unop( Iop_8Sto32, 10041 binop( Iop_And8, 10042 mkexpr( exp_zero ), 10043 mkexpr( frac_not_zero ) ) ); 10044 } 10045 10046 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 10047 { 10048 /* This function will only complement the 64-bit floating point value if it 10049 * is not Nan. NaN is not a signed value. Need to do computations using 10050 * 32-bit operands to ensure it will run in 32-bit mode. 10051 */ 10052 return binop( Iop_32HLto64, 10053 binop( Iop_Or32, 10054 binop( Iop_And32, 10055 nan_mask, 10056 unop( Iop_64HIto32, 10057 unop( Iop_ReinterpF64asI64, 10058 value ) ) ), 10059 binop( Iop_And32, 10060 unop( Iop_Not32, 10061 nan_mask ), 10062 unop( Iop_64HIto32, 10063 unop( Iop_ReinterpF64asI64, 10064 unop( Iop_NegF64, 10065 value ) ) ) ) ), 10066 unop( Iop_64to32, 10067 unop( Iop_ReinterpF64asI64, value ) ) ); 10068 } 10069 10070 /*------------------------------------------------------------*/ 10071 /*--- Floating Point Instruction Translation ---*/ 10072 /*------------------------------------------------------------*/ 10073 10074 /* 10075 Floating Point Load Instructions 10076 */ 10077 static Bool dis_fp_load ( UInt theInstr ) 10078 { 10079 /* X-Form, D-Form */ 10080 UChar opc1 = ifieldOPC(theInstr); 10081 UChar frD_addr = ifieldRegDS(theInstr); 10082 UChar rA_addr = ifieldRegA(theInstr); 10083 UChar rB_addr = ifieldRegB(theInstr); 10084 UInt opc2 = ifieldOPClo10(theInstr); 10085 UChar b0 = ifieldBIT0(theInstr); 10086 UInt uimm16 = ifieldUIMM16(theInstr); 10087 10088 Int simm16 = extend_s_16to32(uimm16); 10089 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10090 IRTemp EA = newTemp(ty); 10091 IRTemp rA = newTemp(ty); 10092 IRTemp rB = newTemp(ty); 10093 IRTemp iHi = newTemp(Ity_I32); 10094 IRTemp iLo = newTemp(Ity_I32); 10095 10096 assign( rA, getIReg(rA_addr) ); 10097 assign( rB, getIReg(rB_addr) ); 10098 10099 /* These are completely straightforward from a rounding and status 10100 bits perspective: no rounding involved and no funny status or CR 10101 bits affected. */ 10102 10103 switch (opc1) { 10104 case 0x30: // lfs (Load Float Single, PPC32 p441) 10105 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10106 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10107 putFReg( frD_addr, 10108 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10109 break; 10110 10111 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 10112 if (rA_addr == 0) 10113 return False; 10114 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10115 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10116 putFReg( frD_addr, 10117 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10118 putIReg( rA_addr, mkexpr(EA) ); 10119 break; 10120 10121 case 0x32: // lfd (Load Float Double, PPC32 p437) 10122 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10123 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10124 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10125 break; 10126 10127 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 10128 if (rA_addr == 0) 10129 return False; 10130 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 10131 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10132 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10133 putIReg( rA_addr, mkexpr(EA) ); 10134 break; 10135 10136 case 0x1F: 10137 if (b0 != 0) { 10138 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 10139 return False; 10140 } 10141 10142 switch(opc2) { 10143 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 10144 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10145 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10146 putFReg( frD_addr, unop( Iop_F32toF64, 10147 load(Ity_F32, mkexpr(EA))) ); 10148 break; 10149 10150 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 10151 if (rA_addr == 0) 10152 return False; 10153 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10154 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10155 putFReg( frD_addr, 10156 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 10157 putIReg( rA_addr, mkexpr(EA) ); 10158 break; 10159 10160 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 10161 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10162 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10163 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10164 break; 10165 10166 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 10167 if (rA_addr == 0) 10168 return False; 10169 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10170 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10171 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 10172 putIReg( rA_addr, mkexpr(EA) ); 10173 break; 10174 10175 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 10176 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10177 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10178 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 10179 assign( iHi, binop(Iop_Sub32, 10180 mkU32(0), 10181 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 10182 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 10183 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 10184 break; 10185 10186 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 10187 { 10188 IRTemp dw = newTemp( Ity_I64 ); 10189 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 10190 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10191 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 10192 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 10193 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 10194 break; 10195 } 10196 10197 default: 10198 vex_printf("dis_fp_load(ppc)(opc2)\n"); 10199 return False; 10200 } 10201 break; 10202 10203 default: 10204 vex_printf("dis_fp_load(ppc)(opc1)\n"); 10205 return False; 10206 } 10207 return True; 10208 } 10209 10210 10211 10212 /* 10213 Floating Point Store Instructions 10214 */ 10215 static Bool dis_fp_store ( UInt theInstr ) 10216 { 10217 /* X-Form, D-Form */ 10218 UChar opc1 = ifieldOPC(theInstr); 10219 UChar frS_addr = ifieldRegDS(theInstr); 10220 UChar rA_addr = ifieldRegA(theInstr); 10221 UChar rB_addr = ifieldRegB(theInstr); 10222 UInt opc2 = ifieldOPClo10(theInstr); 10223 UChar b0 = ifieldBIT0(theInstr); 10224 Int uimm16 = ifieldUIMM16(theInstr); 10225 10226 Int simm16 = extend_s_16to32(uimm16); 10227 IRTemp frS = newTemp(Ity_F64); 10228 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10229 IRTemp EA = newTemp(ty); 10230 IRTemp rA = newTemp(ty); 10231 IRTemp rB = newTemp(ty); 10232 10233 assign( frS, getFReg(frS_addr) ); 10234 assign( rA, getIReg(rA_addr) ); 10235 assign( rB, getIReg(rB_addr) ); 10236 10237 /* These are straightforward from a status bits perspective: no 10238 funny status or CR bits affected. For single precision stores, 10239 the values are truncated and denormalised (not rounded) to turn 10240 them into single precision values. */ 10241 10242 switch (opc1) { 10243 10244 case 0x34: // stfs (Store Float Single, PPC32 p518) 10245 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10246 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10247 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 10248 the value to be stored in the correct way, without any 10249 rounding. */ 10250 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10251 break; 10252 10253 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 10254 if (rA_addr == 0) 10255 return False; 10256 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10257 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10258 /* See comment for stfs */ 10259 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10260 putIReg( rA_addr, mkexpr(EA) ); 10261 break; 10262 10263 case 0x36: // stfd (Store Float Double, PPC32 p513) 10264 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10265 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 10266 store( mkexpr(EA), mkexpr(frS) ); 10267 break; 10268 10269 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 10270 if (rA_addr == 0) 10271 return False; 10272 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 10273 assign( EA, ea_rA_simm(rA_addr, simm16) ); 10274 store( mkexpr(EA), mkexpr(frS) ); 10275 putIReg( rA_addr, mkexpr(EA) ); 10276 break; 10277 10278 case 0x1F: 10279 if (b0 != 0) { 10280 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 10281 return False; 10282 } 10283 switch(opc2) { 10284 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 10285 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10286 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10287 /* See note for stfs */ 10288 store( mkexpr(EA), 10289 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10290 break; 10291 10292 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 10293 if (rA_addr == 0) 10294 return False; 10295 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10296 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10297 /* See note for stfs */ 10298 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 10299 putIReg( rA_addr, mkexpr(EA) ); 10300 break; 10301 10302 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 10303 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10304 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10305 store( mkexpr(EA), mkexpr(frS) ); 10306 break; 10307 10308 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 10309 if (rA_addr == 0) 10310 return False; 10311 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10312 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 10313 store( mkexpr(EA), mkexpr(frS) ); 10314 putIReg( rA_addr, mkexpr(EA) ); 10315 break; 10316 10317 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 10318 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10319 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 10320 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 10321 store( mkexpr(EA), 10322 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 10323 break; 10324 10325 default: 10326 vex_printf("dis_fp_store(ppc)(opc2)\n"); 10327 return False; 10328 } 10329 break; 10330 10331 default: 10332 vex_printf("dis_fp_store(ppc)(opc1)\n"); 10333 return False; 10334 } 10335 return True; 10336 } 10337 10338 10339 10340 /* 10341 Floating Point Arith Instructions 10342 */ 10343 static Bool dis_fp_arith ( UInt theInstr ) 10344 { 10345 /* A-Form */ 10346 UChar opc1 = ifieldOPC(theInstr); 10347 UChar frD_addr = ifieldRegDS(theInstr); 10348 UChar frA_addr = ifieldRegA(theInstr); 10349 UChar frB_addr = ifieldRegB(theInstr); 10350 UChar frC_addr = ifieldRegC(theInstr); 10351 UChar opc2 = ifieldOPClo5(theInstr); 10352 UChar flag_rC = ifieldBIT0(theInstr); 10353 10354 IRTemp frD = newTemp(Ity_F64); 10355 IRTemp frA = newTemp(Ity_F64); 10356 IRTemp frB = newTemp(Ity_F64); 10357 IRTemp frC = newTemp(Ity_F64); 10358 IRExpr* rm = get_IR_roundingmode(); 10359 10360 /* By default, we will examine the results of the operation and set 10361 fpscr[FPRF] accordingly. */ 10362 Bool set_FPRF = True; 10363 10364 /* By default, if flag_RC is set, we will clear cr1 after the 10365 operation. In reality we should set cr1 to indicate the 10366 exception status of the operation, but since we're not 10367 simulating exceptions, the exception status will appear to be 10368 zero. Hence cr1 should be cleared if this is a . form insn. */ 10369 Bool clear_CR1 = True; 10370 10371 assign( frA, getFReg(frA_addr)); 10372 assign( frB, getFReg(frB_addr)); 10373 assign( frC, getFReg(frC_addr)); 10374 10375 switch (opc1) { 10376 case 0x3B: 10377 switch (opc2) { 10378 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 10379 if (frC_addr != 0) 10380 return False; 10381 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10382 frD_addr, frA_addr, frB_addr); 10383 assign( frD, triop( Iop_DivF64r32, 10384 rm, mkexpr(frA), mkexpr(frB) )); 10385 break; 10386 10387 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 10388 if (frC_addr != 0) 10389 return False; 10390 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10391 frD_addr, frA_addr, frB_addr); 10392 assign( frD, triop( Iop_SubF64r32, 10393 rm, mkexpr(frA), mkexpr(frB) )); 10394 break; 10395 10396 case 0x15: // fadds (Floating Add Single, PPC32 p401) 10397 if (frC_addr != 0) 10398 return False; 10399 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10400 frD_addr, frA_addr, frB_addr); 10401 assign( frD, triop( Iop_AddF64r32, 10402 rm, mkexpr(frA), mkexpr(frB) )); 10403 break; 10404 10405 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 10406 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 10407 if (frA_addr != 0 || frC_addr != 0) 10408 return False; 10409 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 10410 frD_addr, frB_addr); 10411 // however illogically, on ppc970 this insn behaves identically 10412 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 10413 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 10414 break; 10415 10416 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 10417 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10418 if (frA_addr != 0 || frC_addr != 0) 10419 return False; 10420 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 10421 frD_addr, frB_addr); 10422 { IRExpr* ieee_one 10423 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 10424 assign( frD, triop( Iop_DivF64r32, 10425 rm, 10426 ieee_one, mkexpr(frB) )); 10427 } 10428 break; 10429 10430 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 10431 if (frB_addr != 0) 10432 return False; 10433 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10434 frD_addr, frA_addr, frC_addr); 10435 assign( frD, triop( Iop_MulF64r32, 10436 rm, mkexpr(frA), mkexpr(frC) )); 10437 break; 10438 10439 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 10440 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10441 // Undocumented instruction? 10442 if (frA_addr != 0 || frC_addr != 0) 10443 return False; 10444 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 10445 frD_addr, frB_addr); 10446 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 10447 break; 10448 10449 default: 10450 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 10451 return False; 10452 } 10453 break; 10454 10455 case 0x3F: 10456 switch (opc2) { 10457 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 10458 if (frC_addr != 0) 10459 return False; 10460 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10461 frD_addr, frA_addr, frB_addr); 10462 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 10463 break; 10464 10465 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 10466 if (frC_addr != 0) 10467 return False; 10468 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10469 frD_addr, frA_addr, frB_addr); 10470 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 10471 break; 10472 10473 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 10474 if (frC_addr != 0) 10475 return False; 10476 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10477 frD_addr, frA_addr, frB_addr); 10478 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 10479 break; 10480 10481 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 10482 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 10483 if (frA_addr != 0 || frC_addr != 0) 10484 return False; 10485 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 10486 frD_addr, frB_addr); 10487 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 10488 break; 10489 10490 case 0x17: { // fsel (Floating Select, PPC32 p426) 10491 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10492 IRTemp cc = newTemp(Ity_I32); 10493 IRTemp cc_b0 = newTemp(Ity_I32); 10494 10495 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10496 frD_addr, frA_addr, frC_addr, frB_addr); 10497 10498 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 10499 // => GT|EQ == (cc & 0x1 == 0) 10500 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 10501 IRExpr_Const(IRConst_F64(0))) ); 10502 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 10503 10504 // frD = (frA >= 0.0) ? frC : frB 10505 // = (cc_b0 == 0) ? frC : frB 10506 assign( frD, 10507 IRExpr_ITE( 10508 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 10509 mkexpr(frC), 10510 mkexpr(frB) )); 10511 10512 /* One of the rare ones which don't mess with FPRF */ 10513 set_FPRF = False; 10514 break; 10515 } 10516 10517 case 0x18: // fre (Floating Reciprocal Estimate) 10518 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10519 // Note: unclear whether this insn really exists or not 10520 // ppc970 doesn't have it, but POWER5 does 10521 if (frA_addr != 0 || frC_addr != 0) 10522 return False; 10523 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 10524 frD_addr, frB_addr); 10525 { IRExpr* ieee_one 10526 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 10527 assign( frD, triop( Iop_DivF64, 10528 rm, 10529 ieee_one, mkexpr(frB) )); 10530 } 10531 break; 10532 10533 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 10534 if (frB_addr != 0) 10535 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 10536 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10537 frD_addr, frA_addr, frC_addr); 10538 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 10539 break; 10540 10541 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 10542 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 10543 if (frA_addr != 0 || frC_addr != 0) 10544 return False; 10545 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 10546 frD_addr, frB_addr); 10547 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) ); 10548 break; 10549 10550 default: 10551 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 10552 return False; 10553 } 10554 break; 10555 10556 default: 10557 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 10558 return False; 10559 } 10560 10561 putFReg( frD_addr, mkexpr(frD) ); 10562 10563 if (set_FPRF) { 10564 // XXX XXX XXX FIXME 10565 // set FPRF from frD 10566 } 10567 10568 if (flag_rC && clear_CR1) { 10569 putCR321( 1, mkU8(0) ); 10570 putCR0( 1, mkU8(0) ); 10571 } 10572 10573 return True; 10574 } 10575 10576 10577 10578 /* 10579 Floating Point Mult-Add Instructions 10580 */ 10581 static Bool dis_fp_multadd ( UInt theInstr ) 10582 { 10583 /* A-Form */ 10584 UChar opc1 = ifieldOPC(theInstr); 10585 UChar frD_addr = ifieldRegDS(theInstr); 10586 UChar frA_addr = ifieldRegA(theInstr); 10587 UChar frB_addr = ifieldRegB(theInstr); 10588 UChar frC_addr = ifieldRegC(theInstr); 10589 UChar opc2 = ifieldOPClo5(theInstr); 10590 UChar flag_rC = ifieldBIT0(theInstr); 10591 10592 IRTemp frD = newTemp(Ity_F64); 10593 IRTemp frA = newTemp(Ity_F64); 10594 IRTemp frB = newTemp(Ity_F64); 10595 IRTemp frC = newTemp(Ity_F64); 10596 IRTemp rmt = newTemp(Ity_I32); 10597 IRTemp tmp = newTemp(Ity_F64); 10598 IRTemp sign_tmp = newTemp(Ity_I64); 10599 IRTemp nan_mask = newTemp(Ity_I32); 10600 IRExpr* rm; 10601 10602 /* By default, we will examine the results of the operation and set 10603 fpscr[FPRF] accordingly. */ 10604 Bool set_FPRF = True; 10605 10606 /* By default, if flag_RC is set, we will clear cr1 after the 10607 operation. In reality we should set cr1 to indicate the 10608 exception status of the operation, but since we're not 10609 simulating exceptions, the exception status will appear to be 10610 zero. Hence cr1 should be cleared if this is a . form insn. */ 10611 Bool clear_CR1 = True; 10612 10613 /* Bind the rounding mode expression to a temp; there's no 10614 point in creating gratuitous CSEs, as we know we'll need 10615 to use it twice. */ 10616 assign( rmt, get_IR_roundingmode() ); 10617 rm = mkexpr(rmt); 10618 10619 assign( frA, getFReg(frA_addr)); 10620 assign( frB, getFReg(frB_addr)); 10621 assign( frC, getFReg(frC_addr)); 10622 10623 /* The rounding in this is all a bit dodgy. The idea is to only do 10624 one rounding. That clearly isn't achieveable without dedicated 10625 four-input IR primops, although in the single precision case we 10626 can sort-of simulate it by doing the inner multiply in double 10627 precision. 10628 10629 In the negated cases, the negation happens after rounding. */ 10630 10631 switch (opc1) { 10632 case 0x3B: 10633 switch (opc2) { 10634 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 10635 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10636 frD_addr, frA_addr, frC_addr, frB_addr); 10637 assign( frD, qop( Iop_MSubF64r32, rm, 10638 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10639 break; 10640 10641 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 10642 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10643 frD_addr, frA_addr, frC_addr, frB_addr); 10644 assign( frD, qop( Iop_MAddF64r32, rm, 10645 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10646 break; 10647 10648 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 10649 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 10650 10651 if (opc2 == 0x1E) { 10652 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10653 frD_addr, frA_addr, frC_addr, frB_addr); 10654 assign( tmp, qop( Iop_MSubF64r32, rm, 10655 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10656 } else { 10657 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10658 frD_addr, frA_addr, frC_addr, frB_addr); 10659 assign( tmp, qop( Iop_MAddF64r32, rm, 10660 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10661 } 10662 10663 assign( nan_mask, Check_NaN( mkexpr( tmp ), 10664 mkU32( NANmaskSingle ) ) ); 10665 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 10666 mkexpr( nan_mask ) ) ); 10667 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 10668 break; 10669 10670 default: 10671 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 10672 return False; 10673 } 10674 break; 10675 10676 case 0x3F: 10677 switch (opc2) { 10678 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 10679 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10680 frD_addr, frA_addr, frC_addr, frB_addr); 10681 assign( frD, qop( Iop_MSubF64, rm, 10682 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10683 break; 10684 10685 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 10686 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10687 frD_addr, frA_addr, frC_addr, frB_addr); 10688 assign( frD, qop( Iop_MAddF64, rm, 10689 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10690 break; 10691 10692 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 10693 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 10694 10695 if (opc2 == 0x1E) { 10696 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10697 frD_addr, frA_addr, frC_addr, frB_addr); 10698 assign( tmp, qop( Iop_MSubF64, rm, 10699 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 10700 } else { 10701 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 10702 frD_addr, frA_addr, frC_addr, frB_addr); 10703 assign( tmp, qop( Iop_MAddF64, rm, 10704 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 10705 } 10706 10707 assign( nan_mask, Check_NaN( mkexpr( tmp ), 10708 mkU32( NANmaskDouble ) ) ); 10709 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 10710 mkexpr( nan_mask ) ) ); 10711 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 10712 break; 10713 10714 default: 10715 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 10716 return False; 10717 } 10718 break; 10719 10720 default: 10721 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 10722 return False; 10723 } 10724 10725 putFReg( frD_addr, mkexpr(frD) ); 10726 10727 if (set_FPRF) { 10728 // XXX XXX XXX FIXME 10729 // set FPRF from frD 10730 } 10731 10732 if (flag_rC && clear_CR1) { 10733 putCR321( 1, mkU8(0) ); 10734 putCR0( 1, mkU8(0) ); 10735 } 10736 10737 return True; 10738 } 10739 10740 /* 10741 * fe_flag is set to 1 if any of the following conditions occurs: 10742 * - The floating-point operand in register FRB is a Zero, a 10743 * NaN, an Infinity, or a negative value. 10744 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 10745 * Otherwise fe_flag is set to 0. 10746 * 10747 * fg_flag is set to 1 if either of the following conditions occurs. 10748 * - The floating-point operand in register FRB is a Zero, an 10749 * Infinity, or a denormalized value. 10750 * Otherwise fg_flag is set to 0. 10751 * 10752 */ 10753 10754 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 10755 { 10756 // The following temps are for holding intermediate results 10757 IRTemp e_b = newTemp(Ity_I32); 10758 IRExpr * fe_flag, * fg_flag; 10759 IRTemp frB_exp_shR = newTemp(Ity_I32); 10760 UInt bias = sp? 127 : 1023; 10761 IRExpr * frbNaN, * frbDenorm, * frBNeg; 10762 IRExpr * eb_LTE; 10763 IRTemp frbZero_tmp = newTemp(Ity_I1); 10764 IRTemp frbInf_tmp = newTemp(Ity_I1); 10765 *fe_flag_tmp = newTemp(Ity_I32); 10766 *fg_flag_tmp = newTemp(Ity_I32); 10767 10768 if ( sp ) 10769 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) ); 10770 else 10771 assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_Int ) ); 10772 10773 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 10774 10775 ////////////////// fe_flag tests BEGIN ////////////////////// 10776 /* We first do all tests that may result in setting fe_flag to '1'. 10777 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 10778 * for details.) 10779 */ 10780 if ( sp ) { 10781 frbNaN = is_NaN( Ity_I32, frB_Int ); 10782 assign( frbInf_tmp, is_Inf( Ity_I32, frB_Int ) ); 10783 assign( frbZero_tmp, is_Zero( Ity_I32, frB_Int ) ); 10784 10785 } else { 10786 frbNaN = is_NaN( Ity_I64, frB_Int ); 10787 assign( frbInf_tmp, is_Inf( Ity_I64, frB_Int ) ); 10788 assign( frbZero_tmp, is_Zero( Ity_I64, frB_Int ) ); 10789 } 10790 10791 { 10792 // Test_value = -970 for double precision 10793 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 10794 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 10795 } 10796 frBNeg = binop( Iop_CmpEQ32, 10797 binop( Iop_Shr32, 10798 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 10799 mkU8( 31 ) ), 10800 mkU32( 1 ) ); 10801 ////////////////// fe_flag tests END ////////////////////// 10802 10803 ////////////////// fg_flag tests BEGIN ////////////////////// 10804 /* 10805 * The following tests were already performed above in the fe_flag 10806 * tests. So these conditions will result in both fe_ and fg_ flags 10807 * being set. 10808 * - Test if FRB is Zero 10809 * - Test if FRB is an Infinity 10810 */ 10811 10812 /* 10813 * Test if FRB holds a denormalized value. A denormalized value is one where 10814 * the exp is 0 and the fraction is non-zero. 10815 */ 10816 if (sp) { 10817 IRTemp frac_part = newTemp(Ity_I32); 10818 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 10819 frbDenorm 10820 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 10821 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 10822 } else { 10823 IRExpr * hi32, * low32, * fraction_is_nonzero; 10824 IRTemp frac_part = newTemp(Ity_I64); 10825 10826 assign( frac_part, FP_FRAC_PART(frB_Int) ); 10827 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 10828 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 10829 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 10830 mkU32( 0 ) ); 10831 frbDenorm 10832 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 10833 fraction_is_nonzero ); 10834 } 10835 ////////////////// fg_flag tests END ////////////////////// 10836 10837 ///////////////////////// 10838 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 10839 mkOR1( frbNaN, 10840 mkOR1( mkexpr( frbInf_tmp ), 10841 mkOR1( frBNeg, eb_LTE ) ) ) ); 10842 10843 fe_flag = unop(Iop_1Uto32, fe_flag); 10844 10845 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 10846 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 10847 fg_flag = unop(Iop_1Uto32, fg_flag); 10848 assign (*fg_flag_tmp, fg_flag); 10849 assign (*fe_flag_tmp, fe_flag); 10850 } 10851 /* 10852 * fe_flag is set to 1 if any of the following conditions occurs: 10853 * - The double-precision floating-point operand in register FRA is a NaN or an 10854 * Infinity. 10855 * - The double-precision floating-point operand in register FRB is a Zero, a 10856 * NaN, or an Infinity. 10857 * - e_b is less than or equal to -1022. 10858 * - e_b is greater than or equal to 1021. 10859 * - The double-precision floating-point operand in register FRA is not a zero 10860 * and the difference, e_a - e_b, is greater than or equal to 1023. 10861 * - The double-precision floating-point operand in register FRA is not a zero 10862 * and the difference, e_a - e_b, is less than or equal to -1021. 10863 * - The double-precision floating-point operand in register FRA is not a zero 10864 * and e_a is less than or equal to -970 10865 * Otherwise fe_flag is set to 0. 10866 * 10867 * fg_flag is set to 1 if either of the following conditions occurs. 10868 * - The double-precision floating-point operand in register FRA is an Infinity. 10869 * - The double-precision floating-point operand in register FRB is a Zero, an 10870 * Infinity, or a denormalized value. 10871 * Otherwise fg_flag is set to 0. 10872 * 10873 */ 10874 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 10875 { 10876 // The following temps are for holding intermediate results 10877 IRTemp e_a = newTemp(Ity_I32); 10878 IRTemp e_b = newTemp(Ity_I32); 10879 IRTemp frA_exp_shR = newTemp(Ity_I32); 10880 IRTemp frB_exp_shR = newTemp(Ity_I32); 10881 10882 UInt bias = sp? 127 : 1023; 10883 *fe_flag_tmp = newTemp(Ity_I32); 10884 *fg_flag_tmp = newTemp(Ity_I32); 10885 10886 /* The following variables hold boolean results from tests 10887 * that are OR'ed together for setting the fe_ and fg_ flags. 10888 * For some cases, the booleans are used more than once, so 10889 * I make those IRTemp's instead of IRExpr's. 10890 */ 10891 IRExpr * fraNaN, * frbNaN, * frbDenorm; 10892 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 10893 IRTemp fraInf_tmp = newTemp(Ity_I1); 10894 IRTemp frbZero_tmp = newTemp(Ity_I1); 10895 IRTemp frbInf_tmp = newTemp(Ity_I1); 10896 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 10897 10898 /* The following are the flags that are set by OR'ing the results of 10899 * all the tests done for tdiv. These flags are the input to the specified CR. 10900 */ 10901 IRExpr * fe_flag, * fg_flag; 10902 10903 // Create temps that will be used throughout the following tests. 10904 if ( sp ) { 10905 assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) ); 10906 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) ); 10907 } else{ 10908 assign( frA_exp_shR, fp_exp_part( Ity_I64, frA_int ) ); 10909 assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_int ) ); 10910 } 10911 10912 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 10913 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 10914 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 10915 10916 10917 ////////////////// fe_flag tests BEGIN ////////////////////// 10918 /* We first do all tests that may result in setting fe_flag to '1'. */ 10919 10920 /* 10921 * Test if the double-precision floating-point operand in register FRA is 10922 * a NaN: 10923 */ 10924 fraNaN = sp ? is_NaN( Ity_I32, frA_int ) : is_NaN( Ity_I64, frA_int ); 10925 /* 10926 * Test if the double-precision floating-point operands in register FRA 10927 * and FRB is an Infinity. Test if FRB is zero. 10928 */ 10929 if ( sp ) { 10930 assign(fraInf_tmp, is_Inf( Ity_I32, frA_int ) ); 10931 assign( frbInf_tmp, is_Inf( Ity_I32, frB_int ) ); 10932 assign( frbZero_tmp, is_Zero( Ity_I32, frB_int ) ); 10933 10934 } else { 10935 assign(fraInf_tmp, is_Inf( Ity_I64, frA_int ) ); 10936 assign( frbInf_tmp, is_Inf( Ity_I64, frB_int ) ); 10937 assign( frbZero_tmp, is_Zero( Ity_I64, frB_int ) ); 10938 } 10939 /* 10940 * Test if the double-precision floating-point operand in register FRB is 10941 * a NaN: 10942 */ 10943 frbNaN = sp ? is_NaN( Ity_I32, frB_int ) : is_NaN( Ity_I64, frB_int ); 10944 10945 /* 10946 * Test if e_b <= -1022 for double precision; 10947 * or e_b <= -126 for single precision 10948 */ 10949 { 10950 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 10951 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 10952 } 10953 10954 /* 10955 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 10956 * or e_b >= -125 (125 < e_b) for single precision 10957 */ 10958 { 10959 Int test_value = sp ? 125 : 1021; 10960 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 10961 } 10962 10963 /* 10964 * Test if FRA != Zero and (e_a - e_b) >= bias 10965 */ 10966 if ( sp ) 10967 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) ); 10968 else 10969 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I64, frA_int ) ) ); 10970 10971 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 10972 binop( Iop_CmpLT32S, mkU32( bias ), 10973 binop( Iop_Sub32, mkexpr( e_a ), 10974 mkexpr( e_b ) ) ) ); 10975 10976 /* 10977 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 10978 */ 10979 { 10980 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 10981 10982 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 10983 binop( Iop_CmpLE32S, 10984 binop( Iop_Sub32, 10985 mkexpr( e_a ), 10986 mkexpr( e_b ) ), 10987 mkU32( test_value ) ) ); 10988 } 10989 10990 /* 10991 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 10992 */ 10993 { 10994 UInt test_value = 0xfffffc36; //Int test_value = -970; 10995 10996 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 10997 mkexpr( e_a ), 10998 mkU32( test_value ) ) ); 10999 } 11000 ////////////////// fe_flag tests END ////////////////////// 11001 11002 ////////////////// fg_flag tests BEGIN ////////////////////// 11003 /* 11004 * The following tests were already performed above in the fe_flag 11005 * tests. So these conditions will result in both fe_ and fg_ flags 11006 * being set. 11007 * - Test if FRA is an Infinity 11008 * - Test if FRB ix Zero 11009 * - Test if FRB is an Infinity 11010 */ 11011 11012 /* 11013 * Test if FRB holds a denormalized value. A denormalized value is one where 11014 * the exp is 0 and the fraction is non-zero. 11015 */ 11016 { 11017 IRExpr * fraction_is_nonzero; 11018 11019 if (sp) { 11020 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 11021 mkU32( 0 ) ); 11022 } else { 11023 IRExpr * hi32, * low32; 11024 IRTemp frac_part = newTemp(Ity_I64); 11025 assign( frac_part, FP_FRAC_PART(frB_int) ); 11026 11027 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 11028 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 11029 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 11030 mkU32( 0 ) ); 11031 } 11032 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 11033 mkU32( 0x0 ) ), fraction_is_nonzero ); 11034 11035 } 11036 ////////////////// fg_flag tests END ////////////////////// 11037 11038 fe_flag 11039 = mkOR1( 11040 fraNaN, 11041 mkOR1( 11042 mkexpr( fraInf_tmp ), 11043 mkOR1( 11044 mkexpr( frbZero_tmp ), 11045 mkOR1( 11046 frbNaN, 11047 mkOR1( 11048 mkexpr( frbInf_tmp ), 11049 mkOR1( eb_LTE, 11050 mkOR1( eb_GTE, 11051 mkOR1( ea_eb_GTE, 11052 mkOR1( ea_eb_LTE, 11053 ea_LTE ) ) ) ) ) ) ) ) ); 11054 11055 fe_flag = unop(Iop_1Uto32, fe_flag); 11056 11057 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 11058 mkOR1( mkexpr( frbInf_tmp ), 11059 frbDenorm ) ) ); 11060 fg_flag = unop(Iop_1Uto32, fg_flag); 11061 assign(*fe_flag_tmp, fe_flag); 11062 assign(*fg_flag_tmp, fg_flag); 11063 } 11064 11065 /* See description for _do_fp_tdiv() above. */ 11066 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 11067 { 11068 IRTemp fe_flag, fg_flag; 11069 ///////////////////////// 11070 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 11071 * where fl_flag == 1 on ppc64. 11072 */ 11073 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 11074 fe_flag = fg_flag = IRTemp_INVALID; 11075 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 11076 return binop( Iop_Or32, 11077 binop( Iop_Or32, 11078 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 11079 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 11080 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 11081 } 11082 11083 static Bool dis_fp_tests ( UInt theInstr ) 11084 { 11085 UChar opc1 = ifieldOPC(theInstr); 11086 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11087 UChar frB_addr = ifieldRegB(theInstr); 11088 UChar b0 = ifieldBIT0(theInstr); 11089 UInt opc2 = ifieldOPClo10(theInstr); 11090 IRTemp frB_I64 = newTemp(Ity_I64); 11091 11092 if (opc1 != 0x3F || b0 != 0 ){ 11093 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 11094 return False; 11095 } 11096 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 11097 11098 switch (opc2) { 11099 case 0x080: // ftdiv 11100 { 11101 UChar frA_addr = ifieldRegA(theInstr); 11102 IRTemp frA_I64 = newTemp(Ity_I64); 11103 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11104 if (b21to22 != 0 ) { 11105 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 11106 return False; 11107 } 11108 11109 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 11110 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 11111 11112 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11113 break; 11114 } 11115 case 0x0A0: // ftsqrt 11116 { 11117 IRTemp flags = newTemp(Ity_I32); 11118 IRTemp fe_flag, fg_flag; 11119 fe_flag = fg_flag = IRTemp_INVALID; 11120 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 11121 if ( b18to22 != 0) { 11122 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 11123 return False; 11124 } 11125 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 11126 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 11127 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 11128 * where fl_flag == 1 on ppc64. 11129 */ 11130 assign( flags, 11131 binop( Iop_Or32, 11132 binop( Iop_Or32, mkU32( 8 ), // fl_flag 11133 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 11134 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 11135 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 11136 break; 11137 } 11138 11139 default: 11140 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 11141 return False; 11142 11143 } 11144 return True; 11145 } 11146 11147 /* 11148 Floating Point Compare Instructions 11149 */ 11150 static Bool dis_fp_cmp ( UInt theInstr ) 11151 { 11152 /* X-Form */ 11153 UChar opc1 = ifieldOPC(theInstr); 11154 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11155 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11156 UChar frA_addr = ifieldRegA(theInstr); 11157 UChar frB_addr = ifieldRegB(theInstr); 11158 UInt opc2 = ifieldOPClo10(theInstr); 11159 UChar b0 = ifieldBIT0(theInstr); 11160 11161 IRTemp ccIR = newTemp(Ity_I32); 11162 IRTemp ccPPC32 = newTemp(Ity_I32); 11163 11164 IRTemp frA = newTemp(Ity_F64); 11165 IRTemp frB = newTemp(Ity_F64); 11166 11167 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 11168 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 11169 return False; 11170 } 11171 11172 assign( frA, getFReg(frA_addr)); 11173 assign( frB, getFReg(frB_addr)); 11174 11175 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 11176 11177 /* Map compare result from IR to PPC32 */ 11178 /* 11179 FP cmp result | PPC | IR 11180 -------------------------- 11181 UN | 0x1 | 0x45 11182 EQ | 0x2 | 0x40 11183 GT | 0x4 | 0x00 11184 LT | 0x8 | 0x01 11185 */ 11186 11187 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 11188 // | ((ccIR ^ (ccIR>>6)) & 1) 11189 assign( 11190 ccPPC32, 11191 binop( 11192 Iop_Shl32, 11193 mkU32(1), 11194 unop( 11195 Iop_32to8, 11196 binop( 11197 Iop_Or32, 11198 binop( 11199 Iop_And32, 11200 unop( 11201 Iop_Not32, 11202 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 11203 ), 11204 mkU32(2) 11205 ), 11206 binop( 11207 Iop_And32, 11208 binop( 11209 Iop_Xor32, 11210 mkexpr(ccIR), 11211 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 11212 ), 11213 mkU32(1) 11214 ) 11215 ) 11216 ) 11217 ) 11218 ); 11219 11220 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 11221 putFPCC( mkexpr( ccPPC32 ) ); 11222 11223 // XXX XXX XXX FIXME 11224 // Also write the result into FPRF (it's not entirely clear how) 11225 11226 /* Note: Differences between fcmpu and fcmpo are only in exception 11227 flag settings, which aren't supported anyway. */ 11228 switch (opc2) { 11229 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 11230 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11231 break; 11232 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 11233 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 11234 break; 11235 default: 11236 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 11237 return False; 11238 } 11239 return True; 11240 } 11241 11242 11243 11244 /* 11245 Floating Point Rounding/Conversion Instructions 11246 */ 11247 static Bool dis_fp_round ( UInt theInstr ) 11248 { 11249 /* X-Form */ 11250 UChar opc1 = ifieldOPC(theInstr); 11251 UChar b16to20 = ifieldRegA(theInstr); 11252 UChar frD_addr = ifieldRegDS(theInstr); 11253 UChar frB_addr = ifieldRegB(theInstr); 11254 UInt opc2 = ifieldOPClo10(theInstr); 11255 UChar flag_rC = ifieldBIT0(theInstr); 11256 11257 IRTemp frD = newTemp(Ity_F64); 11258 IRTemp frB = newTemp(Ity_F64); 11259 IRTemp r_tmp32 = newTemp(Ity_I32); 11260 IRTemp r_tmp64 = newTemp(Ity_I64); 11261 IRExpr* rm = get_IR_roundingmode(); 11262 11263 /* By default, we will examine the results of the operation and set 11264 fpscr[FPRF] accordingly. */ 11265 Bool set_FPRF = True; 11266 11267 /* By default, if flag_RC is set, we will clear cr1 after the 11268 operation. In reality we should set cr1 to indicate the 11269 exception status of the operation, but since we're not 11270 simulating exceptions, the exception status will appear to be 11271 zero. Hence cr1 should be cleared if this is a . form insn. */ 11272 Bool clear_CR1 = True; 11273 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 11274 vex_printf("dis_fp_round(ppc)(instr)\n"); 11275 return False; 11276 } 11277 11278 assign( frB, getFReg(frB_addr)); 11279 if (opc1 == 0x3B) { 11280 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 11281 * they're very similar to the other instructions handled here, but have 11282 * a different primary opcode. 11283 */ 11284 switch (opc2) { 11285 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 11286 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11287 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11288 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 11289 mkexpr( r_tmp64 ) ) ) ); 11290 goto putFR; 11291 11292 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 11293 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11294 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11295 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 11296 goto putFR; 11297 } 11298 } 11299 11300 11301 switch (opc2) { 11302 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 11303 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11304 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 11305 break; 11306 11307 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 11308 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11309 assign( r_tmp32, 11310 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 11311 assign( frD, unop( Iop_ReinterpI64asF64, 11312 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11313 /* FPRF is undefined after fctiw. Leave unchanged. */ 11314 set_FPRF = False; 11315 break; 11316 11317 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 11318 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11319 assign( r_tmp32, 11320 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 11321 assign( frD, unop( Iop_ReinterpI64asF64, 11322 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11323 /* FPRF is undefined after fctiwz. Leave unchanged. */ 11324 set_FPRF = False; 11325 break; 11326 11327 case 0x08F: case 0x08E: // fctiwu[z] 11328 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 11329 flag_rC ? ".":"", frD_addr, frB_addr); 11330 assign( r_tmp32, 11331 binop( Iop_F64toI32U, 11332 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 11333 mkexpr( frB ) ) ); 11334 assign( frD, unop( Iop_ReinterpI64asF64, 11335 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 11336 /* FPRF is undefined after fctiwz. Leave unchanged. */ 11337 set_FPRF = False; 11338 break; 11339 11340 11341 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 11342 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11343 assign( r_tmp64, 11344 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 11345 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11346 /* FPRF is undefined after fctid. Leave unchanged. */ 11347 set_FPRF = False; 11348 break; 11349 11350 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 11351 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11352 assign( r_tmp64, 11353 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 11354 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11355 /* FPRF is undefined after fctidz. Leave unchanged. */ 11356 set_FPRF = False; 11357 break; 11358 11359 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 11360 { 11361 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 11362 flag_rC ? ".":"", frD_addr, frB_addr); 11363 assign( r_tmp64, 11364 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 11365 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 11366 /* FPRF is undefined after fctidz. Leave unchanged. */ 11367 set_FPRF = False; 11368 break; 11369 } 11370 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 11371 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11372 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11373 assign( frD, 11374 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 11375 break; 11376 11377 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 11378 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11379 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 11380 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 11381 break; 11382 11383 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 11384 switch(opc2) { 11385 case 0x188: // frin (Floating Round to Integer Nearest) 11386 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11387 assign( r_tmp64, 11388 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 11389 break; 11390 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 11391 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11392 assign( r_tmp64, 11393 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 11394 break; 11395 case 0x1C8: // frip (Floating Round to Integer Plus) 11396 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11397 assign( r_tmp64, 11398 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 11399 break; 11400 case 0x1E8: // frim (Floating Round to Integer Minus) 11401 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11402 assign( r_tmp64, 11403 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 11404 break; 11405 } 11406 11407 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 11408 /* F64 has only log10(2**52) significant digits anyway */ 11409 /* need to preserve sign of zero */ 11410 /* frD = (fabs(frB) > 9e18) ? frB : 11411 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 11412 assign(frD, IRExpr_ITE( 11413 binop(Iop_CmpNE8, 11414 unop(Iop_32to8, 11415 binop(Iop_CmpF64, 11416 IRExpr_Const(IRConst_F64(9e18)), 11417 unop(Iop_AbsF64, mkexpr(frB)))), 11418 mkU8(0)), 11419 mkexpr(frB), 11420 IRExpr_ITE( 11421 binop(Iop_CmpNE32, 11422 binop(Iop_Shr32, 11423 unop(Iop_64HIto32, 11424 unop(Iop_ReinterpF64asI64, 11425 mkexpr(frB))), 11426 mkU8(31)), 11427 mkU32(0)), 11428 unop(Iop_NegF64, 11429 unop( Iop_AbsF64, 11430 binop(Iop_I64StoF64, mkU32(0), 11431 mkexpr(r_tmp64)) )), 11432 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 11433 ) 11434 )); 11435 break; 11436 11437 default: 11438 vex_printf("dis_fp_round(ppc)(opc2)\n"); 11439 return False; 11440 } 11441 putFR: 11442 putFReg( frD_addr, mkexpr(frD) ); 11443 11444 if (set_FPRF) { 11445 // XXX XXX XXX FIXME 11446 // set FPRF from frD 11447 } 11448 11449 if (flag_rC && clear_CR1) { 11450 putCR321( 1, mkU8(0) ); 11451 putCR0( 1, mkU8(0) ); 11452 } 11453 11454 return True; 11455 } 11456 11457 /* 11458 Floating Point Pair Instructions 11459 */ 11460 static Bool dis_fp_pair ( UInt theInstr ) 11461 { 11462 /* X-Form/DS-Form */ 11463 UChar opc1 = ifieldOPC(theInstr); 11464 UChar frT_hi_addr = ifieldRegDS(theInstr); 11465 UChar frT_lo_addr = frT_hi_addr + 1; 11466 UChar rA_addr = ifieldRegA(theInstr); 11467 UChar rB_addr = ifieldRegB(theInstr); 11468 UInt uimm16 = ifieldUIMM16(theInstr); 11469 Int simm16 = extend_s_16to32(uimm16); 11470 UInt opc2 = ifieldOPClo10(theInstr); 11471 IRType ty = mode64 ? Ity_I64 : Ity_I32; 11472 IRTemp EA_hi = newTemp(ty); 11473 IRTemp EA_lo = newTemp(ty); 11474 IRTemp frT_hi = newTemp(Ity_F64); 11475 IRTemp frT_lo = newTemp(Ity_F64); 11476 UChar b0 = ifieldBIT0(theInstr); 11477 Bool is_load = 0; 11478 11479 switch (opc1) { 11480 case 0x1F: // register offset 11481 /* These instructions work on a pair of registers. The specified 11482 * register must be even. 11483 */ 11484 if ((frT_hi_addr %2) != 0) { 11485 vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n"); 11486 return False; 11487 } 11488 11489 switch(opc2) { 11490 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 11491 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 11492 is_load = 1; 11493 break; 11494 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 11495 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 11496 break; 11497 default: 11498 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 11499 return False; 11500 } 11501 11502 if (b0 != 0) { 11503 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 11504 return False; 11505 } 11506 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 11507 break; 11508 case 0x39: 11509 { 11510 UInt DS = IFIELD( theInstr, 2, 14); 11511 UChar vRT = ifieldRegDS(theInstr); 11512 IRTemp EA = newTemp( ty ); 11513 11514 opc2 = ifieldOPC0o2(theInstr); 11515 11516 switch(opc2) { 11517 case 0x0: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 11518 /* This instruction works on a pair of registers. The specified 11519 * register must be even. 11520 */ 11521 if ((frT_hi_addr %2) != 0) { 11522 vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n"); 11523 return False; 11524 } 11525 11526 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 11527 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 11528 is_load = 1; 11529 break; 11530 11531 case 0x2: // lxsd (Load VSX Scalar Doubleword) 11532 DIP("lxsd v%u,%d(r%u)\n", vRT, DS, rA_addr); 11533 11534 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11535 11536 putVSReg( vRT+32, binop( Iop_64HLtoV128, 11537 load( Ity_I64, mkexpr( EA ) ), 11538 mkU64( 0 ) ) ); 11539 return True; 11540 11541 case 0x3: // lxssp (Load VSX Scalar Single) 11542 DIP("lxssp v%u,%d(r%u)\n", vRT, DS, rA_addr); 11543 11544 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11545 11546 putVSReg( vRT+32, binop( Iop_64HLtoV128, 11547 binop( Iop_32HLto64, 11548 load( Ity_I32, mkexpr( EA ) ), 11549 mkU32( 0 ) ), 11550 mkU64( 0 ) ) ); 11551 return True; 11552 11553 default: 11554 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); 11555 return False; 11556 } 11557 break; 11558 } 11559 case 0x3d: 11560 { 11561 UInt DS = IFIELD( theInstr, 2, 14); 11562 UChar vRS = ifieldRegDS(theInstr); 11563 IRTemp EA = newTemp( ty ); 11564 11565 opc2 = ifieldOPC0o2(theInstr); 11566 11567 switch(opc2) { 11568 case 0x0: 11569 // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 11570 /* This instruction works on a pair of registers. The specified 11571 * register must be even. 11572 */ 11573 if ((frT_hi_addr %2) != 0) { 11574 vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n"); 11575 return False; 11576 } 11577 11578 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 11579 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 11580 break; 11581 11582 case 0x1: 11583 { 11584 UInt ea_off = 8; 11585 IRTemp word[2]; 11586 IRExpr* irx_addr; 11587 UInt T = IFIELD( theInstr, 21, 5); // T or S depending on inst 11588 UInt TX = IFIELD( theInstr, 3, 1); // TX or SX field 11589 11590 word[0] = newTemp(Ity_I64); 11591 word[1] = newTemp(Ity_I64); 11592 DS = IFIELD( theInstr, 4, 12); // DQ in the instruction definition 11593 assign( EA, ea_rAor0_simm( rA_addr, DS<<4 ) ); 11594 11595 if ( IFIELD( theInstr, 0, 3) == 1) { 11596 // lxv (Load VSX Vector) 11597 DIP("lxv v%u,%d(r%u)\n", vRS, DS, rA_addr); 11598 11599 assign( word[0], load( Ity_I64, mkexpr( EA ) ) ); 11600 11601 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11602 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11603 11604 assign( word[1], load( Ity_I64, irx_addr ) ); 11605 11606 if (host_endness == VexEndnessBE) 11607 putVSReg( TX*32+T, binop( Iop_64HLtoV128, 11608 mkexpr( word[0] ), 11609 mkexpr( word[1] ) ) ); 11610 else 11611 putVSReg( TX*32+T, binop( Iop_64HLtoV128, 11612 mkexpr( word[1] ), 11613 mkexpr( word[0] ) ) ); 11614 return True; 11615 11616 } else if ( IFIELD( theInstr, 0, 3) == 5) { 11617 // stxv (Store VSX Vector) 11618 DIP("stxv v%u,%d(r%u)\n", vRS, DS, rA_addr); 11619 11620 if (host_endness == VexEndnessBE) { 11621 store( mkexpr(EA), unop( Iop_V128HIto64, 11622 getVSReg( TX*32+T ) ) ); 11623 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11624 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11625 store( irx_addr, unop( Iop_V128to64, 11626 getVSReg( TX*32+T ) ) ); 11627 } else { 11628 store( mkexpr(EA), unop( Iop_V128to64, 11629 getVSReg( TX*32+T ) ) ); 11630 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 11631 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 11632 store( irx_addr, unop( Iop_V128HIto64, 11633 getVSReg( TX*32+T ) ) ); 11634 } 11635 return True; 11636 11637 } else { 11638 vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n"); 11639 return False; 11640 } 11641 break; 11642 } 11643 case 0x2: 11644 // stxsd (Store VSX Scalar Doubleword) 11645 DIP("stxsd v%u,%d(r%u)\n", vRS, DS, rA_addr); 11646 11647 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11648 11649 store( mkexpr(EA), unop( Iop_V128HIto64, 11650 getVSReg( vRS+32 ) ) ); 11651 /* HW is clearing vector element 1. Don't see that in the ISA but 11652 * matching the HW. 11653 */ 11654 putVSReg( vRS+32, binop( Iop_64HLtoV128, 11655 unop( Iop_V128HIto64, 11656 getVSReg( vRS+32 ) ), 11657 mkU64( 0 ) ) ); 11658 return True; 11659 11660 case 0x3: 11661 // stxssp (Store VSX Scalar Single) 11662 DIP("stxssp v%u,%d(r%u)\n", vRS, DS, rA_addr); 11663 11664 assign( EA, ea_rAor0_simm( rA_addr, DS<<2 ) ); 11665 11666 store( mkexpr(EA), unop( Iop_64HIto32, 11667 unop( Iop_V128HIto64, 11668 getVSReg( vRS+32 ) ) ) ); 11669 return True; 11670 11671 default: 11672 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n"); 11673 return False; 11674 } 11675 break; 11676 } 11677 default: // immediate offset 11678 vex_printf("dis_fp_pair(ppc)(instr)\n"); 11679 return False; 11680 } 11681 11682 if (mode64) 11683 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 11684 else 11685 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 11686 11687 assign( frT_hi, getFReg(frT_hi_addr) ); 11688 assign( frT_lo, getFReg(frT_lo_addr) ); 11689 11690 if (is_load) { 11691 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) ); 11692 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) ); 11693 } else { 11694 store( mkexpr(EA_hi), mkexpr(frT_hi) ); 11695 store( mkexpr(EA_lo), mkexpr(frT_lo) ); 11696 } 11697 11698 return True; 11699 } 11700 11701 11702 /* 11703 Floating Point Merge Instructions 11704 */ 11705 static Bool dis_fp_merge ( UInt theInstr ) 11706 { 11707 /* X-Form */ 11708 UInt opc2 = ifieldOPClo10(theInstr); 11709 UChar frD_addr = ifieldRegDS(theInstr); 11710 UChar frA_addr = ifieldRegA(theInstr); 11711 UChar frB_addr = ifieldRegB(theInstr); 11712 11713 IRTemp frD = newTemp(Ity_F64); 11714 IRTemp frA = newTemp(Ity_F64); 11715 IRTemp frB = newTemp(Ity_F64); 11716 11717 assign( frA, getFReg(frA_addr)); 11718 assign( frB, getFReg(frB_addr)); 11719 11720 switch (opc2) { 11721 case 0x3c6: // fmrgew floating merge even word 11722 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 11723 11724 assign( frD, unop( Iop_ReinterpI64asF64, 11725 binop( Iop_32HLto64, 11726 unop( Iop_64HIto32, 11727 unop( Iop_ReinterpF64asI64, 11728 mkexpr(frA) ) ), 11729 unop( Iop_64HIto32, 11730 unop( Iop_ReinterpF64asI64, 11731 mkexpr(frB) ) ) ) ) ); 11732 break; 11733 11734 case 0x346: // fmrgow floating merge odd word 11735 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 11736 11737 assign( frD, unop( Iop_ReinterpI64asF64, 11738 binop( Iop_32HLto64, 11739 unop( Iop_64to32, 11740 unop( Iop_ReinterpF64asI64, 11741 mkexpr(frA) ) ), 11742 unop( Iop_64to32, 11743 unop( Iop_ReinterpF64asI64, 11744 mkexpr(frB) ) ) ) ) ); 11745 break; 11746 11747 default: 11748 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 11749 return False; 11750 } 11751 11752 putFReg( frD_addr, mkexpr(frD) ); 11753 return True; 11754 } 11755 11756 /* 11757 Floating Point Move Instructions 11758 */ 11759 static Bool dis_fp_move ( UInt theInstr ) 11760 { 11761 /* X-Form */ 11762 UChar opc1 = ifieldOPC(theInstr); 11763 UChar frD_addr = ifieldRegDS(theInstr); 11764 UChar frA_addr = ifieldRegA(theInstr); 11765 UChar frB_addr = ifieldRegB(theInstr); 11766 UInt opc2 = ifieldOPClo10(theInstr); 11767 UChar flag_rC = ifieldBIT0(theInstr); 11768 11769 IRTemp frD = newTemp(Ity_F64); 11770 IRTemp frB = newTemp(Ity_F64); 11771 IRTemp itmpB = newTemp(Ity_F64); 11772 IRTemp frA; 11773 IRTemp signA; 11774 IRTemp hiD; 11775 11776 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 11777 vex_printf("dis_fp_move(ppc)(instr)\n"); 11778 return False; 11779 } 11780 11781 assign( frB, getFReg(frB_addr)); 11782 11783 switch (opc2) { 11784 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 11785 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 11786 frB_addr); 11787 signA = newTemp(Ity_I32); 11788 hiD = newTemp(Ity_I32); 11789 itmpB = newTemp(Ity_I64); 11790 frA = newTemp(Ity_F64); 11791 assign( frA, getFReg(frA_addr) ); 11792 11793 /* get A's sign bit */ 11794 assign(signA, binop(Iop_And32, 11795 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 11796 mkexpr(frA))), 11797 mkU32(0x80000000)) ); 11798 11799 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 11800 11801 /* mask off B's sign bit and or in A's sign bit */ 11802 assign(hiD, binop(Iop_Or32, 11803 binop(Iop_And32, 11804 unop(Iop_64HIto32, 11805 mkexpr(itmpB)), /* frB's high 32 bits */ 11806 mkU32(0x7fffffff)), 11807 mkexpr(signA)) ); 11808 11809 /* combine hiD/loB into frD */ 11810 assign( frD, unop(Iop_ReinterpI64asF64, 11811 binop(Iop_32HLto64, 11812 mkexpr(hiD), 11813 unop(Iop_64to32, 11814 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 11815 break; 11816 11817 case 0x028: // fneg (Floating Negate, PPC32 p416) 11818 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11819 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 11820 break; 11821 11822 case 0x048: // fmr (Floating Move Register, PPC32 p410) 11823 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11824 assign( frD, mkexpr(frB) ); 11825 break; 11826 11827 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 11828 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11829 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 11830 break; 11831 11832 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 11833 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 11834 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 11835 break; 11836 11837 default: 11838 vex_printf("dis_fp_move(ppc)(opc2)\n"); 11839 return False; 11840 } 11841 11842 putFReg( frD_addr, mkexpr(frD) ); 11843 11844 /* None of these change FPRF. cr1 is set in the usual way though, 11845 if flag_rC is set. */ 11846 11847 if (flag_rC) { 11848 putCR321( 1, mkU8(0) ); 11849 putCR0( 1, mkU8(0) ); 11850 } 11851 11852 return True; 11853 } 11854 11855 11856 11857 /* 11858 Floating Point Status/Control Register Instructions 11859 */ 11860 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 11861 { 11862 /* Many forms - see each switch case */ 11863 UChar opc1 = ifieldOPC(theInstr); 11864 UInt opc2 = ifieldOPClo10(theInstr); 11865 UChar flag_rC = ifieldBIT0(theInstr); 11866 11867 if (opc1 != 0x3F) { 11868 vex_printf("dis_fp_scr(ppc)(instr)\n"); 11869 return False; 11870 } 11871 11872 switch (opc2) { 11873 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 11874 // Bit crbD of the FPSCR is set. 11875 UChar crbD = ifieldRegDS(theInstr); 11876 UInt b11to20 = IFIELD(theInstr, 11, 10); 11877 11878 if (b11to20 != 0) { 11879 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 11880 return False; 11881 } 11882 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 11883 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 11884 1ULL << ( 31 - crbD ) ); 11885 break; 11886 } 11887 11888 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 11889 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 11890 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 11891 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 11892 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 11893 IRTemp tmp = newTemp(Ity_I32); 11894 IRExpr* fpscr_all; 11895 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 11896 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 11897 return False; 11898 } 11899 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 11900 vassert(crfD < 8); 11901 vassert(crfS < 8); 11902 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 11903 assign( tmp, binop(Iop_And32, 11904 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 11905 mkU32(0xF)) ); 11906 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 11907 break; 11908 } 11909 11910 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 11911 // Bit crbD of the FPSCR is cleared. 11912 UChar crbD = ifieldRegDS(theInstr); 11913 UInt b11to20 = IFIELD(theInstr, 11, 10); 11914 11915 if (b11to20 != 0) { 11916 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 11917 return False; 11918 } 11919 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 11920 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 11921 break; 11922 } 11923 11924 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 11925 UInt crfD = IFIELD( theInstr, 23, 3 ); 11926 UChar b17to22 = toUChar( IFIELD( theInstr, 17, 6 ) ); 11927 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 11928 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 11929 UChar Wbit = toUChar( IFIELD( theInstr, 16, 1 ) ); 11930 11931 if (b17to22 != 0 || b11 != 0 || (Wbit && !GX_level)) { 11932 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 11933 return False; 11934 } 11935 DIP("mtfsfi%s crf%u,%d%s\n", flag_rC ? ".":"", crfD, IMM, Wbit ? ",1":""); 11936 crfD = crfD + (8 * (1 - Wbit) ); 11937 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 11938 break; 11939 } 11940 11941 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 11942 UChar frD_addr = ifieldRegDS(theInstr); 11943 UChar frB_addr = ifieldRegB(theInstr); 11944 IRTemp frB = newTemp(Ity_F64); 11945 UInt b11to12 = IFIELD(theInstr, 19, 2); 11946 UInt b13to15 = IFIELD(theInstr, 16, 3); 11947 UInt RN = IFIELD(theInstr, 11, 2); 11948 UInt DRN = IFIELD(theInstr, 11, 3); 11949 11950 /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in 11951 * their own 8-bit entries with distinct offsets. The FPSCR 11952 * register is handled as two 32-bit values. We need to 11953 * assemble the pieces into the single 64-bit value to return. 11954 */ 11955 IRExpr* fpscr_lower 11956 = binop( Iop_Or32, 11957 getGST_masked( PPC_GST_FPSCR, (MASK_FPSCR_RN | MASK_FPSCR_C_FPCC) ), 11958 binop( Iop_Or32, 11959 binop( Iop_Shl32, 11960 getC(), 11961 mkU8(63-47) ) , 11962 binop( Iop_Shl32, 11963 getFPCC(), 11964 mkU8(63-51) ) ) ); 11965 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ); 11966 11967 if ((b11to12 == 0) && (b13to15 == 0)) { 11968 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 11969 putFReg( frD_addr, 11970 unop( Iop_ReinterpI64asF64, 11971 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 11972 11973 } else if ((b11to12 == 0) && (b13to15 == 1)) { 11974 DIP("mffsce fr%u\n", frD_addr); 11975 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE, 11976 or XE but in case that changes in the future, do the masking. */ 11977 putFReg( frD_addr, 11978 unop( Iop_ReinterpI64asF64, 11979 binop( Iop_32HLto64, fpscr_upper, 11980 binop( Iop_And32, fpscr_lower, 11981 mkU32( 0xFFFFFF07 ) ) ) ) ); 11982 11983 } else if ((b11to12 == 2) && (b13to15 == 4)) { 11984 IRTemp frB_int = newTemp(Ity_I64); 11985 11986 DIP("mffscdrn fr%u,fr%u\n", frD_addr, frB_addr); 11987 11988 assign( frB, getFReg(frB_addr)); 11989 assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 11990 11991 /* Clear all of the FPSCR bits except for the DRN field, VE, 11992 OE, UE, ZE and XE bits and write the result to the frD 11993 register. Note, currently the exception bits are not tracked but 11994 will mask anyway in case that changes in the future. */ 11995 putFReg( frD_addr, 11996 unop( Iop_ReinterpI64asF64, 11997 binop( Iop_32HLto64, 11998 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 11999 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12000 12001 /* Put new_DRN bits into the FPSCR register */ 12002 putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_DRN ); 12003 12004 } else if ((b11to12 == 2) && (b13to15 == 5)) { 12005 DIP("mffscdrni fr%u,%d\n", frD_addr, DRN); 12006 12007 /* Clear all of the FPSCR bits except for the DRN field, VE, 12008 OE, UE, ZE and XE bits and write the result to the frD 12009 register. Note, currently the exception bits are not tracked but 12010 will mask anyway in case that changes in the future. */ 12011 putFReg( frD_addr, 12012 unop( Iop_ReinterpI64asF64, 12013 binop( Iop_32HLto64, 12014 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12015 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12016 12017 /* Put new_DRN bits into the FPSCR register */ 12018 putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( DRN ), 12019 mkU32( 0 ) ), MASK_FPSCR_DRN ); 12020 12021 } else if ((b11to12 == 2) && (b13to15 == 6)) { 12022 IRTemp frB_int = newTemp(Ity_I64); 12023 12024 DIP("mffscrn fr%u,fr%u\n", frD_addr,frB_addr); 12025 12026 assign( frB, getFReg(frB_addr)); 12027 assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 12028 12029 /* Clear all of the FPSCR bits except for the DRN field, VE, 12030 OE, UE, ZE and XE bits and write the result to the frD 12031 register. Note, currently the exception bits are not tracked but 12032 will mask anyway in case that changes in the future. */ 12033 putFReg( frD_addr, 12034 unop( Iop_ReinterpI64asF64, 12035 binop( Iop_32HLto64, 12036 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12037 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12038 12039 /* Put new_CRN bits into the FPSCR register */ 12040 putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_RN ); 12041 12042 } else if ((b11to12 == 2) && (b13to15 == 7)) { 12043 DIP("mffscrni fr%u,%u\n", frD_addr, RN); 12044 12045 /* Clear all of the FPSCR bits except for the DRN field, VE, 12046 OE, UE, ZE and XE bits and write the result to the frD 12047 register. Note, currently the exception bits are not tracked but 12048 will mask anyway in case that changes in the future. */ 12049 putFReg( frD_addr, 12050 unop( Iop_ReinterpI64asF64, 12051 binop( Iop_32HLto64, 12052 binop( Iop_And32, mkU32(0x7), fpscr_upper ), 12053 binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) ); 12054 12055 /* Put new_RN bits into the FPSCR register */ 12056 putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( 0 ), 12057 mkU32( RN ) ), MASK_FPSCR_RN ); 12058 12059 } else if ((b11to12 == 3) && (b13to15 == 0)) { 12060 DIP("mffsl fr%u\n", frD_addr); 12061 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE, 12062 XE, FR, FI, C, FL, FG, FE, FU. Also only track DRN in the upper 12063 bits but in case that changes in the future we will do the 12064 masking. */ 12065 putFReg( frD_addr, 12066 unop( Iop_ReinterpI64asF64, 12067 binop( Iop_32HLto64, 12068 binop( Iop_And32, fpscr_upper, 12069 mkU32( 0x7 ) ), 12070 binop( Iop_And32, fpscr_lower, 12071 mkU32( 0x7F0FF ) ) ) ) ); 12072 } else { 12073 vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n"); 12074 return False; 12075 } 12076 break; 12077 } 12078 12079 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 12080 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 12081 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 12082 UChar frB_addr = ifieldRegB(theInstr); 12083 IRTemp frB = newTemp(Ity_F64); 12084 IRTemp rB_64 = newTemp( Ity_I64 ); 12085 Int i; 12086 ULong mask; 12087 UChar Wbit; 12088 #define BFP_MASK_SEED 0x3000000000000000ULL 12089 #define DFP_MASK_SEED 0x7000000000000000ULL 12090 12091 if (GX_level) { 12092 /* This implies that Decimal Floating Point is supported, and the 12093 * FPSCR must be managed as a 64-bit register. 12094 */ 12095 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 12096 } else { 12097 Wbit = 0; 12098 } 12099 12100 if (b25 == 1) { 12101 /* new 64 bit move variant for power 6. If L field (bit 25) is 12102 * a one do a full 64 bit move. Note, the FPSCR is not really 12103 * properly modeled. This instruciton only changes the value of 12104 * the rounding mode bit fields RN, FPCC and DRN. The HW exception bits 12105 * do not get set in the simulator. 1/12/09 12106 */ 12107 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 12108 mask = 0x1F0001F003; 12109 12110 } else { 12111 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 12112 // Build 32bit mask from FM: 12113 mask = 0; 12114 for (i=0; i<8; i++) { 12115 if ((FM & (1<<(7-i))) == 1) { 12116 /* FPSCR field k is set to the contents of the corresponding 12117 * field of register FRB, where k = i+8x(1-W). In the Power 12118 * ISA, register field numbering is from left to right, so field 12119 * 15 is the least significant field in a 64-bit register. To 12120 * generate the mask, we set all the appropriate rounding mode 12121 * bits in the highest order nibble (field 0) and shift right 12122 * 'k x nibble length'. 12123 */ 12124 if (Wbit) 12125 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 12126 else 12127 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 12128 } 12129 if ((FM & (1<<(7-i))) == 0x2) { //set the FPCC bits 12130 mask |= 0xF000; 12131 } 12132 if ((FM & (1<<(7-i))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit 12133 mask |= 0x10000; 12134 } 12135 } 12136 } 12137 assign( frB, getFReg(frB_addr)); 12138 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 12139 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 12140 break; 12141 } 12142 12143 default: 12144 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 12145 return False; 12146 } 12147 return True; 12148 } 12149 12150 /*------------------------------------------------------------*/ 12151 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 12152 /*------------------------------------------------------------*/ 12153 #define DFP_LONG 1 12154 #define DFP_EXTND 2 12155 #define DFP_LONG_BIAS 398 12156 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 12157 #define DFP_EXTND_BIAS 6176 12158 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 12159 #define DFP_LONG_EXP_MSK 0XFF 12160 #define DFP_EXTND_EXP_MSK 0XFFF 12161 12162 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 12163 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 12164 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 12165 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 12166 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 12167 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 12168 #define DFP_LONG_EXP_MAX 369 // biased max 12169 #define DFP_LONG_EXP_MIN 0 // biased min 12170 #define DFP_EXTND_EXP_MAX 6111 // biased max 12171 #define DFP_EXTND_EXP_MIN 0 // biased min 12172 #define DFP_LONG_MAX_SIG_DIGITS 16 12173 #define DFP_EXTND_MAX_SIG_DIGITS 34 12174 #define MAX_DIGITS_IN_STRING 8 12175 12176 12177 #define AND(x, y) binop( Iop_And32, x, y ) 12178 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 12179 #define OR(x, y) binop( Iop_Or32, x, y ) 12180 #define OR3(x, y, z) OR( x, OR( y, z ) ) 12181 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 12182 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 12183 12184 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 12185 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 12186 12187 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 12188 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 12189 ((_b1) << 1) | ((_b0) << 0)) 12190 12191 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 12192 { 12193 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 12194 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 12195 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 12196 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 12197 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 12198 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 12199 IRTemp lmd_07_val = newTemp( Ity_I32 ); 12200 IRTemp lmd_8_val = newTemp( Ity_I32 ); 12201 IRTemp lmd_9_val = newTemp( Ity_I32 ); 12202 12203 /* The encodig is as follows: 12204 * lmd - left most digit 12205 * lme - left most 2-bits of the exponent 12206 * 12207 * lmd 12208 * 0 - 7 (lmexp << 3) | lmd 12209 * 8 0b11000 (24 decimal) if lme=0b00; 12210 * 0b11010 (26 decimal) if lme=0b01; 12211 * 0b11100 (28 decimal) if lme=0b10; 12212 * 9 0b11001 (25 decimal) if lme=0b00; 12213 * 0b11011 (27 decimal) if lme=0b01; 12214 * 0b11101 (29 decimal) if lme=0b10; 12215 */ 12216 12217 /* Generate the masks for each condition */ 12218 assign( lmd_07_mask, 12219 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 12220 assign( lmd_8_mask, 12221 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 12222 assign( lmd_9_mask, 12223 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 12224 assign( lmexp_00_mask, 12225 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 12226 assign( lmexp_01_mask, 12227 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 12228 assign( lmexp_10_mask, 12229 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 12230 12231 /* Generate the values for each LMD condition, assuming the condition 12232 * is TRUE. 12233 */ 12234 assign( lmd_07_val, 12235 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 12236 assign( lmd_8_val, 12237 binop( Iop_Or32, 12238 binop( Iop_Or32, 12239 binop( Iop_And32, 12240 mkexpr( lmexp_00_mask ), 12241 mkU32( 24 ) ), 12242 binop( Iop_And32, 12243 mkexpr( lmexp_01_mask ), 12244 mkU32( 26 ) ) ), 12245 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 12246 assign( lmd_9_val, 12247 binop( Iop_Or32, 12248 binop( Iop_Or32, 12249 binop( Iop_And32, 12250 mkexpr( lmexp_00_mask ), 12251 mkU32( 25 ) ), 12252 binop( Iop_And32, 12253 mkexpr( lmexp_01_mask ), 12254 mkU32( 27 ) ) ), 12255 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 12256 12257 /* generate the result from the possible LMD values */ 12258 return binop( Iop_Or32, 12259 binop( Iop_Or32, 12260 binop( Iop_And32, 12261 mkexpr( lmd_07_mask ), 12262 mkexpr( lmd_07_val ) ), 12263 binop( Iop_And32, 12264 mkexpr( lmd_8_mask ), 12265 mkexpr( lmd_8_val ) ) ), 12266 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 12267 } 12268 12269 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 12270 { 12271 /* Extract the exponent and the left most digit of the mantissa 12272 * from the G field bits [0:4]. 12273 */ 12274 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 12275 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 12276 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 12277 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 12278 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 12279 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 12280 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 12281 12282 IRTemp lmd_07_val = newTemp( Ity_I32 ); 12283 IRTemp lmd_8_val = newTemp( Ity_I32 ); 12284 IRTemp lmd_9_val = newTemp( Ity_I32 ); 12285 12286 /* The left most digit (LMD) encoding is as follows: 12287 * lmd 12288 * 0 - 7 (lmexp << 3) | lmd 12289 * 8 0b11000 (24 decimal) if lme=0b00; 12290 * 0b11010 (26 decimal) if lme=0b01; 12291 * 0b11100 (28 decimal) if lme=0b10 12292 * 9 0b11001 (25 decimal) if lme=0b00; 12293 * 0b11011 (27 decimal) if lme=0b01; 12294 * 0b11101 (29 decimal) if lme=0b10; 12295 */ 12296 12297 /* Generate the masks for each condition of LMD and exponent bits */ 12298 assign( lmd_07_mask, 12299 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 12300 gfield_0_4, 12301 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 12302 assign( lmd_8_00_mask, 12303 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12304 gfield_0_4, 12305 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 12306 assign( lmd_8_01_mask, 12307 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12308 gfield_0_4, 12309 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 12310 assign( lmd_8_10_mask, 12311 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12312 gfield_0_4, 12313 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 12314 assign( lmd_9_00_mask, 12315 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12316 gfield_0_4, 12317 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 12318 assign( lmd_9_01_mask, 12319 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12320 gfield_0_4, 12321 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 12322 assign( lmd_9_10_mask, 12323 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 12324 gfield_0_4, 12325 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 12326 12327 /* Generate the values for each LMD condition, assuming the condition 12328 * is TRUE. 12329 */ 12330 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 12331 assign( lmd_8_val, mkU32( 0x8 ) ); 12332 assign( lmd_9_val, mkU32( 0x9 ) ); 12333 12334 assign( *lmd, 12335 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 12336 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 12337 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 12338 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 12339 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 12340 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 12341 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 12342 ) ) ); 12343 } 12344 12345 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 12346 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 12347 #define DIGIT3_SHR 12 12348 #define DIGIT4_SHR 16 12349 #define DIGIT5_SHR 20 12350 #define DIGIT6_SHR 24 12351 #define DIGIT7_SHR 28 12352 12353 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 12354 { 12355 /* 60-bit BCD string stored in two 32-bit values. Check that each, 12356 * digit is a valid BCD number, i.e. less then 9. 12357 */ 12358 IRTemp valid = newTemp( Ity_I32 ); 12359 12360 assign( valid, 12361 AND4( AND4 ( unop( Iop_1Sto32, 12362 binop( Iop_CmpLE32U, 12363 binop( Iop_And32, 12364 bcd_l, 12365 mkU32 ( 0xF ) ), 12366 mkU32( 0x9 ) ) ), 12367 unop( Iop_1Sto32, 12368 binop( Iop_CmpLE32U, 12369 binop( Iop_And32, 12370 binop( Iop_Shr32, 12371 bcd_l, 12372 mkU8 ( DIGIT1_SHR ) ), 12373 mkU32 ( 0xF ) ), 12374 mkU32( 0x9 ) ) ), 12375 unop( Iop_1Sto32, 12376 binop( Iop_CmpLE32U, 12377 binop( Iop_And32, 12378 binop( Iop_Shr32, 12379 bcd_l, 12380 mkU8 ( DIGIT2_SHR ) ), 12381 mkU32 ( 0xF ) ), 12382 mkU32( 0x9 ) ) ), 12383 unop( Iop_1Sto32, 12384 binop( Iop_CmpLE32U, 12385 binop( Iop_And32, 12386 binop( Iop_Shr32, 12387 bcd_l, 12388 mkU8 ( DIGIT3_SHR ) ), 12389 mkU32 ( 0xF ) ), 12390 mkU32( 0x9 ) ) ) ), 12391 AND4 ( unop( Iop_1Sto32, 12392 binop( Iop_CmpLE32U, 12393 binop( Iop_And32, 12394 binop( Iop_Shr32, 12395 bcd_l, 12396 mkU8 ( DIGIT4_SHR ) ), 12397 mkU32 ( 0xF ) ), 12398 mkU32( 0x9 ) ) ), 12399 unop( Iop_1Sto32, 12400 binop( Iop_CmpLE32U, 12401 binop( Iop_And32, 12402 binop( Iop_Shr32, 12403 bcd_l, 12404 mkU8 ( DIGIT5_SHR ) ), 12405 mkU32 ( 0xF ) ), 12406 mkU32( 0x9 ) ) ), 12407 unop( Iop_1Sto32, 12408 binop( Iop_CmpLE32U, 12409 binop( Iop_And32, 12410 binop( Iop_Shr32, 12411 bcd_l, 12412 mkU8 ( DIGIT6_SHR ) ), 12413 mkU32 ( 0xF ) ), 12414 mkU32( 0x9 ) ) ), 12415 unop( Iop_1Sto32, 12416 binop( Iop_CmpLE32U, 12417 binop( Iop_And32, 12418 binop( Iop_Shr32, 12419 bcd_l, 12420 mkU8 ( DIGIT7_SHR ) ), 12421 mkU32 ( 0xF ) ), 12422 mkU32( 0x9 ) ) ) ), 12423 AND4( unop( Iop_1Sto32, 12424 binop( Iop_CmpLE32U, 12425 binop( Iop_And32, 12426 bcd_u, 12427 mkU32 ( 0xF ) ), 12428 mkU32( 0x9 ) ) ), 12429 unop( Iop_1Sto32, 12430 binop( Iop_CmpLE32U, 12431 binop( Iop_And32, 12432 binop( Iop_Shr32, 12433 bcd_u, 12434 mkU8 ( DIGIT1_SHR ) ), 12435 mkU32 ( 0xF ) ), 12436 mkU32( 0x9 ) ) ), 12437 unop( Iop_1Sto32, 12438 binop( Iop_CmpLE32U, 12439 binop( Iop_And32, 12440 binop( Iop_Shr32, 12441 bcd_u, 12442 mkU8 ( DIGIT2_SHR ) ), 12443 mkU32 ( 0xF ) ), 12444 mkU32( 0x9 ) ) ), 12445 unop( Iop_1Sto32, 12446 binop( Iop_CmpLE32U, 12447 binop( Iop_And32, 12448 binop( Iop_Shr32, 12449 bcd_u, 12450 mkU8 ( DIGIT3_SHR ) ), 12451 mkU32 ( 0xF ) ), 12452 mkU32( 0x9 ) ) ) ), 12453 AND4( unop( Iop_1Sto32, 12454 binop( Iop_CmpLE32U, 12455 binop( Iop_And32, 12456 binop( Iop_Shr32, 12457 bcd_u, 12458 mkU8 ( DIGIT4_SHR ) ), 12459 mkU32 ( 0xF ) ), 12460 mkU32( 0x9 ) ) ), 12461 unop( Iop_1Sto32, 12462 binop( Iop_CmpLE32U, 12463 binop( Iop_And32, 12464 binop( Iop_Shr32, 12465 bcd_u, 12466 mkU8 ( DIGIT5_SHR ) ), 12467 mkU32 ( 0xF ) ), 12468 mkU32( 0x9 ) ) ), 12469 unop( Iop_1Sto32, 12470 binop( Iop_CmpLE32U, 12471 binop( Iop_And32, 12472 binop( Iop_Shr32, 12473 bcd_u, 12474 mkU8 ( DIGIT6_SHR ) ), 12475 mkU32 ( 0xF ) ), 12476 mkU32( 0x9 ) ) ), 12477 unop( Iop_1Sto32, 12478 binop( Iop_CmpLE32U, 12479 binop( Iop_And32, 12480 binop( Iop_Shr32, 12481 bcd_u, 12482 mkU8 ( DIGIT7_SHR ) ), 12483 mkU32 ( 0xF ) ), 12484 mkU32( 0x9 ) ) ) ) ) ); 12485 12486 return unop( Iop_Not32, mkexpr( valid ) ); 12487 } 12488 #undef DIGIT1_SHR 12489 #undef DIGIT2_SHR 12490 #undef DIGIT3_SHR 12491 #undef DIGIT4_SHR 12492 #undef DIGIT5_SHR 12493 #undef DIGIT6_SHR 12494 #undef DIGIT7_SHR 12495 12496 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 12497 { 12498 return binop( Iop_Or32, 12499 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 12500 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 12501 ); 12502 } 12503 12504 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 12505 { 12506 return binop( Iop_Or32, 12507 binop( Iop_Or32, 12508 unop( Iop_1Sto32, 12509 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 12510 unop( Iop_1Sto32, 12511 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 12512 binop( Iop_Or32, 12513 unop( Iop_1Sto32, 12514 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 12515 unop( Iop_1Sto32, 12516 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 12517 } 12518 12519 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 12520 IRExpr * neg_sign_mask ) 12521 { 12522 return binop( Iop_Or32, 12523 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 12524 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 12525 } 12526 12527 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 12528 IRExpr * pos_sign_mask, 12529 IRExpr * neg_sign_mask ) 12530 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 12531 { 12532 return binop( Iop_Or32, 12533 invalid_bcd_mask, 12534 unop( Iop_1Sto32, 12535 binop( Iop_CmpEQ32, 12536 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 12537 mkU32( 0x0 ) ) ) ); 12538 } 12539 12540 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 12541 IRTemp * top_12_l, IRTemp * mid_60_u, 12542 IRTemp * mid_60_l, IRTemp * low_60_u, 12543 IRTemp * low_60_l) 12544 { 12545 IRTemp tmplow60 = newTemp( Ity_I64 ); 12546 IRTemp tmpmid60 = newTemp( Ity_I64 ); 12547 IRTemp tmptop12 = newTemp( Ity_I64 ); 12548 IRTemp low_50 = newTemp( Ity_I64 ); 12549 IRTemp mid_50 = newTemp( Ity_I64 ); 12550 IRTemp top_10 = newTemp( Ity_I64 ); 12551 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 12552 12553 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 12554 12555 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 12556 assign( low_50, 12557 binop( Iop_32HLto64, 12558 binop( Iop_And32, 12559 unop( Iop_64HIto32, frBI64_lo ), 12560 mkU32( 0x3FFFF ) ), 12561 unop( Iop_64to32, frBI64_lo ) ) ); 12562 12563 /* Convert the 50 bit densely packed BCD string to a 60 bit 12564 * BCD string. 12565 */ 12566 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 12567 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 12568 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 12569 12570 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 12571 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 12572 */ 12573 assign( mid_50, 12574 binop( Iop_32HLto64, 12575 binop( Iop_Or32, 12576 binop( Iop_Shl32, 12577 binop( Iop_And32, 12578 unop( Iop_64HIto32, frBI64_hi ), 12579 mkU32( 0xF ) ), 12580 mkU8( 14 ) ), 12581 binop( Iop_Shr32, 12582 unop( Iop_64to32, frBI64_hi ), 12583 mkU8( 18 ) ) ), 12584 binop( Iop_Or32, 12585 binop( Iop_Shl32, 12586 unop( Iop_64to32, frBI64_hi ), 12587 mkU8( 14 ) ), 12588 binop( Iop_Shr32, 12589 unop( Iop_64HIto32, frBI64_lo ), 12590 mkU8( 18 ) ) ) ) ); 12591 12592 /* Convert the 50 bit densely packed BCD string to a 60 bit 12593 * BCD string. 12594 */ 12595 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 12596 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 12597 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 12598 12599 /* top_10[49:0] = frBI64_hi[45:36]) | */ 12600 assign( top_10, 12601 binop( Iop_32HLto64, 12602 mkU32( 0 ), 12603 binop( Iop_And32, 12604 binop( Iop_Shr32, 12605 unop( Iop_64HIto32, frBI64_hi ), 12606 mkU8( 4 ) ), 12607 mkU32( 0x3FF ) ) ) ); 12608 12609 /* Convert the 10 bit densely packed BCD string to a 12 bit 12610 * BCD string. 12611 */ 12612 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 12613 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 12614 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 12615 } 12616 12617 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 12618 IRTemp * final_cnt, IRTemp * final_flag, 12619 IRExpr * string ) 12620 { 12621 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 12622 int digits = MAX_DIGITS_IN_STRING; 12623 int i; 12624 12625 cnt[start-1] = newTemp( Ity_I8 ); 12626 flag[start-1] = newTemp( Ity_I8 ); 12627 assign( cnt[start-1], init_cnt); 12628 assign( flag[start-1], init_flag); 12629 12630 for ( i = start; i <= digits; i++) { 12631 cnt[i] = newTemp( Ity_I8 ); 12632 flag[i] = newTemp( Ity_I8 ); 12633 assign( cnt[i], 12634 binop( Iop_Add8, 12635 mkexpr( cnt[i-1] ), 12636 binop(Iop_And8, 12637 unop( Iop_1Uto8, 12638 binop(Iop_CmpEQ32, 12639 binop(Iop_And32, 12640 string, 12641 mkU32( 0xF << 12642 ( ( digits - i ) * 4) ) ), 12643 mkU32( 0 ) ) ), 12644 binop( Iop_Xor8, /* complement flag */ 12645 mkexpr( flag[i - 1] ), 12646 mkU8( 0xFF ) ) ) ) ); 12647 12648 /* set flag to 1 if digit was not a zero */ 12649 assign( flag[i], 12650 binop(Iop_Or8, 12651 unop( Iop_1Sto8, 12652 binop(Iop_CmpNE32, 12653 binop(Iop_And32, 12654 string, 12655 mkU32( 0xF << 12656 ( (digits - i) * 4) ) ), 12657 mkU32( 0 ) ) ), 12658 mkexpr( flag[i - 1] ) ) ); 12659 } 12660 12661 *final_cnt = cnt[digits]; 12662 *final_flag = flag[digits]; 12663 } 12664 12665 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 12666 IRExpr * low_32 ) 12667 { 12668 IRTemp num_lmd = newTemp( Ity_I8 ); 12669 IRTemp num_upper = newTemp( Ity_I8 ); 12670 IRTemp num_low = newTemp( Ity_I8 ); 12671 IRTemp lmd_flag = newTemp( Ity_I8 ); 12672 IRTemp upper_flag = newTemp( Ity_I8 ); 12673 IRTemp low_flag = newTemp( Ity_I8 ); 12674 12675 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 12676 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 12677 12678 Count_zeros( 2, 12679 mkexpr( num_lmd ), 12680 mkexpr( lmd_flag ), 12681 &num_upper, 12682 &upper_flag, 12683 upper_28 ); 12684 12685 Count_zeros( 1, 12686 mkexpr( num_upper ), 12687 mkexpr( upper_flag ), 12688 &num_low, 12689 &low_flag, 12690 low_32 ); 12691 12692 return mkexpr( num_low ); 12693 } 12694 12695 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 12696 IRExpr * mid_60_u, IRExpr * mid_60_l, 12697 IRExpr * low_60_u, IRExpr * low_60_l) 12698 { 12699 IRTemp num_lmd = newTemp( Ity_I8 ); 12700 IRTemp num_top = newTemp( Ity_I8 ); 12701 IRTemp num_mid_u = newTemp( Ity_I8 ); 12702 IRTemp num_mid_l = newTemp( Ity_I8 ); 12703 IRTemp num_low_u = newTemp( Ity_I8 ); 12704 IRTemp num_low_l = newTemp( Ity_I8 ); 12705 12706 IRTemp lmd_flag = newTemp( Ity_I8 ); 12707 IRTemp top_flag = newTemp( Ity_I8 ); 12708 IRTemp mid_u_flag = newTemp( Ity_I8 ); 12709 IRTemp mid_l_flag = newTemp( Ity_I8 ); 12710 IRTemp low_u_flag = newTemp( Ity_I8 ); 12711 IRTemp low_l_flag = newTemp( Ity_I8 ); 12712 12713 /* Check the LMD, digit 34, to see if it is zero. */ 12714 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 12715 12716 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 12717 12718 Count_zeros( 6, 12719 mkexpr( num_lmd ), 12720 mkexpr( lmd_flag ), 12721 &num_top, 12722 &top_flag, 12723 top_12_l ); 12724 12725 Count_zeros( 2, 12726 mkexpr( num_top ), 12727 mkexpr( top_flag ), 12728 &num_mid_u, 12729 &mid_u_flag, 12730 binop( Iop_Or32, 12731 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 12732 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 12733 12734 Count_zeros( 1, 12735 mkexpr( num_mid_u ), 12736 mkexpr( mid_u_flag ), 12737 &num_mid_l, 12738 &mid_l_flag, 12739 mid_60_l ); 12740 12741 Count_zeros( 2, 12742 mkexpr( num_mid_l ), 12743 mkexpr( mid_l_flag ), 12744 &num_low_u, 12745 &low_u_flag, 12746 binop( Iop_Or32, 12747 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 12748 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 12749 12750 Count_zeros( 1, 12751 mkexpr( num_low_u ), 12752 mkexpr( low_u_flag ), 12753 &num_low_l, 12754 &low_l_flag, 12755 low_60_l ); 12756 12757 return mkexpr( num_low_l ); 12758 } 12759 12760 static IRExpr * Check_unordered(IRExpr * val) 12761 { 12762 IRTemp gfield0to5 = newTemp( Ity_I32 ); 12763 12764 /* Extract G[0:4] */ 12765 assign( gfield0to5, 12766 binop( Iop_And32, 12767 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 12768 mkU32( 0x1F ) ) ); 12769 12770 /* Check for unordered, return all 1'x if true */ 12771 return binop( Iop_Or32, /* QNaN check */ 12772 unop( Iop_1Sto32, 12773 binop( Iop_CmpEQ32, 12774 mkexpr( gfield0to5 ), 12775 mkU32( 0x1E ) ) ), 12776 unop( Iop_1Sto32, /* SNaN check */ 12777 binop( Iop_CmpEQ32, 12778 mkexpr( gfield0to5 ), 12779 mkU32( 0x1F ) ) ) ); 12780 } 12781 12782 #undef AND 12783 #undef AND4 12784 #undef OR 12785 #undef OR3 12786 #undef OR4 12787 #undef NOT 12788 #undef SHR 12789 #undef SHL 12790 #undef BITS5 12791 12792 /*------------------------------------------------------------*/ 12793 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 12794 /*------------------------------------------------------------*/ 12795 12796 /* DFP Arithmetic instructions */ 12797 static Bool dis_dfp_arith(UInt theInstr) 12798 { 12799 UInt opc2 = ifieldOPClo10( theInstr ); 12800 UChar frS_addr = ifieldRegDS( theInstr ); 12801 UChar frA_addr = ifieldRegA( theInstr ); 12802 UChar frB_addr = ifieldRegB( theInstr ); 12803 UChar flag_rC = ifieldBIT0( theInstr ); 12804 12805 IRTemp frA = newTemp( Ity_D64 ); 12806 IRTemp frB = newTemp( Ity_D64 ); 12807 IRTemp frS = newTemp( Ity_D64 ); 12808 IRExpr* round = get_IR_roundingmode_DFP(); 12809 12810 /* By default, if flag_RC is set, we will clear cr1 after the 12811 * operation. In reality we should set cr1 to indicate the 12812 * exception status of the operation, but since we're not 12813 * simulating exceptions, the exception status will appear to be 12814 * zero. Hence cr1 should be cleared if this is a . form insn. 12815 */ 12816 Bool clear_CR1 = True; 12817 12818 assign( frA, getDReg( frA_addr ) ); 12819 assign( frB, getDReg( frB_addr ) ); 12820 12821 switch (opc2) { 12822 case 0x2: // dadd 12823 DIP( "dadd%s fr%u,fr%u,fr%u\n", 12824 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12825 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12826 break; 12827 case 0x202: // dsub 12828 DIP( "dsub%s fr%u,fr%u,fr%u\n", 12829 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12830 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12831 break; 12832 case 0x22: // dmul 12833 DIP( "dmul%s fr%u,fr%u,fr%u\n", 12834 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12835 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12836 break; 12837 case 0x222: // ddiv 12838 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 12839 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12840 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 12841 break; 12842 } 12843 12844 putDReg( frS_addr, mkexpr( frS ) ); 12845 12846 if (flag_rC && clear_CR1) { 12847 putCR321( 1, mkU8( 0 ) ); 12848 putCR0( 1, mkU8( 0 ) ); 12849 } 12850 12851 return True; 12852 } 12853 12854 /* Quad DFP Arithmetic instructions */ 12855 static Bool dis_dfp_arithq(UInt theInstr) 12856 { 12857 UInt opc2 = ifieldOPClo10( theInstr ); 12858 UChar frS_addr = ifieldRegDS( theInstr ); 12859 UChar frA_addr = ifieldRegA( theInstr ); 12860 UChar frB_addr = ifieldRegB( theInstr ); 12861 UChar flag_rC = ifieldBIT0( theInstr ); 12862 12863 IRTemp frA = newTemp( Ity_D128 ); 12864 IRTemp frB = newTemp( Ity_D128 ); 12865 IRTemp frS = newTemp( Ity_D128 ); 12866 IRExpr* round = get_IR_roundingmode_DFP(); 12867 12868 /* By default, if flag_RC is set, we will clear cr1 after the 12869 * operation. In reality we should set cr1 to indicate the 12870 * exception status of the operation, but since we're not 12871 * simulating exceptions, the exception status will appear to be 12872 * zero. Hence cr1 should be cleared if this is a . form insn. 12873 */ 12874 Bool clear_CR1 = True; 12875 12876 assign( frA, getDReg_pair( frA_addr ) ); 12877 assign( frB, getDReg_pair( frB_addr ) ); 12878 12879 switch (opc2) { 12880 case 0x2: // daddq 12881 DIP( "daddq%s fr%u,fr%u,fr%u\n", 12882 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12883 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12884 break; 12885 case 0x202: // dsubq 12886 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 12887 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12888 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12889 break; 12890 case 0x22: // dmulq 12891 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 12892 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12893 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12894 break; 12895 case 0x222: // ddivq 12896 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 12897 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 12898 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 12899 break; 12900 } 12901 12902 putDReg_pair( frS_addr, mkexpr( frS ) ); 12903 12904 if (flag_rC && clear_CR1) { 12905 putCR321( 1, mkU8( 0 ) ); 12906 putCR0( 1, mkU8( 0 ) ); 12907 } 12908 12909 return True; 12910 } 12911 12912 /* DFP 64-bit logical shift instructions */ 12913 static Bool dis_dfp_shift(UInt theInstr) { 12914 UInt opc2 = ifieldOPClo9( theInstr ); 12915 UChar frS_addr = ifieldRegDS( theInstr ); 12916 UChar frA_addr = ifieldRegA( theInstr ); 12917 UChar shift_val = IFIELD(theInstr, 10, 6); 12918 UChar flag_rC = ifieldBIT0( theInstr ); 12919 12920 IRTemp frA = newTemp( Ity_D64 ); 12921 IRTemp frS = newTemp( Ity_D64 ); 12922 Bool clear_CR1 = True; 12923 12924 assign( frA, getDReg( frA_addr ) ); 12925 12926 switch (opc2) { 12927 case 0x42: // dscli 12928 DIP( "dscli%s fr%u,fr%u,%u\n", 12929 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12930 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 12931 break; 12932 case 0x62: // dscri 12933 DIP( "dscri%s fr%u,fr%u,%u\n", 12934 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12935 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 12936 break; 12937 } 12938 12939 putDReg( frS_addr, mkexpr( frS ) ); 12940 12941 if (flag_rC && clear_CR1) { 12942 putCR321( 1, mkU8( 0 ) ); 12943 putCR0( 1, mkU8( 0 ) ); 12944 } 12945 12946 return True; 12947 } 12948 12949 /* Quad DFP logical shift instructions */ 12950 static Bool dis_dfp_shiftq(UInt theInstr) { 12951 UInt opc2 = ifieldOPClo9( theInstr ); 12952 UChar frS_addr = ifieldRegDS( theInstr ); 12953 UChar frA_addr = ifieldRegA( theInstr ); 12954 UChar shift_val = IFIELD(theInstr, 10, 6); 12955 UChar flag_rC = ifieldBIT0( theInstr ); 12956 12957 IRTemp frA = newTemp( Ity_D128 ); 12958 IRTemp frS = newTemp( Ity_D128 ); 12959 Bool clear_CR1 = True; 12960 12961 assign( frA, getDReg_pair( frA_addr ) ); 12962 12963 switch (opc2) { 12964 case 0x42: // dscliq 12965 DIP( "dscliq%s fr%u,fr%u,%u\n", 12966 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12967 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 12968 break; 12969 case 0x62: // dscriq 12970 DIP( "dscriq%s fr%u,fr%u,%u\n", 12971 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 12972 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 12973 break; 12974 } 12975 12976 putDReg_pair( frS_addr, mkexpr( frS ) ); 12977 12978 if (flag_rC && clear_CR1) { 12979 putCR321( 1, mkU8( 0 ) ); 12980 putCR0( 1, mkU8( 0 ) ); 12981 } 12982 12983 return True; 12984 } 12985 12986 /* DFP 64-bit format conversion instructions */ 12987 static Bool dis_dfp_fmt_conv(UInt theInstr) { 12988 UInt opc2 = ifieldOPClo10( theInstr ); 12989 UChar frS_addr = ifieldRegDS( theInstr ); 12990 UChar frB_addr = ifieldRegB( theInstr ); 12991 IRExpr* round = get_IR_roundingmode_DFP(); 12992 UChar flag_rC = ifieldBIT0( theInstr ); 12993 IRTemp frB; 12994 IRTemp frS; 12995 Bool clear_CR1 = True; 12996 12997 switch (opc2) { 12998 case 0x102: //dctdp 12999 DIP( "dctdp%s fr%u,fr%u\n", 13000 flag_rC ? ".":"", frS_addr, frB_addr ); 13001 13002 frB = newTemp( Ity_D32 ); 13003 frS = newTemp( Ity_D64 ); 13004 assign( frB, getDReg32( frB_addr ) ); 13005 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 13006 putDReg( frS_addr, mkexpr( frS ) ); 13007 break; 13008 case 0x302: // drsp 13009 DIP( "drsp%s fr%u,fr%u\n", 13010 flag_rC ? ".":"", frS_addr, frB_addr ); 13011 frB = newTemp( Ity_D64 ); 13012 frS = newTemp( Ity_D32 ); 13013 assign( frB, getDReg( frB_addr ) ); 13014 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 13015 putDReg32( frS_addr, mkexpr( frS ) ); 13016 break; 13017 case 0x122: // dctfix 13018 { 13019 IRTemp tmp = newTemp( Ity_I64 ); 13020 13021 DIP( "dctfix%s fr%u,fr%u\n", 13022 flag_rC ? ".":"", frS_addr, frB_addr ); 13023 frB = newTemp( Ity_D64 ); 13024 frS = newTemp( Ity_D64 ); 13025 assign( frB, getDReg( frB_addr ) ); 13026 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 13027 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13028 putDReg( frS_addr, mkexpr( frS ) ); 13029 } 13030 break; 13031 case 0x322: // dcffix 13032 DIP( "dcffix%s fr%u,fr%u\n", 13033 flag_rC ? ".":"", frS_addr, frB_addr ); 13034 frB = newTemp( Ity_D64 ); 13035 frS = newTemp( Ity_D64 ); 13036 assign( frB, getDReg( frB_addr ) ); 13037 assign( frS, binop( Iop_I64StoD64, 13038 round, 13039 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 13040 putDReg( frS_addr, mkexpr( frS ) ); 13041 break; 13042 } 13043 13044 if (flag_rC && clear_CR1) { 13045 putCR321( 1, mkU8( 0 ) ); 13046 putCR0( 1, mkU8( 0 ) ); 13047 } 13048 13049 return True; 13050 } 13051 13052 /* Quad DFP format conversion instructions */ 13053 static Bool dis_dfp_fmt_convq(UInt theInstr) { 13054 UInt opc2 = ifieldOPClo10( theInstr ); 13055 UChar frS_addr = ifieldRegDS( theInstr ); 13056 UChar frB_addr = ifieldRegB( theInstr ); 13057 IRExpr* round = get_IR_roundingmode_DFP(); 13058 IRTemp frB64 = newTemp( Ity_D64 ); 13059 IRTemp frB128 = newTemp( Ity_D128 ); 13060 IRTemp frS64 = newTemp( Ity_D64 ); 13061 IRTemp frS128 = newTemp( Ity_D128 ); 13062 UChar flag_rC = ifieldBIT0( theInstr ); 13063 Bool clear_CR1 = True; 13064 13065 switch (opc2) { 13066 case 0x102: // dctqpq 13067 DIP( "dctqpq%s fr%u,fr%u\n", 13068 flag_rC ? ".":"", frS_addr, frB_addr ); 13069 assign( frB64, getDReg( frB_addr ) ); 13070 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 13071 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 13072 break; 13073 case 0x122: // dctfixq 13074 { 13075 IRTemp tmp = newTemp( Ity_I64 ); 13076 13077 DIP( "dctfixq%s fr%u,fr%u\n", 13078 flag_rC ? ".":"", frS_addr, frB_addr ); 13079 assign( frB128, getDReg_pair( frB_addr ) ); 13080 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 13081 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13082 putDReg( frS_addr, mkexpr( frS64 ) ); 13083 } 13084 break; 13085 case 0x302: //drdpq 13086 DIP( "drdpq%s fr%u,fr%u\n", 13087 flag_rC ? ".":"", frS_addr, frB_addr ); 13088 assign( frB128, getDReg_pair( frB_addr ) ); 13089 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 13090 putDReg( frS_addr, mkexpr( frS64 ) ); 13091 break; 13092 case 0x322: // dcffixq 13093 { 13094 /* Have to introduce an IOP for this instruction so it will work 13095 * on POWER 6 because emulating the instruction requires a POWER 7 13096 * DFP instruction in the emulation code. 13097 */ 13098 DIP( "dcffixq%s fr%u,fr%u\n", 13099 flag_rC ? ".":"", frS_addr, frB_addr ); 13100 assign( frB64, getDReg( frB_addr ) ); 13101 assign( frS128, unop( Iop_I64StoD128, 13102 unop( Iop_ReinterpD64asI64, 13103 mkexpr( frB64 ) ) ) ); 13104 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 13105 break; 13106 } 13107 } 13108 13109 if (flag_rC && clear_CR1) { 13110 putCR321( 1, mkU8( 0 ) ); 13111 putCR0( 1, mkU8( 0 ) ); 13112 } 13113 13114 return True; 13115 } 13116 13117 static Bool dis_dfp_round( UInt theInstr ) { 13118 UChar frS_addr = ifieldRegDS(theInstr); 13119 UChar R = IFIELD(theInstr, 16, 1); 13120 UChar RMC = IFIELD(theInstr, 9, 2); 13121 UChar frB_addr = ifieldRegB( theInstr ); 13122 UChar flag_rC = ifieldBIT0( theInstr ); 13123 IRTemp frB = newTemp( Ity_D64 ); 13124 IRTemp frS = newTemp( Ity_D64 ); 13125 UInt opc2 = ifieldOPClo8( theInstr ); 13126 Bool clear_CR1 = True; 13127 13128 switch (opc2) { 13129 /* drintn, is the same as drintx. The only difference is this 13130 * instruction does not generate an exception for an inexact operation. 13131 * Currently not supporting inexact exceptions. 13132 */ 13133 case 0x63: // drintx 13134 case 0xE3: // drintn 13135 DIP( "drintx/drintn%s fr%u,fr%u\n", 13136 flag_rC ? ".":"", frS_addr, frB_addr ); 13137 13138 /* NOTE, this instruction takes a DFP value and rounds to the 13139 * neares floating point integer value, i.e. fractional part 13140 * is zero. The result is a floating point number. 13141 */ 13142 /* pass the value of R and RMC in the same field */ 13143 assign( frB, getDReg( frB_addr ) ); 13144 assign( frS, binop( Iop_RoundD64toInt, 13145 mkU32( ( R << 3 ) | RMC ), 13146 mkexpr( frB ) ) ); 13147 putDReg( frS_addr, mkexpr( frS ) ); 13148 break; 13149 default: 13150 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 13151 return False; 13152 } 13153 13154 if (flag_rC && clear_CR1) { 13155 putCR321( 1, mkU8( 0 ) ); 13156 putCR0( 1, mkU8( 0 ) ); 13157 } 13158 13159 return True; 13160 } 13161 13162 static Bool dis_dfp_roundq(UInt theInstr) { 13163 UChar frS_addr = ifieldRegDS( theInstr ); 13164 UChar frB_addr = ifieldRegB( theInstr ); 13165 UChar R = IFIELD(theInstr, 16, 1); 13166 UChar RMC = IFIELD(theInstr, 9, 2); 13167 UChar flag_rC = ifieldBIT0( theInstr ); 13168 IRTemp frB = newTemp( Ity_D128 ); 13169 IRTemp frS = newTemp( Ity_D128 ); 13170 Bool clear_CR1 = True; 13171 UInt opc2 = ifieldOPClo8( theInstr ); 13172 13173 switch (opc2) { 13174 /* drintnq, is the same as drintxq. The only difference is this 13175 * instruction does not generate an exception for an inexact operation. 13176 * Currently not supporting inexact exceptions. 13177 */ 13178 case 0x63: // drintxq 13179 case 0xE3: // drintnq 13180 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 13181 flag_rC ? ".":"", frS_addr, frB_addr ); 13182 13183 /* pass the value of R and RMC in the same field */ 13184 assign( frB, getDReg_pair( frB_addr ) ); 13185 assign( frS, binop( Iop_RoundD128toInt, 13186 mkU32( ( R << 3 ) | RMC ), 13187 mkexpr( frB ) ) ); 13188 putDReg_pair( frS_addr, mkexpr( frS ) ); 13189 break; 13190 default: 13191 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 13192 return False; 13193 } 13194 13195 if (flag_rC && clear_CR1) { 13196 putCR321( 1, mkU8( 0 ) ); 13197 putCR0( 1, mkU8( 0 ) ); 13198 } 13199 13200 return True; 13201 } 13202 13203 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 13204 UInt opc2 = ifieldOPClo8( theInstr ); 13205 UChar frS_addr = ifieldRegDS( theInstr ); 13206 UChar frA_addr = ifieldRegA( theInstr ); 13207 UChar frB_addr = ifieldRegB( theInstr ); 13208 UChar flag_rC = ifieldBIT0( theInstr ); 13209 UInt TE_value = IFIELD(theInstr, 16, 4); 13210 UInt TE_sign = IFIELD(theInstr, 20, 1); 13211 UInt RMC = IFIELD(theInstr, 9, 2); 13212 IRTemp frA = newTemp( Ity_D64 ); 13213 IRTemp frB = newTemp( Ity_D64 ); 13214 IRTemp frS = newTemp( Ity_D64 ); 13215 Bool clear_CR1 = True; 13216 13217 assign( frB, getDReg( frB_addr ) ); 13218 13219 switch (opc2) { 13220 case 0x43: // dquai 13221 DIP( "dquai%s fr%u,fr%u,fr%u\n", 13222 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13223 IRTemp TE_I64 = newTemp( Ity_I64 ); 13224 13225 /* Generate a reference DFP value frA with the desired exponent 13226 * given by TE using significand from frB. Need to add the bias 13227 * 398 to TE. TE is stored as a 2's complement number. 13228 */ 13229 if (TE_sign == 1) { 13230 /* Take 2's complement of the 5-bit value and subtract from bias. 13231 * Bias is adjusted for the +1 required when taking 2's complement. 13232 */ 13233 assign( TE_I64, 13234 unop( Iop_32Uto64, 13235 binop( Iop_Sub32, mkU32( 397 ), 13236 binop( Iop_And32, mkU32( 0xF ), 13237 unop( Iop_Not32, mkU32( TE_value ) ) 13238 ) ) ) ); 13239 13240 } else { 13241 assign( TE_I64, 13242 unop( Iop_32Uto64, 13243 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 13244 ) ); 13245 } 13246 13247 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 13248 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 13249 13250 assign( frS, triop( Iop_QuantizeD64, 13251 mkU32( RMC ), 13252 mkexpr( frA ), 13253 mkexpr( frB ) ) ); 13254 break; 13255 13256 case 0x3: // dqua 13257 DIP( "dqua%s fr%u,fr%u,fr%u\n", 13258 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13259 assign( frA, getDReg( frA_addr ) ); 13260 assign( frS, triop( Iop_QuantizeD64, 13261 mkU32( RMC ), 13262 mkexpr( frA ), 13263 mkexpr( frB ) ) ); 13264 break; 13265 case 0x23: // drrnd 13266 { 13267 IRTemp tmp = newTemp( Ity_I8 ); 13268 13269 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 13270 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13271 assign( frA, getDReg( frA_addr ) ); 13272 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 13273 assign( tmp, unop( Iop_32to8, 13274 unop( Iop_64to32, 13275 unop( Iop_ReinterpD64asI64, 13276 mkexpr( frA ) ) ) ) ); 13277 assign( frS, triop( Iop_SignificanceRoundD64, 13278 mkU32( RMC ), 13279 mkexpr( tmp ), 13280 mkexpr( frB ) ) ); 13281 } 13282 break; 13283 default: 13284 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 13285 return False; 13286 } 13287 putDReg( frS_addr, mkexpr( frS ) ); 13288 13289 if (flag_rC && clear_CR1) { 13290 putCR321( 1, mkU8( 0 ) ); 13291 putCR0( 1, mkU8( 0 ) ); 13292 } 13293 13294 return True; 13295 } 13296 13297 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 13298 UInt opc2 = ifieldOPClo8( theInstr ); 13299 UChar frS_addr = ifieldRegDS( theInstr ); 13300 UChar frA_addr = ifieldRegA( theInstr ); 13301 UChar frB_addr = ifieldRegB( theInstr ); 13302 UChar flag_rC = ifieldBIT0( theInstr ); 13303 UInt TE_value = IFIELD(theInstr, 16, 4); 13304 UInt TE_sign = IFIELD(theInstr, 20, 1); 13305 UInt RMC = IFIELD(theInstr, 9, 2); 13306 IRTemp frA = newTemp( Ity_D128 ); 13307 IRTemp frB = newTemp( Ity_D128 ); 13308 IRTemp frS = newTemp( Ity_D128 ); 13309 Bool clear_CR1 = True; 13310 13311 assign( frB, getDReg_pair( frB_addr ) ); 13312 13313 switch (opc2) { 13314 case 0x43: // dquaiq 13315 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 13316 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13317 IRTemp TE_I64 = newTemp( Ity_I64 ); 13318 13319 /* Generate a reference DFP value frA with the desired exponent 13320 * given by TE using significand of 1. Need to add the bias 13321 * 6176 to TE. 13322 */ 13323 if (TE_sign == 1) { 13324 /* Take 2's complement of the 5-bit value and subtract from bias. 13325 * Bias adjusted for the +1 required when taking 2's complement. 13326 */ 13327 assign( TE_I64, 13328 unop( Iop_32Uto64, 13329 binop( Iop_Sub32, mkU32( 6175 ), 13330 binop( Iop_And32, mkU32( 0xF ), 13331 unop( Iop_Not32, mkU32( TE_value ) ) 13332 ) ) ) ); 13333 13334 } else { 13335 assign( TE_I64, 13336 unop( Iop_32Uto64, 13337 binop( Iop_Add32, 13338 mkU32( 6176 ), 13339 mkU32( TE_value ) ) ) ); 13340 } 13341 13342 assign( frA, 13343 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 13344 unop( Iop_D64toD128, 13345 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 13346 assign( frS, triop( Iop_QuantizeD128, 13347 mkU32( RMC ), 13348 mkexpr( frA ), 13349 mkexpr( frB ) ) ); 13350 break; 13351 case 0x3: // dquaq 13352 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 13353 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13354 assign( frA, getDReg_pair( frA_addr ) ); 13355 assign( frS, triop( Iop_QuantizeD128, 13356 mkU32( RMC ), 13357 mkexpr( frA ), 13358 mkexpr( frB ) ) ); 13359 break; 13360 case 0x23: // drrndq 13361 { 13362 IRTemp tmp = newTemp( Ity_I8 ); 13363 13364 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 13365 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13366 assign( frA, getDReg_pair( frA_addr ) ); 13367 assign( tmp, unop( Iop_32to8, 13368 unop( Iop_64to32, 13369 unop( Iop_ReinterpD64asI64, 13370 unop( Iop_D128HItoD64, 13371 mkexpr( frA ) ) ) ) ) ); 13372 assign( frS, triop( Iop_SignificanceRoundD128, 13373 mkU32( RMC ), 13374 mkexpr( tmp ), 13375 mkexpr( frB ) ) ); 13376 } 13377 break; 13378 default: 13379 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 13380 return False; 13381 } 13382 putDReg_pair( frS_addr, mkexpr( frS ) ); 13383 13384 if (flag_rC && clear_CR1) { 13385 putCR321( 1, mkU8( 0 ) ); 13386 putCR0( 1, mkU8( 0 ) ); 13387 } 13388 13389 return True; 13390 } 13391 13392 static Bool dis_dfp_extract_insert(UInt theInstr) { 13393 UInt opc2 = ifieldOPClo10( theInstr ); 13394 UChar frS_addr = ifieldRegDS( theInstr ); 13395 UChar frA_addr = ifieldRegA( theInstr ); 13396 UChar frB_addr = ifieldRegB( theInstr ); 13397 UChar flag_rC = ifieldBIT0( theInstr ); 13398 Bool clear_CR1 = True; 13399 13400 IRTemp frA = newTemp( Ity_D64 ); 13401 IRTemp frB = newTemp( Ity_D64 ); 13402 IRTemp frS = newTemp( Ity_D64 ); 13403 IRTemp tmp = newTemp( Ity_I64 ); 13404 13405 assign( frA, getDReg( frA_addr ) ); 13406 assign( frB, getDReg( frB_addr ) ); 13407 13408 switch (opc2) { 13409 case 0x162: // dxex 13410 DIP( "dxex%s fr%u,fr%u,fr%u\n", 13411 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13412 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 13413 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13414 break; 13415 case 0x362: // diex 13416 DIP( "diex%s fr%u,fr%u,fr%u\n", 13417 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13418 assign( frS, binop( Iop_InsertExpD64, 13419 unop( Iop_ReinterpD64asI64, 13420 mkexpr( frA ) ), 13421 mkexpr( frB ) ) ); 13422 break; 13423 default: 13424 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 13425 return False; 13426 } 13427 13428 putDReg( frS_addr, mkexpr( frS ) ); 13429 13430 if (flag_rC && clear_CR1) { 13431 putCR321( 1, mkU8( 0 ) ); 13432 putCR0( 1, mkU8( 0 ) ); 13433 } 13434 13435 return True; 13436 } 13437 13438 static Bool dis_dfp_extract_insertq(UInt theInstr) { 13439 UInt opc2 = ifieldOPClo10( theInstr ); 13440 UChar frS_addr = ifieldRegDS( theInstr ); 13441 UChar frA_addr = ifieldRegA( theInstr ); 13442 UChar frB_addr = ifieldRegB( theInstr ); 13443 UChar flag_rC = ifieldBIT0( theInstr ); 13444 13445 IRTemp frA = newTemp( Ity_D64 ); 13446 IRTemp frB = newTemp( Ity_D128 ); 13447 IRTemp frS64 = newTemp( Ity_D64 ); 13448 IRTemp frS = newTemp( Ity_D128 ); 13449 IRTemp tmp = newTemp( Ity_I64 ); 13450 Bool clear_CR1 = True; 13451 13452 assign( frB, getDReg_pair( frB_addr ) ); 13453 13454 switch (opc2) { 13455 case 0x162: // dxexq 13456 DIP( "dxexq%s fr%u,fr%u\n", 13457 flag_rC ? ".":"", frS_addr, frB_addr ); 13458 /* Instruction actually returns a 64-bit result. So as to be 13459 * consistent and not have to add a new struct, the emulation returns 13460 * the 64-bit result in the upper and lower register. 13461 */ 13462 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 13463 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 13464 putDReg( frS_addr, mkexpr( frS64 ) ); 13465 break; 13466 case 0x362: // diexq 13467 DIP( "diexq%s fr%u,fr%u,fr%u\n", 13468 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 13469 assign( frA, getDReg( frA_addr ) ); 13470 assign( frS, binop( Iop_InsertExpD128, 13471 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 13472 mkexpr( frB ) ) ); 13473 putDReg_pair( frS_addr, mkexpr( frS ) ); 13474 break; 13475 default: 13476 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 13477 return False; 13478 } 13479 13480 if (flag_rC && clear_CR1) { 13481 putCR321( 1, mkU8( 0 ) ); 13482 putCR0( 1, mkU8( 0 ) ); 13483 } 13484 13485 return True; 13486 } 13487 13488 /* DFP 64-bit comparison instructions */ 13489 static Bool dis_dfp_compare(UInt theInstr) { 13490 /* X-Form */ 13491 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 13492 UChar frA_addr = ifieldRegA( theInstr ); 13493 UChar frB_addr = ifieldRegB( theInstr ); 13494 UInt opc1 = ifieldOPC( theInstr ); 13495 IRTemp frA; 13496 IRTemp frB; 13497 13498 IRTemp ccIR = newTemp( Ity_I32 ); 13499 IRTemp ccPPC32 = newTemp( Ity_I32 ); 13500 13501 13502 /* Note: Differences between dcmpu and dcmpo are only in exception 13503 flag settings, which aren't supported anyway. */ 13504 switch (opc1) { 13505 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 13506 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 13507 frA = newTemp( Ity_D64 ); 13508 frB = newTemp( Ity_D64 ); 13509 13510 assign( frA, getDReg( frA_addr ) ); 13511 assign( frB, getDReg( frB_addr ) ); 13512 13513 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 13514 break; 13515 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 13516 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 13517 frA = newTemp( Ity_D128 ); 13518 frB = newTemp( Ity_D128 ); 13519 13520 assign( frA, getDReg_pair( frA_addr ) ); 13521 assign( frB, getDReg_pair( frB_addr ) ); 13522 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 13523 break; 13524 default: 13525 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 13526 return False; 13527 } 13528 13529 /* Map compare result from IR to PPC32 */ 13530 /* 13531 FP cmp result | PPC | IR 13532 -------------------------- 13533 UN | 0x1 | 0x45 13534 EQ | 0x2 | 0x40 13535 GT | 0x4 | 0x00 13536 LT | 0x8 | 0x01 13537 */ 13538 13539 assign( ccPPC32, 13540 binop( Iop_Shl32, 13541 mkU32( 1 ), 13542 unop( Iop_32to8, 13543 binop( Iop_Or32, 13544 binop( Iop_And32, 13545 unop( Iop_Not32, 13546 binop( Iop_Shr32, 13547 mkexpr( ccIR ), 13548 mkU8( 5 ) ) ), 13549 mkU32( 2 ) ), 13550 binop( Iop_And32, 13551 binop( Iop_Xor32, 13552 mkexpr( ccIR ), 13553 binop( Iop_Shr32, 13554 mkexpr( ccIR ), 13555 mkU8( 6 ) ) ), 13556 mkU32( 1 ) ) ) ) ) ); 13557 13558 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 13559 putFPCC( mkexpr( ccPPC32 ) ); 13560 return True; 13561 } 13562 13563 /* Test class/group/exponent/significance instructions. */ 13564 static Bool dis_dfp_exponent_test ( UInt theInstr ) 13565 { 13566 UChar frA_addr = ifieldRegA( theInstr ); 13567 UChar frB_addr = ifieldRegB( theInstr ); 13568 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13569 IRTemp frA = newTemp( Ity_D64 ); 13570 IRTemp frB = newTemp( Ity_D64 ); 13571 IRTemp frA128 = newTemp( Ity_D128 ); 13572 IRTemp frB128 = newTemp( Ity_D128 ); 13573 UInt opc1 = ifieldOPC( theInstr ); 13574 IRTemp gfield_A = newTemp( Ity_I32 ); 13575 IRTemp gfield_B = newTemp( Ity_I32 ); 13576 IRTemp gfield_mask = newTemp( Ity_I32 ); 13577 IRTemp exponent_A = newTemp( Ity_I32 ); 13578 IRTemp exponent_B = newTemp( Ity_I32 ); 13579 IRTemp A_NaN_true = newTemp( Ity_I32 ); 13580 IRTemp B_NaN_true = newTemp( Ity_I32 ); 13581 IRTemp A_inf_true = newTemp( Ity_I32 ); 13582 IRTemp B_inf_true = newTemp( Ity_I32 ); 13583 IRTemp A_equals_B = newTemp( Ity_I32 ); 13584 IRTemp finite_number = newTemp( Ity_I32 ); 13585 IRTemp cc0 = newTemp( Ity_I32 ); 13586 IRTemp cc1 = newTemp( Ity_I32 ); 13587 IRTemp cc2 = newTemp( Ity_I32 ); 13588 IRTemp cc3 = newTemp( Ity_I32 ); 13589 IRTemp cc = newTemp( Ity_I32 ); 13590 13591 /* The dtstex and dtstexg instructions only differ in the size of the 13592 * exponent field. The following switch statement takes care of the size 13593 * specific setup. Once the value of the exponents, the G-field shift 13594 * and mask is setup the remaining code is identical. 13595 */ 13596 switch (opc1) { 13597 case 0x3b: // dtstex Extended instruction setup 13598 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 13599 assign( frA, getDReg( frA_addr ) ); 13600 assign( frB, getDReg( frB_addr ) ); 13601 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 13602 assign(exponent_A, unop( Iop_64to32, 13603 unop( Iop_ExtractExpD64, 13604 mkexpr( frA ) ) ) ); 13605 assign(exponent_B, unop( Iop_64to32, 13606 unop( Iop_ExtractExpD64, 13607 mkexpr( frB ) ) ) ); 13608 break; 13609 13610 case 0x3F: // dtstexq Quad instruction setup 13611 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 13612 assign( frA128, getDReg_pair( frA_addr ) ); 13613 assign( frB128, getDReg_pair( frB_addr ) ); 13614 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 13615 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 13616 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 13617 assign( exponent_A, unop( Iop_64to32, 13618 unop( Iop_ExtractExpD128, 13619 mkexpr( frA128 ) ) ) ); 13620 assign( exponent_B, unop( Iop_64to32, 13621 unop( Iop_ExtractExpD128, 13622 mkexpr( frB128 ) ) ) ); 13623 break; 13624 default: 13625 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 13626 return False; 13627 } 13628 13629 /* Extract the Gfield */ 13630 assign( gfield_A, binop( Iop_And32, 13631 mkexpr( gfield_mask ), 13632 unop( Iop_64HIto32, 13633 unop( Iop_ReinterpD64asI64, 13634 mkexpr(frA) ) ) ) ); 13635 13636 assign( gfield_B, binop( Iop_And32, 13637 mkexpr( gfield_mask ), 13638 unop( Iop_64HIto32, 13639 unop( Iop_ReinterpD64asI64, 13640 mkexpr(frB) ) ) ) ); 13641 13642 /* check for NAN */ 13643 assign( A_NaN_true, binop(Iop_Or32, 13644 unop( Iop_1Sto32, 13645 binop( Iop_CmpEQ32, 13646 mkexpr( gfield_A ), 13647 mkU32( 0x7C000000 ) ) ), 13648 unop( Iop_1Sto32, 13649 binop( Iop_CmpEQ32, 13650 mkexpr( gfield_A ), 13651 mkU32( 0x7E000000 ) ) 13652 ) ) ); 13653 assign( B_NaN_true, binop(Iop_Or32, 13654 unop( Iop_1Sto32, 13655 binop( Iop_CmpEQ32, 13656 mkexpr( gfield_B ), 13657 mkU32( 0x7C000000 ) ) ), 13658 unop( Iop_1Sto32, 13659 binop( Iop_CmpEQ32, 13660 mkexpr( gfield_B ), 13661 mkU32( 0x7E000000 ) ) 13662 ) ) ); 13663 13664 /* check for infinity */ 13665 assign( A_inf_true, 13666 unop( Iop_1Sto32, 13667 binop( Iop_CmpEQ32, 13668 mkexpr( gfield_A ), 13669 mkU32( 0x78000000 ) ) ) ); 13670 13671 assign( B_inf_true, 13672 unop( Iop_1Sto32, 13673 binop( Iop_CmpEQ32, 13674 mkexpr( gfield_B ), 13675 mkU32( 0x78000000 ) ) ) ); 13676 13677 assign( finite_number, 13678 unop( Iop_Not32, 13679 binop( Iop_Or32, 13680 binop( Iop_Or32, 13681 mkexpr( A_NaN_true ), 13682 mkexpr( B_NaN_true ) ), 13683 binop( Iop_Or32, 13684 mkexpr( A_inf_true ), 13685 mkexpr( B_inf_true ) ) ) ) ); 13686 13687 /* Calculate the condition code bits 13688 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 13689 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 13690 * cc0, cc1 and cc0 reflect the results of the comparisons. 13691 */ 13692 assign( A_equals_B, 13693 binop( Iop_Or32, 13694 unop( Iop_1Uto32, 13695 binop( Iop_CmpEQ32, 13696 mkexpr( exponent_A ), 13697 mkexpr( exponent_B ) ) ), 13698 binop( Iop_Or32, 13699 binop( Iop_And32, 13700 mkexpr( A_inf_true ), 13701 mkexpr( B_inf_true ) ), 13702 binop( Iop_And32, 13703 mkexpr( A_NaN_true ), 13704 mkexpr( B_NaN_true ) ) ) ) ); 13705 13706 assign( cc0, binop( Iop_And32, 13707 mkexpr( finite_number ), 13708 binop( Iop_Shl32, 13709 unop( Iop_1Uto32, 13710 binop( Iop_CmpLT32U, 13711 mkexpr( exponent_A ), 13712 mkexpr( exponent_B ) ) ), 13713 mkU8( 3 ) ) ) ); 13714 13715 assign( cc1, binop( Iop_And32, 13716 mkexpr( finite_number ), 13717 binop( Iop_Shl32, 13718 unop( Iop_1Uto32, 13719 binop( Iop_CmpLT32U, 13720 mkexpr( exponent_B ), 13721 mkexpr( exponent_A ) ) ), 13722 mkU8( 2 ) ) ) ); 13723 13724 assign( cc2, binop( Iop_Shl32, 13725 binop( Iop_And32, 13726 mkexpr( A_equals_B ), 13727 mkU32( 1 ) ), 13728 mkU8( 1 ) ) ); 13729 13730 assign( cc3, binop( Iop_And32, 13731 unop( Iop_Not32, mkexpr( A_equals_B ) ), 13732 binop( Iop_And32, 13733 mkU32( 0x1 ), 13734 binop( Iop_Or32, 13735 binop( Iop_Or32, 13736 mkexpr ( A_inf_true ), 13737 mkexpr ( B_inf_true ) ), 13738 binop( Iop_Or32, 13739 mkexpr ( A_NaN_true ), 13740 mkexpr ( B_NaN_true ) ) ) 13741 ) ) ); 13742 13743 /* store the condition code */ 13744 assign( cc, binop( Iop_Or32, 13745 mkexpr( cc0 ), 13746 binop( Iop_Or32, 13747 mkexpr( cc1 ), 13748 binop( Iop_Or32, 13749 mkexpr( cc2 ), 13750 mkexpr( cc3 ) ) ) ) ); 13751 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD ); 13752 putFPCC( mkexpr( cc ) ); 13753 return True; 13754 } 13755 13756 /* Test class/group/exponent/significance instructions. */ 13757 static Bool dis_dfp_class_test ( UInt theInstr ) 13758 { 13759 UChar frA_addr = ifieldRegA( theInstr ); 13760 IRTemp frA = newTemp( Ity_D64 ); 13761 IRTemp abs_frA = newTemp( Ity_D64 ); 13762 IRTemp frAI64_hi = newTemp( Ity_I64 ); 13763 IRTemp frAI64_lo = newTemp( Ity_I64 ); 13764 UInt opc1 = ifieldOPC( theInstr ); 13765 UInt opc2 = ifieldOPClo9( theInstr ); 13766 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 13767 UInt DCM = IFIELD( theInstr, 10, 6 ); 13768 IRTemp DCM_calc = newTemp( Ity_I32 ); 13769 UInt max_exp = 0; 13770 UInt min_exp = 0; 13771 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 13772 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 13773 IRTemp significand64 = newTemp( Ity_D64 ); 13774 IRTemp significand128 = newTemp( Ity_D128 ); 13775 IRTemp exp_min_normal = newTemp( Ity_I64 ); 13776 IRTemp exponent = newTemp( Ity_I32 ); 13777 13778 IRTemp infinity_true = newTemp( Ity_I32 ); 13779 IRTemp SNaN_true = newTemp( Ity_I32 ); 13780 IRTemp QNaN_true = newTemp( Ity_I32 ); 13781 IRTemp subnormal_true = newTemp( Ity_I32 ); 13782 IRTemp normal_true = newTemp( Ity_I32 ); 13783 IRTemp extreme_true = newTemp( Ity_I32 ); 13784 IRTemp lmd = newTemp( Ity_I32 ); 13785 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 13786 IRTemp zero_true = newTemp( Ity_I32 ); 13787 IRTemp sign = newTemp( Ity_I32 ); 13788 IRTemp field = newTemp( Ity_I32 ); 13789 IRTemp ccIR_zero = newTemp( Ity_I32 ); 13790 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 13791 13792 /* UInt size = DFP_LONG; JRS:unused */ 13793 IRTemp gfield = newTemp( Ity_I32 ); 13794 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 13795 IRTemp gfield_mask = newTemp( Ity_I32 ); 13796 IRTemp dcm0 = newTemp( Ity_I32 ); 13797 IRTemp dcm1 = newTemp( Ity_I32 ); 13798 IRTemp dcm2 = newTemp( Ity_I32 ); 13799 IRTemp dcm3 = newTemp( Ity_I32 ); 13800 IRTemp dcm4 = newTemp( Ity_I32 ); 13801 IRTemp dcm5 = newTemp( Ity_I32 ); 13802 13803 /* The only difference between the dtstdc and dtstdcq instructions is 13804 * size of the T and G fields. The calculation of the 4 bit field 13805 * is the same. Setup the parameters and values that are DFP size 13806 * specific. The rest of the code is independent of the DFP size. 13807 * 13808 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 13809 * The interpretation of the ccIR values is as follows: 13810 * 13811 * DFP cmp result | IR 13812 * -------------------------- 13813 * UN | 0x45 13814 * EQ | 0x40 13815 * GT | 0x00 13816 * LT | 0x01 13817 */ 13818 13819 assign( frA, getDReg( frA_addr ) ); 13820 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 13821 13822 assign( abs_frA, unop( Iop_ReinterpI64asD64, 13823 binop( Iop_And64, 13824 unop( Iop_ReinterpD64asI64, 13825 mkexpr( frA ) ), 13826 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 13827 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 13828 switch (opc1) { 13829 case 0x3b: // dtstdc, dtstdg 13830 DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 13831 crfD, frA_addr, DCM); 13832 /* setup the parameters for the long format of the two instructions */ 13833 assign( frAI64_lo, mkU64( 0 ) ); 13834 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 13835 max_exp = DFP_LONG_EXP_MAX; 13836 min_exp = DFP_LONG_EXP_MIN; 13837 13838 assign( exponent, unop( Iop_64to32, 13839 unop( Iop_ExtractExpD64, 13840 mkexpr( frA ) ) ) ); 13841 assign( significand64, 13842 unop( Iop_ReinterpI64asD64, 13843 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 13844 assign( exp_min_normal,mkU64( 398 - 383 ) ); 13845 assign( min_subnormalD64, 13846 binop( Iop_InsertExpD64, 13847 mkexpr( exp_min_normal ), 13848 mkexpr( significand64 ) ) ); 13849 13850 assign( ccIR_subnormal, 13851 binop( Iop_CmpD64, 13852 mkexpr( abs_frA ), 13853 mkexpr( min_subnormalD64 ) ) ); 13854 13855 /* compare absolute value of frA with zero */ 13856 assign( ccIR_zero, 13857 binop( Iop_CmpD64, 13858 mkexpr( abs_frA ), 13859 unop( Iop_ReinterpI64asD64, 13860 mkU64( 0x2238000000000000ULL ) ) ) ); 13861 13862 /* size = DFP_LONG; JRS: unused */ 13863 break; 13864 13865 case 0x3F: // dtstdcq, dtstdgq 13866 DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g", 13867 crfD, frA_addr, DCM); 13868 /* setup the parameters for the extended format of the 13869 * two instructions 13870 */ 13871 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 13872 getDReg( frA_addr+1 ) ) ); 13873 13874 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 13875 max_exp = DFP_EXTND_EXP_MAX; 13876 min_exp = DFP_EXTND_EXP_MIN; 13877 assign( exponent, unop( Iop_64to32, 13878 unop( Iop_ExtractExpD128, 13879 getDReg_pair( frA_addr) ) ) ); 13880 13881 /* create quand exponent for minimum normal number */ 13882 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 13883 assign( significand128, 13884 unop( Iop_D64toD128, 13885 unop( Iop_ReinterpI64asD64, 13886 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 13887 13888 assign( min_subnormalD128, 13889 binop( Iop_InsertExpD128, 13890 mkexpr( exp_min_normal ), 13891 mkexpr( significand128 ) ) ); 13892 13893 assign( ccIR_subnormal, 13894 binop( Iop_CmpD128, 13895 binop( Iop_D64HLtoD128, 13896 unop( Iop_ReinterpI64asD64, 13897 binop( Iop_And64, 13898 unop( Iop_ReinterpD64asI64, 13899 mkexpr( frA ) ), 13900 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 13901 getDReg( frA_addr+1 ) ), 13902 mkexpr( min_subnormalD128 ) ) ); 13903 assign( ccIR_zero, 13904 binop( Iop_CmpD128, 13905 binop( Iop_D64HLtoD128, 13906 mkexpr( abs_frA ), 13907 getDReg( frA_addr+1 ) ), 13908 unop( Iop_D64toD128, 13909 unop( Iop_ReinterpI64asD64, 13910 mkU64( 0x0ULL ) ) ) ) ); 13911 13912 /* size = DFP_EXTND; JRS:unused */ 13913 break; 13914 default: 13915 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 13916 return False; 13917 } 13918 13919 /* The G-field is in the upper 32-bits. The I64 logical operations 13920 * do not seem to be supported in 32-bit mode so keep things as 32-bit 13921 * operations. 13922 */ 13923 assign( gfield, binop( Iop_And32, 13924 mkexpr( gfield_mask ), 13925 unop( Iop_64HIto32, 13926 mkexpr(frAI64_hi) ) ) ); 13927 13928 /* There is a lot of code that is the same to do the class and group 13929 * instructions. Later there is an if statement to handle the specific 13930 * instruction. 13931 * 13932 * Will be using I32 values, compares, shifts and logical operations for 13933 * this code as the 64-bit compare, shifts, logical operations are not 13934 * supported in 32-bit mode. 13935 */ 13936 13937 /* Check the bits for Infinity, QNaN or Signaling NaN */ 13938 assign( infinity_true, 13939 unop( Iop_1Sto32, 13940 binop( Iop_CmpEQ32, 13941 binop( Iop_And32, 13942 mkU32( 0x7C000000 ), 13943 mkexpr( gfield ) ), 13944 mkU32( 0x78000000 ) ) ) ); 13945 13946 assign( SNaN_true, 13947 unop( Iop_1Sto32, 13948 binop( Iop_CmpEQ32, 13949 binop( Iop_And32, 13950 mkU32( 0x7E000000 ), 13951 mkexpr( gfield ) ), 13952 mkU32( 0x7E000000 ) ) ) ); 13953 13954 assign( QNaN_true, 13955 binop( Iop_And32, 13956 unop( Iop_1Sto32, 13957 binop( Iop_CmpEQ32, 13958 binop( Iop_And32, 13959 mkU32( 0x7E000000 ), 13960 mkexpr( gfield ) ), 13961 mkU32( 0x7C000000 ) ) ), 13962 unop( Iop_Not32, 13963 mkexpr( SNaN_true ) ) ) ); 13964 13965 assign( zero_true, 13966 binop( Iop_And32, 13967 unop(Iop_1Sto32, 13968 binop( Iop_CmpEQ32, 13969 mkexpr( ccIR_zero ), 13970 mkU32( 0x40 ) ) ), // ccIR code for Equal 13971 unop( Iop_Not32, 13972 binop( Iop_Or32, 13973 mkexpr( infinity_true ), 13974 binop( Iop_Or32, 13975 mkexpr( QNaN_true ), 13976 mkexpr( SNaN_true ) ) ) ) ) ); 13977 13978 /* Do compare of frA the minimum normal value. Comparison is size 13979 * depenent and was done above to get the ccIR value. 13980 */ 13981 assign( subnormal_true, 13982 binop( Iop_And32, 13983 binop( Iop_Or32, 13984 unop( Iop_1Sto32, 13985 binop( Iop_CmpEQ32, 13986 mkexpr( ccIR_subnormal ), 13987 mkU32( 0x40 ) ) ), // ccIR code for Equal 13988 unop( Iop_1Sto32, 13989 binop( Iop_CmpEQ32, 13990 mkexpr( ccIR_subnormal ), 13991 mkU32( 0x1 ) ) ) ), // ccIR code for LT 13992 unop( Iop_Not32, 13993 binop( Iop_Or32, 13994 binop( Iop_Or32, 13995 mkexpr( infinity_true ), 13996 mkexpr( zero_true) ), 13997 binop( Iop_Or32, 13998 mkexpr( QNaN_true ), 13999 mkexpr( SNaN_true ) ) ) ) ) ); 14000 14001 /* Normal number is not subnormal, infinity, NaN or Zero */ 14002 assign( normal_true, 14003 unop( Iop_Not32, 14004 binop( Iop_Or32, 14005 binop( Iop_Or32, 14006 mkexpr( infinity_true ), 14007 mkexpr( zero_true ) ), 14008 binop( Iop_Or32, 14009 mkexpr( subnormal_true ), 14010 binop( Iop_Or32, 14011 mkexpr( QNaN_true ), 14012 mkexpr( SNaN_true ) ) ) ) ) ); 14013 14014 /* Calculate the DCM bit field based on the tests for the specific 14015 * instruction 14016 */ 14017 if (opc2 == 0xC2) { // dtstdc, dtstdcq 14018 /* DCM[0:5] Bit Data Class definition 14019 * 0 Zero 14020 * 1 Subnormal 14021 * 2 Normal 14022 * 3 Infinity 14023 * 4 Quiet NaN 14024 * 5 Signaling NaN 14025 */ 14026 14027 assign( dcm0, binop( Iop_Shl32, 14028 mkexpr( zero_true ), 14029 mkU8( 5 ) ) ); 14030 assign( dcm1, binop( Iop_Shl32, 14031 binop( Iop_And32, 14032 mkexpr( subnormal_true ), 14033 mkU32( 1 ) ), 14034 mkU8( 4 ) ) ); 14035 assign( dcm2, binop( Iop_Shl32, 14036 binop( Iop_And32, 14037 mkexpr( normal_true ), 14038 mkU32( 1 ) ), 14039 mkU8( 3 ) ) ); 14040 assign( dcm3, binop( Iop_Shl32, 14041 binop( Iop_And32, 14042 mkexpr( infinity_true), 14043 mkU32( 1 ) ), 14044 mkU8( 2 ) ) ); 14045 assign( dcm4, binop( Iop_Shl32, 14046 binop( Iop_And32, 14047 mkexpr( QNaN_true ), 14048 mkU32( 1 ) ), 14049 mkU8( 1 ) ) ); 14050 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 14051 14052 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 14053 /* check if the exponent is extreme */ 14054 assign( extreme_true, binop( Iop_Or32, 14055 unop( Iop_1Sto32, 14056 binop( Iop_CmpEQ32, 14057 mkexpr( exponent ), 14058 mkU32( max_exp ) ) ), 14059 unop( Iop_1Sto32, 14060 binop( Iop_CmpEQ32, 14061 mkexpr( exponent ), 14062 mkU32( min_exp ) ) ) ) ); 14063 14064 /* Check if LMD is zero */ 14065 Get_lmd( &lmd, binop( Iop_Shr32, 14066 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 14067 14068 assign( lmd_zero_true, unop( Iop_1Sto32, 14069 binop( Iop_CmpEQ32, 14070 mkexpr( lmd ), 14071 mkU32( 0 ) ) ) ); 14072 14073 /* DCM[0:5] Bit Data Class definition 14074 * 0 Zero with non-extreme exponent 14075 * 1 Zero with extreme exponent 14076 * 2 Subnormal or (Normal with extreme exponent) 14077 * 3 Normal with non-extreme exponent and 14078 * leftmost zero digit in significand 14079 * 4 Normal with non-extreme exponent and 14080 * leftmost nonzero digit in significand 14081 * 5 Special symbol (Infinity, QNaN, or SNaN) 14082 */ 14083 assign( dcm0, binop( Iop_Shl32, 14084 binop( Iop_And32, 14085 binop( Iop_And32, 14086 unop( Iop_Not32, 14087 mkexpr( extreme_true ) ), 14088 mkexpr( zero_true ) ), 14089 mkU32( 0x1 ) ), 14090 mkU8( 5 ) ) ); 14091 14092 assign( dcm1, binop( Iop_Shl32, 14093 binop( Iop_And32, 14094 binop( Iop_And32, 14095 mkexpr( extreme_true ), 14096 mkexpr( zero_true ) ), 14097 mkU32( 0x1 ) ), 14098 mkU8( 4 ) ) ); 14099 14100 assign( dcm2, binop( Iop_Shl32, 14101 binop( Iop_And32, 14102 binop( Iop_Or32, 14103 binop( Iop_And32, 14104 mkexpr( extreme_true ), 14105 mkexpr( normal_true ) ), 14106 mkexpr( subnormal_true ) ), 14107 mkU32( 0x1 ) ), 14108 mkU8( 3 ) ) ); 14109 14110 assign( dcm3, binop( Iop_Shl32, 14111 binop( Iop_And32, 14112 binop( Iop_And32, 14113 binop( Iop_And32, 14114 unop( Iop_Not32, 14115 mkexpr( extreme_true ) ), 14116 mkexpr( normal_true ) ), 14117 unop( Iop_1Sto32, 14118 binop( Iop_CmpEQ32, 14119 mkexpr( lmd ), 14120 mkU32( 0 ) ) ) ), 14121 mkU32( 0x1 ) ), 14122 mkU8( 2 ) ) ); 14123 14124 assign( dcm4, binop( Iop_Shl32, 14125 binop( Iop_And32, 14126 binop( Iop_And32, 14127 binop( Iop_And32, 14128 unop( Iop_Not32, 14129 mkexpr( extreme_true ) ), 14130 mkexpr( normal_true ) ), 14131 unop( Iop_1Sto32, 14132 binop( Iop_CmpNE32, 14133 mkexpr( lmd ), 14134 mkU32( 0 ) ) ) ), 14135 mkU32( 0x1 ) ), 14136 mkU8( 1 ) ) ); 14137 14138 assign( dcm5, binop( Iop_And32, 14139 binop( Iop_Or32, 14140 mkexpr( SNaN_true), 14141 binop( Iop_Or32, 14142 mkexpr( QNaN_true), 14143 mkexpr( infinity_true) ) ), 14144 mkU32( 0x1 ) ) ); 14145 } 14146 14147 /* create DCM field */ 14148 assign( DCM_calc, 14149 binop( Iop_Or32, 14150 mkexpr( dcm0 ), 14151 binop( Iop_Or32, 14152 mkexpr( dcm1 ), 14153 binop( Iop_Or32, 14154 mkexpr( dcm2 ), 14155 binop( Iop_Or32, 14156 mkexpr( dcm3 ), 14157 binop( Iop_Or32, 14158 mkexpr( dcm4 ), 14159 mkexpr( dcm5 ) ) ) ) ) ) ); 14160 14161 /* Get the sign of the DFP number, ignore sign for QNaN */ 14162 assign( sign, 14163 unop( Iop_1Uto32, 14164 binop( Iop_CmpEQ32, 14165 binop( Iop_Shr32, 14166 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 14167 mkU8( 63 - 32 ) ), 14168 mkU32( 1 ) ) ) ); 14169 14170 /* This instruction generates a four bit field to be stored in the 14171 * condition code register. The condition code register consists of 7 14172 * fields. The field to be written to is specified by the BF (AKA crfD) 14173 * field. 14174 * 14175 * The field layout is as follows: 14176 * 14177 * Field Meaning 14178 * 0000 Operand positive with no match 14179 * 0100 Operand positive with at least one match 14180 * 0001 Operand negative with no match 14181 * 0101 Operand negative with at least one match 14182 */ 14183 assign( field, binop( Iop_Or32, 14184 binop( Iop_Shl32, 14185 mkexpr( sign ), 14186 mkU8( 3 ) ), 14187 binop( Iop_Shl32, 14188 unop( Iop_1Uto32, 14189 binop( Iop_CmpNE32, 14190 binop( Iop_And32, 14191 mkU32( DCM ), 14192 mkexpr( DCM_calc ) ), 14193 mkU32( 0 ) ) ), 14194 mkU8( 1 ) ) ) ); 14195 14196 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 14197 putFPCC( mkexpr( field ) ); 14198 return True; 14199 } 14200 14201 static Bool dis_dfp_bcd(UInt theInstr) { 14202 UInt opc2 = ifieldOPClo10( theInstr ); 14203 ULong sp = IFIELD(theInstr, 19, 2); 14204 ULong s = IFIELD(theInstr, 20, 1); 14205 UChar frT_addr = ifieldRegDS( theInstr ); 14206 UChar frB_addr = ifieldRegB( theInstr ); 14207 IRTemp frB = newTemp( Ity_D64 ); 14208 IRTemp frBI64 = newTemp( Ity_I64 ); 14209 IRTemp result = newTemp( Ity_I64 ); 14210 IRTemp resultD64 = newTemp( Ity_D64 ); 14211 IRTemp bcd64 = newTemp( Ity_I64 ); 14212 IRTemp bcd_u = newTemp( Ity_I32 ); 14213 IRTemp bcd_l = newTemp( Ity_I32 ); 14214 IRTemp dbcd_u = newTemp( Ity_I32 ); 14215 IRTemp dbcd_l = newTemp( Ity_I32 ); 14216 IRTemp lmd = newTemp( Ity_I32 ); 14217 14218 assign( frB, getDReg( frB_addr ) ); 14219 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 14220 14221 switch ( opc2 ) { 14222 case 0x142: // ddedpd DFP Decode DPD to BCD 14223 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 14224 14225 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 14226 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 14227 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 14228 14229 if ( ( sp == 0 ) || ( sp == 1 ) ) { 14230 /* Unsigned BCD string */ 14231 Get_lmd( &lmd, 14232 binop( Iop_Shr32, 14233 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14234 mkU8( 31 - 5 ) ) ); // G-field[0:4] 14235 14236 assign( result, 14237 binop( Iop_32HLto64, 14238 binop( Iop_Or32, 14239 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 14240 mkexpr( bcd_u ) ), 14241 mkexpr( bcd_l ) ) ); 14242 14243 } else { 14244 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 14245 * the positive and negative values are encoded in the least 14246 * significant bits. 14247 */ 14248 IRTemp sign = newTemp( Ity_I32 ); 14249 14250 if (sp == 2) { 14251 /* Positive sign = 0xC, negative sign = 0xD */ 14252 14253 assign( sign, 14254 binop( Iop_Or32, 14255 binop( Iop_Shr32, 14256 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14257 mkU8( 31 ) ), 14258 mkU32( 0xC ) ) ); 14259 14260 } else if ( sp == 3 ) { 14261 /* Positive sign = 0xF, negative sign = 0xD */ 14262 IRTemp tmp32 = newTemp( Ity_I32 ); 14263 14264 /* Complement sign bit then OR into bit position 1 */ 14265 assign( tmp32, 14266 binop( Iop_Xor32, 14267 binop( Iop_Shr32, 14268 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14269 mkU8( 30 ) ), 14270 mkU32( 0x2 ) ) ); 14271 14272 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 14273 14274 } else { 14275 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 14276 } 14277 14278 /* Put sign in bottom 4 bits, move most significant 4-bits from 14279 * bcd_l to bcd_u. 14280 */ 14281 assign( result, 14282 binop( Iop_32HLto64, 14283 binop( Iop_Or32, 14284 binop( Iop_Shr32, 14285 mkexpr( bcd_l ), 14286 mkU8( 28 ) ), 14287 binop( Iop_Shl32, 14288 mkexpr( bcd_u ), 14289 mkU8( 4 ) ) ), 14290 binop( Iop_Or32, 14291 mkexpr( sign ), 14292 binop( Iop_Shl32, 14293 mkexpr( bcd_l ), 14294 mkU8( 4 ) ) ) ) ); 14295 } 14296 14297 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 14298 break; 14299 14300 case 0x342: // denbcd DFP Encode BCD to DPD 14301 { 14302 IRTemp valid_mask = newTemp( Ity_I32 ); 14303 IRTemp invalid_mask = newTemp( Ity_I32 ); 14304 IRTemp without_lmd = newTemp( Ity_I64 ); 14305 IRTemp tmp64 = newTemp( Ity_I64 ); 14306 IRTemp dbcd64 = newTemp( Ity_I64 ); 14307 IRTemp left_exp = newTemp( Ity_I32 ); 14308 IRTemp g0_4 = newTemp( Ity_I32 ); 14309 14310 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 14311 14312 if ( s == 0 ) { 14313 /* Unsigned BCD string */ 14314 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 14315 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 14316 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 14317 14318 assign( lmd, 14319 binop( Iop_Shr32, 14320 binop( Iop_And32, 14321 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14322 mkU32( 0xF0000000 ) ), 14323 mkU8( 28 ) ) ); 14324 14325 assign( invalid_mask, 14326 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14327 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 14328 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14329 14330 assign( without_lmd, 14331 unop( Iop_ReinterpD64asI64, 14332 binop( Iop_InsertExpD64, 14333 mkU64( DFP_LONG_BIAS ), 14334 unop( Iop_ReinterpI64asD64, 14335 binop( Iop_32HLto64, 14336 mkexpr( dbcd_u ), 14337 mkexpr( dbcd_l ) ) ) ) ) ); 14338 assign( left_exp, 14339 binop( Iop_Shr32, 14340 binop( Iop_And32, 14341 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 14342 mkU32( 0x60000000 ) ), 14343 mkU8( 29 ) ) ); 14344 14345 assign( g0_4, 14346 binop( Iop_Shl32, 14347 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 14348 mkU8( 26 ) ) ); 14349 14350 assign( tmp64, 14351 binop( Iop_32HLto64, 14352 binop( Iop_Or32, 14353 binop( Iop_And32, 14354 unop( Iop_64HIto32, 14355 mkexpr( without_lmd ) ), 14356 mkU32( 0x83FFFFFF ) ), 14357 mkexpr( g0_4 ) ), 14358 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 14359 14360 } else if ( s == 1 ) { 14361 IRTemp sign = newTemp( Ity_I32 ); 14362 IRTemp sign_bit = newTemp( Ity_I32 ); 14363 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 14364 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 14365 IRTemp tmp = newTemp( Ity_I64 ); 14366 14367 /* Signed BCD string, least significant 4 bits are sign bits 14368 * positive sign = 0xC, negative sign = 0xD 14369 */ 14370 assign( tmp, unop( Iop_BCDtoDPB, 14371 binop( Iop_32HLto64, 14372 binop( Iop_Shr32, 14373 unop( Iop_64HIto32, 14374 mkexpr( frBI64 ) ), 14375 mkU8( 4 ) ), 14376 binop( Iop_Or32, 14377 binop( Iop_Shr32, 14378 unop( Iop_64to32, 14379 mkexpr( frBI64 ) ), 14380 mkU8( 4 ) ), 14381 binop( Iop_Shl32, 14382 unop( Iop_64HIto32, 14383 mkexpr( frBI64 ) ), 14384 mkU8( 28 ) ) ) ) ) ); 14385 14386 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 14387 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 14388 14389 /* Get the sign of the BCD string. */ 14390 assign( sign, 14391 binop( Iop_And32, 14392 unop( Iop_64to32, mkexpr( frBI64 ) ), 14393 mkU32( 0xF ) ) ); 14394 14395 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 14396 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 14397 assign( sign_bit, 14398 Generate_sign_bit( mkexpr( pos_sign_mask ), 14399 mkexpr( neg_sign_mask ) ) ); 14400 14401 /* Check for invalid sign and BCD digit. Don't check the bottom 14402 * four bits of bcd_l as that is the sign value. 14403 */ 14404 assign( invalid_mask, 14405 Generate_inv_mask( 14406 bcd_digit_inval( unop( Iop_64HIto32, 14407 mkexpr( frBI64 ) ), 14408 binop( Iop_Shr32, 14409 unop( Iop_64to32, 14410 mkexpr( frBI64 ) ), 14411 mkU8( 4 ) ) ), 14412 mkexpr( pos_sign_mask ), 14413 mkexpr( neg_sign_mask ) ) ); 14414 14415 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14416 14417 /* Generate the result assuming the sign value was valid. */ 14418 assign( tmp64, 14419 unop( Iop_ReinterpD64asI64, 14420 binop( Iop_InsertExpD64, 14421 mkU64( DFP_LONG_BIAS ), 14422 unop( Iop_ReinterpI64asD64, 14423 binop( Iop_32HLto64, 14424 binop( Iop_Or32, 14425 mkexpr( dbcd_u ), 14426 mkexpr( sign_bit ) ), 14427 mkexpr( dbcd_l ) ) ) ) ) ); 14428 } 14429 14430 /* Generate the value to store depending on the validity of the 14431 * sign value and the validity of the BCD digits. 14432 */ 14433 assign( resultD64, 14434 unop( Iop_ReinterpI64asD64, 14435 binop( Iop_32HLto64, 14436 binop( Iop_Or32, 14437 binop( Iop_And32, 14438 mkexpr( valid_mask ), 14439 unop( Iop_64HIto32, 14440 mkexpr( tmp64 ) ) ), 14441 binop( Iop_And32, 14442 mkU32( 0x7C000000 ), 14443 mkexpr( invalid_mask ) ) ), 14444 binop( Iop_Or32, 14445 binop( Iop_And32, 14446 mkexpr( valid_mask ), 14447 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 14448 binop( Iop_And32, 14449 mkU32( 0x0 ), 14450 mkexpr( invalid_mask ) ) ) ) ) ); 14451 putDReg( frT_addr, mkexpr( resultD64 ) ); 14452 } 14453 break; 14454 default: 14455 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 14456 return False; 14457 } 14458 return True; 14459 } 14460 14461 static Bool dis_dfp_bcdq( UInt theInstr ) 14462 { 14463 UInt opc2 = ifieldOPClo10( theInstr ); 14464 ULong sp = IFIELD(theInstr, 19, 2); 14465 ULong s = IFIELD(theInstr, 20, 1); 14466 IRTemp frB_hi = newTemp( Ity_D64 ); 14467 IRTemp frB_lo = newTemp( Ity_D64 ); 14468 IRTemp frBI64_hi = newTemp( Ity_I64 ); 14469 IRTemp frBI64_lo = newTemp( Ity_I64 ); 14470 UChar frT_addr = ifieldRegDS( theInstr ); 14471 UChar frB_addr = ifieldRegB( theInstr ); 14472 14473 IRTemp lmd = newTemp( Ity_I32 ); 14474 IRTemp result_hi = newTemp( Ity_I64 ); 14475 IRTemp result_lo = newTemp( Ity_I64 ); 14476 14477 assign( frB_hi, getDReg( frB_addr ) ); 14478 assign( frB_lo, getDReg( frB_addr + 1 ) ); 14479 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 14480 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 14481 14482 switch ( opc2 ) { 14483 case 0x142: // ddedpdq DFP Decode DPD to BCD 14484 { 14485 IRTemp low_60_u = newTemp( Ity_I32 ); 14486 IRTemp low_60_l = newTemp( Ity_I32 ); 14487 IRTemp mid_60_u = newTemp( Ity_I32 ); 14488 IRTemp mid_60_l = newTemp( Ity_I32 ); 14489 IRTemp top_12_l = newTemp( Ity_I32 ); 14490 14491 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 14492 14493 /* Note, instruction only stores the lower 32 BCD digits in 14494 * the result 14495 */ 14496 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 14497 mkexpr( frBI64_lo ), 14498 &top_12_l, 14499 &mid_60_u, 14500 &mid_60_l, 14501 &low_60_u, 14502 &low_60_l ); 14503 14504 if ( ( sp == 0 ) || ( sp == 1 ) ) { 14505 /* Unsigned BCD string */ 14506 assign( result_hi, 14507 binop( Iop_32HLto64, 14508 binop( Iop_Or32, 14509 binop( Iop_Shl32, 14510 mkexpr( top_12_l ), 14511 mkU8( 24 ) ), 14512 binop( Iop_Shr32, 14513 mkexpr( mid_60_u ), 14514 mkU8( 4 ) ) ), 14515 binop( Iop_Or32, 14516 binop( Iop_Shl32, 14517 mkexpr( mid_60_u ), 14518 mkU8( 28 ) ), 14519 binop( Iop_Shr32, 14520 mkexpr( mid_60_l ), 14521 mkU8( 4 ) ) ) ) ); 14522 14523 assign( result_lo, 14524 binop( Iop_32HLto64, 14525 binop( Iop_Or32, 14526 binop( Iop_Shl32, 14527 mkexpr( mid_60_l ), 14528 mkU8( 28 ) ), 14529 mkexpr( low_60_u ) ), 14530 mkexpr( low_60_l ) ) ); 14531 14532 } else { 14533 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 14534 * the positive and negative values are encoded in the least 14535 * significant bits. 14536 */ 14537 IRTemp sign = newTemp( Ity_I32 ); 14538 14539 if ( sp == 2 ) { 14540 /* Positive sign = 0xC, negative sign = 0xD */ 14541 assign( sign, 14542 binop( Iop_Or32, 14543 binop( Iop_Shr32, 14544 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14545 mkU8( 31 ) ), 14546 mkU32( 0xC ) ) ); 14547 14548 } else if ( sp == 3 ) { 14549 IRTemp tmp32 = newTemp( Ity_I32 ); 14550 14551 /* Positive sign = 0xF, negative sign = 0xD. 14552 * Need to complement sign bit then OR into bit position 1. 14553 */ 14554 assign( tmp32, 14555 binop( Iop_Xor32, 14556 binop( Iop_Shr32, 14557 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14558 mkU8( 30 ) ), 14559 mkU32( 0x2 ) ) ); 14560 14561 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 14562 14563 } else { 14564 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 14565 } 14566 14567 assign( result_hi, 14568 binop( Iop_32HLto64, 14569 binop( Iop_Or32, 14570 binop( Iop_Shl32, 14571 mkexpr( top_12_l ), 14572 mkU8( 28 ) ), 14573 mkexpr( mid_60_u ) ), 14574 mkexpr( mid_60_l ) ) ); 14575 14576 assign( result_lo, 14577 binop( Iop_32HLto64, 14578 binop( Iop_Or32, 14579 binop( Iop_Shl32, 14580 mkexpr( low_60_u ), 14581 mkU8( 4 ) ), 14582 binop( Iop_Shr32, 14583 mkexpr( low_60_l ), 14584 mkU8( 28 ) ) ), 14585 binop( Iop_Or32, 14586 binop( Iop_Shl32, 14587 mkexpr( low_60_l ), 14588 mkU8( 4 ) ), 14589 mkexpr( sign ) ) ) ); 14590 } 14591 14592 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 14593 putDReg( frT_addr + 1, 14594 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 14595 } 14596 break; 14597 case 0x342: // denbcdq DFP Encode BCD to DPD 14598 { 14599 IRTemp valid_mask = newTemp( Ity_I32 ); 14600 IRTemp invalid_mask = newTemp( Ity_I32 ); 14601 IRTemp result128 = newTemp( Ity_D128 ); 14602 IRTemp dfp_significand = newTemp( Ity_D128 ); 14603 IRTemp tmp_hi = newTemp( Ity_I64 ); 14604 IRTemp tmp_lo = newTemp( Ity_I64 ); 14605 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 14606 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 14607 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 14608 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 14609 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 14610 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 14611 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 14612 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 14613 IRTemp sign_bit = newTemp( Ity_I32 ); 14614 IRTemp tmptop10 = newTemp( Ity_I64 ); 14615 IRTemp tmpmid50 = newTemp( Ity_I64 ); 14616 IRTemp tmplow50 = newTemp( Ity_I64 ); 14617 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 14618 14619 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 14620 14621 if ( s == 0 ) { 14622 /* Unsigned BCD string */ 14623 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 14624 14625 assign( bcd_top_8, 14626 binop( Iop_32HLto64, 14627 mkU32( 0 ), 14628 binop( Iop_And32, 14629 binop( Iop_Shr32, 14630 unop( Iop_64HIto32, 14631 mkexpr( frBI64_hi ) ), 14632 mkU8( 24 ) ), 14633 mkU32( 0xFF ) ) ) ); 14634 assign( bcd_mid_60, 14635 binop( Iop_32HLto64, 14636 binop( Iop_Or32, 14637 binop( Iop_Shr32, 14638 unop( Iop_64to32, 14639 mkexpr( frBI64_hi ) ), 14640 mkU8( 28 ) ), 14641 binop( Iop_Shl32, 14642 unop( Iop_64HIto32, 14643 mkexpr( frBI64_hi ) ), 14644 mkU8( 4 ) ) ), 14645 binop( Iop_Or32, 14646 binop( Iop_Shl32, 14647 unop( Iop_64to32, 14648 mkexpr( frBI64_hi ) ), 14649 mkU8( 4 ) ), 14650 binop( Iop_Shr32, 14651 unop( Iop_64HIto32, 14652 mkexpr( frBI64_lo ) ), 14653 mkU8( 28 ) ) ) ) ); 14654 14655 /* Note, the various helper functions ignores top 4-bits */ 14656 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 14657 14658 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 14659 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 14660 14661 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 14662 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 14663 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 14664 14665 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 14666 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 14667 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 14668 14669 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 14670 * value is not part of the final result. Only the right most 14671 * BCD digits are stored. 14672 */ 14673 assign( lmd, mkU32( 0 ) ); 14674 14675 assign( invalid_mask, 14676 binop( Iop_Or32, 14677 bcd_digit_inval( mkU32( 0 ), 14678 unop( Iop_64to32, 14679 mkexpr( bcd_top_8 ) ) ), 14680 binop( Iop_Or32, 14681 bcd_digit_inval( unop( Iop_64HIto32, 14682 mkexpr( bcd_mid_60 ) ), 14683 unop( Iop_64to32, 14684 mkexpr( bcd_mid_60 ) ) ), 14685 bcd_digit_inval( unop( Iop_64HIto32, 14686 mkexpr( bcd_low_60 ) ), 14687 unop( Iop_64to32, 14688 mkexpr( bcd_low_60 ) ) 14689 ) ) ) ); 14690 14691 } else if ( s == 1 ) { 14692 IRTemp sign = newTemp( Ity_I32 ); 14693 IRTemp zero = newTemp( Ity_I32 ); 14694 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 14695 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 14696 14697 /* The sign of the BCD string is stored in lower 4 bits */ 14698 assign( sign, 14699 binop( Iop_And32, 14700 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 14701 mkU32( 0xF ) ) ); 14702 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 14703 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 14704 assign( sign_bit, 14705 Generate_sign_bit( mkexpr( pos_sign_mask ), 14706 mkexpr( neg_sign_mask ) ) ); 14707 14708 /* Generate the value assuminig the sign and BCD digits are vaild */ 14709 assign( bcd_top_8, 14710 binop( Iop_32HLto64, 14711 mkU32( 0x0 ), 14712 binop( Iop_Shr32, 14713 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 14714 mkU8( 28 ) ) ) ); 14715 14716 /* The various helper routines ignore the upper 4-bits */ 14717 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 14718 14719 /* Remove bottom four sign bits */ 14720 assign( bcd_low_60, 14721 binop( Iop_32HLto64, 14722 binop( Iop_Shr32, 14723 unop( Iop_64HIto32, 14724 mkexpr( frBI64_lo ) ), 14725 mkU8( 4 ) ), 14726 binop( Iop_Or32, 14727 binop( Iop_Shl32, 14728 unop( Iop_64HIto32, 14729 mkexpr( frBI64_lo ) ), 14730 mkU8( 28 ) ), 14731 binop( Iop_Shr32, 14732 unop( Iop_64to32, 14733 mkexpr( frBI64_lo ) ), 14734 mkU8( 4 ) ) ) ) ); 14735 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 14736 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 14737 14738 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 14739 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 14740 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 14741 14742 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 14743 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 14744 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 14745 14746 /* The entire BCD string fits in lower 110-bits. The LMD value 14747 * is not stored in the final result for the DFP Long instruction. 14748 */ 14749 assign( lmd, mkU32( 0 ) ); 14750 14751 /* Check for invalid sign and invalid BCD digit. Don't check the 14752 * bottom four bits of frBI64_lo as that is the sign value. 14753 */ 14754 assign( zero, mkU32( 0 ) ); 14755 assign( inval_bcd_digit_mask, 14756 binop( Iop_Or32, 14757 bcd_digit_inval( mkexpr( zero ), 14758 unop( Iop_64to32, 14759 mkexpr( bcd_top_8 ) ) ), 14760 binop( Iop_Or32, 14761 bcd_digit_inval( unop( Iop_64HIto32, 14762 mkexpr( bcd_mid_60 ) ), 14763 unop( Iop_64to32, 14764 mkexpr( bcd_mid_60 ) ) ), 14765 bcd_digit_inval( unop( Iop_64HIto32, 14766 mkexpr( frBI64_lo ) ), 14767 binop( Iop_Shr32, 14768 unop( Iop_64to32, 14769 mkexpr( frBI64_lo ) ), 14770 mkU8( 4 ) ) ) ) ) ); 14771 assign( invalid_mask, 14772 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 14773 mkexpr( pos_sign_mask ), 14774 mkexpr( neg_sign_mask ) ) ); 14775 14776 } 14777 14778 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 14779 14780 /* Calculate the value of the result assuming sign and BCD digits 14781 * are all valid. 14782 */ 14783 assign( dfp_significand, 14784 binop( Iop_D64HLtoD128, 14785 unop( Iop_ReinterpI64asD64, 14786 binop( Iop_32HLto64, 14787 binop( Iop_Or32, 14788 mkexpr( sign_bit ), 14789 mkexpr( dbcd_top_l ) ), 14790 binop( Iop_Or32, 14791 binop( Iop_Shl32, 14792 mkexpr( dbcd_mid_u ), 14793 mkU8( 18 ) ), 14794 binop( Iop_Shr32, 14795 mkexpr( dbcd_mid_l ), 14796 mkU8( 14 ) ) ) ) ), 14797 unop( Iop_ReinterpI64asD64, 14798 binop( Iop_32HLto64, 14799 binop( Iop_Or32, 14800 mkexpr( dbcd_low_u ), 14801 binop( Iop_Shl32, 14802 mkexpr( dbcd_mid_l ), 14803 mkU8( 18 ) ) ), 14804 mkexpr( dbcd_low_l ) ) ) ) ); 14805 14806 /* Break the result back down to 32-bit chunks and replace chunks. 14807 * If there was an invalid BCD digit or invalid sign value, replace 14808 * the calculated result with the invalid bit string. 14809 */ 14810 assign( result128, 14811 binop( Iop_InsertExpD128, 14812 mkU64( DFP_EXTND_BIAS ), 14813 mkexpr( dfp_significand ) ) ); 14814 14815 assign( tmp_hi, 14816 unop( Iop_ReinterpD64asI64, 14817 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 14818 14819 assign( tmp_lo, 14820 unop( Iop_ReinterpD64asI64, 14821 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 14822 14823 assign( result_hi, 14824 binop( Iop_32HLto64, 14825 binop( Iop_Or32, 14826 binop( Iop_And32, 14827 mkexpr( valid_mask ), 14828 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 14829 binop( Iop_And32, 14830 mkU32( 0x7C000000 ), 14831 mkexpr( invalid_mask ) ) ), 14832 binop( Iop_Or32, 14833 binop( Iop_And32, 14834 mkexpr( valid_mask ), 14835 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 14836 binop( Iop_And32, 14837 mkU32( 0x0 ), 14838 mkexpr( invalid_mask ) ) ) ) ); 14839 14840 assign( result_lo, 14841 binop( Iop_32HLto64, 14842 binop( Iop_Or32, 14843 binop( Iop_And32, 14844 mkexpr( valid_mask ), 14845 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 14846 binop( Iop_And32, 14847 mkU32( 0x0 ), 14848 mkexpr( invalid_mask ) ) ), 14849 binop( Iop_Or32, 14850 binop( Iop_And32, 14851 mkexpr( valid_mask ), 14852 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 14853 binop( Iop_And32, 14854 mkU32( 0x0 ), 14855 mkexpr( invalid_mask ) ) ) ) ); 14856 14857 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 14858 putDReg( frT_addr + 1, 14859 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 14860 14861 } 14862 break; 14863 default: 14864 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 14865 break; 14866 } 14867 return True; 14868 } 14869 14870 static Bool dis_dfp_significant_digits( UInt theInstr ) 14871 { 14872 UInt opc1 = ifieldOPC( theInstr ); 14873 UInt opc2 = ifieldOPClo10(theInstr); 14874 UChar frA_addr = ifieldRegA( theInstr ); 14875 UChar frB_addr = ifieldRegB( theInstr ); 14876 IRTemp frA = newTemp( Ity_D64 ); 14877 IRTemp B_sig = newTemp( Ity_I8 ); 14878 IRTemp K = newTemp( Ity_I8 ); 14879 IRTemp lmd_B = newTemp( Ity_I32 ); 14880 IRTemp field = newTemp( Ity_I32 ); 14881 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 14882 IRTemp Unordered_true = newTemp( Ity_I32 ); 14883 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 14884 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 14885 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 14886 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 14887 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 14888 IRTemp cc = newTemp( Ity_I32 ); 14889 UChar UIM = toUChar( IFIELD( theInstr, 16, 6 ) ); 14890 IRTemp BCD_valid = newTemp( Ity_I32 ); 14891 14892 if (opc2 == 0x2A2) { // dtstsf DFP Test Significance 14893 // dtstsfq DFP Test Significance Quad 14894 /* Get the reference singificance stored in frA */ 14895 assign( frA, getDReg( frA_addr ) ); 14896 14897 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 14898 * supported in 32-bit mode. 14899 */ 14900 assign( K, unop( Iop_32to8, 14901 binop( Iop_And32, 14902 unop( Iop_64to32, 14903 unop( Iop_ReinterpD64asI64, 14904 mkexpr( frA ) ) ), 14905 mkU32( 0x3F ) ) ) ); 14906 14907 } else if (opc2 == 0x2A3) { // dtstsfi DFP Test Significance Immediate 14908 // dtstsfiq DFP Test Significance Quad Immediate 14909 /* get the significane from the immediate field */ 14910 assign( K, mkU8( UIM) ); 14911 14912 } else { 14913 vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n"); 14914 return False; 14915 } 14916 14917 switch ( opc1 ) { 14918 case 0x3b: // dtstsf DFP Test Significance 14919 // dtstsfi DFP Test Significance Immediate 14920 { 14921 IRTemp frB = newTemp( Ity_D64 ); 14922 IRTemp frBI64 = newTemp( Ity_I64 ); 14923 IRTemp B_bcd_u = newTemp( Ity_I32 ); 14924 IRTemp B_bcd_l = newTemp( Ity_I32 ); 14925 IRTemp tmp64 = newTemp( Ity_I64 ); 14926 14927 if (opc2 == 0x2A2) { 14928 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 14929 } else { 14930 DIP( "dtstsfi %u,%u,r%u\n", crfD, UIM, frB_addr ); 14931 } 14932 14933 assign( frB, getDReg( frB_addr ) ); 14934 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 14935 14936 /* Get the BCD string for the value stored in a series of I32 values. 14937 * Count the number of leading zeros. Subtract the number of leading 14938 * zeros from 16 (maximum number of significant digits in DFP 14939 * Long). 14940 */ 14941 Get_lmd( &lmd_B, 14942 binop( Iop_Shr32, 14943 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 14944 mkU8( 31 - 5 ) ) ); // G-field[0:4] 14945 14946 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 14947 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 14948 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 14949 14950 assign( B_sig, 14951 binop( Iop_Sub8, 14952 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 14953 Count_leading_zeros_60( mkexpr( lmd_B ), 14954 mkexpr( B_bcd_u ), 14955 mkexpr( B_bcd_l ) ) ) ); 14956 14957 assign( BCD_valid, 14958 binop( Iop_Or32, 14959 bcd_digit_inval( mkexpr( B_bcd_u), mkexpr( B_bcd_l) ), 14960 bcd_digit_inval( mkexpr( lmd_B), mkU32( 0 ) ) ) ); 14961 14962 /* Set unordered to True if the number is NaN, Inf or an invalid 14963 * digit. 14964 */ 14965 assign( Unordered_true, 14966 binop( Iop_Or32, 14967 Check_unordered( mkexpr( frBI64 ) ), 14968 mkexpr( BCD_valid) ) ); 14969 } 14970 break; 14971 case 0x3F: // dtstsfq DFP Test Significance 14972 // dtstsfqi DFP Test Significance Immediate 14973 { 14974 IRTemp frB_hi = newTemp( Ity_D64 ); 14975 IRTemp frB_lo = newTemp( Ity_D64 ); 14976 IRTemp frBI64_hi = newTemp( Ity_I64 ); 14977 IRTemp frBI64_lo = newTemp( Ity_I64 ); 14978 IRTemp B_low_60_u = newTemp( Ity_I32 ); 14979 IRTemp B_low_60_l = newTemp( Ity_I32 ); 14980 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 14981 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 14982 IRTemp B_top_12_l = newTemp( Ity_I32 ); 14983 14984 if (opc2 == 0x2A2) { 14985 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 14986 } else { 14987 DIP( "dtstsfiq %u,%u,r%u\n", crfD, UIM, frB_addr ); 14988 } 14989 14990 assign( frB_hi, getDReg( frB_addr ) ); 14991 assign( frB_lo, getDReg( frB_addr + 1 ) ); 14992 14993 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 14994 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 14995 14996 /* Get the BCD string for the value stored in a series of I32 values. 14997 * Count the number of leading zeros. Subtract the number of leading 14998 * zeros from 32 (maximum number of significant digits in DFP 14999 * extended). 15000 */ 15001 Get_lmd( &lmd_B, 15002 binop( Iop_Shr32, 15003 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 15004 mkU8( 31 - 5 ) ) ); // G-field[0:4] 15005 15006 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 15007 mkexpr( frBI64_lo ), 15008 &B_top_12_l, 15009 &B_mid_60_u, 15010 &B_mid_60_l, 15011 &B_low_60_u, 15012 &B_low_60_l ); 15013 15014 assign( BCD_valid, 15015 binop( Iop_Or32, 15016 binop( Iop_Or32, 15017 bcd_digit_inval( mkexpr( lmd_B ), 15018 mkexpr( B_top_12_l ) ), 15019 bcd_digit_inval( mkexpr( B_mid_60_u ), 15020 mkexpr( B_mid_60_l ) ) ), 15021 bcd_digit_inval( mkexpr( B_low_60_u ), 15022 mkexpr( B_low_60_l ) ) ) ); 15023 15024 assign( B_sig, 15025 binop( Iop_Sub8, 15026 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 15027 Count_leading_zeros_128( mkexpr( lmd_B ), 15028 mkexpr( B_top_12_l ), 15029 mkexpr( B_mid_60_u ), 15030 mkexpr( B_mid_60_l ), 15031 mkexpr( B_low_60_u ), 15032 mkexpr( B_low_60_l ) ) ) ); 15033 15034 /* Set unordered to True if the number is NaN, Inf or an invalid 15035 * digit. 15036 */ 15037 assign( Unordered_true, 15038 binop( Iop_Or32, 15039 Check_unordered( mkexpr( frBI64_hi ) ), 15040 mkexpr( BCD_valid) ) ); 15041 } 15042 break; 15043 } 15044 15045 /* Compare (16 - cnt[0]) against K and set the condition code field 15046 * accordingly. 15047 * 15048 * The field layout is as follows: 15049 * 15050 * bit[3:0] Description 15051 * 3 K != 0 and K < Number of significant digits if FRB 15052 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 15053 * 1 K != 0 and K = Number of significant digits if FRB 15054 * 0 K ? Number of significant digits if FRB 15055 */ 15056 assign( Eq_true_mask, 15057 unop( Iop_1Sto32, 15058 binop( Iop_CmpEQ32, 15059 unop( Iop_8Uto32, mkexpr( K ) ), 15060 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 15061 assign( Lt_true_mask, 15062 unop( Iop_1Sto32, 15063 binop( Iop_CmpLT32U, 15064 unop( Iop_8Uto32, mkexpr( K ) ), 15065 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 15066 assign( Gt_true_mask, 15067 unop( Iop_1Sto32, 15068 binop( Iop_CmpLT32U, 15069 unop( Iop_8Uto32, mkexpr( B_sig ) ), 15070 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 15071 15072 assign( KisZero_true_mask, 15073 unop( Iop_1Sto32, 15074 binop( Iop_CmpEQ32, 15075 unop( Iop_8Uto32, mkexpr( K ) ), 15076 mkU32( 0 ) ) ) ); 15077 assign( KisZero_false_mask, 15078 unop( Iop_1Sto32, 15079 binop( Iop_CmpNE32, 15080 unop( Iop_8Uto32, mkexpr( K ) ), 15081 mkU32( 0 ) ) ) ); 15082 15083 assign( field, 15084 binop( Iop_Or32, 15085 binop( Iop_And32, 15086 mkexpr( KisZero_false_mask ), 15087 binop( Iop_Or32, 15088 binop( Iop_And32, 15089 mkexpr( Lt_true_mask ), 15090 mkU32( 0x8 ) ), 15091 binop( Iop_Or32, 15092 binop( Iop_And32, 15093 mkexpr( Gt_true_mask ), 15094 mkU32( 0x4 ) ), 15095 binop( Iop_And32, 15096 mkexpr( Eq_true_mask ), 15097 mkU32( 0x2 ) ) ) ) ), 15098 binop( Iop_And32, 15099 mkexpr( KisZero_true_mask ), 15100 mkU32( 0x4 ) ) ) ); 15101 15102 assign( cc, binop( Iop_Or32, 15103 binop( Iop_And32, 15104 mkexpr( Unordered_true ), 15105 mkU32( 0x1 ) ), 15106 binop( Iop_And32, 15107 unop( Iop_Not32, mkexpr( Unordered_true ) ), 15108 mkexpr( field ) ) ) ); 15109 15110 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD ); 15111 putFPCC( mkexpr( cc ) ); 15112 15113 return True; 15114 } 15115 /*------------------------------------------------------------*/ 15116 /*--- AltiVec Instruction Translation ---*/ 15117 /*------------------------------------------------------------*/ 15118 15119 /* 15120 Altivec Cache Control Instructions (Data Streams) 15121 */ 15122 static Bool dis_av_datastream ( UInt theInstr ) 15123 { 15124 /* X-Form */ 15125 UChar opc1 = ifieldOPC(theInstr); 15126 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 15127 UChar flag_A = flag_T; 15128 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 15129 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 15130 UChar rA_addr = ifieldRegA(theInstr); 15131 UChar rB_addr = ifieldRegB(theInstr); 15132 UInt opc2 = ifieldOPClo10(theInstr); 15133 UChar b0 = ifieldBIT0(theInstr); 15134 15135 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 15136 vex_printf("dis_av_datastream(ppc)(instr)\n"); 15137 return False; 15138 } 15139 15140 switch (opc2) { 15141 case 0x156: // dst (Data Stream Touch, AV p115) 15142 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 15143 rA_addr, rB_addr, STRM); 15144 break; 15145 15146 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 15147 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 15148 rA_addr, rB_addr, STRM); 15149 break; 15150 15151 case 0x336: // dss (Data Stream Stop, AV p114) 15152 if (rA_addr != 0 || rB_addr != 0) { 15153 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 15154 return False; 15155 } 15156 if (flag_A == 0) { 15157 DIP("dss %d\n", STRM); 15158 } else { 15159 DIP("dssall\n"); 15160 } 15161 break; 15162 15163 default: 15164 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 15165 return False; 15166 } 15167 return True; 15168 } 15169 15170 /* 15171 AltiVec Processor Control Instructions 15172 */ 15173 static Bool dis_av_procctl ( UInt theInstr ) 15174 { 15175 /* VX-Form */ 15176 UChar opc1 = ifieldOPC(theInstr); 15177 UChar vD_addr = ifieldRegDS(theInstr); 15178 UChar vA_addr = ifieldRegA(theInstr); 15179 UChar vB_addr = ifieldRegB(theInstr); 15180 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15181 15182 if (opc1 != 0x4) { 15183 vex_printf("dis_av_procctl(ppc)(instr)\n"); 15184 return False; 15185 } 15186 15187 switch (opc2) { 15188 case 0x604: // mfvscr (Move from VSCR, AV p129) 15189 if (vA_addr != 0 || vB_addr != 0) { 15190 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 15191 return False; 15192 } 15193 DIP("mfvscr v%d\n", vD_addr); 15194 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 15195 break; 15196 15197 case 0x644: { // mtvscr (Move to VSCR, AV p130) 15198 IRTemp vB = newTemp(Ity_V128); 15199 if (vD_addr != 0 || vA_addr != 0) { 15200 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 15201 return False; 15202 } 15203 DIP("mtvscr v%d\n", vB_addr); 15204 assign( vB, getVReg(vB_addr)); 15205 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 15206 break; 15207 } 15208 default: 15209 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 15210 return False; 15211 } 15212 return True; 15213 } 15214 15215 /* 15216 Vector Extend Sign Instructions 15217 */ 15218 static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 ) 15219 { 15220 /* VX-Form, sort of, the A register field is used to select the specific 15221 * sign extension instruction or count leading/trailing zero LSB 15222 * instruction. 15223 */ 15224 15225 UChar opc1 = ifieldOPC( theInstr ); 15226 UChar rT_addr = ifieldRegDS (theInstr ); 15227 UChar rA_addr = ifieldRegA( theInstr ); 15228 UChar vB_addr = ifieldRegB( theInstr ); 15229 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15230 15231 IRTemp vB = newTemp( Ity_V128 ); 15232 IRTemp vT = newTemp( Ity_V128 ); 15233 15234 assign( vB, getVReg ( vB_addr ) ); 15235 15236 if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) ) { 15237 vex_printf("dis_av_extend_sign(ppc)(instr)\n"); 15238 return False; 15239 } 15240 15241 switch ( rA_addr ) { 15242 case 0: 15243 case 1: 15244 { 15245 UInt i; 15246 IRTemp count[17]; 15247 IRTemp bit_zero[16]; 15248 IRTemp byte_mask[17]; 15249 15250 /* These instructions store the result in the general purpose 15251 * register in the rT_addr field. 15252 */ 15253 15254 byte_mask[0] = newTemp( Ity_I32 ); 15255 count[0] = newTemp( Ity_I32 ); 15256 assign( count[0], mkU32( 0 ) ); 15257 assign( byte_mask[0], mkU32( 0x1 ) ); 15258 15259 if ( rA_addr == 0 ) { 15260 // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte) 15261 DIP("vclzlsbb %d,v%d\n", rT_addr, vB_addr); 15262 15263 } else { 15264 // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte) 15265 DIP("vctzlsbb %d,v%d\n", rT_addr, vB_addr); 15266 } 15267 15268 for( i = 0; i < 16; i++ ) { 15269 byte_mask[i+1] = newTemp( Ity_I32 ); 15270 count[i+1] = newTemp( Ity_I32 ); 15271 bit_zero[i] = newTemp( Ity_I1 ); 15272 15273 /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of 15274 * byte. When the first 1 bit is found it causes the byte_mask 15275 * to change from 0x1 to 0x0. Thus the AND of the lsb and byte_mask 15276 * will be zero which will be equal to the zero byte_mask causing 15277 * the value of bit_zero[i] to be equal to 0x1 for all remaining bits. 15278 */ 15279 15280 if ( rA_addr == 0 ) 15281 /* leading zero bit in byte count, 15282 work bytes from left to right 15283 */ 15284 assign( bit_zero[i], 15285 binop( Iop_CmpEQ32, 15286 binop( Iop_And32, 15287 unop( Iop_V128to32, 15288 binop( Iop_ShrV128, 15289 mkexpr( vB ), 15290 mkU8( ( 15 - i) * 8 ) ) ), 15291 mkexpr( byte_mask[i] ) ), 15292 mkexpr( byte_mask[i] ) ) ); 15293 15294 else if ( rA_addr == 1 ) 15295 /* trailing zero bit in byte count, 15296 * work bytes from right to left 15297 */ 15298 assign( bit_zero[i], 15299 binop( Iop_CmpEQ32, 15300 binop( Iop_And32, 15301 unop( Iop_V128to32, 15302 binop( Iop_ShrV128, 15303 mkexpr( vB ), 15304 mkU8( i * 8 ) ) ), 15305 mkexpr( byte_mask[i] ) ), 15306 mkexpr( byte_mask[i] ) ) ); 15307 15308 /* Increment count as long as bit_zero = 0 */ 15309 assign( count[i+1], binop( Iop_Add32, 15310 mkexpr( count[i] ), 15311 unop( Iop_1Uto32, 15312 unop( Iop_Not1, 15313 mkexpr( bit_zero[i] ) ) ) ) ); 15314 15315 /* If comparison fails to find a zero bit, set the byte_mask to zero 15316 * for all future comparisons so there will be no more matches. 15317 */ 15318 assign( byte_mask[i+1], 15319 binop( Iop_And32, 15320 unop( Iop_1Uto32, 15321 unop( Iop_Not1, 15322 mkexpr( bit_zero[i] ) ) ), 15323 mkexpr( byte_mask[i] ) ) ); 15324 } 15325 putIReg( rT_addr, unop( Iop_32Uto64, mkexpr( count[16] ) ) ); 15326 return True; 15327 } 15328 15329 case 6: // vnegw, Vector Negate Word 15330 DIP("vnegw v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15331 15332 /* multiply each word by -1 */ 15333 assign( vT, binop( Iop_Mul32x4, mkexpr( vB ), mkV128( 0xFFFF ) ) ); 15334 break; 15335 15336 case 7: // vnegd, Vector Negate Doubleword 15337 DIP("vnegd v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15338 15339 /* multiply each word by -1 */ 15340 assign( vT, binop( Iop_64HLtoV128, 15341 binop( Iop_Mul64, 15342 unop( Iop_V128HIto64, 15343 mkexpr( vB ) ), 15344 mkU64( 0xFFFFFFFFFFFFFFFF ) ), 15345 binop( Iop_Mul64, 15346 unop( Iop_V128to64, 15347 mkexpr( vB ) ), 15348 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ); 15349 break; 15350 15351 case 8: // vprtybw, Vector Parity Byte Word 15352 case 9: // vprtybd, Vector Parity Byte Doubleword 15353 case 10: // vprtybq, Vector Parity Byte Quadword 15354 { 15355 UInt i; 15356 IRTemp bit_in_byte[16]; 15357 IRTemp word_parity[4]; 15358 15359 for( i = 0; i < 16; i++ ) { 15360 bit_in_byte[i] = newTemp( Ity_I32 ); 15361 assign( bit_in_byte[i], 15362 binop( Iop_And32, 15363 unop( Iop_V128to32, 15364 binop( Iop_ShrV128, 15365 mkexpr( vB ), 15366 mkU8( ( 15 - i ) * 8 ) ) ), 15367 mkU32( 0x1 ) ) ); 15368 } 15369 15370 for( i = 0; i < 4; i++ ) { 15371 word_parity[i] = newTemp(Ity_I32); 15372 assign( word_parity[i], 15373 mkXOr4_32( bit_in_byte[0 + i * 4], 15374 bit_in_byte[1 + i * 4], 15375 bit_in_byte[2 + i * 4], 15376 bit_in_byte[3 + i * 4] ) ); 15377 } 15378 15379 if ( rA_addr == 8 ) { 15380 DIP("vprtybw v%d,v%d", rT_addr, vB_addr); 15381 15382 assign( vT, mkV128from32( word_parity[0], word_parity[1], 15383 word_parity[2], word_parity[3] ) ); 15384 15385 } else if ( rA_addr == 9 ) { 15386 DIP("vprtybd v%d,v%d", rT_addr, vB_addr); 15387 15388 assign( vT, 15389 binop( Iop_64HLtoV128, 15390 binop( Iop_32HLto64, 15391 mkU32( 0 ), 15392 binop( Iop_Xor32, 15393 mkexpr( word_parity[0] ), 15394 mkexpr( word_parity[1] ) ) ), 15395 binop( Iop_32HLto64, 15396 mkU32( 0 ), 15397 binop( Iop_Xor32, 15398 mkexpr( word_parity[2] ), 15399 mkexpr( word_parity[3] ) ) ) ) ); 15400 15401 } else if ( rA_addr == 10 ) { 15402 DIP("vprtybq v%d,v%d", rT_addr, vB_addr); 15403 15404 assign( vT, 15405 binop( Iop_64HLtoV128, 15406 mkU64( 0 ), 15407 unop( Iop_32Uto64, 15408 mkXOr4_32( word_parity[0], 15409 word_parity[1], 15410 word_parity[2], 15411 word_parity[3] ) ) ) ); 15412 } 15413 } 15414 break; 15415 15416 case 16: // vextsb2w, Vector Extend Sign Byte to Word 15417 DIP("vextsb2w v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15418 15419 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to 15420 * two byte sign extended result. Then do a two byte to four byte sign 15421 * extended multiply. Note contents of upper three bytes in word are 15422 * "over written". So just take source and multiply by 1. 15423 */ 15424 assign( vT, binop( Iop_MullEven16Sx8, 15425 binop( Iop_64HLtoV128, 15426 mkU64( 0x0000000100000001 ), 15427 mkU64( 0x0000000100000001 ) ), 15428 binop( Iop_MullEven8Sx16, 15429 mkexpr( vB ), 15430 binop( Iop_64HLtoV128, 15431 mkU64( 0x0001000100010001 ), 15432 mkU64( 0x0001000100010001 ) ) ) ) ); 15433 break; 15434 15435 case 17: // vextsh2w, Vector Extend Sign Halfword to Word 15436 DIP("vextsh2w v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15437 15438 /* Iop_MullEven16Sx8 does a signed widening multiply of four byte 15439 * 8 bytes. Note contents of upper two bytes in word are 15440 * "over written". So just take source and multiply by 1. 15441 */ 15442 assign( vT, binop( Iop_MullEven16Sx8, 15443 binop( Iop_64HLtoV128, 15444 mkU64( 0x0000000100000001 ), 15445 mkU64( 0x0000000100000001 ) ), 15446 mkexpr( vB ) ) ); 15447 15448 break; 15449 15450 case 24: // vextsb2d, Vector Extend Sign Byte to Doubleword 15451 DIP("vextsb2d v%d,%d,v%d", rT_addr, rA_addr, vB_addr); 15452 15453 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to 15454 * two byte sign extended result. Then do a two byte to four byte sign 15455 * extended multiply. Then do four byte to eight byte multiply. 15456 */ 15457 assign( vT, binop( Iop_MullEven32Sx4, 15458 binop( Iop_64HLtoV128, 15459 mkU64( 0x0000000000000001 ), 15460 mkU64( 0x0000000000000001 ) ), 15461 binop( Iop_MullEven16Sx8, 15462 binop( Iop_64HLtoV128, 15463 mkU64( 0x0000000100000001 ),