Home | History | Annotate | Download | only in priv
      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 ),