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 ),
   15464                                       mkU64( 0x0000000100000001 ) ),
   15465                               binop( Iop_MullEven8Sx16,
   15466                                      binop( Iop_64HLtoV128,
   15467                                             mkU64( 0x0001000100010001 ),
   15468                                             mkU64( 0x0001000100010001 ) ),
   15469                                     mkexpr( vB ) ) ) ) );
   15470       break;
   15471 
   15472    case 25: // vextsh2d,  Vector Extend Sign Halfword to Doubleword
   15473       DIP("vextsh2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15474 
   15475       assign( vT, binop( Iop_MullEven32Sx4,
   15476                          binop( Iop_64HLtoV128,
   15477                                 mkU64( 0x0000000000000001 ),
   15478                                 mkU64( 0x0000000000000001 ) ),
   15479                         binop( Iop_MullEven16Sx8,
   15480                                binop( Iop_64HLtoV128,
   15481                                       mkU64( 0x0000000100000001 ),
   15482                                       mkU64( 0x0000000100000001 ) ),
   15483                                mkexpr( vB ) ) ) );
   15484       break;
   15485 
   15486    case 26: // vextsw2d,  Vector Extend Sign Word to Doubleword
   15487       DIP("vextsw2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15488 
   15489       assign( vT, binop( Iop_MullEven32Sx4,
   15490                          binop( Iop_64HLtoV128,
   15491                                 mkU64( 0x0000000000000001 ),
   15492                                 mkU64( 0x0000000000000001 ) ),
   15493                         mkexpr( vB ) ) );
   15494       break;
   15495 
   15496    case 28: // vctzb,  Vector Count Trailing Zeros Byte
   15497       {
   15498          DIP("vctzb  v%d,v%d", rT_addr, vB_addr);
   15499 
   15500          /* This instruction is only available in the ISA 3.0 */
   15501          if ( !mode64 || !allow_isa_3_0 ) {
   15502             vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
   15503             return False;
   15504          }
   15505          assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) );
   15506       }
   15507       break;
   15508 
   15509    case 29: // vctzh,  Vector Count Trailing Zeros Halfword
   15510       {
   15511          DIP("vctzh  v%d,v%d", rT_addr, vB_addr);
   15512 
   15513          /* This instruction is only available in the ISA 3.0 */
   15514          if ( !mode64 || !allow_isa_3_0 ) {
   15515             vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
   15516             return False;
   15517          }
   15518          assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) );
   15519       }
   15520       break;
   15521 
   15522    case 30: // vctzw,  Vector Count Trailing Zeros Word
   15523       {
   15524          DIP("vctzw  v%d,v%d", rT_addr, vB_addr);
   15525 
   15526          /* This instruction is only available in the ISA 3.0 */
   15527          if ( !mode64 || !allow_isa_3_0 ) {
   15528             vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
   15529             return False;
   15530          }
   15531          assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) );
   15532       }
   15533       break;
   15534 
   15535    case 31: // vctzd,  Vector Count Trailing Zeros Double word
   15536       {
   15537          DIP("vctzd  v%d,v%d", rT_addr, vB_addr);
   15538 
   15539          /* This instruction is only available in the ISA 3.0 */
   15540          if ( !mode64 || !allow_isa_3_0 ) {
   15541             vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
   15542             return False;
   15543          }
   15544          assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) );
   15545       }
   15546       break;
   15547 
   15548    default:
   15549       vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
   15550       return False;
   15551    }
   15552 
   15553    putVReg( rT_addr, mkexpr( vT ) );
   15554    return True;
   15555 }
   15556 
   15557 /*
   15558 Vector Rotate Instructions
   15559 */
   15560 static Bool dis_av_rotate ( UInt theInstr )
   15561 {
   15562    /* VX-Form */
   15563 
   15564    UChar opc1    = ifieldOPC( theInstr );
   15565    UChar vT_addr = ifieldRegDS( theInstr );
   15566    UChar vA_addr = ifieldRegA( theInstr );
   15567    UChar vB_addr = ifieldRegB( theInstr );
   15568    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   15569 
   15570    IRTemp vA    = newTemp( Ity_V128 );
   15571    IRTemp vB    = newTemp( Ity_V128 );
   15572    IRTemp src3  = newTemp( Ity_V128 );
   15573    IRTemp vT    = newTemp( Ity_V128 );
   15574    IRTemp field_mask = newTemp( Ity_V128 );
   15575    IRTemp mask128 = newTemp( Ity_V128 );
   15576    IRTemp vA_word[4];
   15577    IRTemp left_bits[4];
   15578    IRTemp right_bits[4];
   15579    IRTemp shift[4];
   15580    IRTemp mask[4];
   15581    IRTemp tmp128[4];
   15582    UInt i;
   15583    UInt num_words;
   15584    UInt word_size;
   15585    unsigned long long word_mask;
   15586 
   15587    if ( opc1 != 0x4 ) {
   15588       vex_printf("dis_av_rotate(ppc)(instr)\n");
   15589       return False;
   15590    }
   15591 
   15592    assign( vA, getVReg( vA_addr ) );
   15593    assign( vB, getVReg( vB_addr ) );
   15594 
   15595    switch (opc2) {
   15596    case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
   15597    case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
   15598       num_words = 4;
   15599       word_size = 32;
   15600       assign( field_mask, binop( Iop_64HLtoV128,
   15601                                  mkU64( 0 ),
   15602                                  mkU64( 0x1F ) ) );
   15603       word_mask = 0xFFFFFFFF;
   15604       break;
   15605 
   15606    case 0x0C5: // vrldmi,  Vector Rotate Left Doubleword then Mask Insert
   15607    case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
   15608       num_words = 2;
   15609       word_size = 64;
   15610       assign( field_mask, binop( Iop_64HLtoV128,
   15611                                  mkU64( 0 ),
   15612                                  mkU64( 0x3F ) ) );
   15613       word_mask = 0xFFFFFFFFFFFFFFFFULL;
   15614       break;
   15615    default:
   15616       vex_printf("dis_av_rotate(ppc)(opc2)\n");
   15617       return False;
   15618    }
   15619 
   15620    for( i = 0; i < num_words; i++ ) {
   15621       left_bits[i]  = newTemp( Ity_I8 );
   15622       right_bits[i] = newTemp( Ity_I8 );
   15623       shift[i] = newTemp( Ity_I8 );
   15624       mask[i]  = newTemp( Ity_V128 );
   15625       tmp128[i] = newTemp( Ity_V128 );
   15626       vA_word[i] = newTemp( Ity_V128 );
   15627 
   15628       assign( shift[i],
   15629               unop( Iop_64to8,
   15630                     unop( Iop_V128to64,
   15631                           binop( Iop_AndV128,
   15632                                  binop( Iop_ShrV128,
   15633                                         mkexpr( vB ),
   15634                                         mkU8( (num_words - 1 - i )
   15635                                               * word_size ) ),
   15636                                  mkexpr( field_mask ) ) ) ) );
   15637 
   15638       /* left_bits = 63 - mb.  Tells us how many bits to the left
   15639        * of mb to clear. Note for a word left_bits = 32+mb, for a double
   15640        * word left_bits = mb
   15641        */
   15642       assign( left_bits[i],
   15643               unop( Iop_64to8,
   15644                     binop( Iop_Add64,
   15645                            mkU64( 64 - word_size ),
   15646                            unop( Iop_V128to64,
   15647                                  binop( Iop_AndV128,
   15648                                         binop( Iop_ShrV128,
   15649                                                mkexpr( vB ),
   15650                                                mkU8( ( num_words - 1 - i )
   15651                                                      * word_size + 16 ) ),
   15652                                         mkexpr( field_mask ) ) ) ) ) );
   15653       /* right_bits = 63 - me.  Tells us how many bits to the right
   15654        * of me to clear. Note for a word, left_bits = me+32, for a double
   15655        * word left_bits = me
   15656        */
   15657       assign( right_bits[i],
   15658               unop( Iop_64to8,
   15659                     binop( Iop_Sub64,
   15660                            mkU64( word_size - 1 ),
   15661                            unop( Iop_V128to64,
   15662                                  binop( Iop_AndV128,
   15663                                         binop( Iop_ShrV128,
   15664                                                mkexpr( vB ),
   15665                                                mkU8( ( num_words - 1 - i )
   15666                                                      * word_size + 8 ) ),
   15667                                         mkexpr( field_mask ) ) ) ) ) );
   15668 
   15669       /* create mask for 32-bit word or 64-bit word */
   15670       assign( mask[i],
   15671               binop( Iop_64HLtoV128,
   15672                      mkU64( 0 ),
   15673                      binop( Iop_Shl64,
   15674                             binop( Iop_Shr64,
   15675                                    binop( Iop_Shr64,
   15676                                           binop( Iop_Shl64,
   15677                                                  mkU64( 0xFFFFFFFFFFFFFFFF ),
   15678                                                  mkexpr( left_bits[i] ) ),
   15679                                           mkexpr( left_bits[i] ) ),
   15680                                    mkexpr( right_bits[i] ) ),
   15681                             mkexpr( right_bits[i] ) ) ) );
   15682 
   15683       /* Need to rotate vA using a left and right shift of vA OR'd together
   15684        * then ANDed with the mask.
   15685        */
   15686       assign( vA_word[i], binop( Iop_AndV128,
   15687                                  mkexpr( vA ),
   15688                                  binop( Iop_ShlV128,
   15689                                         binop( Iop_64HLtoV128,
   15690                                                mkU64( 0 ),
   15691                                                mkU64( word_mask ) ),
   15692                                         mkU8( ( num_words - 1 - i )
   15693                                               * word_size ) ) ) );
   15694       assign( tmp128[i],
   15695               binop( Iop_AndV128,
   15696                      binop( Iop_ShlV128,
   15697                             mkexpr( mask[i] ),
   15698                             mkU8( ( num_words - 1 - i) * word_size ) ),
   15699                      binop( Iop_OrV128,
   15700                             binop( Iop_ShlV128,
   15701                                    mkexpr( vA_word[i] ),
   15702                                    mkexpr( shift[i] ) ),
   15703                             binop( Iop_ShrV128,
   15704                                    mkexpr( vA_word[i] ),
   15705                                    unop( Iop_32to8,
   15706                                          binop(Iop_Sub32,
   15707                                                mkU32( word_size ),
   15708                                                unop( Iop_8Uto32,
   15709                                                      mkexpr( shift[i] ) ) )
   15710                                          ) ) ) ) );
   15711    }
   15712 
   15713    switch (opc2) {
   15714    case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
   15715       DIP("vrlwmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
   15716 
   15717       assign( src3, getVReg( vT_addr ) );
   15718       assign( mask128, unop( Iop_NotV128,
   15719                              mkOr4_V128_expr( binop( Iop_ShlV128,
   15720                                                      mkexpr( mask[0] ),
   15721                                                      mkU8( 96 ) ),
   15722                                               binop( Iop_ShlV128,
   15723                                                      mkexpr( mask[1] ),
   15724                                                      mkU8( 64 ) ),
   15725                                               binop( Iop_ShlV128,
   15726                                                      mkexpr( mask[2] ),
   15727                                                      mkU8( 32 ) ),
   15728                                               mkexpr( mask[3] ) ) ) );
   15729       assign( vT, binop( Iop_OrV128,
   15730                          binop( Iop_AndV128,
   15731                                 mkexpr( src3 ),
   15732                                 mkexpr( mask128 ) ),
   15733                          mkOr4_V128( tmp128[0], tmp128[1],
   15734                                      tmp128[2], tmp128[3] ) ) );
   15735       break;
   15736 
   15737    case 0xC5: // vrldmi,  Vector Rotate Left Double word then Mask Insert
   15738       DIP("vrldmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
   15739 
   15740       assign( src3, getVReg( vT_addr ) );
   15741       assign( mask128, unop( Iop_NotV128,
   15742                              binop( Iop_OrV128,
   15743                                     binop( Iop_ShlV128,
   15744                                            mkexpr( mask[0] ),
   15745                                            mkU8( 64 ) ),
   15746                                     mkexpr( mask[1] ) ) ) );
   15747 
   15748       assign( vT, binop( Iop_OrV128,
   15749                          binop( Iop_AndV128,
   15750                                 mkexpr( src3 ),
   15751                                 mkexpr( mask128 ) ),
   15752                          binop( Iop_OrV128,
   15753                                 mkexpr( tmp128[0] ),
   15754                                 mkexpr( tmp128[1] ) ) ) );
   15755       break;
   15756 
   15757    case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
   15758       DIP("vrlwnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
   15759       assign( vT, mkOr4_V128( tmp128[0], tmp128[1], tmp128[2], tmp128[3] ) );
   15760       break;
   15761 
   15762    case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
   15763       DIP("vrldnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
   15764       assign( vT, binop( Iop_OrV128,
   15765                          mkexpr( tmp128[0] ),
   15766                          mkexpr( tmp128[1] ) ) );
   15767       break;
   15768    }
   15769 
   15770    putVReg( vT_addr, mkexpr( vT ) );
   15771    return True;
   15772 }
   15773 
   15774 /*
   15775   AltiVec Vector Extract Element Instructions
   15776 */
   15777 static Bool dis_av_extract_element ( UInt theInstr )
   15778 {
   15779    /* VX-Form,
   15780     * sorta destination and first source are GPR not vector registers
   15781     */
   15782 
   15783    UChar opc1    = ifieldOPC( theInstr );
   15784    UChar rT_addr = ifieldRegDS( theInstr );
   15785    UChar rA_addr = ifieldRegA( theInstr );
   15786    UChar vB_addr = ifieldRegB( theInstr );
   15787    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   15788 
   15789    IRTemp vB = newTemp( Ity_V128 );
   15790    IRTemp rA = newTemp( Ity_I64 );
   15791    IRTemp rT = newTemp( Ity_I64 );
   15792 
   15793    assign( vB, getVReg( vB_addr ) );
   15794    assign( rA, getIReg( rA_addr ) );
   15795 
   15796    if ( opc1 != 0x4 ) {
   15797       vex_printf("dis_av_extract_element(ppc)(instr)\n");
   15798       return False;
   15799    }
   15800 
   15801    switch ( opc2 ) {
   15802    case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed
   15803       DIP("vextublx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15804 
   15805       assign( rT, extract_field_from_vector( vB,
   15806                                              binop( Iop_Sub64,
   15807                                                     mkU64( 15 ),
   15808                                                     mkexpr( rA ) ),
   15809                                              0xFF ) );
   15810 
   15811       break;
   15812 
   15813    case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed
   15814       DIP("vextuhlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15815 
   15816       assign( rT, extract_field_from_vector( vB,
   15817                                              binop( Iop_Sub64,
   15818                                                     mkU64( 14 ),
   15819                                                     mkexpr( rA ) ),
   15820                                              0xFFFF ) );
   15821       break;
   15822 
   15823    case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed
   15824       DIP("vextuwlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15825 
   15826       assign( rT, extract_field_from_vector( vB,
   15827                                              binop( Iop_Sub64,
   15828                                                     mkU64( 12 ),
   15829                                                     mkexpr( rA ) ),
   15830                                              0xFFFFFFFF ) );
   15831       break;
   15832 
   15833    case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed
   15834       DIP("vextubrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15835 
   15836       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFF ) );
   15837       break;
   15838 
   15839    case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed
   15840       DIP("vextuhrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15841 
   15842       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFF ) );
   15843       break;
   15844 
   15845    case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed
   15846       DIP("vextuwrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
   15847 
   15848       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFFFFFF ) );
   15849       break;
   15850 
   15851    default:
   15852       vex_printf("dis_av_extract_element(ppc)(opc2)\n");
   15853       return False;
   15854    }
   15855    putIReg( rT_addr, mkexpr( rT ) );
   15856    return True;
   15857 }
   15858 
   15859 /*
   15860  * VSX scalar and vector convert instructions
   15861  */
   15862 static Bool
   15863 dis_vx_conv ( UInt theInstr, UInt opc2 )
   15864 {
   15865    /* XX2-Form */
   15866    UChar opc1 = ifieldOPC( theInstr );
   15867    UChar XT = ifieldRegXT( theInstr );
   15868    UChar XB = ifieldRegXB( theInstr );
   15869    IRTemp xB, xB2;
   15870    IRTemp b3, b2, b1, b0;
   15871    xB = xB2 = IRTemp_INVALID;
   15872 
   15873    if (opc1 != 0x3C) {
   15874       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   15875       return False;
   15876    }
   15877 
   15878    /* Create and assign temps only as needed for the given instruction. */
   15879    switch (opc2) {
   15880       // scalar double-precision floating point argument
   15881       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
   15882          xB = newTemp(Ity_F64);
   15883          assign( xB,
   15884                  unop( Iop_ReinterpI64asF64,
   15885                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   15886          break;
   15887       // vector double-precision floating point arguments
   15888       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   15889 
   15890          xB = newTemp(Ity_F64);
   15891          xB2 = newTemp(Ity_F64);
   15892          assign( xB,
   15893                  unop( Iop_ReinterpI64asF64,
   15894                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   15895          assign( xB2,
   15896                  unop( Iop_ReinterpI64asF64,
   15897                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   15898          break;
   15899       // vector single precision or [un]signed integer word arguments
   15900       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   15901       case 0x1f0: case 0x1d0:
   15902          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   15903          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   15904          break;
   15905          // vector [un]signed integer doubleword argument
   15906       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   15907          xB = newTemp(Ity_I64);
   15908          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   15909          xB2 = newTemp(Ity_I64);
   15910          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   15911          break;
   15912       // scalar [un]signed integer doubleword argument
   15913       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
   15914          xB = newTemp(Ity_I64);
   15915          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   15916          break;
   15917       // scalar single precision argument
   15918       case 0x292: // xscvspdp
   15919          xB  = newTemp(Ity_I32);
   15920 
   15921          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
   15922                                                   unop( Iop_V128HIto64,
   15923                                                         getVSReg( XB ) ) ) ) );
   15924          break;
   15925       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
   15926          xB = newTemp(Ity_I32);
   15927          assign( xB,
   15928                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   15929          break;
   15930 
   15931       /* Certain instructions have their complete implementation in the main switch statement
   15932        * that follows this one; thus we have a "do nothing" case for those instructions here.
   15933        */
   15934       case 0x170: case 0x150:
   15935          break; // do nothing
   15936 
   15937       default:
   15938          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   15939          return False;
   15940    }
   15941 
   15942 
   15943    switch (opc2) {
   15944       case 0x2B0:
   15945          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   15946          //             to Signed Integer Doubleword format with Saturate)
   15947          DIP("xscvdpsxds v%u,v%u\n", XT, XB);
   15948          putVSReg( XT,
   15949                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   15950                                                  mkU32( Irrm_ZERO ),
   15951                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   15952          break;
   15953       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   15954                   //             Convert to Signed Integer Word format with Saturate)
   15955          DIP("xscvdpsxws v%u,v%u\n", XT, XB);
   15956          putVSReg( XT,
   15957                    binop( Iop_64HLtoV128,
   15958                           unop( Iop_32Sto64,
   15959                                 binop( Iop_F64toI32S,
   15960                                        mkU32( Irrm_ZERO ),
   15961                                        mkexpr( xB ) ) ),
   15962                                        mkU64( 0ULL ) ) );
   15963          break;
   15964       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   15965                   //             to Unsigned Integer Doubleword format with Saturate)
   15966          DIP("xscvdpuxds v%u,v%u\n", XT, XB);
   15967          putVSReg( XT,
   15968                    binop( Iop_64HLtoV128,
   15969                           binop( Iop_F64toI64U,
   15970                                  mkU32( Irrm_ZERO ),
   15971                                  mkexpr( xB ) ),
   15972                                  mkU64( 0ULL ) ) );
   15973          break;
   15974       case 0x270:
   15975          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
   15976          //             to Single-Precision format)
   15977          DIP("xscvsxdsp v%u,v%u\n", XT, XB);
   15978          putVSReg( XT,
   15979                    binop( Iop_64HLtoV128,
   15980                           unop( Iop_ReinterpF64asI64,
   15981                                 binop( Iop_RoundF64toF32,
   15982                                        get_IR_roundingmode(),
   15983                                        binop( Iop_I64StoF64,
   15984                                               get_IR_roundingmode(),
   15985                                               mkexpr( xB ) ) ) ),
   15986                           mkU64( 0 ) ) );
   15987          break;
   15988       case 0x2F0:
   15989          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   15990          //            Double-Precision format)
   15991          DIP("xscvsxddp v%u,v%u\n", XT, XB);
   15992          putVSReg( XT,
   15993                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   15994                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   15995                                                        mkexpr( xB ) ) ),
   15996                                                        mkU64( 0 ) ) );
   15997          break;
   15998       case 0x250:
   15999          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
   16000          //            Doubleword to Singel-Precision format)
   16001          DIP("xscvuxdsp v%u,v%u\n", XT, XB);
   16002          putVSReg( XT,
   16003                    binop( Iop_64HLtoV128,
   16004                           unop( Iop_ReinterpF64asI64,
   16005                                 binop( Iop_RoundF64toF32,
   16006                                        get_IR_roundingmode(),
   16007                                        binop( Iop_I64UtoF64,
   16008                                               get_IR_roundingmode(),
   16009                                               mkexpr( xB ) ) ) ),
   16010                           mkU64( 0 ) ) );
   16011          break;
   16012       case 0x2D0:
   16013          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   16014          //            Double-Precision format)
   16015          DIP("xscvuxddp v%u,v%u\n", XT, XB);
   16016          putVSReg( XT,
   16017                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   16018                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   16019                                                        mkexpr( xB ) ) ),
   16020                                                        mkU64( 0 ) ) );
   16021          break;
   16022       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   16023                   //             to Signed Integer Word format with Saturate)
   16024       {
   16025          IRTemp hiResult_32 = newTemp(Ity_I32);
   16026          IRTemp loResult_32 = newTemp(Ity_I32);
   16027          IRExpr* rmZero = mkU32(Irrm_ZERO);
   16028 
   16029          DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
   16030          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   16031          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   16032          putVSReg( XT,
   16033                    binop( Iop_64HLtoV128,
   16034                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   16035                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   16036          break;
   16037       }
   16038       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   16039          //  (VSX Vector truncate Single-Precision to integer and
   16040          //   Convert to [Un]signed Integer Word format with Saturate)
   16041       {
   16042          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   16043          IRTemp tempResult = newTemp(Ity_V128);
   16044          IRTemp res0 = newTemp(Ity_I32);
   16045          IRTemp res1 = newTemp(Ity_I32);
   16046          IRTemp res2 = newTemp(Ity_I32);
   16047          IRTemp res3 = newTemp(Ity_I32);
   16048          IRTemp hi64 = newTemp(Ity_I64);
   16049          IRTemp lo64 = newTemp(Ity_I64);
   16050          Bool un_signed = (opc2 == 0x110);
   16051          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   16052 
   16053          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
   16054          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   16055           * then result is set to 0x80000000.  */
   16056          assign(tempResult, unop(op, getVSReg(XB)));
   16057          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   16058          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   16059          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   16060          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   16061          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   16062          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   16063 
   16064          b3_result = IRExpr_ITE(is_NaN(Ity_I32, b3),
   16065                                 // then: result is 0x{8|0}80000000
   16066                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   16067                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   16068                                 mkexpr(res3));
   16069          b2_result = IRExpr_ITE(is_NaN(Ity_I32, b2),
   16070                                 // then: result is 0x{8|0}80000000
   16071                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   16072                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   16073                                 mkexpr(res2));
   16074          b1_result = IRExpr_ITE(is_NaN(Ity_I32, b1),
   16075                                 // then: result is 0x{8|0}80000000
   16076                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   16077                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   16078                                 mkexpr(res1));
   16079          b0_result = IRExpr_ITE(is_NaN(Ity_I32, b0),
   16080                                 // then: result is 0x{8|0}80000000
   16081                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   16082                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   16083                                 mkexpr(res0));
   16084 
   16085          putVSReg( XT,
   16086                    binop( Iop_64HLtoV128,
   16087                           binop( Iop_32HLto64, b3_result, b2_result ),
   16088                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   16089          break;
   16090       }
   16091       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   16092                   //           Convert to Single-Precision format
   16093          DIP("xscvdpsp v%u,v%u\n", XT, XB);
   16094          putVSReg( XT,
   16095                    binop( Iop_64HLtoV128,
   16096                           binop( Iop_32HLto64,
   16097                                  unop( Iop_ReinterpF32asI32,
   16098                                        unop( Iop_TruncF64asF32,
   16099                                              binop( Iop_RoundF64toF32,
   16100                                                     get_IR_roundingmode(),
   16101                                                     mkexpr( xB ) ) ) ),
   16102                                  mkU32( 0 ) ),
   16103                           mkU64( 0ULL ) ) );
   16104          break;
   16105       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
   16106                               vector Single-Precision non-signalling */
   16107          DIP("xscvdpspn v%u,v%u\n", XT, XB);
   16108          putVSReg( XT,
   16109                    binop( Iop_64HLtoV128,
   16110                           binop( Iop_32HLto64,
   16111                                  unop( Iop_ReinterpF32asI32,
   16112                                        unop( Iop_TruncF64asF32,
   16113                                              mkexpr( xB ) ) ),
   16114                                  mkU32( 0 ) ),
   16115                           mkU64( 0ULL ) ) );
   16116          break;
   16117       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   16118                   //             and Convert to Unsigned Integer Word format with Saturate)
   16119          DIP("xscvdpuxws v%u,v%u\n", XT, XB);
   16120          putVSReg( XT,
   16121                    binop( Iop_64HLtoV128,
   16122                           binop( Iop_32HLto64,
   16123                                  mkU32( 0 ),
   16124                                  binop( Iop_F64toI32U,
   16125                                         mkU32( Irrm_ZERO ),
   16126                                         mkexpr( xB ) ) ),
   16127                           mkU64( 0ULL ) ) );
   16128          break;
   16129       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
   16130          DIP("xscvspdp v%u,v%u\n", XT, XB);
   16131          putVSReg( XT,
   16132                    binop( Iop_64HLtoV128,
   16133                           unop( Iop_ReinterpF64asI64,
   16134                                 unop( Iop_F32toF64,
   16135                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   16136                           mkU64( 0ULL ) ) );
   16137          break;
   16138       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
   16139          DIP("xscvspdpn v%u,v%u\n", XT, XB);
   16140          putVSReg( XT,
   16141                    binop( Iop_64HLtoV128,
   16142                           unop( Iop_ReinterpF64asI64,
   16143                                 unop( Iop_F32toF64,
   16144                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   16145                                       mkU64( 0ULL ) ) );
   16146          break;
   16147       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   16148                   //           and Convert to Single-Precision format)
   16149          DIP("xvcvdpsp v%u,v%u\n", XT, XB);
   16150          putVSReg( XT,
   16151                    binop( Iop_64HLtoV128,
   16152                           binop( Iop_32HLto64,
   16153                                  unop( Iop_ReinterpF32asI32,
   16154                                        unop( Iop_TruncF64asF32,
   16155                                              binop( Iop_RoundF64toF32,
   16156                                                     get_IR_roundingmode(),
   16157                                                     mkexpr( xB ) ) ) ),
   16158                                  mkU32( 0 ) ),
   16159                           binop( Iop_32HLto64,
   16160                                  unop( Iop_ReinterpF32asI32,
   16161                                        unop( Iop_TruncF64asF32,
   16162                                              binop( Iop_RoundF64toF32,
   16163                                                     get_IR_roundingmode(),
   16164                                                     mkexpr( xB2 ) ) ) ),
   16165                                  mkU32( 0 ) ) ) );
   16166          break;
   16167       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   16168                   //             and Convert to Unsigned Integer Doubleword format
   16169                   //             with Saturate)
   16170          DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
   16171          putVSReg( XT,
   16172                    binop( Iop_64HLtoV128,
   16173                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   16174                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   16175          break;
   16176       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   16177                   //             Convert to Unsigned Integer Word format with Saturate)
   16178          DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
   16179          putVSReg( XT,
   16180                    binop( Iop_64HLtoV128,
   16181                           binop( Iop_32HLto64,
   16182                                  binop( Iop_F64toI32U,
   16183                                         mkU32( Irrm_ZERO ),
   16184                                         mkexpr( xB ) ),
   16185                                  mkU32( 0 ) ),
   16186                           binop( Iop_32HLto64,
   16187                                  binop( Iop_F64toI32U,
   16188                                         mkU32( Irrm_ZERO ),
   16189                                         mkexpr( xB2 ) ),
   16190                                  mkU32( 0 ) ) ) );
   16191          break;
   16192       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   16193          DIP("xvcvspdp v%u,v%u\n", XT, XB);
   16194          putVSReg( XT,
   16195                    binop( Iop_64HLtoV128,
   16196                           unop( Iop_ReinterpF64asI64,
   16197                                 unop( Iop_F32toF64,
   16198                                       unop( Iop_ReinterpI32asF32,
   16199                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
   16200                           unop( Iop_ReinterpF64asI64,
   16201                                 unop( Iop_F32toF64,
   16202                                       unop( Iop_ReinterpI32asF32,
   16203                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
   16204          break;
   16205       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   16206                   //           Convert to Signed Integer Doubleword format with Saturate)
   16207          DIP("xvcvspsxds v%u,v%u\n", XT, XB);
   16208          putVSReg( XT,
   16209                    binop( Iop_64HLtoV128,
   16210                           binop( Iop_F64toI64S,
   16211                                  mkU32( Irrm_ZERO ),
   16212                                  unop( Iop_F32toF64,
   16213                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   16214                           binop( Iop_F64toI64S,
   16215                                  mkU32( Irrm_ZERO ),
   16216                                  unop( Iop_F32toF64,
   16217                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   16218          break;
   16219       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   16220                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   16221          DIP("xvcvspuxds v%u,v%u\n", XT, XB);
   16222          putVSReg( XT,
   16223                    binop( Iop_64HLtoV128,
   16224                           binop( Iop_F64toI64U,
   16225                                  mkU32( Irrm_ZERO ),
   16226                                  unop( Iop_F32toF64,
   16227                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   16228                           binop( Iop_F64toI64U,
   16229                                  mkU32( Irrm_ZERO ),
   16230                                  unop( Iop_F32toF64,
   16231                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   16232          break;
   16233       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   16234                   //             Convert to Signed Integer Doubleword format with Saturate)
   16235          DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
   16236          putVSReg( XT,
   16237                    binop( Iop_64HLtoV128,
   16238                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   16239                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   16240          break;
   16241       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   16242                   //            to Double-Precision format)
   16243          DIP("xvcvsxddp v%u,v%u\n", XT, XB);
   16244          putVSReg( XT,
   16245                    binop( Iop_64HLtoV128,
   16246                           unop( Iop_ReinterpF64asI64,
   16247                                 binop( Iop_I64StoF64,
   16248                                        get_IR_roundingmode(),
   16249                                        mkexpr( xB ) ) ),
   16250                           unop( Iop_ReinterpF64asI64,
   16251                                 binop( Iop_I64StoF64,
   16252                                        get_IR_roundingmode(),
   16253                                        mkexpr( xB2 ) ) ) ) );
   16254          break;
   16255       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   16256                   //            to Double-Precision format)
   16257          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
   16258          putVSReg( XT,
   16259                    binop( Iop_64HLtoV128,
   16260                           unop( Iop_ReinterpF64asI64,
   16261                                 binop( Iop_I64UtoF64,
   16262                                        get_IR_roundingmode(),
   16263                                        mkexpr( xB ) ) ),
   16264                           unop( Iop_ReinterpF64asI64,
   16265                                 binop( Iop_I64UtoF64,
   16266                                        get_IR_roundingmode(),
   16267                                        mkexpr( xB2 ) ) ) ) );
   16268 
   16269          break;
   16270       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   16271                   //            to Single-Precision format)
   16272          DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
   16273          putVSReg( XT,
   16274                    binop( Iop_64HLtoV128,
   16275                           binop( Iop_32HLto64,
   16276                                  unop( Iop_ReinterpF32asI32,
   16277                                        unop( Iop_TruncF64asF32,
   16278                                              binop( Iop_RoundF64toF32,
   16279                                                     get_IR_roundingmode(),
   16280                                                     binop( Iop_I64StoF64,
   16281                                                            get_IR_roundingmode(),
   16282                                                            mkexpr( xB ) ) ) ) ),
   16283                                  mkU32( 0 ) ),
   16284                           binop( Iop_32HLto64,
   16285                                  unop( Iop_ReinterpF32asI32,
   16286                                        unop( Iop_TruncF64asF32,
   16287                                              binop( Iop_RoundF64toF32,
   16288                                                     get_IR_roundingmode(),
   16289                                                     binop( Iop_I64StoF64,
   16290                                                            get_IR_roundingmode(),
   16291                                                            mkexpr( xB2 ) ) ) ) ),
   16292                                  mkU32( 0 ) ) ) );
   16293          break;
   16294       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   16295                   //            to Single-Precision format)
   16296          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
   16297          putVSReg( XT,
   16298                    binop( Iop_64HLtoV128,
   16299                           binop( Iop_32HLto64,
   16300                                  unop( Iop_ReinterpF32asI32,
   16301                                        unop( Iop_TruncF64asF32,
   16302                                              binop( Iop_RoundF64toF32,
   16303                                                     get_IR_roundingmode(),
   16304                                                     binop( Iop_I64UtoF64,
   16305                                                            get_IR_roundingmode(),
   16306                                                            mkexpr( xB ) ) ) ) ),
   16307                                  mkU32( 0 ) ),
   16308                           binop( Iop_32HLto64,
   16309                                  unop( Iop_ReinterpF32asI32,
   16310                                        unop( Iop_TruncF64asF32,
   16311                                              binop( Iop_RoundF64toF32,
   16312                                                     get_IR_roundingmode(),
   16313                                                     binop( Iop_I64UtoF64,
   16314                                                            get_IR_roundingmode(),
   16315                                                            mkexpr( xB2 ) ) ) ) ),
   16316                                  mkU32( 0 ) ) ) );
   16317          break;
   16318 
   16319       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   16320          DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
   16321          putVSReg( XT,
   16322                    binop( Iop_64HLtoV128,
   16323                           unop( Iop_ReinterpF64asI64,
   16324                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   16325                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   16326                           unop( Iop_ReinterpF64asI64,
   16327                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   16328                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   16329          break;
   16330       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   16331          DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
   16332          putVSReg( XT,
   16333                    binop( Iop_64HLtoV128,
   16334                           unop( Iop_ReinterpF64asI64,
   16335                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   16336                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   16337                           unop( Iop_ReinterpF64asI64,
   16338                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   16339                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   16340          break;
   16341       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   16342          DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
   16343          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   16344          break;
   16345       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   16346          DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
   16347          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   16348          break;
   16349 
   16350       default:
   16351          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   16352          return False;
   16353    }
   16354    return True;
   16355 }
   16356 
   16357 /*
   16358  * VSX vector Double Precision Floating Point Arithmetic Instructions
   16359  */
   16360 static Bool
   16361 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   16362 {
   16363    /* XX3-Form */
   16364    UChar opc1 = ifieldOPC( theInstr );
   16365    UChar XT = ifieldRegXT( theInstr );
   16366    UChar XA = ifieldRegXA( theInstr );
   16367    UChar XB = ifieldRegXB( theInstr );
   16368    IRExpr* rm = get_IR_roundingmode();
   16369    IRTemp frA = newTemp(Ity_F64);
   16370    IRTemp frB = newTemp(Ity_F64);
   16371    IRTemp frA2 = newTemp(Ity_F64);
   16372    IRTemp frB2 = newTemp(Ity_F64);
   16373 
   16374    if (opc1 != 0x3C) {
   16375       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   16376       return False;
   16377    }
   16378 
   16379    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   16380    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   16381    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   16382    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   16383 
   16384    switch (opc2) {
   16385       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   16386       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   16387       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   16388       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   16389       {
   16390          IROp mOp;
   16391          const HChar * oper_name;
   16392          switch (opc2) {
   16393             case 0x1E0:
   16394                mOp = Iop_DivF64;
   16395                oper_name = "div";
   16396                break;
   16397             case 0x1C0:
   16398                mOp = Iop_MulF64;
   16399                oper_name = "mul";
   16400                break;
   16401             case 0x180:
   16402                mOp = Iop_AddF64;
   16403                oper_name = "add";
   16404                break;
   16405             case 0x1A0:
   16406                mOp = Iop_SubF64;
   16407                oper_name = "sub";
   16408                break;
   16409 
   16410             default:
   16411                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   16412          }
   16413          IRTemp hiResult = newTemp(Ity_I64);
   16414          IRTemp loResult = newTemp(Ity_I64);
   16415          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
   16416 
   16417          assign( hiResult,
   16418                  unop( Iop_ReinterpF64asI64,
   16419                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   16420          assign( loResult,
   16421                  unop( Iop_ReinterpF64asI64,
   16422                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   16423          putVSReg( XT,
   16424                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   16425          break;
   16426       }
   16427       case 0x196: // xvsqrtdp
   16428       {
   16429          IRTemp hiResult = newTemp(Ity_I64);
   16430          IRTemp loResult = newTemp(Ity_I64);
   16431          DIP("xvsqrtdp v%d,v%d\n", XT, XB);
   16432 
   16433          assign( hiResult,
   16434                  unop( Iop_ReinterpF64asI64,
   16435                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   16436          assign( loResult,
   16437                  unop( Iop_ReinterpF64asI64,
   16438                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   16439          putVSReg( XT,
   16440                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   16441          break;
   16442       }
   16443       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   16444       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   16445       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   16446       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   16447       {
   16448          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   16449           *    XT == FRC
   16450           *    XA == FRA
   16451           *    XB == FRB
   16452           *
   16453           * and for xvm{add|sub}adp . . .
   16454           *    XT == FRB
   16455           *    XA == FRA
   16456           *    XB == FRC
   16457           */
   16458          Bool negate;
   16459          IROp mOp = Iop_INVALID;
   16460          const HChar * oper_name = NULL;
   16461          Bool mdp = False;
   16462 
   16463          switch (opc2) {
   16464             case 0x184: case 0x1A4:
   16465             case 0x384: case 0x3A4:
   16466                mOp = Iop_MAddF64;
   16467                oper_name = "add";
   16468                mdp = (opc2 & 0x0FF) == 0x0A4;
   16469                break;
   16470 
   16471             case 0x1C4: case 0x1E4:
   16472             case 0x3C4: case 0x3E4:
   16473                mOp = Iop_MSubF64;
   16474                oper_name = "sub";
   16475                mdp = (opc2 & 0x0FF) == 0x0E4;
   16476                break;
   16477 
   16478             default:
   16479                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   16480          }
   16481 
   16482          switch (opc2) {
   16483             case 0x384: case 0x3A4:
   16484             case 0x3C4: case 0x3E4:
   16485                negate = True;
   16486                break;
   16487             default:
   16488                negate = False;
   16489          }
   16490          IRTemp hiResult = newTemp(Ity_I64);
   16491          IRTemp loResult = newTemp(Ity_I64);
   16492          IRTemp frT = newTemp(Ity_F64);
   16493          IRTemp frT2 = newTemp(Ity_F64);
   16494          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   16495              XT, XA, XB);
   16496          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   16497          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   16498 
   16499          assign( hiResult,
   16500                  unop( Iop_ReinterpF64asI64,
   16501                        qop( mOp,
   16502                             rm,
   16503                             mkexpr( frA ),
   16504                             mkexpr( mdp ? frT : frB ),
   16505                             mkexpr( mdp ? frB : frT ) ) ) );
   16506          assign( loResult,
   16507                  unop( Iop_ReinterpF64asI64,
   16508                        qop( mOp,
   16509                             rm,
   16510                             mkexpr( frA2 ),
   16511                             mkexpr( mdp ? frT2 : frB2 ),
   16512                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   16513          putVSReg( XT,
   16514                    binop( Iop_64HLtoV128,
   16515                           mkexpr( negate ? getNegatedResult( hiResult )
   16516                                          : hiResult ),
   16517                           mkexpr( negate ? getNegatedResult( loResult )
   16518                                          : loResult ) ) );
   16519          break;
   16520       }
   16521       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   16522       {
   16523          IRTemp frBHi_I64 = newTemp(Ity_I64);
   16524          IRTemp frBLo_I64 = newTemp(Ity_I64);
   16525          IRTemp flagsHi = newTemp(Ity_I32);
   16526          IRTemp flagsLo = newTemp(Ity_I32);
   16527          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   16528          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   16529          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   16530 
   16531          DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
   16532          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   16533          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   16534          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   16535          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   16536          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   16537           * where fl_flag == 1 on ppc64.
   16538           */
   16539          assign( flagsHi,
   16540                  binop( Iop_Or32,
   16541                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16542                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   16543                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   16544          assign( flagsLo,
   16545                  binop( Iop_Or32,
   16546                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16547                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   16548                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   16549          putGST_field( PPC_GST_CR,
   16550                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   16551                        crfD );
   16552          break;
   16553       }
   16554       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   16555       {
   16556          IRTemp frBHi_I64 = newTemp(Ity_I64);
   16557          IRTemp frBLo_I64 = newTemp(Ity_I64);
   16558          IRTemp frAHi_I64 = newTemp(Ity_I64);
   16559          IRTemp frALo_I64 = newTemp(Ity_I64);
   16560          IRTemp flagsHi = newTemp(Ity_I32);
   16561          IRTemp flagsLo = newTemp(Ity_I32);
   16562          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   16563          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   16564          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   16565 
   16566          DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
   16567          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   16568          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   16569          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   16570          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   16571 
   16572          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   16573          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   16574          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   16575           * where fl_flag == 1 on ppc64.
   16576           */
   16577          assign( flagsHi,
   16578                  binop( Iop_Or32,
   16579                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16580                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   16581                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   16582          assign( flagsLo,
   16583                  binop( Iop_Or32,
   16584                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16585                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   16586                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   16587          putGST_field( PPC_GST_CR,
   16588                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   16589                        crfD );
   16590          break;
   16591       }
   16592 
   16593       default:
   16594          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   16595          return False;
   16596    }
   16597    return True;
   16598 }
   16599 
   16600 /*
   16601  * VSX vector Single Precision Floating Point Arithmetic Instructions
   16602  */
   16603 static Bool
   16604 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   16605 {
   16606    /* XX3-Form */
   16607    UChar opc1 = ifieldOPC( theInstr );
   16608    UChar XT = ifieldRegXT( theInstr );
   16609    UChar XA = ifieldRegXA( theInstr );
   16610    UChar XB = ifieldRegXB( theInstr );
   16611    IRExpr* rm = get_IR_roundingmode();
   16612    IRTemp a3, a2, a1, a0;
   16613    IRTemp b3, b2, b1, b0;
   16614    IRTemp res0 = newTemp(Ity_I32);
   16615    IRTemp res1 = newTemp(Ity_I32);
   16616    IRTemp res2 = newTemp(Ity_I32);
   16617    IRTemp res3 = newTemp(Ity_I32);
   16618 
   16619    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   16620    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   16621 
   16622    if (opc1 != 0x3C) {
   16623       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   16624       return False;
   16625    }
   16626 
   16627    switch (opc2) {
   16628       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   16629          DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
   16630          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
   16631          putVSReg( XT, triop(Iop_Add32Fx4, rm,
   16632                              getVSReg( XA ), getVSReg( XB )) );
   16633          break;
   16634 
   16635       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   16636          DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
   16637          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
   16638          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
   16639                              getVSReg( XA ), getVSReg( XB )) );
   16640          break;
   16641 
   16642       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   16643          DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
   16644          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
   16645          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
   16646                              getVSReg( XA ), getVSReg( XB )) );
   16647          break;
   16648 
   16649       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   16650       {
   16651          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   16652           * So there are two choices:
   16653           *   1. Implement the xvdivsp with a native insn; or
   16654           *   2. Extract the 4 single precision floats from each vector
   16655           *      register inputs and perform fdivs on each pair
   16656           * I will do the latter, due to the general philosophy of
   16657           * reusing existing implementations when practical.
   16658           */
   16659          DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
   16660          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   16661          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   16662 
   16663          assign( res0,
   16664               unop( Iop_ReinterpF32asI32,
   16665                     unop( Iop_TruncF64asF32,
   16666                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   16667          assign( res1,
   16668                  unop( Iop_ReinterpF32asI32,
   16669                        unop( Iop_TruncF64asF32,
   16670                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   16671          assign( res2,
   16672                  unop( Iop_ReinterpF32asI32,
   16673                        unop( Iop_TruncF64asF32,
   16674                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   16675          assign( res3,
   16676                  unop( Iop_ReinterpF32asI32,
   16677                        unop( Iop_TruncF64asF32,
   16678                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   16679 
   16680          putVSReg( XT,
   16681                    binop( Iop_64HLtoV128,
   16682                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   16683                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   16684          break;
   16685       }
   16686       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   16687       {
   16688          DIP("xvsqrtsp v%d,v%d\n", XT, XB);
   16689          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   16690          /* Note: The native xvsqrtsp insruction does not always give the same precision
   16691           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   16692           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   16693           * to the actual instruction.
   16694           */
   16695 
   16696          assign( res0,
   16697                  unop( Iop_ReinterpF32asI32,
   16698                        unop( Iop_TruncF64asF32,
   16699                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   16700          assign( res1,
   16701                  unop( Iop_ReinterpF32asI32,
   16702                        unop( Iop_TruncF64asF32,
   16703                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   16704          assign( res2,
   16705                  unop( Iop_ReinterpF32asI32,
   16706                        unop( Iop_TruncF64asF32,
   16707                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   16708          assign( res3,
   16709                  unop( Iop_ReinterpF32asI32,
   16710                        unop( Iop_TruncF64asF32,
   16711                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   16712 
   16713          putVSReg( XT,
   16714                    binop( Iop_64HLtoV128,
   16715                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   16716                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   16717          break;
   16718       }
   16719 
   16720       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   16721       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   16722       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   16723       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   16724       {
   16725          IRTemp t3, t2, t1, t0;
   16726          Bool msp = False;
   16727          Bool negate;
   16728          const HChar * oper_name = NULL;
   16729          IROp mOp = Iop_INVALID;
   16730          switch (opc2) {
   16731             case 0x104: case 0x124:
   16732             case 0x304: case 0x324:
   16733                msp = (opc2 & 0x0FF) == 0x024;
   16734                mOp = Iop_MAddF64r32;
   16735                oper_name = "madd";
   16736                break;
   16737 
   16738             case 0x144: case 0x164:
   16739             case 0x344: case 0x364:
   16740                msp = (opc2 & 0x0FF) == 0x064;
   16741                mOp = Iop_MSubF64r32;
   16742                oper_name = "sub";
   16743                break;
   16744 
   16745             default:
   16746                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   16747          }
   16748 
   16749          switch (opc2) {
   16750             case 0x304: case 0x324:
   16751             case 0x344: case 0x364:
   16752                negate = True;
   16753                break;
   16754 
   16755             default:
   16756                negate = False;
   16757          }
   16758 
   16759          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
   16760              msp ? "msp" : "asp", XT, XA, XB);
   16761 
   16762          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   16763          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   16764          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   16765          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   16766 
   16767          assign( res0,
   16768                  unop( Iop_ReinterpF32asI32,
   16769                        unop( Iop_TruncF64asF32,
   16770                              qop( mOp,
   16771                                   rm,
   16772                                   mkexpr( a0 ),
   16773                                   mkexpr( msp ? t0 : b0 ),
   16774                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   16775          assign( res1,
   16776                  unop( Iop_ReinterpF32asI32,
   16777                        unop( Iop_TruncF64asF32,
   16778                              qop( mOp,
   16779                                   rm,
   16780                                   mkexpr( a1 ),
   16781                                   mkexpr( msp ? t1 : b1 ),
   16782                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   16783          assign( res2,
   16784                  unop( Iop_ReinterpF32asI32,
   16785                        unop( Iop_TruncF64asF32,
   16786                              qop( mOp,
   16787                                   rm,
   16788                                   mkexpr( a2 ),
   16789                                   mkexpr( msp ? t2 : b2 ),
   16790                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   16791          assign( res3,
   16792                  unop( Iop_ReinterpF32asI32,
   16793                        unop( Iop_TruncF64asF32,
   16794                              qop( mOp,
   16795                                   rm,
   16796                                   mkexpr( a3 ),
   16797                                   mkexpr( msp ? t3 : b3 ),
   16798                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   16799 
   16800          putVSReg( XT,
   16801                    binop( Iop_64HLtoV128,
   16802                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   16803                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   16804                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   16805                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   16806 
   16807          break;
   16808       }
   16809       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   16810       {
   16811          IRTemp flags0 = newTemp(Ity_I32);
   16812          IRTemp flags1 = newTemp(Ity_I32);
   16813          IRTemp flags2 = newTemp(Ity_I32);
   16814          IRTemp flags3 = newTemp(Ity_I32);
   16815          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   16816          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   16817          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   16818          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   16819          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   16820          DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
   16821 
   16822          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   16823          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   16824          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   16825          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   16826          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   16827 
   16828          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   16829           * where fl_flag == 1 on ppc64.
   16830           */
   16831          assign( flags0,
   16832                  binop( Iop_Or32,
   16833                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16834                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   16835                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   16836          assign( flags1,
   16837                  binop( Iop_Or32,
   16838                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16839                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   16840                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   16841          assign( flags2,
   16842                  binop( Iop_Or32,
   16843                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16844                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   16845                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   16846          assign( flags3,
   16847                  binop( Iop_Or32,
   16848                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16849                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   16850                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   16851          putGST_field( PPC_GST_CR,
   16852                        binop( Iop_Or32,
   16853                               mkexpr( flags0 ),
   16854                               binop( Iop_Or32,
   16855                                      mkexpr( flags1 ),
   16856                                      binop( Iop_Or32,
   16857                                             mkexpr( flags2 ),
   16858                                             mkexpr( flags3 ) ) ) ),
   16859                        crfD );
   16860 
   16861          break;
   16862       }
   16863       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   16864       {
   16865          IRTemp flags0 = newTemp(Ity_I32);
   16866          IRTemp flags1 = newTemp(Ity_I32);
   16867          IRTemp flags2 = newTemp(Ity_I32);
   16868          IRTemp flags3 = newTemp(Ity_I32);
   16869          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   16870          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   16871          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   16872          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   16873          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   16874          DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
   16875 
   16876          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   16877          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   16878          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   16879          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   16880          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   16881          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   16882 
   16883          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   16884           * where fl_flag == 1 on ppc64.
   16885           */
   16886          assign( flags0,
   16887                  binop( Iop_Or32,
   16888                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16889                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   16890                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   16891          assign( flags1,
   16892                  binop( Iop_Or32,
   16893                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16894                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   16895                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   16896          assign( flags2,
   16897                  binop( Iop_Or32,
   16898                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16899                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   16900                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   16901          assign( flags3,
   16902                  binop( Iop_Or32,
   16903                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   16904                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   16905                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   16906          putGST_field( PPC_GST_CR,
   16907                        binop( Iop_Or32,
   16908                               mkexpr( flags0 ),
   16909                               binop( Iop_Or32,
   16910                                      mkexpr( flags1 ),
   16911                                      binop( Iop_Or32,
   16912                                             mkexpr( flags2 ),
   16913                                             mkexpr( flags3 ) ) ) ),
   16914                        crfD );
   16915 
   16916          break;
   16917       }
   16918 
   16919       default:
   16920          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   16921          return False;
   16922    }
   16923    return True;
   16924 }
   16925 
   16926 /*
   16927  * Vector Population Count/bit matrix transpose
   16928  */
   16929 static Bool
   16930 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
   16931 {
   16932    UChar vRB_addr = ifieldRegB(theInstr);
   16933    UChar vRT_addr = ifieldRegDS(theInstr);
   16934    UChar opc1 = ifieldOPC( theInstr );
   16935    IRTemp vB = newTemp(Ity_V128);
   16936    assign( vB, getVReg(vRB_addr));
   16937 
   16938    if (opc1 != 0x4) {
   16939       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
   16940       return False;
   16941    }
   16942 
   16943    switch (opc2) {
   16944       case 0x702:    // vclzb
   16945          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
   16946          putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
   16947          break;
   16948 
   16949       case 0x742:    // vclzh
   16950          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
   16951          putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
   16952          break;
   16953 
   16954       case 0x782:    // vclzw
   16955          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
   16956          putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
   16957          break;
   16958 
   16959       case 0x7C2:    // vclzd
   16960          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
   16961          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
   16962          break;
   16963 
   16964       case 0x703:    // vpopcntb
   16965       {
   16966          /* Break vector into 32-bit words and do the population count
   16967           * on byte in the words
   16968           */
   16969          IRType ty = Ity_I32;
   16970          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   16971          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   16972          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   16973          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   16974 
   16975          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
   16976          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   16977          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
   16978          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
   16979          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
   16980          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
   16981 
   16982          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   16983                                          cnt_bits32_63, cnt_bits0_31) );
   16984          break;
   16985       }
   16986 
   16987       case 0x743:    // vpopcnth
   16988       {
   16989          /* Break vector into 32-bit words and do the population count
   16990           * for each half word
   16991           */
   16992          IRType ty = Ity_I32;
   16993          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   16994          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   16995          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   16996          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   16997 
   16998          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
   16999          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   17000 
   17001          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
   17002          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
   17003          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
   17004          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
   17005 
   17006          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   17007                                          cnt_bits32_63, cnt_bits0_31) );
   17008          break;
   17009       }
   17010 
   17011       case 0x783:    // vpopcntw
   17012       {
   17013          /* Break vector into 32-bit words and do the population count
   17014           * on each word.
   17015           */
   17016          IRType ty = Ity_I32;
   17017          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   17018          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   17019          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   17020          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   17021 
   17022          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
   17023          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   17024 
   17025          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
   17026          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
   17027          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
   17028          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
   17029 
   17030          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   17031                                          cnt_bits32_63, cnt_bits0_31) );
   17032          break;
   17033       }
   17034 
   17035       case 0x7C3:    // vpopcntd
   17036       {
   17037          if (mode64) {
   17038             /* Break vector into 64-bit double words and do the population count
   17039              * on each double word.
   17040              */
   17041             IRType ty = Ity_I64;
   17042             IRTemp bits0_63   = newTemp(Ity_I64);
   17043             IRTemp bits64_127 = newTemp(Ity_I64);
   17044             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   17045             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
   17046 
   17047             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   17048 
   17049             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
   17050             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   17051             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
   17052             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
   17053 
   17054             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   17055                                       mkexpr( cnt_bits64_127 ),
   17056                                       mkexpr( cnt_bits0_63 ) ) );
   17057          } else {
   17058             /* Break vector into 32-bit words and do the population count
   17059              * on each doubleword.
   17060              */
   17061             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   17062             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   17063             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   17064             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
   17065 
   17066             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   17067             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   17068 
   17069             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
   17070             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
   17071 
   17072             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   17073                                       mkexpr( cnt_bits64_127 ),
   17074                                       mkexpr( cnt_bits0_63 ) ) );
   17075          }
   17076          break;
   17077       }
   17078 
   17079       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
   17080          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
   17081          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
   17082          break;
   17083 
   17084       case 0x5CC:  // vbpermd Vector Bit Permute Doubleword
   17085       {
   17086          UChar vRA_addr = ifieldRegA( theInstr );
   17087          IRTemp vA = newTemp( Ity_V128 );
   17088          UInt j;
   17089          IRTemp index_dword_hi[8]; // index in double word
   17090          IRTemp index_dword_lo[8];
   17091          IRTemp index_dword_hi_valid[8];
   17092          IRTemp index_dword_lo_valid[8];
   17093          IRTemp pb_dword_hi[8];  // permute bit
   17094          IRTemp pb_dword_lo[8];
   17095          IRTemp tmp_hi[9];
   17096          IRTemp tmp_lo[9];
   17097 
   17098          DIP("vbpermd v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17099 
   17100          tmp_hi[0] = newTemp( Ity_I64 );
   17101          tmp_lo[0] = newTemp( Ity_I64 );
   17102 
   17103          assign( vA, getVReg(vRA_addr) );
   17104          assign( tmp_hi[0], mkU64( 0 ) );
   17105          assign( tmp_lo[0], mkU64( 0 ) );
   17106 
   17107          for (j=0; j<8; j++) {
   17108             index_dword_hi[j] = newTemp( Ity_I64 );
   17109             index_dword_lo[j] = newTemp( Ity_I64 );
   17110             index_dword_hi_valid[j] = newTemp( Ity_I64 );
   17111             index_dword_lo_valid[j] = newTemp( Ity_I64 );
   17112             pb_dword_hi[j] = newTemp( Ity_I64 );
   17113             pb_dword_lo[j] = newTemp( Ity_I64 );
   17114             tmp_hi[j+1] = newTemp( Ity_I64 );
   17115             tmp_lo[j+1] = newTemp( Ity_I64 );
   17116 
   17117             assign( index_dword_hi[j],
   17118                     binop( Iop_And64,
   17119                            binop( Iop_Shr64,
   17120                                   unop( Iop_V128HIto64,
   17121                                         mkexpr( vB ) ),
   17122                                   mkU8( ( 7 - j ) * 8 ) ),
   17123                            mkU64( 0xFF ) ) );
   17124 
   17125             assign( index_dword_lo[j],
   17126                     binop( Iop_And64,
   17127                            binop( Iop_Shr64,
   17128                                   unop( Iop_V128to64,
   17129                                         mkexpr( vB ) ),
   17130                                   mkU8( ( 7 - j ) * 8 ) ),
   17131                            mkU64( 0xFF ) ) );
   17132 
   17133             assign( index_dword_hi_valid[j],
   17134                     unop( Iop_1Sto64,
   17135                           binop( Iop_CmpLT64U,
   17136                                  mkexpr( index_dword_hi[j] ),
   17137                                  mkU64( 64 ) ) ) );
   17138 
   17139             assign( index_dword_lo_valid[j],
   17140                     unop( Iop_1Sto64,
   17141                           binop( Iop_CmpLT64U,
   17142                                  mkexpr( index_dword_lo[j] ),
   17143                                  mkU64( 64 ) ) ) );
   17144             assign( pb_dword_hi[j],
   17145                     binop( Iop_And64,
   17146                            binop( Iop_Shr64,
   17147                                   unop( Iop_V128HIto64,
   17148                                         mkexpr( vA ) ),
   17149                                   unop( Iop_64to8,
   17150                                         binop( Iop_Sub64,
   17151                                                mkU64( 63 ),
   17152                                                mkexpr( index_dword_hi[j] )
   17153                                                ) ) ),
   17154                            mkU64( 0x1 ) ) );
   17155 
   17156             assign( pb_dword_lo[j],
   17157                     binop( Iop_And64,
   17158                            binop( Iop_Shr64,
   17159                                   unop( Iop_V128to64,
   17160                                         mkexpr( vA ) ),
   17161                                   unop( Iop_64to8,
   17162                                         binop( Iop_Sub64,
   17163                                                mkU64( 63 ),
   17164                                                mkexpr( index_dword_lo[j] )
   17165                                                ) ) ),
   17166                            mkU64( 0x1 ) ) );
   17167 
   17168             assign( tmp_hi[j+1],
   17169                     binop( Iop_Or64,
   17170                            binop( Iop_And64,
   17171                                   mkexpr( index_dword_hi_valid[j] ),
   17172                                   binop( Iop_Shl64,
   17173                                          mkexpr( pb_dword_hi[j] ),
   17174                                          mkU8( 7 - j ) ) ),
   17175                            mkexpr( tmp_hi[j] ) ) );
   17176 
   17177             assign( tmp_lo[j+1],
   17178                     binop( Iop_Or64,
   17179                            binop( Iop_And64,
   17180                                   mkexpr( index_dword_lo_valid[j] ),
   17181                                   binop( Iop_Shl64,
   17182                                          mkexpr( pb_dword_lo[j] ),
   17183                                          mkU8( 7 - j ) ) ),
   17184                            mkexpr( tmp_lo[j] ) ) );
   17185          }
   17186 
   17187          putVReg( vRT_addr,
   17188                   binop( Iop_64HLtoV128,
   17189                          mkexpr( tmp_hi[8] ),
   17190                          mkexpr( tmp_lo[8] ) ) );
   17191       }
   17192       break;
   17193 
   17194       default:
   17195          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
   17196          return False;
   17197       break;
   17198    }
   17199    return True;
   17200 }
   17201 
   17202 typedef enum {
   17203    PPC_CMP_EQ = 2,
   17204    PPC_CMP_GT = 4,
   17205    PPC_CMP_GE = 6,
   17206    PPC_CMP_LT = 8
   17207 } ppc_cmp_t;
   17208 
   17209 
   17210 /*
   17211   This helper function takes as input the IRExpr returned
   17212   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   17213   in IR form.  This helper function converts it to PPC form.
   17214 
   17215   Map compare result from IR to PPC
   17216 
   17217   FP cmp result | PPC | IR
   17218   --------------------------
   17219   UN            | 0x1 | 0x45
   17220   EQ            | 0x2 | 0x40
   17221   GT            | 0x4 | 0x00
   17222   LT            | 0x8 | 0x01
   17223 
   17224  condcode = Shl(1, (~(ccIR>>5) & 2)
   17225                     | ((ccIR ^ (ccIR>>6)) & 1)
   17226 */
   17227 static IRTemp
   17228 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   17229 {
   17230    IRTemp condcode = newTemp( Ity_I32 );
   17231    IRTemp ccIR = newTemp( Ity_I32 );
   17232 
   17233    assign(ccIR, ccIR_expr);
   17234    assign( condcode,
   17235            binop( Iop_Shl32,
   17236                   mkU32( 1 ),
   17237                   unop( Iop_32to8,
   17238                         binop( Iop_Or32,
   17239                                binop( Iop_And32,
   17240                                       unop( Iop_Not32,
   17241                                             binop( Iop_Shr32,
   17242                                                    mkexpr( ccIR ),
   17243                                                    mkU8( 5 ) ) ),
   17244                                       mkU32( 2 ) ),
   17245                                binop( Iop_And32,
   17246                                       binop( Iop_Xor32,
   17247                                              mkexpr( ccIR ),
   17248                                              binop( Iop_Shr32,
   17249                                                     mkexpr( ccIR ),
   17250                                                     mkU8( 6 ) ) ),
   17251                                       mkU32( 1 ) ) ) ) ) );
   17252    return condcode;
   17253 }
   17254 
   17255 /*
   17256  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   17257  * following these special rules:
   17258  *   - The max/min of a QNaN and any value is that value
   17259  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   17260  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   17261  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   17262  */
   17263 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   17264 {
   17265    IRTemp frA_isNaN = newTemp(Ity_I1);
   17266    IRTemp frB_isNaN = newTemp(Ity_I1);
   17267    IRTemp frA_isSNaN = newTemp(Ity_I1);
   17268    IRTemp frB_isSNaN = newTemp(Ity_I1);
   17269    IRTemp frA_isQNaN = newTemp(Ity_I1);
   17270    IRTemp frB_isQNaN = newTemp(Ity_I1);
   17271 
   17272    assign( frA_isNaN, is_NaN( Ity_I64, frA_I64 ) );
   17273    assign( frB_isNaN, is_NaN( Ity_I64, frB_I64 ) );
   17274    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   17275    assign( frA_isSNaN,
   17276            mkAND1( mkexpr(frA_isNaN),
   17277                    binop( Iop_CmpEQ32,
   17278                           binop( Iop_And32,
   17279                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   17280                                  mkU32( 0x00080000 ) ),
   17281                           mkU32( 0 ) ) ) );
   17282    assign( frB_isSNaN,
   17283            mkAND1( mkexpr(frB_isNaN),
   17284                    binop( Iop_CmpEQ32,
   17285                           binop( Iop_And32,
   17286                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   17287                                  mkU32( 0x00080000 ) ),
   17288                           mkU32( 0 ) ) ) );
   17289    assign( frA_isQNaN,
   17290            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   17291    assign( frB_isQNaN,
   17292            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   17293 
   17294    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   17295     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   17296     *   if frA is a SNaN
   17297     *     result = frA converted to QNaN
   17298     *   else if frB is a SNaN
   17299     *     result = frB converted to QNaN
   17300     *   else if frB is a QNaN
   17301     *     result = frA
   17302     *   // One of frA or frB was a NaN in order for this function to be called, so
   17303     *   // if we get to this point, we KNOW that frA must be a QNaN.
   17304     *   else // frA is a QNaN
   17305     *     result = frB
   17306     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   17307     */
   17308 
   17309 #define SNAN_MASK 0x0008000000000000ULL
   17310    return
   17311    IRExpr_ITE(mkexpr(frA_isSNaN),
   17312               /* then: result = frA converted to QNaN */
   17313               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
   17314               /* else:  if frB is a SNaN */
   17315               IRExpr_ITE(mkexpr(frB_isSNaN),
   17316                          /* then: result = frB converted to QNaN */
   17317                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
   17318                          /* else:  if frB is a QNaN */
   17319                          IRExpr_ITE(mkexpr(frB_isQNaN),
   17320                                     /* then: result = frA */
   17321                                     mkexpr(frA_I64),
   17322                                     /* else:  frA is a QNaN, so result = frB */
   17323                                     mkexpr(frB_I64))));
   17324 }
   17325 
   17326 /*
   17327  * Helper function for get_max_min_fp.
   17328  */
   17329 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   17330 {
   17331    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   17332                                                   unop( Iop_ReinterpI64asF64,
   17333                                                         mkexpr( src1 ) ),
   17334                                                   unop( Iop_ReinterpI64asF64,
   17335                                                         mkexpr( src2 ) ) ) );
   17336 
   17337    return IRExpr_ITE( binop( Iop_CmpEQ32,
   17338                                mkexpr( src1cmpsrc2 ),
   17339                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
   17340                       /* then: use src1 */
   17341                       mkexpr( src1 ),
   17342                       /* else: use src2 */
   17343                       mkexpr( src2 ) );
   17344 }
   17345 
   17346 /*
   17347  * Helper function for "Maximum/Minimum Double Precision" operations.
   17348  * Arguments: frA and frb are Ity_I64
   17349  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   17350  */
   17351 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   17352 {
   17353    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   17354     * for ascertaining the maximum between two doubles:
   17355     *   1. The max/min of +0 and -0 is +0.
   17356     *   2. The max/min of a QNaN and any value is that value.
   17357     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   17358     * We perform the check for [+/-]0 here in this function and use the
   17359     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   17360     * to do the standard comparison function.
   17361     */
   17362    IRTemp anyNaN = newTemp(Ity_I1);
   17363    IRTemp frA_isZero = newTemp(Ity_I1);
   17364    IRTemp frB_isZero = newTemp(Ity_I1);
   17365    assign( frA_isZero, is_Zero( Ity_I64, frA_I64 ) );
   17366    assign( frB_isZero, is_Zero( Ity_I64, frB_I64 ) );
   17367    assign( anyNaN, mkOR1( is_NaN( Ity_I64, frA_I64 ),
   17368                           is_NaN(Ity_I64, frB_I64 ) ) );
   17369 #define MINUS_ZERO 0x8000000000000000ULL
   17370 
   17371    return IRExpr_ITE( /* If both arguments are zero . . . */
   17372                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
   17373                      /* then: if frA is -0 and isMin==True, return -0;
   17374                       *     else if frA is +0 and isMin==False; return +0;
   17375                       *     otherwise, simply return frB. */
   17376                      IRExpr_ITE( binop( Iop_CmpEQ32,
   17377                                         unop( Iop_64HIto32,
   17378                                               mkexpr( frA_I64 ) ),
   17379                                         mkU32( isMin ? 0x80000000 : 0 ) ),
   17380                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
   17381                                  mkexpr( frB_I64 ) ),
   17382                      /* else: check if either input is a NaN*/
   17383                      IRExpr_ITE( mkexpr( anyNaN ),
   17384                                  /* then: use "NaN helper" */
   17385                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
   17386                                  /* else: use "comparison helper" */
   17387                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
   17388 }
   17389 
   17390 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
   17391 {
   17392    switch (opc2 & 0x7F) {
   17393       case 0x72:
   17394          return "m";
   17395       case 0x52:
   17396          return "p";
   17397       case 0x56:
   17398          return "c";
   17399       case 0x32:
   17400          return "z";
   17401       case 0x12:
   17402          return "";
   17403 
   17404       default: // Impossible to get here
   17405          vex_printf("Unrecognized opcode %x\n", opc2);
   17406          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
   17407    }
   17408 }
   17409 
   17410 /*
   17411  * Helper function for vector/scalar double precision fp round to integer instructions.
   17412  */
   17413 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
   17414 {
   17415 
   17416    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   17417    IRTemp frB = newTemp(Ity_F64);
   17418    IRTemp frD = newTemp(Ity_F64);
   17419    IRTemp intermediateResult = newTemp(Ity_I64);
   17420    IRTemp is_SNAN = newTemp(Ity_I1);
   17421    IRExpr * hi32;
   17422    IRExpr * rxpi_rm;
   17423    switch (opc2 & 0x7F) {
   17424       case 0x72:
   17425          rxpi_rm = mkU32(Irrm_NegINF);
   17426          break;
   17427       case 0x52:
   17428          rxpi_rm = mkU32(Irrm_PosINF);
   17429          break;
   17430       case 0x56:
   17431          rxpi_rm = get_IR_roundingmode();
   17432          break;
   17433       case 0x32:
   17434          rxpi_rm = mkU32(Irrm_ZERO);
   17435          break;
   17436       case 0x12:
   17437          rxpi_rm = mkU32(Irrm_NEAREST);
   17438          break;
   17439 
   17440       default: // Impossible to get here
   17441          vex_printf("Unrecognized opcode %x\n", opc2);
   17442          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
   17443    }
   17444    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   17445    assign( intermediateResult,
   17446            binop( Iop_F64toI64S, rxpi_rm,
   17447                   mkexpr( frB ) ) );
   17448 
   17449    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   17450    /* F64 has only log10(2**52) significant digits anyway */
   17451    /* need to preserve sign of zero */
   17452    /*   frD = (fabs(frB) > 9e18) ? frB :
   17453             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   17454    assign( frD,
   17455            IRExpr_ITE(
   17456               binop( Iop_CmpNE8,
   17457                      unop( Iop_32to8,
   17458                            binop( Iop_CmpF64,
   17459                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
   17460                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   17461                      mkU8(0) ),
   17462               mkexpr( frB ),
   17463               IRExpr_ITE(
   17464                  binop( Iop_CmpNE32,
   17465                         binop( Iop_Shr32,
   17466                                unop( Iop_64HIto32,
   17467                                      mkexpr( frB_I64 ) ),
   17468                                mkU8( 31 ) ),
   17469                         mkU32(0) ),
   17470                  unop( Iop_NegF64,
   17471                        unop( Iop_AbsF64,
   17472                              binop( Iop_I64StoF64,
   17473                                     mkU32( 0 ),
   17474                                     mkexpr( intermediateResult ) ) ) ),
   17475                  binop( Iop_I64StoF64,
   17476                         mkU32( 0 ),
   17477                         mkexpr( intermediateResult ) )
   17478               )
   17479            )
   17480    );
   17481 
   17482    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   17483     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   17484     */
   17485 #define SNAN_MASK 0x0008000000000000ULL
   17486    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   17487    assign( is_SNAN,
   17488            mkAND1( is_NaN( Ity_I64, frB_I64 ),
   17489                    binop( Iop_CmpEQ32,
   17490                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   17491                           mkU32( 0 ) ) ) );
   17492 
   17493    return IRExpr_ITE( mkexpr( is_SNAN ),
   17494                         unop( Iop_ReinterpI64asF64,
   17495                               binop( Iop_Xor64,
   17496                                      mkU64( SNAN_MASK ),
   17497                                      mkexpr( frB_I64 ) ) ),
   17498                       mkexpr( frD ));
   17499 }
   17500 
   17501 /*
   17502  * Miscellaneous VSX vector instructions
   17503  */
   17504 static Bool
   17505 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   17506 {
   17507    /* XX3-Form */
   17508    UChar opc1 = ifieldOPC( theInstr );
   17509    UChar XT = ifieldRegXT( theInstr );
   17510    UChar XB = ifieldRegXB( theInstr );
   17511 
   17512    if (opc1 != 0x3C) {
   17513       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   17514       return False;
   17515    }
   17516 
   17517    switch (opc2) {
   17518       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   17519       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   17520                    //             Double-Precision)
   17521       {
   17522          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   17523          IRExpr* rm  = get_IR_roundingmode();
   17524          IRTemp frB = newTemp(Ity_I64);
   17525          IRTemp frB2 = newTemp(Ity_I64);
   17526          Bool redp = opc2 == 0x1B4;
   17527          IRTemp sqrtHi = newTemp(Ity_F64);
   17528          IRTemp sqrtLo = newTemp(Ity_F64);
   17529          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   17530          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   17531 
   17532          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
   17533 
   17534          if (!redp) {
   17535             assign( sqrtHi,
   17536                     binop( Iop_SqrtF64,
   17537                            rm,
   17538                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   17539             assign( sqrtLo,
   17540                     binop( Iop_SqrtF64,
   17541                            rm,
   17542                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   17543          }
   17544          putVSReg( XT,
   17545                    binop( Iop_64HLtoV128,
   17546                           unop( Iop_ReinterpF64asI64,
   17547                                 triop( Iop_DivF64,
   17548                                        rm,
   17549                                        ieee_one,
   17550                                        redp ? unop( Iop_ReinterpI64asF64,
   17551                                                     mkexpr( frB ) )
   17552                                             : mkexpr( sqrtHi ) ) ),
   17553                           unop( Iop_ReinterpF64asI64,
   17554                                 triop( Iop_DivF64,
   17555                                        rm,
   17556                                        ieee_one,
   17557                                        redp ? unop( Iop_ReinterpI64asF64,
   17558                                                     mkexpr( frB2 ) )
   17559                                             : mkexpr( sqrtLo ) ) ) ) );
   17560          break;
   17561 
   17562       }
   17563       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   17564       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   17565       {
   17566          IRTemp b3, b2, b1, b0;
   17567          IRTemp res0 = newTemp(Ity_I32);
   17568          IRTemp res1 = newTemp(Ity_I32);
   17569          IRTemp res2 = newTemp(Ity_I32);
   17570          IRTemp res3 = newTemp(Ity_I32);
   17571          IRTemp sqrt3 = newTemp(Ity_F64);
   17572          IRTemp sqrt2 = newTemp(Ity_F64);
   17573          IRTemp sqrt1 = newTemp(Ity_F64);
   17574          IRTemp sqrt0 = newTemp(Ity_F64);
   17575          IRExpr* rm  = get_IR_roundingmode();
   17576          Bool resp = opc2 == 0x134;
   17577 
   17578          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   17579 
   17580          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   17581          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
   17582          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   17583 
   17584          if (!resp) {
   17585             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   17586             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   17587             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   17588             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   17589          }
   17590 
   17591          assign( res0,
   17592                  unop( Iop_ReinterpF32asI32,
   17593                        unop( Iop_TruncF64asF32,
   17594                              triop( Iop_DivF64r32,
   17595                                     rm,
   17596                                     ieee_one,
   17597                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   17598          assign( res1,
   17599                  unop( Iop_ReinterpF32asI32,
   17600                        unop( Iop_TruncF64asF32,
   17601                              triop( Iop_DivF64r32,
   17602                                     rm,
   17603                                     ieee_one,
   17604                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   17605          assign( res2,
   17606                  unop( Iop_ReinterpF32asI32,
   17607                        unop( Iop_TruncF64asF32,
   17608                              triop( Iop_DivF64r32,
   17609                                     rm,
   17610                                     ieee_one,
   17611                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   17612          assign( res3,
   17613                  unop( Iop_ReinterpF32asI32,
   17614                        unop( Iop_TruncF64asF32,
   17615                              triop( Iop_DivF64r32,
   17616                                     rm,
   17617                                     ieee_one,
   17618                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   17619          putVSReg( XT,
   17620                    binop( Iop_64HLtoV128,
   17621                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   17622                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   17623          break;
   17624       }
   17625       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   17626       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   17627       {
   17628          UChar XA = ifieldRegXA( theInstr );
   17629          IRTemp a3, a2, a1, a0;
   17630          IRTemp b3, b2, b1, b0;
   17631          IRTemp res0 = newTemp( Ity_I32 );
   17632          IRTemp res1 = newTemp( Ity_I32 );
   17633          IRTemp res2 = newTemp( Ity_I32 );
   17634          IRTemp res3 = newTemp( Ity_I32 );
   17635          IRTemp a0_I64 = newTemp( Ity_I64 );
   17636          IRTemp a1_I64 = newTemp( Ity_I64 );
   17637          IRTemp a2_I64 = newTemp( Ity_I64 );
   17638          IRTemp a3_I64 = newTemp( Ity_I64 );
   17639          IRTemp b0_I64 = newTemp( Ity_I64 );
   17640          IRTemp b1_I64 = newTemp( Ity_I64 );
   17641          IRTemp b2_I64 = newTemp( Ity_I64 );
   17642          IRTemp b3_I64 = newTemp( Ity_I64 );
   17643 
   17644          Bool isMin = opc2 == 0x320 ? True : False;
   17645 
   17646          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   17647          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   17648          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
   17649          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   17650          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   17651          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   17652          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   17653          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   17654          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   17655          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   17656          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   17657          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   17658          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   17659          assign( res0,
   17660                  unop( Iop_ReinterpF32asI32,
   17661                        unop( Iop_TruncF64asF32,
   17662                              unop( Iop_ReinterpI64asF64,
   17663                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   17664          assign( res1,
   17665                  unop( Iop_ReinterpF32asI32,
   17666                        unop( Iop_TruncF64asF32,
   17667                              unop( Iop_ReinterpI64asF64,
   17668                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   17669          assign( res2,
   17670                  unop( Iop_ReinterpF32asI32,
   17671                        unop( Iop_TruncF64asF32,
   17672                              unop( Iop_ReinterpI64asF64,
   17673                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   17674          assign( res3,
   17675                  unop( Iop_ReinterpF32asI32,
   17676                        unop( Iop_TruncF64asF32,
   17677                              unop( Iop_ReinterpI64asF64,
   17678                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   17679          putVSReg( XT,
   17680                    binop( Iop_64HLtoV128,
   17681                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   17682                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   17683          break;
   17684       }
   17685       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   17686       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   17687       {
   17688          UChar XA = ifieldRegXA( theInstr );
   17689          IRTemp frA = newTemp(Ity_I64);
   17690          IRTemp frB = newTemp(Ity_I64);
   17691          IRTemp frA2 = newTemp(Ity_I64);
   17692          IRTemp frB2 = newTemp(Ity_I64);
   17693          Bool isMin = opc2 == 0x3A0 ? True : False;
   17694 
   17695          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   17696          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   17697          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   17698          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   17699          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
   17700          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   17701 
   17702          break;
   17703       }
   17704       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   17705       {
   17706          UChar XA = ifieldRegXA( theInstr );
   17707          IRTemp frA = newTemp(Ity_I64);
   17708          IRTemp frB = newTemp(Ity_I64);
   17709          IRTemp frA2 = newTemp(Ity_I64);
   17710          IRTemp frB2 = newTemp(Ity_I64);
   17711          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   17712          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   17713          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   17714          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   17715 
   17716          DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
   17717          putVSReg( XT,
   17718                    binop( Iop_64HLtoV128,
   17719                           binop( Iop_Or64,
   17720                                  binop( Iop_And64,
   17721                                         mkexpr( frA ),
   17722                                         mkU64( SIGN_BIT ) ),
   17723                                  binop( Iop_And64,
   17724                                         mkexpr( frB ),
   17725                                         mkU64( SIGN_MASK ) ) ),
   17726                           binop( Iop_Or64,
   17727                                  binop( Iop_And64,
   17728                                         mkexpr( frA2 ),
   17729                                         mkU64( SIGN_BIT ) ),
   17730                                  binop( Iop_And64,
   17731                                         mkexpr( frB2 ),
   17732                                         mkU64( SIGN_MASK ) ) ) ) );
   17733          break;
   17734       }
   17735       case 0x340: // xvcpsgnsp
   17736       {
   17737          UChar XA = ifieldRegXA( theInstr );
   17738          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   17739          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   17740          IRTemp resHi = newTemp(Ity_I64);
   17741          IRTemp resLo = newTemp(Ity_I64);
   17742 
   17743          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   17744          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   17745          DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
   17746          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   17747          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   17748 
   17749          assign( resHi,
   17750                  binop( Iop_32HLto64,
   17751                         binop( Iop_Or32,
   17752                                binop( Iop_And32,
   17753                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   17754                                       mkU32( SIGN_BIT32 ) ),
   17755                                binop( Iop_And32,
   17756                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   17757                                       mkU32( SIGN_MASK32) ) ),
   17758 
   17759                         binop( Iop_Or32,
   17760                                binop( Iop_And32,
   17761                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   17762                                       mkU32( SIGN_BIT32 ) ),
   17763                                binop( Iop_And32,
   17764                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   17765                                       mkU32( SIGN_MASK32 ) ) ) ) );
   17766          assign( resLo,
   17767                  binop( Iop_32HLto64,
   17768                         binop( Iop_Or32,
   17769                                binop( Iop_And32,
   17770                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   17771                                       mkU32( SIGN_BIT32 ) ),
   17772                                binop( Iop_And32,
   17773                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   17774                                       mkU32( SIGN_MASK32 ) ) ),
   17775 
   17776                         binop( Iop_Or32,
   17777                                binop( Iop_And32,
   17778                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   17779                                       mkU32( SIGN_BIT32 ) ),
   17780                                binop( Iop_And32,
   17781                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   17782                                       mkU32( SIGN_MASK32 ) ) ) ) );
   17783          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   17784          break;
   17785       }
   17786       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   17787       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   17788       {
   17789          IRTemp frB = newTemp(Ity_F64);
   17790          IRTemp frB2 = newTemp(Ity_F64);
   17791          IRTemp abs_resultHi = newTemp(Ity_F64);
   17792          IRTemp abs_resultLo = newTemp(Ity_F64);
   17793          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   17794          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   17795          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   17796 
   17797          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
   17798          if (make_negative) {
   17799             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   17800             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   17801 
   17802          } else {
   17803             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   17804             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   17805          }
   17806          putVSReg( XT, binop( Iop_64HLtoV128,
   17807                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   17808                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   17809          break;
   17810       }
   17811       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   17812       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   17813       {
   17814          /*
   17815           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   17816           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   17817           * of this function is so easy using shifts, I choose to emulate this instruction that
   17818           * way versus a native instruction method of implementation.
   17819           */
   17820          Bool make_negative = (opc2 == 0x352) ? True : False;
   17821          IRTemp shiftVector = newTemp(Ity_V128);
   17822          IRTemp absVal_vector = newTemp(Ity_V128);
   17823          assign( shiftVector,
   17824                  binop( Iop_64HLtoV128,
   17825                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   17826                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   17827          assign( absVal_vector,
   17828                    binop( Iop_Shr32x4,
   17829                           binop( Iop_Shl32x4,
   17830                                  getVSReg( XB ),
   17831                                  mkexpr( shiftVector ) ),
   17832                           mkexpr( shiftVector ) ) );
   17833          if (make_negative) {
   17834             IRTemp signBit_vector = newTemp(Ity_V128);
   17835             assign( signBit_vector,
   17836                     binop( Iop_64HLtoV128,
   17837                            binop( Iop_32HLto64,
   17838                                   mkU32( 0x80000000 ),
   17839                                   mkU32( 0x80000000 ) ),
   17840                            binop( Iop_32HLto64,
   17841                                   mkU32( 0x80000000 ),
   17842                                   mkU32( 0x80000000 ) ) ) );
   17843             putVSReg( XT,
   17844                       binop( Iop_OrV128,
   17845                              mkexpr( absVal_vector ),
   17846                              mkexpr( signBit_vector ) ) );
   17847          } else {
   17848             putVSReg( XT, mkexpr( absVal_vector ) );
   17849          }
   17850          break;
   17851       }
   17852       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   17853       {
   17854          IRTemp frB = newTemp(Ity_F64);
   17855          IRTemp frB2 = newTemp(Ity_F64);
   17856          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   17857          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   17858          DIP("xvnegdp v%d,v%d\n",  XT, XB);
   17859          putVSReg( XT,
   17860                    binop( Iop_64HLtoV128,
   17861                           unop( Iop_ReinterpF64asI64,
   17862                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   17863                           unop( Iop_ReinterpF64asI64,
   17864                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   17865          break;
   17866       }
   17867       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   17868       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   17869       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   17870       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   17871       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   17872       {
   17873          IRTemp frBHi_I64 = newTemp(Ity_I64);
   17874          IRTemp frBLo_I64 = newTemp(Ity_I64);
   17875          IRExpr * frD_fp_roundHi = NULL;
   17876          IRExpr * frD_fp_roundLo = NULL;
   17877 
   17878          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   17879          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
   17880          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   17881          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
   17882 
   17883          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
   17884          putVSReg( XT,
   17885                    binop( Iop_64HLtoV128,
   17886                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   17887                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   17888          break;
   17889       }
   17890       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   17891       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   17892       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   17893       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   17894       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   17895       {
   17896          const HChar * insn_suffix = NULL;
   17897          IROp op;
   17898          if (opc2 != 0x156) {
   17899             // Use pre-defined IRop's for vrfi{m|n|p|z}
   17900             switch (opc2) {
   17901                case 0x112:
   17902                   insn_suffix = "";
   17903                   op = Iop_RoundF32x4_RN;
   17904                   break;
   17905                case 0x172:
   17906                   insn_suffix = "m";
   17907                   op = Iop_RoundF32x4_RM;
   17908                   break;
   17909                case 0x152:
   17910                   insn_suffix = "p";
   17911                   op = Iop_RoundF32x4_RP;
   17912                   break;
   17913                case 0x132:
   17914                   insn_suffix = "z";
   17915                   op = Iop_RoundF32x4_RZ;
   17916                   break;
   17917 
   17918                default:
   17919                   vex_printf("Unrecognized opcode %x\n", opc2);
   17920                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
   17921             }
   17922             DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
   17923             putVSReg( XT, unop( op, getVSReg(XB) ) );
   17924          } else {
   17925             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   17926             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   17927             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   17928             IRTemp b3_I64 = newTemp(Ity_I64);
   17929             IRTemp b2_I64 = newTemp(Ity_I64);
   17930             IRTemp b1_I64 = newTemp(Ity_I64);
   17931             IRTemp b0_I64 = newTemp(Ity_I64);
   17932 
   17933             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   17934             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   17935             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   17936             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   17937             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   17938             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   17939             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   17940             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   17941                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
   17942             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   17943                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
   17944             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   17945                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
   17946             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   17947                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
   17948             DIP("xvrspic v%d,v%d\n", XT, XB);
   17949             putVSReg( XT,
   17950                       binop( Iop_64HLtoV128,
   17951                              binop( Iop_32HLto64,
   17952                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   17953                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   17954                              binop( Iop_32HLto64,
   17955                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   17956                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   17957          }
   17958          break;
   17959       }
   17960 
   17961       default:
   17962          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   17963          return False;
   17964    }
   17965    return True;
   17966 }
   17967 
   17968 
   17969 /*
   17970  * VSX Scalar Floating Point Arithmetic Instructions
   17971  */
   17972 static Bool
   17973 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   17974 {
   17975    /* XX3-Form */
   17976    UChar opc1 = ifieldOPC( theInstr );
   17977    UChar XT = ifieldRegXT( theInstr );
   17978    UChar XA = ifieldRegXA( theInstr );
   17979    UChar XB = ifieldRegXB( theInstr );
   17980    IRExpr* rm = get_IR_roundingmode();
   17981    IRTemp frA = newTemp(Ity_F64);
   17982    IRTemp frB = newTemp(Ity_F64);
   17983 
   17984    if (opc1 != 0x3C) {
   17985       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   17986       return False;
   17987    }
   17988 
   17989    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   17990    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   17991 
   17992    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   17993     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   17994     * element to zero where it makes sense to do so.
   17995     */
   17996    switch (opc2) {
   17997       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
   17998          DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
   17999          putVSReg( XT, binop( Iop_64HLtoV128,
   18000                               unop( Iop_ReinterpF64asI64,
   18001                                     binop( Iop_RoundF64toF32, rm,
   18002                                            triop( Iop_AddF64, rm,
   18003                                                   mkexpr( frA ),
   18004                                                   mkexpr( frB ) ) ) ),
   18005                               mkU64( 0 ) ) );
   18006          break;
   18007       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
   18008          DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
   18009          putVSReg( XT, binop( Iop_64HLtoV128,
   18010                               unop( Iop_ReinterpF64asI64,
   18011                                     binop( Iop_RoundF64toF32, rm,
   18012                                            triop( Iop_SubF64, rm,
   18013                                                   mkexpr( frA ),
   18014                                                   mkexpr( frB ) ) ) ),
   18015                               mkU64( 0 ) ) );
   18016          break;
   18017       case 0x080: // xsadddp (VSX scalar add double-precision)
   18018          DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
   18019          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18020                                                     triop( Iop_AddF64, rm,
   18021                                                            mkexpr( frA ),
   18022                                                            mkexpr( frB ) ) ),
   18023                               mkU64( 0 ) ) );
   18024          break;
   18025       case 0x060: // xsdivsp (VSX scalar divide single-precision)
   18026          DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
   18027          putVSReg( XT, binop( Iop_64HLtoV128,
   18028                               unop( Iop_ReinterpF64asI64,
   18029                                     binop( Iop_RoundF64toF32, rm,
   18030                                            triop( Iop_DivF64, rm,
   18031                                                   mkexpr( frA ),
   18032                                                   mkexpr( frB ) ) ) ),
   18033                                mkU64( 0 ) ) );
   18034          break;
   18035       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   18036          DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
   18037          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18038                                                     triop( Iop_DivF64, rm,
   18039                                                            mkexpr( frA ),
   18040                                                            mkexpr( frB ) ) ),
   18041                               mkU64( 0 ) ) );
   18042          break;
   18043       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
   18044                                * single-precision)
   18045                                */
   18046       {
   18047          IRTemp frT = newTemp(Ity_F64);
   18048          Bool mdp = opc2 == 0x024;
   18049          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18050          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18051                                                         getVSReg( XT ) ) ) );
   18052          putVSReg( XT,
   18053                    binop( Iop_64HLtoV128,
   18054                           unop( Iop_ReinterpF64asI64,
   18055                                 binop( Iop_RoundF64toF32, rm,
   18056                                        qop( Iop_MAddF64, rm,
   18057                                             mkexpr( frA ),
   18058                                             mkexpr( mdp ? frT : frB ),
   18059                                             mkexpr( mdp ? frB : frT ) ) ) ),
   18060                           mkU64( 0 ) ) );
   18061          break;
   18062       }
   18063       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   18064       {
   18065          IRTemp frT = newTemp(Ity_F64);
   18066          Bool mdp = opc2 == 0x0A4;
   18067          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18068          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18069                                                         getVSReg( XT ) ) ) );
   18070          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18071                                                     qop( Iop_MAddF64, rm,
   18072                                                          mkexpr( frA ),
   18073                                                          mkexpr( mdp ? frT : frB ),
   18074                                                          mkexpr( mdp ? frB : frT ) ) ),
   18075                               mkU64( 0 ) ) );
   18076          break;
   18077       }
   18078       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
   18079                                * multiply-subtract single-precision)
   18080 			       */
   18081       {
   18082          IRTemp frT = newTemp(Ity_F64);
   18083          Bool mdp = opc2 == 0x064;
   18084          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18085          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18086                                                         getVSReg( XT ) ) ) );
   18087          putVSReg( XT,
   18088                    binop( Iop_64HLtoV128,
   18089                           unop( Iop_ReinterpF64asI64,
   18090                                 binop( Iop_RoundF64toF32, rm,
   18091                                        qop( Iop_MSubF64, rm,
   18092                                             mkexpr( frA ),
   18093                                             mkexpr( mdp ? frT : frB ),
   18094                                             mkexpr( mdp ? frB : frT ) ) ) ),
   18095                           mkU64( 0 ) ) );
   18096          break;
   18097       }
   18098       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   18099       {
   18100          IRTemp frT = newTemp(Ity_F64);
   18101          Bool mdp = opc2 == 0x0E4;
   18102          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18103          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18104                                                         getVSReg( XT ) ) ) );
   18105          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18106                                                     qop( Iop_MSubF64, rm,
   18107                                                          mkexpr( frA ),
   18108                                                          mkexpr( mdp ? frT : frB ),
   18109                                                          mkexpr( mdp ? frB : frT ) ) ),
   18110                               mkU64( 0 ) ) );
   18111          break;
   18112       }
   18113       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   18114       {
   18115          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   18116           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   18117           * way it blindly negates the signbit, even if the floating point result is a NaN.
   18118           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   18119           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
   18120           * bit for NaN result.
   18121           */
   18122          Bool mdp = opc2 == 0x2A4;
   18123          IRTemp frT = newTemp(Ity_F64);
   18124          IRTemp maddResult = newTemp(Ity_I64);
   18125 
   18126          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18127          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18128                                                         getVSReg( XT ) ) ) );
   18129          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   18130                                                               mkexpr( frA ),
   18131                                                               mkexpr( mdp ? frT : frB ),
   18132                                                               mkexpr( mdp ? frB : frT ) ) ) );
   18133 
   18134          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   18135                               mkU64( 0 ) ) );
   18136          break;
   18137       }
   18138       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
   18139                                * multiply-add single-precision)
   18140                                */
   18141       {
   18142          Bool mdp = opc2 == 0x224;
   18143          IRTemp frT = newTemp(Ity_F64);
   18144          IRTemp maddResult = newTemp(Ity_I64);
   18145 
   18146          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18147          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18148                                                         getVSReg( XT ) ) ) );
   18149          assign( maddResult,
   18150                  unop( Iop_ReinterpF64asI64,
   18151                        binop( Iop_RoundF64toF32, rm,
   18152                               qop( Iop_MAddF64, rm,
   18153                                    mkexpr( frA ),
   18154                                    mkexpr( mdp ? frT : frB ),
   18155                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   18156 
   18157          putVSReg( XT, binop( Iop_64HLtoV128,
   18158                               mkexpr( getNegatedResult(maddResult) ),
   18159                               mkU64( 0 ) ) );
   18160          break;
   18161       }
   18162       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
   18163                                * Multiply-Subtract Single-Precision)
   18164                                */
   18165       {
   18166          IRTemp frT = newTemp(Ity_F64);
   18167          Bool mdp = opc2 == 0x264;
   18168          IRTemp msubResult = newTemp(Ity_I64);
   18169 
   18170          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18171          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18172                                                         getVSReg( XT ) ) ) );
   18173          assign( msubResult,
   18174                  unop( Iop_ReinterpF64asI64,
   18175                        binop( Iop_RoundF64toF32, rm,
   18176                               qop( Iop_MSubF64, rm,
   18177                                    mkexpr( frA ),
   18178                                    mkexpr( mdp ? frT : frB ),
   18179                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   18180 
   18181          putVSReg( XT, binop( Iop_64HLtoV128,
   18182                               mkexpr( getNegatedResult(msubResult) ),
   18183                               mkU64( 0 ) ) );
   18184 
   18185          break;
   18186       }
   18187 
   18188       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   18189       {
   18190          IRTemp frT = newTemp(Ity_F64);
   18191          Bool mdp = opc2 == 0x2E4;
   18192          IRTemp msubResult = newTemp(Ity_I64);
   18193 
   18194          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   18195          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   18196                                                         getVSReg( XT ) ) ) );
   18197          assign(msubResult, unop( Iop_ReinterpF64asI64,
   18198                                       qop( Iop_MSubF64,
   18199                                            rm,
   18200                                            mkexpr( frA ),
   18201                                            mkexpr( mdp ? frT : frB ),
   18202                                            mkexpr( mdp ? frB : frT ) ) ));
   18203 
   18204          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   18205 
   18206          break;
   18207       }
   18208 
   18209       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
   18210          DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
   18211          putVSReg( XT, binop( Iop_64HLtoV128,
   18212                               unop( Iop_ReinterpF64asI64,
   18213                                     binop( Iop_RoundF64toF32, rm,
   18214                                            triop( Iop_MulF64, rm,
   18215                                                    mkexpr( frA ),
   18216                                                    mkexpr( frB ) ) ) ),
   18217                               mkU64( 0 ) ) );
   18218          break;
   18219 
   18220       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   18221          DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
   18222          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18223                                                     triop( Iop_MulF64, rm,
   18224                                                            mkexpr( frA ),
   18225                                                            mkexpr( frB ) ) ),
   18226                               mkU64( 0 ) ) );
   18227          break;
   18228       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   18229          DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
   18230          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18231                                                     triop( Iop_SubF64, rm,
   18232                                                            mkexpr( frA ),
   18233                                                            mkexpr( frB ) ) ),
   18234                               mkU64( 0 ) ) );
   18235          break;
   18236 
   18237       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
   18238          DIP("xssqrtsp v%d,v%d\n", XT, XB);
   18239          putVSReg( XT,
   18240                    binop( Iop_64HLtoV128,
   18241                           unop( Iop_ReinterpF64asI64,
   18242                                 binop( Iop_RoundF64toF32, rm,
   18243                                        binop( Iop_SqrtF64, rm,
   18244                                               mkexpr( frB ) ) ) ),
   18245                           mkU64( 0 ) ) );
   18246          break;
   18247 
   18248       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   18249          DIP("xssqrtdp v%d,v%d\n", XT, XB);
   18250          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   18251                                                      binop( Iop_SqrtF64, rm,
   18252                                                             mkexpr( frB ) ) ),
   18253                                mkU64( 0 ) ) );
   18254          break;
   18255 
   18256       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   18257       {
   18258          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   18259          IRTemp frA_I64 = newTemp(Ity_I64);
   18260          IRTemp frB_I64 = newTemp(Ity_I64);
   18261          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
   18262          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   18263          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   18264          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   18265          break;
   18266       }
   18267       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   18268       {
   18269          IRTemp frB_I64 = newTemp(Ity_I64);
   18270          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   18271          IRTemp flags = newTemp(Ity_I32);
   18272          IRTemp  fe_flag, fg_flag;
   18273          fe_flag = fg_flag = IRTemp_INVALID;
   18274          DIP("xstsqrtdp v%d,v%d\n", XT, XB);
   18275          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   18276          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   18277          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   18278           * where fl_flag == 1 on ppc64.
   18279           */
   18280          assign( flags,
   18281                  binop( Iop_Or32,
   18282                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   18283                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   18284                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   18285          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   18286          break;
   18287       }
   18288 
   18289       default:
   18290          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   18291          return False;
   18292    }
   18293 
   18294    return True;
   18295 }
   18296 
   18297 
   18298 /*
   18299  * VSX Floating Point Compare Instructions
   18300  */
   18301 static Bool
   18302 dis_vx_cmp( UInt theInstr, UInt opc2 )
   18303 {
   18304    /* XX3-Form and XX2-Form */
   18305    UChar opc1 = ifieldOPC( theInstr );
   18306    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   18307    IRTemp ccPPC32;
   18308    UChar XA       = ifieldRegXA ( theInstr );
   18309    UChar XB       = ifieldRegXB ( theInstr );
   18310    IRTemp frA     = newTemp(Ity_F64);
   18311    IRTemp frB     = newTemp(Ity_F64);
   18312 
   18313    if (opc1 != 0x3C) {
   18314       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   18315       return False;
   18316    }
   18317 
   18318    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   18319    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   18320    switch (opc2) {
   18321       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   18322          /* Note: Differences between xscmpudp and xscmpodp are only in
   18323           * exception flag settings, which aren't supported anyway. */
   18324          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   18325                                            crfD, XA, XB);
   18326          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   18327          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   18328          putFPCC( mkexpr( ccPPC32 ) );
   18329          break;
   18330 
   18331       default:
   18332          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   18333          return False;
   18334    }
   18335    return True;
   18336 }
   18337 
   18338 static void
   18339 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   18340                  ppc_cmp_t cmp_type )
   18341 {
   18342    IRTemp frA_hi     = newTemp(Ity_F64);
   18343    IRTemp frB_hi     = newTemp(Ity_F64);
   18344    IRTemp frA_lo     = newTemp(Ity_F64);
   18345    IRTemp frB_lo     = newTemp(Ity_F64);
   18346    IRTemp ccPPC32    = newTemp(Ity_I32);
   18347    IRTemp ccIR_hi;
   18348    IRTemp ccIR_lo;
   18349 
   18350    IRTemp hiResult = newTemp(Ity_I64);
   18351    IRTemp loResult = newTemp(Ity_I64);
   18352    IRTemp hiEQlo = newTemp(Ity_I1);
   18353    IRTemp all_elem_true = newTemp(Ity_I32);
   18354    IRTemp all_elem_false = newTemp(Ity_I32);
   18355 
   18356    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   18357    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   18358    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   18359    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   18360 
   18361    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   18362                                        mkexpr( frA_hi ),
   18363                                        mkexpr( frB_hi ) ) );
   18364    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   18365                                        mkexpr( frA_lo ),
   18366                                        mkexpr( frB_lo ) ) );
   18367 
   18368    if (cmp_type != PPC_CMP_GE) {
   18369       assign( hiResult,
   18370               unop( Iop_1Sto64,
   18371                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   18372       assign( loResult,
   18373               unop( Iop_1Sto64,
   18374                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   18375    } else {
   18376       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   18377       // the other element compare may return "2" (for "equal to").
   18378       IRTemp lo_GE = newTemp(Ity_I1);
   18379       IRTemp hi_GE = newTemp(Ity_I1);
   18380 
   18381       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   18382                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   18383       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   18384 
   18385       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   18386                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   18387       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   18388    }
   18389 
   18390    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   18391    assign( hiEQlo,
   18392            binop( Iop_CmpEQ32,
   18393                   unop( Iop_64to32, mkexpr( hiResult ) ),
   18394                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   18395    putVSReg( XT,
   18396              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   18397 
   18398    assign( all_elem_true,
   18399            unop( Iop_1Uto32,
   18400                  mkAND1( mkexpr( hiEQlo ),
   18401                          binop( Iop_CmpEQ32,
   18402                                 mkU32( 0xffffffff ),
   18403                                 unop( Iop_64to32,
   18404                                 mkexpr( hiResult ) ) ) ) ) );
   18405 
   18406    assign( all_elem_false,
   18407            unop( Iop_1Uto32,
   18408                  mkAND1( mkexpr( hiEQlo ),
   18409                          binop( Iop_CmpEQ32,
   18410                                 mkU32( 0 ),
   18411                                 unop( Iop_64to32,
   18412                                 mkexpr( hiResult ) ) ) ) ) );
   18413    assign( ccPPC32,
   18414            binop( Iop_Or32,
   18415                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   18416                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   18417 
   18418    if (flag_rC) {
   18419       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   18420    }
   18421 }
   18422 
   18423 /*
   18424  * VSX Vector Compare Instructions
   18425  */
   18426 static Bool
   18427 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   18428 {
   18429    /* XX3-Form */
   18430    UChar opc1 = ifieldOPC( theInstr );
   18431    UChar XT = ifieldRegXT ( theInstr );
   18432    UChar XA = ifieldRegXA ( theInstr );
   18433    UChar XB = ifieldRegXB ( theInstr );
   18434    UChar flag_rC  = ifieldBIT10(theInstr);
   18435    IRTemp vA = newTemp( Ity_V128 );
   18436    IRTemp vB = newTemp( Ity_V128 );
   18437 
   18438    if (opc1 != 0x3C) {
   18439       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   18440       return False;
   18441    }
   18442 
   18443    assign( vA, getVSReg( XA ) );
   18444    assign( vB, getVSReg( XB ) );
   18445 
   18446    switch (opc2) {
   18447       case 0x18C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   18448       {
   18449          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18450              XT, XA, XB);
   18451          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   18452          break;
   18453       }
   18454 
   18455       case 0x1CC:  // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   18456       {
   18457          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18458              XT, XA, XB);
   18459          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   18460          break;
   18461       }
   18462 
   18463       case 0x1AC:  // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   18464       {
   18465          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18466              XT, XA, XB);
   18467          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   18468          break;
   18469       }
   18470 
   18471       case 0x10C:  // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   18472       {
   18473          IRTemp vD = newTemp(Ity_V128);
   18474 
   18475          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18476              XT, XA, XB);
   18477          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   18478          putVSReg( XT, mkexpr(vD) );
   18479          if (flag_rC) {
   18480             set_AV_CR6( mkexpr(vD), True );
   18481          }
   18482          break;
   18483       }
   18484 
   18485       case 0x14C:  // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   18486       {
   18487          IRTemp vD = newTemp(Ity_V128);
   18488 
   18489          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18490              XT, XA, XB);
   18491          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   18492          putVSReg( XT, mkexpr(vD) );
   18493          if (flag_rC) {
   18494             set_AV_CR6( mkexpr(vD), True );
   18495          }
   18496          break;
   18497       }
   18498 
   18499       case 0x12C:  //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   18500       {
   18501          IRTemp vD = newTemp(Ity_V128);
   18502 
   18503          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   18504              XT, XA, XB);
   18505          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   18506          putVSReg( XT, mkexpr(vD) );
   18507          if (flag_rC) {
   18508             set_AV_CR6( mkexpr(vD), True );
   18509          }
   18510          break;
   18511       }
   18512 
   18513       default:
   18514          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   18515          return False;
   18516    }
   18517    return True;
   18518 }
   18519 /*
   18520  * Miscellaneous VSX Scalar Instructions
   18521  */
   18522 static Bool
   18523 dis_vxs_misc( UInt theInstr, UInt opc2, int allow_isa_3_0 )
   18524 {
   18525 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
   18526    /* XX3-Form and XX2-Form */
   18527    UChar opc1 = ifieldOPC( theInstr );
   18528    UChar XT = ifieldRegXT ( theInstr );
   18529    UChar XA = ifieldRegXA ( theInstr );
   18530    UChar XB = ifieldRegXB ( theInstr );
   18531    IRTemp vA = newTemp( Ity_V128 );
   18532    IRTemp vB = newTemp( Ity_V128 );
   18533 
   18534    if (opc1 != 0x3C) {
   18535       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   18536       return False;
   18537    }
   18538 
   18539    assign( vA, getVSReg( XA ) );
   18540    assign( vB, getVSReg( XB ) );
   18541 
   18542    /* For all the VSX move instructions, the contents of doubleword element 1
   18543     * of VSX[XT] are undefined after the operation; therefore, we can simply
   18544     * move the entire array element where it makes sense to do so.
   18545     */
   18546    if (( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )
   18547       {
   18548          /* Special case of XX1-Form with immediate value
   18549           *  xxspltib (VSX Vector Splat Immediate Byte)
   18550           */
   18551          UInt uim = IFIELD( theInstr, 11, 8 );
   18552          UInt word_value = ( uim << 24 ) | ( uim << 16 ) | ( uim << 8 ) | uim;
   18553 
   18554          DIP("xxspltib v%d,%d\n", (UInt)XT, uim);
   18555          putVSReg(XT, binop( Iop_64HLtoV128,
   18556                              binop( Iop_32HLto64,
   18557                                     mkU32( word_value ),
   18558                                     mkU32( word_value ) ),
   18559                              binop( Iop_32HLto64,
   18560                                     mkU32( word_value ),
   18561                                     mkU32( word_value ) ) ) );
   18562          return True;
   18563       }
   18564 
   18565    switch ( opc2 ) {
   18566       case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision)
   18567       {
   18568          /* Compare 64-bit data, 128-bit layout:
   18569             src1[0:63] is double word, src1[64:127] is unused
   18570             src2[0:63] is double word, src2[64:127] is unused
   18571          */
   18572          IRExpr *bit4, *bit5, *bit6, *bit7;
   18573          UInt BF = IFIELD( theInstr, 23, 3 );
   18574          IRTemp eq_lt_gt = newTemp( Ity_I32 );
   18575          IRTemp CC = newTemp( Ity_I32 );
   18576          IRTemp vA_hi = newTemp( Ity_I64 );
   18577          IRTemp vB_hi = newTemp( Ity_I64 );
   18578          IRExpr *mask = mkU64( 0x7FF0000000000000 );
   18579 
   18580          DIP("xscmpexpdp %d,v%d,v%d\n", BF, XA, XB);
   18581 
   18582          assign( vA_hi, unop( Iop_V128HIto64, mkexpr( vA ) ) );
   18583          assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   18584 
   18585          /* A exp < B exp */
   18586          bit4 = binop( Iop_CmpLT64U,
   18587                       binop( Iop_And64,
   18588                              mkexpr( vA_hi ),
   18589                              mask ),
   18590                       binop( Iop_And64,
   18591                              mkexpr( vB_hi ),
   18592                              mask ) );
   18593          /*  A exp > B exp */
   18594          bit5 = binop( Iop_CmpLT64U,
   18595                       binop( Iop_And64,
   18596                              mkexpr( vB_hi ),
   18597                              mask ),
   18598                       binop( Iop_And64,
   18599                              mkexpr( vA_hi ),
   18600                              mask ) );
   18601          /* test equal */
   18602          bit6 = binop( Iop_CmpEQ64,
   18603                       binop( Iop_And64,
   18604                              mkexpr( vA_hi ),
   18605                              mask ),
   18606                       binop( Iop_And64,
   18607                              mkexpr( vB_hi ),
   18608                              mask ) );
   18609 
   18610          /* exp A or exp B is NaN */
   18611          bit7 = mkOR1( is_NaN( Ity_I64, vA_hi ),
   18612                        is_NaN( Ity_I64, vB_hi ) );
   18613 
   18614          assign( eq_lt_gt, binop( Iop_Or32,
   18615                                   binop( Iop_Shl32,
   18616                                          unop( Iop_1Uto32, bit4 ),
   18617                                          mkU8( 3) ),
   18618                                   binop( Iop_Or32,
   18619                                          binop( Iop_Shl32,
   18620                                                 unop( Iop_1Uto32, bit5 ),
   18621                                                 mkU8( 2) ),
   18622                                          binop( Iop_Shl32,
   18623                                                 unop( Iop_1Uto32, bit6 ),
   18624                                                 mkU8( 1 ) ) ) ) );
   18625          assign(CC, binop( Iop_Or32,
   18626                            binop( Iop_And32,
   18627                                   mkexpr( eq_lt_gt ) ,
   18628                                   unop( Iop_Not32, unop( Iop_1Sto32, bit7 ) ) ),
   18629                            unop( Iop_1Uto32, bit7 ) ) );
   18630 
   18631          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
   18632          putFPCC( mkexpr( CC ) );
   18633          return True;
   18634       }
   18635       break;
   18636 
   18637       case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word)
   18638       {
   18639          UInt uim = IFIELD( theInstr, 16, 4 );
   18640 
   18641          DIP("xxextractuw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
   18642 
   18643          putVSReg( XT,
   18644                    binop( Iop_ShlV128,
   18645                           binop( Iop_AndV128,
   18646                                  binop( Iop_ShrV128,
   18647                                         mkexpr( vB ),
   18648                                         mkU8( ( 12 - uim ) * 8 ) ),
   18649                                  binop(Iop_64HLtoV128,
   18650                                        mkU64( 0 ),
   18651                                        mkU64( 0xFFFFFFFF ) ) ),
   18652                           mkU8( ( 32*2 ) ) ) );
   18653          break;
   18654       }
   18655       case 0x16A: // xxinsertw (VSX Vector insert Word)
   18656       {
   18657          UInt uim = IFIELD( theInstr, 16, 4 );
   18658          IRTemp vT = newTemp( Ity_V128 );
   18659          IRTemp tmp = newTemp( Ity_V128 );
   18660 
   18661          DIP("xxinsertw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
   18662 
   18663          assign( vT, getVSReg( XT ) );
   18664          assign( tmp, binop( Iop_AndV128,
   18665                              mkexpr( vT ),
   18666                              unop( Iop_NotV128,
   18667                                    binop( Iop_ShlV128,
   18668                                           binop( Iop_64HLtoV128,
   18669                                                  mkU64( 0x0 ),
   18670                                                  mkU64( 0xFFFFFFFF) ),
   18671                                           mkU8( ( 12 - uim ) * 8 ) ) ) ) );
   18672 
   18673          putVSReg( XT,
   18674                    binop( Iop_OrV128,
   18675                           binop( Iop_ShlV128,
   18676                                  binop( Iop_AndV128,
   18677                                         binop( Iop_ShrV128,
   18678                                                mkexpr( vB ),
   18679                                                mkU8( 32 * 2 ) ),
   18680                                         binop( Iop_64HLtoV128,
   18681                                                mkU64( 0 ),
   18682                                                mkU64( 0xFFFFFFFF ) ) ),
   18683                                  mkU8( ( 12 - uim ) * 8 ) ),
   18684                           mkexpr( tmp ) ) );
   18685          break;
   18686       }
   18687 
   18688       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   18689       {
   18690          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   18691          IRTemp absVal = newTemp(Ity_V128);
   18692          if (host_endness == VexEndnessLE) {
   18693             IRTemp hi64 = newTemp(Ity_I64);
   18694             IRTemp lo64 = newTemp(Ity_I64);
   18695             assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
   18696             assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
   18697             assign( absVal, binop( Iop_64HLtoV128,
   18698                                    binop( Iop_And64, mkexpr(hi64),
   18699                                           mkU64(VG_PPC_SIGN_MASK) ),
   18700                                    mkexpr(lo64) ) );
   18701          } else {
   18702             assign(absVal, binop(Iop_ShrV128,
   18703                                  binop(Iop_ShlV128, mkexpr(vB),
   18704                                        mkU8(1)), mkU8(1)));
   18705          }
   18706          DIP("xsabsdp v%d,v%d\n", XT, XB);
   18707          putVSReg(XT, mkexpr(absVal));
   18708          break;
   18709       }
   18710 
   18711       case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
   18712                   // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
   18713                   // xsvhpdp  (VSX Scalar Convert Half-Precision format
   18714                   //           to Double-Precision format)
   18715                   // xscvdphp (VSX Scalar round & convert Double-precision
   18716                   //           format to Half-precision format)
   18717       {
   18718          IRTemp rT = newTemp( Ity_I64 );
   18719          UInt inst_select = IFIELD( theInstr, 16, 5);
   18720 
   18721          if (inst_select == 0) {
   18722             DIP("xsxexpd %d,v%d\n", (UInt)XT, (UInt)XB);
   18723 
   18724             assign( rT, binop( Iop_Shr64,
   18725                                binop( Iop_And64,
   18726                                       unop( Iop_V128HIto64, mkexpr( vB ) ),
   18727                                       mkU64( 0x7FF0000000000000 ) ),
   18728                                mkU8 ( 52 ) ) );
   18729          } else if (inst_select == 1) {
   18730             IRExpr *normal;
   18731             IRTemp tmp = newTemp(Ity_I64);
   18732 
   18733             DIP("xsxsigdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
   18734 
   18735             assign( tmp, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   18736 
   18737             /* Value is normal if it isn't infinite, zero or denormalized */
   18738             normal = mkNOT1( mkOR1(
   18739                                    mkOR1( is_NaN( Ity_I64, tmp ),
   18740                                           is_Inf( Ity_I64, tmp ) ),
   18741                                    mkOR1( is_Zero( Ity_I64, tmp ),
   18742                                           is_Denorm( Ity_I64, tmp ) ) ) );
   18743 
   18744             assign( rT, binop( Iop_Or64,
   18745                                binop( Iop_And64,
   18746                                       mkexpr( tmp ),
   18747                                       mkU64( 0xFFFFFFFFFFFFF ) ),
   18748                                binop( Iop_Shl64,
   18749                                       unop( Iop_1Uto64, normal),
   18750                                       mkU8( 52 ) ) ) );
   18751             putIReg( XT, mkexpr( rT ) );
   18752 
   18753         } else if (inst_select == 16) {
   18754             IRTemp result = newTemp( Ity_V128 );
   18755             IRTemp value = newTemp( Ity_I64 );
   18756             /* Note: PPC only coverts the 16-bit value in the upper 64-bits
   18757              * of the source V128 to a 64-bit value stored in the upper
   18758              * 64-bits of the V128 result.  The contents of the lower 64-bits
   18759              * is undefined.
   18760              */
   18761 
   18762             DIP("xscvhpdp v%d, v%d\n", (UInt)XT, (UInt)XB);
   18763             assign( result, unop( Iop_F16toF64x2, mkexpr( vB ) ) );
   18764 
   18765             putVSReg( XT, mkexpr( result ) );
   18766 
   18767             assign( value, unop( Iop_V128HIto64, mkexpr( result ) ) );
   18768             generate_store_FPRF( Ity_I64, value );
   18769             return True;
   18770 
   18771          } else if (inst_select == 17) {   // xscvdphp
   18772             IRTemp value = newTemp( Ity_I32 );
   18773             IRTemp result = newTemp( Ity_V128 );
   18774             /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
   18775              * the V128 and stores the 16-bit result in the upper word of the
   18776              * V128 result.  The contents of the lower 64-bits is undefined.
   18777              */
   18778             DIP("xscvdphp v%d, v%d\n", (UInt)XT, (UInt)XB);
   18779             assign( result,  unop( Iop_F64toF16x2, mkexpr( vB ) ) );
   18780             assign( value, unop( Iop_64to32, unop( Iop_V128HIto64,
   18781                                                    mkexpr( result ) ) ) );
   18782             putVSReg( XT, mkexpr( result ) );
   18783             generate_store_FPRF( Ity_I16, value );
   18784             return True;
   18785 
   18786          } else {
   18787             vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
   18788             vex_printf("inst_select = %d\n", inst_select);
   18789             return False;
   18790          }
   18791       }
   18792       break;
   18793 
   18794       case 0x254:  // xststdcsp (VSX Scalar Test Data Class Single-Precision)
   18795       case 0x2D4:  // xststdcdp (VSX Scalar Test Data Class Double-Precision)
   18796       {
   18797          /* These instructions only differ in that the single precision
   18798             instruction, xststdcsp, has the additional constraint on the
   18799             denormal test that the exponent be greater then zero and
   18800             less then 0x381. */
   18801          IRTemp vB_hi = newTemp( Ity_I64 );
   18802          UInt BF = IFIELD( theInstr, 23, 3 );
   18803          UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
   18804          IRTemp NaN = newTemp( Ity_I64 );
   18805          IRTemp inf = newTemp( Ity_I64 );
   18806          IRTemp zero = newTemp( Ity_I64 );
   18807          IRTemp dnorm = newTemp( Ity_I64 );
   18808          IRTemp pos = newTemp( Ity_I64 );
   18809          IRTemp not_sp = newTemp( Ity_I64 );
   18810          IRTemp DCM = newTemp( Ity_I64 );
   18811          IRTemp CC = newTemp( Ity_I64 );
   18812          IRTemp exponent = newTemp( Ity_I64 );
   18813          IRTemp tmp = newTemp( Ity_I64 );
   18814 
   18815          assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   18816 
   18817          assign( pos, unop( Iop_1Uto64,
   18818                             binop( Iop_CmpEQ64,
   18819                                    binop( Iop_Shr64,
   18820                                           mkexpr( vB_hi ),
   18821                                           mkU8( 63 ) ),
   18822                                    mkU64( 0 ) ) ) );
   18823 
   18824          assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_I64, vB_hi ) ) );
   18825          assign( inf, unop( Iop_1Uto64, is_Inf( Ity_I64, vB_hi ) ) );
   18826          assign( zero, unop( Iop_1Uto64, is_Zero( Ity_I64, vB_hi ) ) );
   18827 
   18828          if (opc2 == 0x254) {
   18829             DIP("xststdcsp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
   18830 
   18831             /* The least significant bit of the CC is set to 1 if the double
   18832                precision value is not representable as a single precision
   18833                value. The spec says the bit is set if:
   18834                   src != convert_SPtoDP(convert_DPtoSP(src))
   18835             */
   18836             assign( tmp,
   18837                     unop( Iop_ReinterpF64asI64,
   18838                                 unop( Iop_F32toF64,
   18839                                       unop( Iop_TruncF64asF32,
   18840                                             unop( Iop_ReinterpI64asF64,
   18841                                                   mkexpr( vB_hi ) ) ) ) ) );
   18842             assign( not_sp, unop( Iop_1Uto64,
   18843                                   mkNOT1( binop( Iop_CmpEQ64,
   18844                                                  mkexpr( vB_hi ),
   18845                                                  mkexpr( tmp ) ) ) ) );
   18846             assign( exponent,
   18847                     binop( Iop_Shr64,
   18848                            binop( Iop_And64,
   18849                                   mkexpr( vB_hi ),
   18850                                   mkU64( 0x7ff0000000000000 ) ),
   18851                            mkU8( 52 ) ) );
   18852             assign( dnorm, unop( Iop_1Uto64,
   18853                                  mkOR1( is_Denorm( Ity_I64, vB_hi ),
   18854                                         mkAND1( binop( Iop_CmpLT64U,
   18855                                                        mkexpr( exponent ),
   18856                                                        mkU64( 0x381 ) ),
   18857                                                 binop( Iop_CmpNE64,
   18858                                                        mkexpr( exponent ),
   18859                                                        mkU64( 0x0 ) ) ) ) ) );
   18860 
   18861          } else {
   18862             DIP("xststdcdp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
   18863             assign( not_sp,  mkU64( 0 ) );
   18864             assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_I64, vB_hi ) ) );
   18865          }
   18866 
   18867          assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
   18868          assign( CC,
   18869                  binop( Iop_Or64,
   18870                         binop( Iop_And64,    /* vB sign bit */
   18871                                binop( Iop_Shr64,
   18872                                       mkexpr( vB_hi ),
   18873                                       mkU8( 60 ) ),
   18874                                mkU64( 0x8 ) ),
   18875                         binop( Iop_Or64,
   18876                                binop( Iop_Shl64,
   18877                                       unop( Iop_1Uto64,
   18878                                             binop( Iop_CmpNE64,
   18879                                                    binop( Iop_And64,
   18880                                                           mkexpr( DCM ),
   18881                                                           mkU64( DCMX_mask ) ),
   18882                                                    mkU64( 0 ) ) ),
   18883                                       mkU8( 1 ) ),
   18884                                mkexpr( not_sp ) ) ) );
   18885          putGST_field( PPC_GST_CR, unop( Iop_64to32, mkexpr( CC ) ), BF );
   18886          putFPCC( unop( Iop_64to32, mkexpr( CC ) ) );
   18887       }
   18888       return True;
   18889 
   18890       case 0x2C0: // xscpsgndp
   18891       {
   18892          /* Scalar copy sign double-precision */
   18893          IRTemp vecA_signed = newTemp(Ity_I64);
   18894          IRTemp vecB_unsigned = newTemp(Ity_I64);
   18895          IRTemp vec_result = newTemp(Ity_V128);
   18896          DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
   18897          assign( vecA_signed, binop( Iop_And64,
   18898                                      unop( Iop_V128HIto64,
   18899                                            mkexpr(vA)),
   18900                                            mkU64(~VG_PPC_SIGN_MASK) ) );
   18901          assign( vecB_unsigned, binop( Iop_And64,
   18902                                        unop( Iop_V128HIto64,
   18903                                              mkexpr(vB) ),
   18904                                              mkU64(VG_PPC_SIGN_MASK) ) );
   18905          assign( vec_result, binop( Iop_64HLtoV128,
   18906                                     binop( Iop_Or64,
   18907                                            mkexpr(vecA_signed),
   18908                                            mkexpr(vecB_unsigned) ),
   18909                                     mkU64(0x0ULL)));
   18910          putVSReg(XT, mkexpr(vec_result));
   18911          break;
   18912       }
   18913       case 0x2D2: // xsnabsdp
   18914       {
   18915          /* Scalar negative absolute value double-precision */
   18916          IRTemp BHi_signed = newTemp(Ity_I64);
   18917          DIP("xsnabsdp v%d,v%d\n", XT, XB);
   18918          assign( BHi_signed, binop( Iop_Or64,
   18919                                     unop( Iop_V128HIto64,
   18920                                           mkexpr(vB) ),
   18921                                           mkU64(~VG_PPC_SIGN_MASK) ) );
   18922          putVSReg(XT, binop( Iop_64HLtoV128,
   18923                              mkexpr(BHi_signed), mkU64(0x0ULL) ) );
   18924          break;
   18925       }
   18926       case 0x2F2: // xsnegdp
   18927       {
   18928          /* Scalar negate double-precision */
   18929          IRTemp BHi_signed = newTemp(Ity_I64);
   18930          IRTemp BHi_unsigned = newTemp(Ity_I64);
   18931          IRTemp BHi_negated = newTemp(Ity_I64);
   18932          IRTemp BHi_negated_signbit = newTemp(Ity_I1);
   18933          IRTemp vec_result = newTemp(Ity_V128);
   18934          DIP("xsnabsdp v%d,v%d\n", XT, XB);
   18935          assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
   18936          assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
   18937                                       mkU64(VG_PPC_SIGN_MASK) ) );
   18938          assign( BHi_negated_signbit,
   18939                  unop( Iop_Not1,
   18940                        unop( Iop_32to1,
   18941                              binop( Iop_Shr32,
   18942                                     unop( Iop_64HIto32,
   18943                                           binop( Iop_And64,
   18944                                                  mkexpr(BHi_signed),
   18945                                                  mkU64(~VG_PPC_SIGN_MASK) )
   18946                                           ),
   18947                                     mkU8(31) ) ) ) );
   18948          assign( BHi_negated,
   18949                  binop( Iop_Or64,
   18950                         binop( Iop_32HLto64,
   18951                                binop( Iop_Shl32,
   18952                                       unop( Iop_1Uto32,
   18953                                             mkexpr(BHi_negated_signbit) ),
   18954                                       mkU8(31) ),
   18955                                mkU32(0) ),
   18956                         mkexpr(BHi_unsigned) ) );
   18957          assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
   18958                                     mkU64(0x0ULL)));
   18959          putVSReg( XT, mkexpr(vec_result));
   18960          break;
   18961       }
   18962       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   18963       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   18964       {
   18965          IRTemp frA     = newTemp(Ity_I64);
   18966          IRTemp frB     = newTemp(Ity_I64);
   18967          Bool isMin = opc2 == 0x2A0 ? True : False;
   18968          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
   18969 
   18970          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   18971          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   18972          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   18973 
   18974          break;
   18975       }
   18976       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   18977       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   18978       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   18979       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   18980       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   18981       {
   18982          IRTemp frB_I64 = newTemp(Ity_I64);
   18983          IRExpr * frD_fp_round = NULL;
   18984 
   18985          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   18986          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
   18987 
   18988          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
   18989          putVSReg( XT,
   18990                    binop( Iop_64HLtoV128,
   18991                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   18992                           mkU64( 0 ) ) );
   18993          break;
   18994       }
   18995       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
   18996       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
   18997                    * single-Precision)
   18998                    */
   18999       {
   19000          IRTemp frB = newTemp(Ity_F64);
   19001          IRTemp sqrt = newTemp(Ity_F64);
   19002          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   19003          IRExpr* rm  = get_IR_roundingmode();
   19004          Bool redp = opc2 == 0x034;
   19005          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
   19006              XB);
   19007 
   19008          assign( frB,
   19009                  unop( Iop_ReinterpI64asF64,
   19010                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   19011 
   19012          if (!redp)
   19013             assign( sqrt,
   19014                     binop( Iop_SqrtF64,
   19015                            rm,
   19016                            mkexpr(frB) ) );
   19017          putVSReg( XT,
   19018                       binop( Iop_64HLtoV128,
   19019                              unop( Iop_ReinterpF64asI64,
   19020                                    binop( Iop_RoundF64toF32, rm,
   19021                                           triop( Iop_DivF64,
   19022                                                  rm,
   19023                                                  ieee_one,
   19024                                                  redp ? mkexpr( frB ) :
   19025                                                         mkexpr( sqrt ) ) ) ),
   19026                              mkU64( 0 ) ) );
   19027          break;
   19028       }
   19029 
   19030       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   19031       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   19032 
   19033       {
   19034          IRTemp frB = newTemp(Ity_F64);
   19035          IRTemp sqrt = newTemp(Ity_F64);
   19036          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   19037          IRExpr* rm  = get_IR_roundingmode();
   19038          Bool redp = opc2 == 0x0B4;
   19039          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
   19040          assign( frB,
   19041                  unop( Iop_ReinterpI64asF64,
   19042                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   19043 
   19044          if (!redp)
   19045             assign( sqrt,
   19046                     binop( Iop_SqrtF64,
   19047                            rm,
   19048                            mkexpr(frB) ) );
   19049          putVSReg( XT,
   19050                       binop( Iop_64HLtoV128,
   19051                              unop( Iop_ReinterpF64asI64,
   19052                                    triop( Iop_DivF64,
   19053                                           rm,
   19054                                           ieee_one,
   19055                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   19056                              mkU64( 0 ) ) );
   19057          break;
   19058       }
   19059 
   19060       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
   19061       {
   19062          IRTemp frB = newTemp(Ity_F64);
   19063          IRExpr* rm  = get_IR_roundingmode();
   19064          DIP("xsrsp v%d, v%d\n", XT, XB);
   19065          assign( frB,
   19066                  unop( Iop_ReinterpI64asF64,
   19067                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   19068 
   19069          putVSReg( XT, binop( Iop_64HLtoV128,
   19070                               unop( Iop_ReinterpF64asI64,
   19071                                     binop( Iop_RoundF64toF32,
   19072                                            rm,
   19073                                            mkexpr( frB ) ) ),
   19074                               mkU64( 0 ) ) );
   19075          break;
   19076       }
   19077 
   19078       case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision)
   19079       {
   19080          UInt DX_mask = IFIELD( theInstr, 16, 5 );
   19081          UInt DC_mask = IFIELD( theInstr, 6, 1 );
   19082          UInt DM_mask = IFIELD( theInstr, 2, 1 );
   19083          UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
   19084 
   19085          IRTemp match_value[4];
   19086          IRTemp value[4];
   19087          IRTemp NaN[4];
   19088          IRTemp inf[4];
   19089          IRTemp pos[4];
   19090          IRTemp DCM[4];
   19091          IRTemp zero[4];
   19092          IRTemp dnorm[4];
   19093          Int i;
   19094 
   19095          DIP("xvtstdcsp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
   19096 
   19097          for (i = 0; i < 4; i++) {
   19098             NaN[i]   = newTemp(Ity_I32);
   19099             inf[i]   = newTemp(Ity_I32);
   19100             pos[i]   = newTemp(Ity_I32);
   19101             DCM[i]   = newTemp(Ity_I32);
   19102             zero[i]  = newTemp(Ity_I32);
   19103             dnorm[i] = newTemp(Ity_I32);
   19104 
   19105             value[i] = newTemp(Ity_I32);
   19106             match_value[i] = newTemp(Ity_I32);
   19107 
   19108             assign( value[i],
   19109                     unop( Iop_64to32,
   19110                           unop( Iop_V128to64,
   19111                                 binop( Iop_AndV128,
   19112                                        binop( Iop_ShrV128,
   19113                                               mkexpr( vB ),
   19114                                               mkU8( (3-i)*32 ) ),
   19115                                        binop( Iop_64HLtoV128,
   19116                                               mkU64( 0x0 ),
   19117                                               mkU64( 0xFFFFFFFF ) ) ) ) ) );
   19118 
   19119             assign( pos[i], unop( Iop_1Uto32,
   19120                                   binop( Iop_CmpEQ32,
   19121                                          binop( Iop_Shr32,
   19122                                                 mkexpr( value[i] ),
   19123                                                 mkU8( 31 ) ),
   19124                                          mkU32( 0 ) ) ) );
   19125 
   19126             assign( NaN[i], unop( Iop_1Uto32, is_NaN( Ity_I32, value[i] ) ));
   19127             assign( inf[i], unop( Iop_1Uto32, is_Inf( Ity_I32, value[i] ) ) );
   19128             assign( zero[i], unop( Iop_1Uto32, is_Zero( Ity_I32, value[i] ) ) );
   19129 
   19130             assign( dnorm[i], unop( Iop_1Uto32, is_Denorm( Ity_I32,
   19131                                                            value[i] ) ) );
   19132             assign( DCM[i], create_DCM( Ity_I32, NaN[i], inf[i], zero[i],
   19133                                         dnorm[i], pos[i] ) );
   19134 
   19135             assign( match_value[i],
   19136                     unop( Iop_1Sto32,
   19137                           binop( Iop_CmpNE32,
   19138                                  binop( Iop_And32,
   19139                                         mkU32( DCMX_mask ),
   19140                                         mkexpr( DCM[i] ) ),
   19141                                  mkU32( 0 ) ) ) );
   19142          }
   19143 
   19144          putVSReg( XT, binop( Iop_64HLtoV128,
   19145                               binop( Iop_32HLto64,
   19146                                      mkexpr( match_value[0] ),
   19147                                      mkexpr( match_value[1] ) ),
   19148                               binop( Iop_32HLto64,
   19149                                      mkexpr( match_value[2] ),
   19150                                      mkexpr( match_value[3] ) ) ) );
   19151       }
   19152       break;
   19153 
   19154       case 0x360:  // xviexpsp  (VSX Vector Insert Exponent Single-Precision)
   19155       {
   19156             Int i;
   19157             IRTemp new_XT[5];
   19158             IRTemp A_value[4];
   19159             IRTemp B_value[4];
   19160             IRExpr *sign[4], *expr[4], *fract[4];
   19161 
   19162             DIP("xviexpsp v%d,v%d\n", XT, XB);
   19163             new_XT[0] = newTemp(Ity_V128);
   19164             assign( new_XT[0], binop( Iop_64HLtoV128,
   19165                                       mkU64( 0x0 ),
   19166                                       mkU64( 0x0 ) ) );
   19167 
   19168             for (i = 0; i < 4; i++) {
   19169                A_value[i] = newTemp(Ity_I32);
   19170                B_value[i] = newTemp(Ity_I32);
   19171 
   19172                assign( A_value[i],
   19173                        unop( Iop_64to32,
   19174                              unop( Iop_V128to64,
   19175                                    binop( Iop_AndV128,
   19176                                           binop( Iop_ShrV128,
   19177                                                  mkexpr( vA ),
   19178                                                  mkU8( (3-i)*32 ) ),
   19179                                           binop( Iop_64HLtoV128,
   19180                                                  mkU64( 0x0 ),
   19181                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
   19182                assign( B_value[i],
   19183                        unop( Iop_64to32,
   19184                              unop( Iop_V128to64,
   19185                                    binop( Iop_AndV128,
   19186                                           binop( Iop_ShrV128,
   19187                                                  mkexpr( vB ),
   19188                                                  mkU8( (3-i)*32 ) ),
   19189                                           binop( Iop_64HLtoV128,
   19190                                                  mkU64( 0x0 ),
   19191                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
   19192 
   19193                sign[i] = binop( Iop_And32, mkexpr( A_value[i] ),
   19194                                 mkU32( 0x80000000 ) );
   19195                expr[i] = binop( Iop_Shl32,
   19196                                 binop( Iop_And32, mkexpr( B_value[i] ),
   19197                                        mkU32( 0xFF ) ),
   19198                                 mkU8( 23 ) );
   19199                fract[i] = binop( Iop_And32, mkexpr( A_value[i] ),
   19200                                  mkU32( 0x007FFFFF ) );
   19201 
   19202                new_XT[i+1] = newTemp(Ity_V128);
   19203                assign( new_XT[i+1],
   19204                        binop( Iop_OrV128,
   19205                               binop( Iop_ShlV128,
   19206                                      binop( Iop_64HLtoV128,
   19207                                             mkU64( 0 ),
   19208                                             binop( Iop_32HLto64,
   19209                                                    mkU32( 0 ),
   19210                                                    binop( Iop_Or32,
   19211                                                          binop( Iop_Or32,
   19212                                                                  sign[i],
   19213                                                                  expr[i] ),
   19214                                                           fract[i] ) ) ),
   19215                                      mkU8( (3-i)*32 ) ),
   19216                               mkexpr( new_XT[i] ) ) );
   19217             }
   19218             putVSReg( XT, mkexpr( new_XT[4] ) );
   19219       }
   19220       break;
   19221 
   19222       case 0x396:  // xsiexpdp (VSX Scalar Insert Exponent Double-Precision)
   19223       {
   19224          IRExpr *sign, *expr, *fract;
   19225          UChar rA_addr = ifieldRegA(theInstr);
   19226          UChar rB_addr = ifieldRegB(theInstr);
   19227          IRTemp rA = newTemp( Ity_I64 );
   19228          IRTemp rB = newTemp( Ity_I64 );
   19229 
   19230          DIP("xsiexpdp v%d,%d,%d\n", (UInt)XT, (UInt)rA_addr, (UInt)rB_addr);
   19231          assign( rA, getIReg(rA_addr));
   19232          assign( rB, getIReg(rB_addr));
   19233 
   19234          sign = binop( Iop_And64, mkexpr( rA ), mkU64( 0x8000000000000000 ) );
   19235          expr = binop( Iop_Shl64,
   19236                        binop( Iop_And64, mkexpr( rB ), mkU64( 0x7FF ) ),
   19237                        mkU8( 52 ) );
   19238          fract = binop( Iop_And64, mkexpr( rA ), mkU64( 0x000FFFFFFFFFFFFF ) );
   19239 
   19240          putVSReg( XT, binop( Iop_64HLtoV128,
   19241                               binop( Iop_Or64,
   19242                                      binop( Iop_Or64, sign, expr ),
   19243                                      fract ),
   19244                               mkU64( 0 ) ) );
   19245       }
   19246       break;
   19247 
   19248       case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
   19249                   // xvxsigdp (VSX Vector Extract Significand Double-Precision)
   19250                   // xxbrh
   19251                   // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
   19252                   // xvxsigsp (VSX Vector Extract Significand Single-Precision)
   19253                   // xxbrw
   19254                   // xxbrd
   19255                   // xxbrq
   19256                   // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
   19257                   // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
   19258       {
   19259          UInt inst_select = IFIELD( theInstr, 16, 5);
   19260 
   19261          if (inst_select == 0) {
   19262             DIP("xvxexpdp v%d,v%d\n", XT, XB);
   19263 
   19264             putVSReg( XT, binop( Iop_ShrV128,
   19265                                  binop( Iop_AndV128,
   19266                                         mkexpr( vB ),
   19267                                         binop( Iop_64HLtoV128,
   19268                                                mkU64( 0x7FF0000000000000 ),
   19269                                                mkU64( 0x7FF0000000000000 ) ) ),
   19270                                  mkU8( 52 ) ) );
   19271 
   19272          } else if (inst_select == 1) {
   19273             Int i;
   19274             IRExpr *normal[2];
   19275             IRTemp value[2];
   19276             IRTemp new_XT[3];
   19277 
   19278             DIP("xvxsigdp v%d,v%d\n", XT, XB);
   19279             new_XT[0] = newTemp(Ity_V128);
   19280             assign( new_XT[0], binop( Iop_64HLtoV128,
   19281                                       mkU64( 0x0 ),
   19282                                       mkU64( 0x0 ) ) );
   19283 
   19284             for (i = 0; i < 2; i++) {
   19285                value[i] = newTemp(Ity_I64);
   19286                assign( value[i],
   19287                        unop( Iop_V128to64,
   19288                             binop( Iop_AndV128,
   19289                                     binop( Iop_ShrV128,
   19290                                            mkexpr( vB ),
   19291                                            mkU8( (1-i)*64 ) ),
   19292                                     binop( Iop_64HLtoV128,
   19293                                            mkU64( 0x0 ),
   19294                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
   19295 
   19296                /* Value is normal if it isn't infinite, zero or denormalized */
   19297                normal[i] = mkNOT1( mkOR1(
   19298                                          mkOR1( is_NaN( Ity_I64, value[i] ),
   19299                                                 is_Inf( Ity_I64, value[i] ) ),
   19300                                          mkOR1( is_Zero( Ity_I64, value[i] ),
   19301                                                 is_Denorm( Ity_I64,
   19302                                                            value[i] ) ) ) );
   19303                new_XT[i+1] = newTemp(Ity_V128);
   19304 
   19305                assign( new_XT[i+1],
   19306                        binop( Iop_OrV128,
   19307                               binop( Iop_ShlV128,
   19308                                      binop( Iop_64HLtoV128,
   19309                                             mkU64( 0x0 ),
   19310                                             binop( Iop_Or64,
   19311                                                    binop( Iop_And64,
   19312                                                           mkexpr( value[i] ),
   19313                                                           mkU64( 0xFFFFFFFFFFFFF ) ),
   19314                                                    binop( Iop_Shl64,
   19315                                                           unop( Iop_1Uto64,
   19316                                                                 normal[i]),
   19317                                                           mkU8( 52 ) ) ) ),
   19318                                      mkU8( (1-i)*64 ) ),
   19319                               mkexpr( new_XT[i] ) ) );
   19320             }
   19321             putVSReg( XT, mkexpr( new_XT[2] ) );
   19322 
   19323          } else if (inst_select == 7) {
   19324             IRTemp sub_element0 = newTemp( Ity_V128 );
   19325             IRTemp sub_element1 = newTemp( Ity_V128 );
   19326 
   19327             DIP("xxbrh v%d, v%d\n", (UInt)XT, (UInt)XB);
   19328 
   19329             assign( sub_element0,
   19330                     binop( Iop_ShrV128,
   19331                            binop( Iop_AndV128,
   19332                                   binop(Iop_64HLtoV128,
   19333                                         mkU64( 0xFF00FF00FF00FF00 ),
   19334                                         mkU64( 0xFF00FF00FF00FF00 ) ),
   19335                                   mkexpr( vB ) ),
   19336                            mkU8( 8 ) ) );
   19337             assign( sub_element1,
   19338                     binop( Iop_ShlV128,
   19339                            binop( Iop_AndV128,
   19340                                   binop(Iop_64HLtoV128,
   19341                                         mkU64( 0x00FF00FF00FF00FF ),
   19342                                         mkU64( 0x00FF00FF00FF00FF ) ),
   19343                                   mkexpr( vB ) ),
   19344                            mkU8( 8 ) ) );
   19345 
   19346             putVSReg(XT, binop( Iop_OrV128,
   19347                                 mkexpr( sub_element1 ),
   19348                                 mkexpr( sub_element0 ) ) );
   19349 
   19350          } else if (inst_select == 8) {
   19351             DIP("xvxexpsp v%d,v%d\n", XT, XB);
   19352 
   19353             putVSReg( XT, binop( Iop_ShrV128,
   19354                                  binop( Iop_AndV128,
   19355                                         mkexpr( vB ),
   19356                                         binop( Iop_64HLtoV128,
   19357                                                mkU64( 0x7F8000007F800000 ),
   19358                                                mkU64( 0x7F8000007F800000 ) ) ),
   19359                                  mkU8( 23 ) ) );
   19360          } else if (inst_select == 9) {
   19361             Int i;
   19362             IRExpr *normal[4];
   19363             IRTemp value[4];
   19364             IRTemp new_value[4];
   19365             IRTemp new_XT[5];
   19366 
   19367             DIP("xvxsigsp v%d,v%d\n", XT, XB);
   19368             new_XT[0] = newTemp(Ity_V128);
   19369             assign( new_XT[0], binop( Iop_64HLtoV128,
   19370                                       mkU64( 0x0 ),
   19371                                       mkU64( 0x0 ) ) );
   19372 
   19373             for (i = 0; i < 4; i++) {
   19374                value[i] = newTemp(Ity_I32);
   19375                assign( value[i],
   19376                        unop( Iop_64to32,
   19377                              unop( Iop_V128to64,
   19378                                    binop( Iop_AndV128,
   19379                                           binop( Iop_ShrV128,
   19380                                                  mkexpr( vB ),
   19381                                                  mkU8( (3-i)*32 ) ),
   19382                                           binop( Iop_64HLtoV128,
   19383                                                  mkU64( 0x0 ),
   19384                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
   19385 
   19386                new_XT[i+1] = newTemp(Ity_V128);
   19387 
   19388                /* Value is normal if it isn't infinite, zero or denormalized */
   19389                normal[i] = mkNOT1( mkOR1(
   19390                                          mkOR1( is_NaN( Ity_I32, value[i] ),
   19391                                                 is_Inf( Ity_I32, value[i] ) ),
   19392                                          mkOR1( is_Zero( Ity_I32, value[i] ),
   19393                                                 is_Denorm( Ity_I32,
   19394                                                            value[i] ) ) ) );
   19395                new_value[i] = newTemp(Ity_I32);
   19396                assign( new_value[i],
   19397                        binop( Iop_Or32,
   19398                               binop( Iop_And32,
   19399                                      mkexpr( value[i] ),
   19400                                      mkU32( 0x7FFFFF ) ),
   19401                               binop( Iop_Shl32,
   19402                                      unop( Iop_1Uto32,
   19403                                            normal[i]),
   19404                                      mkU8( 23 ) ) ) );
   19405 
   19406                assign( new_XT[i+1],
   19407                        binop( Iop_OrV128,
   19408                               binop( Iop_ShlV128,
   19409                                      binop( Iop_64HLtoV128,
   19410                                             mkU64( 0x0 ),
   19411                                             binop( Iop_32HLto64,
   19412                                                    mkU32( 0x0 ),
   19413                                                    mkexpr( new_value[i] ) ) ),
   19414                                      mkU8( (3-i)*32 ) ),
   19415                               mkexpr( new_XT[i] ) ) );
   19416             }
   19417             putVSReg( XT, mkexpr( new_XT[4] ) );
   19418 
   19419          } else if (inst_select == 15) {
   19420             IRTemp sub_element0 = newTemp( Ity_V128 );
   19421             IRTemp sub_element1 = newTemp( Ity_V128 );
   19422             IRTemp sub_element2 = newTemp( Ity_V128 );
   19423             IRTemp sub_element3 = newTemp( Ity_V128 );
   19424 
   19425             DIP("xxbrw v%d, v%d\n", (UInt)XT, (UInt)XB);
   19426 
   19427             assign( sub_element0,
   19428                     binop( Iop_ShrV128,
   19429                            binop( Iop_AndV128,
   19430                                   binop(Iop_64HLtoV128,
   19431                                         mkU64( 0xFF000000FF000000 ),
   19432                                         mkU64( 0xFF000000FF000000 ) ),
   19433                                   mkexpr( vB ) ),
   19434                            mkU8( 24 ) ) );
   19435             assign( sub_element1,
   19436                     binop( Iop_ShrV128,
   19437                            binop( Iop_AndV128,
   19438                                   binop(Iop_64HLtoV128,
   19439                                         mkU64( 0x00FF000000FF0000 ),
   19440                                         mkU64( 0x00FF000000FF0000 ) ),
   19441                                   mkexpr( vB ) ),
   19442                            mkU8( 8 ) ) );
   19443             assign( sub_element2,
   19444                     binop( Iop_ShlV128,
   19445                            binop( Iop_AndV128,
   19446                                   binop(Iop_64HLtoV128,
   19447                                         mkU64( 0x0000FF000000FF00 ),
   19448                                         mkU64( 0x0000FF000000FF00 ) ),
   19449                                   mkexpr( vB ) ),
   19450                            mkU8( 8 ) ) );
   19451             assign( sub_element3,
   19452                     binop( Iop_ShlV128,
   19453                            binop( Iop_AndV128,
   19454                                   binop(Iop_64HLtoV128,
   19455                                         mkU64( 0x00000000FF000000FF ),
   19456                                         mkU64( 0x00000000FF000000FF ) ),
   19457                                   mkexpr( vB ) ),
   19458                            mkU8( 24 ) ) );
   19459 
   19460             putVSReg( XT,
   19461                       binop( Iop_OrV128,
   19462                              binop( Iop_OrV128,
   19463                                     mkexpr( sub_element3 ),
   19464                                     mkexpr( sub_element2 ) ),
   19465                              binop( Iop_OrV128,
   19466                                     mkexpr( sub_element1 ),
   19467                                     mkexpr( sub_element0 ) ) ) );
   19468 
   19469          } else if (inst_select == 23) {
   19470             DIP("xxbrd v%d, v%d\n", (UInt)XT, (UInt)XB);
   19471 
   19472             int i;
   19473             int shift = 56;
   19474             IRTemp sub_element[16];
   19475             IRTemp new_xT[17];
   19476 
   19477             new_xT[0] = newTemp( Ity_V128 );
   19478             assign( new_xT[0], binop( Iop_64HLtoV128,
   19479                                       mkU64( 0 ),
   19480                                       mkU64( 0 ) ) );
   19481 
   19482             for ( i = 0; i < 4; i++ ) {
   19483                new_xT[i+1] = newTemp( Ity_V128 );
   19484                sub_element[i]   = newTemp( Ity_V128 );
   19485                sub_element[i+4] = newTemp( Ity_V128 );
   19486 
   19487                assign( sub_element[i],
   19488                        binop( Iop_ShrV128,
   19489                               binop( Iop_AndV128,
   19490                                      binop( Iop_64HLtoV128,
   19491                                             mkU64( (0xFFULL << (7 - i) * 8) ),
   19492                                             mkU64( (0xFFULL << (7 - i) * 8) ) ),
   19493                                      mkexpr( vB ) ),
   19494                               mkU8( shift ) ) );
   19495 
   19496                assign( sub_element[i+4],
   19497                        binop( Iop_ShlV128,
   19498                               binop( Iop_AndV128,
   19499                                      binop( Iop_64HLtoV128,
   19500                                             mkU64( (0xFFULL << i*8) ),
   19501                                             mkU64( (0xFFULL << i*8) ) ),
   19502                                      mkexpr( vB ) ),
   19503                               mkU8( shift ) ) );
   19504                shift = shift - 16;
   19505 
   19506                assign( new_xT[i+1],
   19507                        binop( Iop_OrV128,
   19508                               mkexpr( new_xT[i] ),
   19509                               binop( Iop_OrV128,
   19510                                      mkexpr ( sub_element[i] ),
   19511                                      mkexpr ( sub_element[i+4] ) ) ) );
   19512                }
   19513 
   19514             putVSReg( XT, mkexpr( new_xT[4] ) );
   19515 
   19516          } else if (inst_select == 24) {
   19517             // xvcvhpsp, (VSX Vector Convert half-precision format to
   19518             //           Single-precision format)
   19519             /* only supported on ISA 3.0 and newer */
   19520             IRTemp result = newTemp( Ity_V128 );
   19521             IRTemp src  = newTemp( Ity_I64 );
   19522 
   19523             if (!allow_isa_3_0) return False;
   19524 
   19525             DIP("xvcvhpsp v%d,v%d\n", XT,XB);
   19526             /* The instruction does not set the C or FPCC fields.  The
   19527              * instruction takes four 16-bit values stored in a 128-bit value
   19528              * as follows:   x V | x V | x V | x V  where V is a 16-bit
   19529              * value and x is an unused 16-bit value. To use Iop_F16toF32x4
   19530              * the four 16-bit values will be gathered into a single 64 bit
   19531              * value.  The backend will scatter the four 16-bit values back
   19532              * into a 128-bit operand before issuing the instruction.
   19533              */
   19534             /* Gather 16-bit float values from V128 source into new 64-bit
   19535              * source value for the Iop.
   19536              */
   19537             assign( src,
   19538                     unop( Iop_V128to64,
   19539                           binop( Iop_Perm8x16,
   19540                                  mkexpr( vB ),
   19541                                  binop ( Iop_64HLtoV128,
   19542                                          mkU64( 0 ),
   19543                                          mkU64( 0x020306070A0B0E0F) ) ) ) );
   19544 
   19545             assign( result, unop( Iop_F16toF32x4, mkexpr( src ) ) );
   19546 
   19547             putVSReg( XT, mkexpr( result ) );
   19548 
   19549          } else if (inst_select == 25) {
   19550             // xvcvsphp, (VSX Vector round and Convert single-precision
   19551             // format to half-precision format)
   19552             /* only supported on ISA 3.0 and newer */
   19553             IRTemp result = newTemp( Ity_V128 );
   19554             IRTemp tmp64  = newTemp( Ity_I64 );
   19555 
   19556             if (!allow_isa_3_0) return False;
   19557             DIP("xvcvsphp v%d,v%d\n", XT,XB);
   19558 
   19559             /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
   19560              * I64 result to the V128 register to store.
   19561              */
   19562             assign( tmp64, unop( Iop_F32toF16x4, mkexpr( vB ) ) );
   19563 
   19564             /* Scatter 16-bit float values from returned 64-bit value
   19565              * of V128 result.
   19566              */
   19567             if (host_endness == VexEndnessLE)
   19568                /* Note location 0 may have a valid number in it.  Location
   19569                 * 15 should always be zero.  Use 0xF to put zeros in the
   19570                 * desired bytes.
   19571                 */
   19572                assign( result,
   19573                        binop( Iop_Perm8x16,
   19574                               binop( Iop_64HLtoV128,
   19575                                      mkexpr( tmp64 ),
   19576                                      mkU64( 0 ) ),
   19577                               binop ( Iop_64HLtoV128,
   19578                                       mkU64( 0x0F0F00010F0F0203 ),
   19579                                       mkU64( 0x0F0F04050F0F0607 ) ) ) );
   19580             else
   19581                assign( result,
   19582                        binop( Iop_Perm8x16,
   19583                               binop( Iop_64HLtoV128,
   19584                                      mkexpr( tmp64 ),
   19585                                      mkU64( 0 ) ),
   19586                               binop ( Iop_64HLtoV128,
   19587                                       mkU64( 0x0F0F06070F0F0405 ),
   19588                                       mkU64( 0x0F0F02030F0F0001 ) ) ) );
   19589             putVSReg( XT, mkexpr( result ) );
   19590 
   19591          } else if ( inst_select == 31 ) {
   19592             int i;
   19593             int shift_left = 8;
   19594             int shift_right = 120;
   19595             IRTemp sub_element[16];
   19596             IRTemp new_xT[9];
   19597 
   19598             DIP("xxbrq v%d, v%d\n", (UInt) XT, (UInt) XB);
   19599 
   19600             new_xT[0] = newTemp( Ity_V128 );
   19601             assign( new_xT[0], binop( Iop_64HLtoV128,
   19602                                       mkU64( 0 ),
   19603                                       mkU64( 0 ) ) );
   19604 
   19605             for ( i = 0; i < 8; i++ ) {
   19606                new_xT[i+1] = newTemp( Ity_V128 );
   19607                sub_element[i]   = newTemp( Ity_V128 );
   19608                sub_element[i+8] = newTemp( Ity_V128 );
   19609 
   19610                assign( sub_element[i],
   19611                        binop( Iop_ShrV128,
   19612                               binop( Iop_AndV128,
   19613                                      binop( Iop_64HLtoV128,
   19614                                             mkU64( ( 0xFFULL << (7 - i) * 8 ) ),
   19615                                             mkU64( 0x0ULL ) ),
   19616                                      mkexpr( vB ) ),
   19617                               mkU8( shift_right ) ) );
   19618                shift_right = shift_right - 16;
   19619 
   19620                assign( sub_element[i+8],
   19621                        binop( Iop_ShlV128,
   19622                               binop( Iop_AndV128,
   19623                                      binop( Iop_64HLtoV128,
   19624                                             mkU64( 0x0ULL ),
   19625                                             mkU64( ( 0xFFULL << (7 - i) * 8 ) ) ),
   19626                                      mkexpr( vB ) ),
   19627                               mkU8( shift_left ) ) );
   19628                shift_left = shift_left + 16;
   19629 
   19630                assign( new_xT[i+1],
   19631                        binop( Iop_OrV128,
   19632                               mkexpr( new_xT[i] ),
   19633                               binop( Iop_OrV128,
   19634                                      mkexpr ( sub_element[i] ),
   19635                                      mkexpr ( sub_element[i+8] ) ) ) );
   19636                }
   19637 
   19638             putVSReg( XT, mkexpr( new_xT[8] ) );
   19639 
   19640          } else {
   19641             vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
   19642             return False;
   19643          }
   19644          break;
   19645       }
   19646 
   19647       case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision)
   19648       {
   19649          UInt DX_mask = IFIELD( theInstr, 16, 5 );
   19650          UInt DC_mask = IFIELD( theInstr, 6, 1 );
   19651          UInt DM_mask = IFIELD( theInstr, 2, 1 );
   19652          UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
   19653 
   19654          IRTemp NaN[2], inf[2], zero[2], dnorm[2], pos[2], DCM[2];
   19655          IRTemp match_value[2];
   19656          IRTemp value[2];
   19657          Int i;
   19658 
   19659          DIP("xvtstdcdp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
   19660 
   19661          for (i = 0; i < 2; i++) {
   19662             NaN[i] = newTemp(Ity_I64);
   19663             inf[i] = newTemp(Ity_I64);
   19664             pos[i] = newTemp(Ity_I64);
   19665             DCM[i] = newTemp(Ity_I64);
   19666             zero[i] = newTemp(Ity_I64);
   19667             dnorm[i] = newTemp(Ity_I64);
   19668 
   19669             value[i] = newTemp(Ity_I64);
   19670             match_value[i] = newTemp(Ity_I64);
   19671 
   19672             assign( value[i],
   19673                     unop( Iop_V128to64,
   19674                           binop( Iop_AndV128,
   19675                                  binop( Iop_ShrV128,
   19676                                         mkexpr( vB ),
   19677                                         mkU8( (1-i)*64 ) ),
   19678                                  binop( Iop_64HLtoV128,
   19679                                         mkU64( 0x0 ),
   19680                                         mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
   19681 
   19682             assign( pos[i], unop( Iop_1Uto64,
   19683                                  binop( Iop_CmpEQ64,
   19684                                         binop( Iop_Shr64,
   19685                                                mkexpr( value[i] ),
   19686                                                mkU8( 63 ) ),
   19687                                         mkU64( 0 ) ) ) );
   19688 
   19689             assign( NaN[i], unop( Iop_1Uto64, is_NaN( Ity_I64, value[i] ) ) );
   19690             assign( inf[i], unop( Iop_1Uto64, is_Inf( Ity_I64, value[i] ) ) );
   19691             assign( zero[i], unop( Iop_1Uto64, is_Zero( Ity_I64, value[i] ) ) );
   19692             assign( dnorm[i], unop( Iop_1Uto64, is_Denorm( Ity_I64,
   19693                                                            value[i] ) ) );
   19694 
   19695             assign( DCM[i], create_DCM( Ity_I64, NaN[i], inf[i], zero[i],
   19696                                         dnorm[i], pos[i] ) );
   19697 
   19698             assign( match_value[i],
   19699                     unop( Iop_1Sto64,
   19700                           binop( Iop_CmpNE64,
   19701                                  binop( Iop_And64,
   19702                                         mkU64( DCMX_mask ),
   19703                                         mkexpr( DCM[i] ) ),
   19704                                  mkU64( 0 ) ) ) );
   19705          }
   19706          putVSReg( XT, binop( Iop_64HLtoV128,
   19707                               mkexpr( match_value[0] ),
   19708                               mkexpr( match_value[1] ) ) );
   19709       }
   19710       break;
   19711 
   19712       case 0x3E0:  // xviexpdp (VSX Vector Insert Exponent Double-Precision)
   19713       {
   19714             Int i;
   19715             IRTemp new_XT[3];
   19716             IRTemp A_value[2];
   19717             IRTemp B_value[2];
   19718             IRExpr *sign[2], *expr[2], *fract[2];
   19719 
   19720             DIP("xviexpdp v%d,v%d\n", XT, XB);
   19721             new_XT[0] = newTemp(Ity_V128);
   19722             assign( new_XT[0], binop( Iop_64HLtoV128,
   19723                                       mkU64( 0x0 ),
   19724                                       mkU64( 0x0 ) ) );
   19725 
   19726             for (i = 0; i < 2; i++) {
   19727                A_value[i] = newTemp(Ity_I64);
   19728                B_value[i] = newTemp(Ity_I64);
   19729 
   19730                assign( A_value[i],
   19731                        unop( Iop_V128to64,
   19732                              binop( Iop_AndV128,
   19733                                     binop( Iop_ShrV128,
   19734                                            mkexpr( vA ),
   19735                                            mkU8( (1-i)*64 ) ),
   19736                                     binop( Iop_64HLtoV128,
   19737                                            mkU64( 0x0 ),
   19738                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
   19739                assign( B_value[i],
   19740                        unop( Iop_V128to64,
   19741                              binop( Iop_AndV128,
   19742                                     binop( Iop_ShrV128,
   19743                                            mkexpr( vB ),
   19744                                            mkU8( (1-i)*64 ) ),
   19745                                     binop( Iop_64HLtoV128,
   19746                                            mkU64( 0x0 ),
   19747                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
   19748 
   19749                sign[i] = binop( Iop_And64, mkexpr( A_value[i] ),
   19750                                 mkU64( 0x8000000000000000 ) );
   19751                expr[i] = binop( Iop_Shl64,
   19752                                 binop( Iop_And64, mkexpr( B_value[i] ),
   19753                                        mkU64( 0x7FF ) ),
   19754                                 mkU8( 52 ) );
   19755                fract[i] = binop( Iop_And64, mkexpr( A_value[i] ),
   19756                                  mkU64( 0x000FFFFFFFFFFFFF ) );
   19757 
   19758                new_XT[i+1] = newTemp(Ity_V128);
   19759                assign( new_XT[i+1],
   19760                        binop( Iop_OrV128,
   19761                               binop( Iop_ShlV128,
   19762                                      binop( Iop_64HLtoV128,
   19763                                             mkU64( 0 ),
   19764                                             binop( Iop_Or64,
   19765                                                    binop( Iop_Or64,
   19766                                                           sign[i],
   19767                                                           expr[i] ),
   19768                                                    fract[i] ) ),
   19769                                      mkU8( (1-i)*64 ) ),
   19770                               mkexpr( new_XT[i] ) ) );
   19771             }
   19772             putVSReg( XT, mkexpr( new_XT[2] ) );
   19773       }
   19774       break;
   19775 
   19776       default:
   19777          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   19778          return False;
   19779    }
   19780    return True;
   19781 }
   19782 
   19783 /*
   19784  * VSX Logical Instructions
   19785  */
   19786 static Bool
   19787 dis_vx_logic ( UInt theInstr, UInt opc2 )
   19788 {
   19789    /* XX3-Form */
   19790    UChar opc1 = ifieldOPC( theInstr );
   19791    UChar XT = ifieldRegXT ( theInstr );
   19792    UChar XA = ifieldRegXA ( theInstr );
   19793    UChar XB = ifieldRegXB ( theInstr );
   19794    IRTemp vA = newTemp( Ity_V128 );
   19795    IRTemp vB = newTemp( Ity_V128 );
   19796 
   19797    if (opc1 != 0x3C) {
   19798       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   19799       return False;
   19800    }
   19801 
   19802    assign( vA, getVSReg( XA ) );
   19803    assign( vB, getVSReg( XB ) );
   19804 
   19805    switch (opc2) {
   19806       case 0x268: // xxlxor
   19807          DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
   19808          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   19809          break;
   19810       case 0x248: // xxlor
   19811          DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
   19812          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   19813          break;
   19814       case 0x288: // xxlnor
   19815          DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
   19816          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   19817                                                  mkexpr( vB ) ) ) );
   19818          break;
   19819       case 0x208: // xxland
   19820          DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
   19821          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   19822          break;
   19823       case 0x228: //xxlandc
   19824          DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
   19825          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   19826                                                                mkexpr( vB ) ) ) );
   19827          break;
   19828       case 0x2A8: // xxlorc (VSX Logical OR with complement)
   19829          DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
   19830          putVSReg( XT, binop( Iop_OrV128,
   19831                               mkexpr( vA ),
   19832                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
   19833          break;
   19834       case 0x2C8: // xxlnand (VSX Logical NAND)
   19835          DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
   19836          putVSReg( XT, unop( Iop_NotV128,
   19837                              binop( Iop_AndV128, mkexpr( vA ),
   19838                                     mkexpr( vB ) ) ) );
   19839          break;
   19840       case 0x2E8: // xxleqv (VSX Logical Equivalence)
   19841          DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
   19842          putVSReg( XT, unop( Iop_NotV128,
   19843                              binop( Iop_XorV128,
   19844                              mkexpr( vA ), mkexpr( vB ) ) ) );
   19845          break;
   19846       default:
   19847          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   19848          return False;
   19849    }
   19850    return True;
   19851 }
   19852 
   19853 /*
   19854  * VSX Load Instructions
   19855  * NOTE: VSX supports word-aligned storage access.
   19856  */
   19857 static Bool
   19858 dis_vx_load ( UInt theInstr )
   19859 {
   19860    /* XX1-Form */
   19861    UChar opc1 = ifieldOPC( theInstr );
   19862    UChar XT = ifieldRegXT ( theInstr );
   19863    UChar rA_addr = ifieldRegA( theInstr );
   19864    UChar rB_addr = ifieldRegB( theInstr );
   19865    UInt opc2 = ifieldOPClo10( theInstr );
   19866 
   19867    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   19868    IRTemp EA = newTemp( ty );
   19869 
   19870    if (opc1 != 0x1F) {
   19871       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   19872       return False;
   19873    }
   19874 
   19875    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   19876 
   19877    switch (opc2) {
   19878    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
   19879    {
   19880       IRExpr * exp;
   19881       DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   19882 
   19883       if (host_endness == VexEndnessLE)
   19884          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   19885       else
   19886          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   19887 
   19888       putVSReg( XT, binop( Iop_64HLtoV128,
   19889                            unop( Iop_32Uto64, exp),
   19890                            mkU64(0) ) );
   19891       break;
   19892    }
   19893    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
   19894    {
   19895       IRExpr * exp;
   19896       DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   19897 
   19898       if (host_endness == VexEndnessLE)
   19899          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   19900       else
   19901          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   19902 
   19903       putVSReg( XT, binop( Iop_64HLtoV128,
   19904                            unop( Iop_32Sto64, exp),
   19905                            mkU64(0) ) );
   19906       break;
   19907    }
   19908    case 0x10C: // lxvx
   19909    {
   19910       UInt ea_off = 0;
   19911       IRExpr* irx_addr;
   19912       IRTemp word[4];
   19913       int i;
   19914 
   19915       DIP("lxvx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   19916 
   19917       if ( host_endness == VexEndnessBE ) {
   19918          for ( i = 3; i>= 0; i-- ) {
   19919             word[i] = newTemp( Ity_I64 );
   19920 
   19921             irx_addr =
   19922                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   19923                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   19924 
   19925             assign( word[i], unop( Iop_32Uto64,
   19926                                    load( Ity_I32, irx_addr ) ) );
   19927             ea_off += 4;
   19928          }
   19929 
   19930          putVSReg( XT, binop( Iop_64HLtoV128,
   19931                               binop( Iop_Or64,
   19932                                      mkexpr( word[2] ),
   19933                                      binop( Iop_Shl64,
   19934                                             mkexpr( word[3] ),
   19935                                             mkU8( 32 ) ) ),
   19936                               binop( Iop_Or64,
   19937                                      mkexpr( word[0] ),
   19938                                      binop( Iop_Shl64,
   19939                                             mkexpr( word[1] ),
   19940                                             mkU8( 32 ) ) ) ) );
   19941       } else {
   19942          for ( i = 0; i< 4; i++ ) {
   19943             word[i] = newTemp( Ity_I64 );
   19944 
   19945             irx_addr =
   19946                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   19947                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   19948 
   19949             assign( word[i], unop( Iop_32Uto64,
   19950                                    load( Ity_I32, irx_addr ) ) );
   19951             ea_off += 4;
   19952          }
   19953 
   19954          putVSReg( XT, binop( Iop_64HLtoV128,
   19955                               binop( Iop_Or64,
   19956                                      mkexpr( word[2] ),
   19957                                      binop( Iop_Shl64,
   19958                                             mkexpr( word[3] ),
   19959                                             mkU8( 32 ) ) ),
   19960                               binop( Iop_Or64,
   19961                                      mkexpr( word[0] ),
   19962                                      binop( Iop_Shl64,
   19963                                             mkexpr( word[1] ),
   19964                                             mkU8( 32 ) ) ) ) );
   19965       }
   19966       break;
   19967    }
   19968 
   19969    case 0x10D: // lxvl
   19970    {
   19971       DIP("lxvl %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   19972 
   19973       IRTemp byte[16];
   19974       UInt i;
   19975       UInt ea_off = 0;
   19976       IRExpr* irx_addr;
   19977       IRTemp tmp_low[9];
   19978       IRTemp tmp_hi[9];
   19979       IRTemp shift = newTemp( Ity_I8 );
   19980       IRTemp nb_gt16 = newTemp( Ity_I8 );
   19981       IRTemp ld_result = newTemp( Ity_V128 );
   19982       IRTemp nb_not_zero = newTemp( Ity_I64 );
   19983 
   19984       IRTemp base_addr = newTemp( ty );
   19985 
   19986       tmp_low[0] = newTemp( Ity_I64 );
   19987       tmp_hi[0] = newTemp( Ity_I64 );
   19988 
   19989       assign( base_addr, ea_rAor0( rA_addr ) );
   19990       assign( tmp_low[0], mkU64( 0 ) );
   19991       assign( tmp_hi[0], mkU64( 0 ) );
   19992 
   19993       /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */
   19994       assign( nb_not_zero, unop( Iop_1Sto64,
   19995                                   binop( Iop_CmpNE64,
   19996                                          mkU64( 0 ),
   19997                                          binop( Iop_Shr64,
   19998                                                 getIReg( rB_addr ),
   19999                                                 mkU8( 56 ) ) ) ) );
   20000 
   20001       assign( nb_gt16, unop( Iop_1Sto8,
   20002                              binop( Iop_CmpLT64U,
   20003                                     binop( Iop_Shr64,
   20004                                            getIReg( rB_addr ),
   20005                                            mkU8( 60 ) ),
   20006                                     mkU64( 1 ) ) ) );
   20007 
   20008       /* Set the shift to 0, by ANDing with nb_gt16.  nb_gt16 will be all
   20009        * zeros if nb > 16.  This will result in quad word load being stored.
   20010        */
   20011       assign( shift,
   20012               binop( Iop_And8,
   20013                      unop( Iop_64to8,
   20014                            binop( Iop_Mul64,
   20015                                   binop( Iop_Sub64,
   20016                                          mkU64 ( 16 ),
   20017                                          binop( Iop_Shr64,
   20018                                                 getIReg( rB_addr ),
   20019                                                 mkU8( 56 ) ) ),
   20020                                   mkU64( 8 ) ) ),
   20021                      mkexpr( nb_gt16 ) ) );
   20022 
   20023       /* fetch all 16 bytes, we will remove what we don't want later */
   20024       if ( host_endness == VexEndnessBE ) {
   20025          for ( i = 0; i < 8; i++ ) {
   20026             byte[i] = newTemp( Ity_I64 );
   20027             tmp_hi[i+1] = newTemp( Ity_I64 );
   20028 
   20029             irx_addr =
   20030                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20031                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20032             ea_off += 1;
   20033 
   20034             assign( byte[i], binop( Iop_Shl64,
   20035                                       unop( Iop_8Uto64,
   20036                                             load( Ity_I8, irx_addr ) ),
   20037                                       mkU8( 8 * ( 7 - i ) ) ) );
   20038 
   20039             assign( tmp_hi[i+1], binop( Iop_Or64,
   20040                                         mkexpr( byte[i] ),
   20041                                         mkexpr( tmp_hi[i] ) ) );
   20042          }
   20043 
   20044          for ( i = 0; i < 8; i++ ) {
   20045             byte[i+8] = newTemp( Ity_I64 );
   20046             tmp_low[i+1] = newTemp( Ity_I64 );
   20047 
   20048             irx_addr =
   20049                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20050                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20051             ea_off += 1;
   20052 
   20053             assign( byte[i+8], binop( Iop_Shl64,
   20054                                     unop( Iop_8Uto64,
   20055                                           load( Ity_I8, irx_addr ) ),
   20056                                     mkU8( 8 * ( 7 - i ) ) ) );
   20057 
   20058             assign( tmp_low[i+1], binop( Iop_Or64,
   20059                                          mkexpr( byte[i+8] ),
   20060                                          mkexpr( tmp_low[i] ) ) );
   20061          }
   20062          assign( ld_result, binop( Iop_ShlV128,
   20063                                    binop( Iop_ShrV128,
   20064                                           binop( Iop_64HLtoV128,
   20065                                                  mkexpr( tmp_hi[8] ),
   20066                                                  mkexpr( tmp_low[8] ) ),
   20067                                           mkexpr( shift ) ),
   20068                                    mkexpr( shift ) ) );
   20069       } else {
   20070          for ( i = 0; i < 8; i++ ) {
   20071             byte[i] = newTemp( Ity_I64 );
   20072             tmp_low[i+1] = newTemp( Ity_I64 );
   20073 
   20074             irx_addr =
   20075                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20076                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20077             ea_off += 1;
   20078 
   20079             assign( byte[i], binop( Iop_Shl64,
   20080                                     unop( Iop_8Uto64,
   20081                                           load( Ity_I8, irx_addr ) ),
   20082                                     mkU8( 8 * i ) ) );
   20083 
   20084             assign( tmp_low[i+1],
   20085                     binop( Iop_Or64,
   20086                            mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
   20087          }
   20088 
   20089          for ( i = 0; i < 8; i++ ) {
   20090             byte[i + 8] = newTemp( Ity_I64 );
   20091             tmp_hi[i+1] = newTemp( Ity_I64 );
   20092 
   20093             irx_addr =
   20094                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20095                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20096             ea_off += 1;
   20097 
   20098             assign( byte[i+8], binop( Iop_Shl64,
   20099                                       unop( Iop_8Uto64,
   20100                                             load( Ity_I8, irx_addr ) ),
   20101                                       mkU8( 8 * i ) ) );
   20102 
   20103             assign( tmp_hi[i+1], binop( Iop_Or64,
   20104                                         mkexpr( byte[i+8] ),
   20105                                         mkexpr( tmp_hi[i] ) ) );
   20106          }
   20107          assign( ld_result, binop( Iop_ShrV128,
   20108                                    binop( Iop_ShlV128,
   20109                                           binop( Iop_64HLtoV128,
   20110                                                  mkexpr( tmp_hi[8] ),
   20111                                                  mkexpr( tmp_low[8] ) ),
   20112                                           mkexpr( shift ) ),
   20113                                    mkexpr( shift ) ) );
   20114       }
   20115 
   20116 
   20117       /* If nb = 0, mask out the calculated load result so the stored
   20118        * value is zero.
   20119        */
   20120 
   20121       putVSReg( XT, binop( Iop_AndV128,
   20122                            mkexpr( ld_result ),
   20123                            binop( Iop_64HLtoV128,
   20124                                   mkexpr( nb_not_zero ),
   20125                                   mkexpr( nb_not_zero ) ) ) );
   20126       break;
   20127    }
   20128 
   20129    case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
   20130    {
   20131       IRTemp byte[16];
   20132       IRTemp tmp_low[9];
   20133       IRTemp tmp_hi[9];
   20134       IRTemp mask = newTemp(Ity_V128);
   20135       IRTemp rB = newTemp( Ity_I64 );
   20136       IRTemp nb = newTemp( Ity_I64 );
   20137       IRTemp nb_zero = newTemp(Ity_V128);
   20138       IRTemp mask_shift = newTemp(Ity_I64);
   20139       Int i;
   20140       UInt ea_off = 0;
   20141       IRExpr* irx_addr;
   20142       IRTemp base_addr = newTemp( ty );
   20143       IRTemp nb_compare_zero = newTemp( Ity_I64 );
   20144 
   20145       DIP("lxvll %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20146 
   20147       tmp_low[0] = newTemp(Ity_I64);
   20148       tmp_hi[0] = newTemp(Ity_I64);
   20149 
   20150       assign( rB, getIReg(rB_addr));
   20151       assign( base_addr, ea_rAor0( rA_addr ) );
   20152       assign( tmp_low[0], mkU64( 0 ) );
   20153       assign( tmp_hi[0], mkU64( 0 ) );
   20154 
   20155       /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */
   20156       assign( nb, binop( Iop_Shr64, mkexpr( rB ), mkU8( 56 )  ) );
   20157 
   20158       assign( nb_compare_zero, unop( Iop_1Sto64,
   20159                                      binop( Iop_CmpEQ64,
   20160                                             mkexpr( nb ),
   20161                                             mkU64( 0 ) ) ) );
   20162 
   20163       /* nb_zero is 0xFF..FF if the nb_field = 0 */
   20164       assign( nb_zero, binop( Iop_64HLtoV128,
   20165                               mkexpr( nb_compare_zero ),
   20166                               mkexpr( nb_compare_zero ) ) );
   20167 
   20168       assign( mask_shift, binop( Iop_Sub64,
   20169                                  mkU64( 16*8 ),
   20170                                  binop( Iop_Mul64,
   20171                                         mkexpr( nb ),
   20172                                         mkU64( 8 ) ) ) );
   20173 
   20174       /* fetch all 16 bytes, we will remove what we don't want later */
   20175       for (i = 0; i < 8; i++) {
   20176          byte[i] = newTemp(Ity_I64);
   20177          tmp_hi[i+1] = newTemp(Ity_I64);
   20178 
   20179          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20180                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20181          ea_off += 1;
   20182 
   20183          /* Instruction always loads in Big Endian format */
   20184          assign( byte[i], binop( Iop_Shl64,
   20185                                  unop( Iop_8Uto64,
   20186                                        load( Ity_I8, irx_addr ) ),
   20187                                  mkU8( 8 * (7 - i) ) ) );
   20188          assign( tmp_hi[i+1],
   20189                  binop( Iop_Or64,
   20190                         mkexpr( byte[i] ), mkexpr( tmp_hi[i] ) ) );
   20191       }
   20192 
   20193       for (i = 0; i < 8; i++) {
   20194          byte[i + 8]  = newTemp(Ity_I64);
   20195          tmp_low[i+1] = newTemp(Ity_I64);
   20196 
   20197          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20198                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20199          ea_off += 1;
   20200 
   20201          /* Instruction always loads in Big Endian format */
   20202         assign( byte[i+8], binop( Iop_Shl64,
   20203                                    unop( Iop_8Uto64,
   20204                                          load( Ity_I8, irx_addr ) ),
   20205                                    mkU8( 8 * (7 - i) ) ) );
   20206          assign( tmp_low[i+1], binop( Iop_Or64,
   20207                                       mkexpr( byte[i+8] ),
   20208                                       mkexpr( tmp_low[i] ) ) );
   20209       }
   20210 
   20211       /* Create mask to clear the right most 16 - nb bytes, set to zero
   20212        * if nb= 0.
   20213        */
   20214       assign( mask, binop( Iop_AndV128,
   20215                           binop( Iop_ShlV128,
   20216                                   binop( Iop_ShrV128,
   20217                                          mkV128( 0xFFFF ),
   20218                                          unop( Iop_64to8, mkexpr( mask_shift ) ) ),
   20219                                   unop( Iop_64to8, mkexpr( mask_shift ) ) ),
   20220                            unop( Iop_NotV128, mkexpr( nb_zero ) ) ) );
   20221 
   20222       putVSReg( XT, binop( Iop_AndV128,
   20223                            mkexpr( mask ),
   20224                            binop( Iop_64HLtoV128,
   20225                                   mkexpr( tmp_hi[8] ),
   20226                                   mkexpr( tmp_low[8] ) ) ) );
   20227       break;
   20228    }
   20229 
   20230    case 0x16C: // lxvwsx
   20231    {
   20232       IRTemp data = newTemp( Ity_I64 );
   20233 
   20234       DIP("lxvwsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20235 
   20236       /* The load is a 64-bit fetch that is Endian aware, just want
   20237        * the lower 32 bits. */
   20238       if ( host_endness == VexEndnessBE ) {
   20239          UInt ea_off = 4;
   20240          IRExpr* irx_addr;
   20241 
   20242          irx_addr =
   20243             binop( mkSzOp( ty, Iop_Sub8 ), mkexpr( EA ),
   20244                    ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20245 
   20246          assign( data, binop( Iop_And64,
   20247                               load( Ity_I64, irx_addr ),
   20248                               mkU64( 0xFFFFFFFF ) ) );
   20249 
   20250       } else {
   20251          assign( data, binop( Iop_And64,
   20252                               load( Ity_I64, mkexpr( EA ) ),
   20253                               mkU64( 0xFFFFFFFF ) ) );
   20254       }
   20255 
   20256       /* Take lower 32-bits and spat across the four word positions */
   20257       putVSReg( XT,
   20258                 binop( Iop_64HLtoV128,
   20259                        binop( Iop_Or64,
   20260                               mkexpr( data ),
   20261                               binop( Iop_Shl64,
   20262                                      mkexpr( data ),
   20263                                      mkU8( 32 ) ) ),
   20264                        binop( Iop_Or64,
   20265                               mkexpr( data ),
   20266                               binop( Iop_Shl64,
   20267                                      mkexpr( data ),
   20268                                      mkU8( 32 ) ) ) ) );
   20269       break;
   20270    }
   20271 
   20272    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
   20273    {
   20274       IRExpr * exp;
   20275       DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   20276       /* Take 32-bit floating point value in the upper half of the fetched
   20277        * 64-bit value, convert to 64-bit floating point value and load into
   20278        * top word of V128.
   20279        */
   20280       exp = unop( Iop_ReinterpF64asI64,
   20281                   unop( Iop_F32toF64,
   20282                         unop( Iop_ReinterpI32asF32,
   20283                               load( Ity_I32, mkexpr( EA ) ) ) ) );
   20284 
   20285       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
   20286       break;
   20287    }
   20288    case 0x24C: // lxsdx
   20289    {
   20290       IRExpr * exp;
   20291       DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   20292       exp = load( Ity_I64, mkexpr( EA ) );
   20293       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   20294       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   20295       // are undefined after this operation, we can just do a splat op.
   20296       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   20297       break;
   20298    }
   20299 
   20300    case 0x30D: // lxsibzx
   20301    {
   20302       IRExpr *byte;
   20303       IRExpr* irx_addr;
   20304 
   20305       DIP("lxsibzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20306 
   20307       if ( host_endness == VexEndnessBE )
   20308          irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 7 ) );
   20309 
   20310       else
   20311          irx_addr = mkexpr( EA );
   20312 
   20313       byte = load( Ity_I64, irx_addr );
   20314       putVSReg( XT, binop( Iop_64HLtoV128,
   20315                             binop( Iop_And64,
   20316                                    byte,
   20317                                    mkU64( 0xFF ) ),
   20318                            mkU64( 0 ) ) );
   20319       break;
   20320    }
   20321 
   20322    case 0x32D: // lxsihzx
   20323    {
   20324       IRExpr *byte;
   20325       IRExpr* irx_addr;
   20326 
   20327       DIP("lxsihzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20328 
   20329       if ( host_endness == VexEndnessBE )
   20330          irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 6 ) );
   20331 
   20332       else
   20333          irx_addr = mkexpr( EA );
   20334 
   20335       byte = load( Ity_I64, irx_addr );
   20336       putVSReg( XT, binop( Iop_64HLtoV128,
   20337                             binop( Iop_And64,
   20338                                    byte,
   20339                                    mkU64( 0xFFFF ) ),
   20340                            mkU64( 0 ) ) );
   20341       break;
   20342    }
   20343    case 0x34C: // lxvd2x
   20344    {
   20345       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   20346       IRExpr * high, *low;
   20347       ULong ea_off = 8;
   20348       IRExpr* high_addr;
   20349       DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   20350       high = load( Ity_I64, mkexpr( EA ) );
   20351       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   20352             : mkU32( ea_off ) );
   20353       low = load( Ity_I64, high_addr );
   20354       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   20355       break;
   20356    }
   20357    case 0x14C: // lxvdsx
   20358    {
   20359       IRTemp data = newTemp(Ity_I64);
   20360       DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   20361       assign( data, load( Ity_I64, mkexpr( EA ) ) );
   20362       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   20363       break;
   20364    }
   20365    case 0x30C:
   20366    {
   20367       IRExpr *t0;
   20368 
   20369       DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   20370 
   20371       /* The load will result in the data being in BE order. */
   20372       if (host_endness == VexEndnessLE) {
   20373          IRExpr *t0_BE;
   20374          IRTemp perm_LE = newTemp(Ity_V128);
   20375 
   20376          t0_BE = load( Ity_V128, mkexpr( EA ) );
   20377 
   20378          /*  Permute the data to LE format */
   20379          assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
   20380                                  mkU64(0x0405060700010203ULL)));
   20381 
   20382          t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
   20383       } else {
   20384          t0 = load( Ity_V128, mkexpr( EA ) );
   20385       }
   20386 
   20387       putVSReg( XT, t0 );
   20388       break;
   20389    }
   20390 
   20391    case 0x32C: // lxvh8x
   20392    {
   20393       DIP("lxvh8x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20394 
   20395       IRTemp h_word[8];
   20396       int i;
   20397       UInt ea_off = 0;
   20398       IRExpr* irx_addr;
   20399       IRTemp tmp_low[5];
   20400       IRTemp tmp_hi[5];
   20401 
   20402       tmp_low[0] = newTemp( Ity_I64 );
   20403       tmp_hi[0] = newTemp( Ity_I64 );
   20404       assign( tmp_low[0], mkU64( 0 ) );
   20405       assign( tmp_hi[0], mkU64( 0 ) );
   20406 
   20407       for ( i = 0; i < 4; i++ ) {
   20408          h_word[i]    = newTemp(Ity_I64);
   20409          tmp_low[i+1] = newTemp(Ity_I64);
   20410 
   20411          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20412                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20413          ea_off += 2;
   20414 
   20415          assign( h_word[i], binop( Iop_Shl64,
   20416                                    unop( Iop_16Uto64,
   20417                                          load( Ity_I16, irx_addr ) ),
   20418                                    mkU8( 16 * ( 3 - i ) ) ) );
   20419 
   20420          assign( tmp_low[i+1],
   20421                  binop( Iop_Or64,
   20422                         mkexpr( h_word[i] ), mkexpr( tmp_low[i] ) ) );
   20423       }
   20424 
   20425       for ( i = 0; i < 4; i++ ) {
   20426          h_word[i+4]   = newTemp( Ity_I64 );
   20427          tmp_hi[i+1] = newTemp( Ity_I64 );
   20428 
   20429          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20430                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20431          ea_off += 2;
   20432 
   20433          assign( h_word[i+4], binop( Iop_Shl64,
   20434                                      unop( Iop_16Uto64,
   20435                                            load( Ity_I16, irx_addr ) ),
   20436                                      mkU8( 16 * ( 3 - i ) ) ) );
   20437 
   20438          assign( tmp_hi[i+1], binop( Iop_Or64,
   20439                                      mkexpr( h_word[i+4] ),
   20440                                      mkexpr( tmp_hi[i] ) ) );
   20441       }
   20442       putVSReg( XT, binop( Iop_64HLtoV128,
   20443                            mkexpr( tmp_low[4] ), mkexpr( tmp_hi[4] ) ) );
   20444       break;
   20445    }
   20446 
   20447    case 0x36C: // lxvb16x
   20448    {
   20449       DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   20450 
   20451       IRTemp byte[16];
   20452       int i;
   20453       UInt ea_off = 0;
   20454       IRExpr* irx_addr;
   20455       IRTemp tmp_low[9];
   20456       IRTemp tmp_hi[9];
   20457 
   20458       tmp_low[0] = newTemp( Ity_I64 );
   20459       tmp_hi[0] = newTemp( Ity_I64 );
   20460       assign( tmp_low[0], mkU64( 0 ) );
   20461       assign( tmp_hi[0], mkU64( 0 ) );
   20462 
   20463       for ( i = 0; i < 8; i++ ) {
   20464          byte[i] = newTemp( Ity_I64 );
   20465          tmp_low[i+1] = newTemp( Ity_I64 );
   20466 
   20467          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20468                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20469          ea_off += 1;
   20470 
   20471          assign( byte[i], binop( Iop_Shl64,
   20472                                  unop( Iop_8Uto64,
   20473                                        load( Ity_I8, irx_addr ) ),
   20474                                  mkU8( 8 * ( 7 - i ) ) ) );
   20475 
   20476          assign( tmp_low[i+1],
   20477                  binop( Iop_Or64,
   20478                         mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
   20479       }
   20480 
   20481       for ( i = 0; i < 8; i++ ) {
   20482          byte[i + 8] = newTemp( Ity_I64 );
   20483          tmp_hi[i+1] = newTemp( Ity_I64 );
   20484 
   20485          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20486                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20487          ea_off += 1;
   20488 
   20489          assign( byte[i+8], binop( Iop_Shl64,
   20490                                    unop( Iop_8Uto64,
   20491                                          load( Ity_I8, irx_addr ) ),
   20492                                    mkU8( 8 * ( 7 - i ) ) ) );
   20493          assign( tmp_hi[i+1], binop( Iop_Or64,
   20494                                      mkexpr( byte[i+8] ),
   20495                                      mkexpr( tmp_hi[i] ) ) );
   20496       }
   20497       putVSReg( XT, binop( Iop_64HLtoV128,
   20498                            mkexpr( tmp_low[8] ), mkexpr( tmp_hi[8] ) ) );
   20499       break;
   20500    }
   20501 
   20502    default:
   20503       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   20504       return False;
   20505    }
   20506    return True;
   20507 }
   20508 
   20509 /*
   20510  * VSX Move Instructions
   20511  */
   20512 static Bool
   20513 dis_vx_move ( UInt theInstr )
   20514 {
   20515    /* XX1-Form */
   20516    UChar opc1 = ifieldOPC( theInstr );
   20517    UChar XS = ifieldRegXS( theInstr );
   20518    UChar rA_addr = ifieldRegA( theInstr );
   20519    UChar rB_addr = ifieldRegB( theInstr );
   20520    IRTemp vS = newTemp( Ity_V128 );
   20521    UInt opc2 = ifieldOPClo10( theInstr );
   20522    IRType ty = Ity_I64;
   20523 
   20524    if ( opc1 != 0x1F ) {
   20525       vex_printf( "dis_vx_move(ppc)(instr)\n" );
   20526       return False;
   20527    }
   20528 
   20529    switch (opc2) {
   20530    case 0x133: // mfvsrld RA,XS   Move From VSR Lower Doubleword
   20531       DIP("mfvsrld %d,r%u\n", (UInt)XS, rA_addr);
   20532 
   20533       assign( vS, getVSReg( XS ) );
   20534       putIReg( rA_addr, unop(Iop_V128to64, mkexpr( vS) ) );
   20535 
   20536       break;
   20537 
   20538    case 0x193: // mfvsrdd  XT,RA,RB  Move to VSR Double Doubleword
   20539    {
   20540       IRTemp tmp = newTemp( Ity_I32 );
   20541 
   20542       DIP("mfvsrdd %d,r%u\n", (UInt)XS, rA_addr);
   20543 
   20544       assign( tmp, unop( Iop_64to32, getIReg(rA_addr) ) );
   20545       assign( vS, binop( Iop_64HLtoV128,
   20546                          binop( Iop_32HLto64,
   20547                                 mkexpr( tmp ),
   20548                                 mkexpr( tmp ) ),
   20549                          binop( Iop_32HLto64,
   20550                                 mkexpr( tmp ),
   20551                                 mkexpr( tmp ) ) ) );
   20552       putVSReg( XS, mkexpr( vS ) );
   20553    }
   20554    break;
   20555 
   20556    case 0x1B3: // mtvsrws  XT,RA  Move to VSR word & Splat
   20557    {
   20558       IRTemp rA = newTemp( ty );
   20559       IRTemp rB = newTemp( ty );
   20560 
   20561       DIP("mfvsrws %d,r%u\n", (UInt)XS, rA_addr);
   20562 
   20563       if ( rA_addr == 0 )
   20564          assign( rA, mkU64 ( 0 ) );
   20565       else
   20566          assign( rA, getIReg(rA_addr) );
   20567 
   20568       assign( rB, getIReg(rB_addr) );
   20569       assign( vS, binop( Iop_64HLtoV128, mkexpr( rA ), mkexpr( rB ) ) );
   20570       putVSReg( XS, mkexpr( vS ) );
   20571    }
   20572    break;
   20573 
   20574    default:
   20575       vex_printf( "dis_vx_move(ppc)(opc2)\n" );
   20576       return False;
   20577    }
   20578    return True;
   20579 }
   20580 
   20581 /*
   20582  * VSX Store Instructions
   20583  * NOTE: VSX supports word-aligned storage access.
   20584  */
   20585 static Bool
   20586 dis_vx_store ( UInt theInstr )
   20587 {
   20588    /* XX1-Form */
   20589    UChar opc1 = ifieldOPC( theInstr );
   20590    UChar XS = ifieldRegXS( theInstr );
   20591    UChar rA_addr = ifieldRegA( theInstr );
   20592    UChar rB_addr = ifieldRegB( theInstr );
   20593    IRTemp vS = newTemp( Ity_V128 );
   20594    UInt opc2 = ifieldOPClo10( theInstr );
   20595 
   20596    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   20597    IRTemp EA = newTemp( ty );
   20598 
   20599    if (opc1 != 0x1F) {
   20600       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   20601       return False;
   20602    }
   20603 
   20604    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   20605    assign( vS, getVSReg( XS ) );
   20606 
   20607    switch (opc2) {
   20608    case 0x08C:
   20609    {
   20610      /* Need the next to the most significant 32-bit word from
   20611       * the 128-bit vector.
   20612       */
   20613       IRExpr * high64, * low32;
   20614       DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   20615       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   20616       low32  = unop( Iop_64to32, high64 );
   20617       store( mkexpr( EA ), low32 );
   20618       break;
   20619    }
   20620 
   20621    case 0x18C: // stxvx Store VSX Vector Indexed
   20622    {
   20623       UInt ea_off = 0;
   20624       IRExpr* irx_addr;
   20625       IRTemp word0 = newTemp( Ity_I64 );
   20626       IRTemp word1 = newTemp( Ity_I64 );
   20627       IRTemp word2 = newTemp( Ity_I64 );
   20628       IRTemp word3 = newTemp( Ity_I64 );
   20629       DIP("stxvx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   20630 
   20631       assign( word0,  binop( Iop_Shr64,
   20632                              unop( Iop_V128HIto64, mkexpr( vS ) ),
   20633                              mkU8( 32 ) ) );
   20634 
   20635       assign( word1, binop( Iop_And64,
   20636                             unop( Iop_V128HIto64, mkexpr( vS ) ),
   20637                             mkU64( 0xFFFFFFFF ) ) );
   20638 
   20639       assign( word2, binop( Iop_Shr64,
   20640                             unop( Iop_V128to64, mkexpr( vS ) ),
   20641                             mkU8( 32 ) ) );
   20642 
   20643       assign( word3, binop( Iop_And64,
   20644                             unop( Iop_V128to64, mkexpr( vS ) ),
   20645                             mkU64( 0xFFFFFFFF ) ) );
   20646 
   20647       if (host_endness == VexEndnessBE) {
   20648          store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word0 ) ) );
   20649 
   20650          ea_off += 4;
   20651          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20652                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20653 
   20654          store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
   20655 
   20656          ea_off += 4;
   20657          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20658                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20659 
   20660          store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
   20661          ea_off += 4;
   20662          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20663                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20664 
   20665          store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
   20666       } else {
   20667          store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word3 ) ) );
   20668 
   20669          ea_off += 4;
   20670          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20671                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20672 
   20673          store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
   20674 
   20675          ea_off += 4;
   20676          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20677                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20678 
   20679          store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
   20680          ea_off += 4;
   20681          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   20682                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20683 
   20684          store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
   20685       }
   20686       break;
   20687    }
   20688 
   20689    case 0x18D: // stxvl Store VSX Vector Indexed
   20690    {
   20691       UInt ea_off = 0;
   20692       IRExpr* irx_addr;
   20693       IRTemp word0 = newTemp( Ity_I64 );
   20694       IRTemp word1 = newTemp( Ity_I64 );
   20695       IRTemp word2 = newTemp( Ity_I64 );
   20696       IRTemp word3 = newTemp( Ity_I64 );
   20697       IRTemp shift = newTemp( Ity_I8 );
   20698       IRTemp nb_gt16 = newTemp( Ity_I8 );
   20699       IRTemp nb_zero = newTemp( Ity_V128 );
   20700       IRTemp nb = newTemp( Ity_I8 );
   20701       IRTemp nb_field = newTemp( Ity_I64 );
   20702       IRTemp n_bytes = newTemp( Ity_I8 );
   20703       IRTemp base_addr = newTemp( ty );
   20704       IRTemp current_mem = newTemp( Ity_V128 );
   20705       IRTemp store_val = newTemp( Ity_V128 );
   20706       IRTemp nb_mask = newTemp( Ity_V128 );
   20707 
   20708       DIP("stxvl %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   20709 
   20710       assign( nb_field, binop( Iop_Shr64,
   20711                                getIReg(rB_addr),
   20712                                mkU8( 56 ) ) );
   20713 
   20714       assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
   20715 
   20716       /* nb_gt16 will be all zeros if nb > 16 */
   20717       assign( nb_gt16, unop( Iop_1Sto8,
   20718                              binop( Iop_CmpLT64U,
   20719                                     binop( Iop_Shr64,
   20720                                            mkexpr( nb_field ),
   20721                                            mkU8( 4 ) ),
   20722                                     mkU64( 1 ) ) ) );
   20723 
   20724       /* nb_zero is 0xFF..FF if the nb_field = 0 */
   20725       assign( nb_zero, binop( Iop_64HLtoV128,
   20726                               unop( Iop_1Sto64,
   20727                                     binop( Iop_CmpEQ64,
   20728                                            mkexpr( nb_field ),
   20729                                            mkU64( 0 ) ) ),
   20730                               unop( Iop_1Sto64,
   20731                                     binop( Iop_CmpEQ64,
   20732                                            mkexpr( nb_field ),
   20733                                            mkU64( 0 ) ) ) ) );
   20734 
   20735       /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
   20736       assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
   20737       assign( shift, unop( Iop_64to8,
   20738                            binop( Iop_Mul64,
   20739                                   binop( Iop_Sub64,
   20740                                          mkU64( 16 ),
   20741                                          unop( Iop_8Uto64,
   20742                                                mkexpr( n_bytes ) ) ),
   20743                                   mkU64( 8 ) ) ) );
   20744 
   20745       /* We only have a 32-bit store function. So, need to fetch the
   20746        * contents of memory merge with the store value and do two
   20747        * 32-byte stores so we preserve the contents of memory not
   20748        * addressed by nb.
   20749        */
   20750       assign( base_addr, ea_rAor0( rA_addr ) );
   20751 
   20752       assign( current_mem,
   20753               binop( Iop_64HLtoV128,
   20754                      load( Ity_I64, mkexpr( base_addr ) ),
   20755                      load( Ity_I64,
   20756                            binop( mkSzOp( ty, Iop_Add8 ),
   20757                                   mkexpr( base_addr ),
   20758                                   ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 )
   20759                                   ) ) ) );
   20760 
   20761       /* Set the nb_mask to all zeros if nb = 0 so the current contents
   20762        * of memory get written back without modifications.
   20763        *
   20764        * The store_val is a combination of the current memory value
   20765        * and the bytes you want to store.  The nb_mask selects the
   20766        * bytes you want stored from Vs.
   20767        */
   20768       if (host_endness == VexEndnessBE) {
   20769          assign( nb_mask,
   20770                  binop( Iop_OrV128,
   20771                         binop( Iop_AndV128,
   20772                                binop( Iop_ShlV128,
   20773                                       mkV128( 0xFFFF ),
   20774                                       mkexpr( shift ) ),
   20775                                unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
   20776                         binop( Iop_AndV128,
   20777                                mkexpr( nb_zero ),
   20778                                mkV128( 0 ) ) ) );
   20779 
   20780          assign( store_val,
   20781                  binop( Iop_OrV128,
   20782                         binop( Iop_AndV128,
   20783                                binop( Iop_ShrV128,
   20784                                       mkexpr( vS ),
   20785                                       mkexpr( shift ) ),
   20786                                mkexpr( nb_mask ) ),
   20787                         binop( Iop_AndV128,
   20788                                unop( Iop_NotV128, mkexpr( nb_mask ) ),
   20789                                mkexpr( current_mem) ) ) );
   20790 
   20791       } else {
   20792             assign( nb_mask,
   20793                  binop( Iop_OrV128,
   20794                         binop( Iop_AndV128,
   20795                                binop( Iop_ShrV128,
   20796                                       binop( Iop_ShlV128,
   20797                                              mkV128( 0xFFFF ),
   20798                                              mkexpr( shift ) ),
   20799                                       mkexpr( shift ) ),
   20800                                unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
   20801                         binop( Iop_AndV128,
   20802                                mkexpr( nb_zero ),
   20803                                mkV128( 0 ) ) ) );
   20804 
   20805          assign( store_val,
   20806                  binop( Iop_OrV128,
   20807                         binop( Iop_AndV128,
   20808                                binop( Iop_ShrV128,
   20809                                       binop( Iop_ShlV128,
   20810                                              mkexpr( vS ),
   20811                                              mkexpr( shift ) ),
   20812                                       mkexpr( shift ) ),
   20813                                mkexpr( nb_mask ) ),
   20814                         binop( Iop_AndV128,
   20815                                unop( Iop_NotV128, mkexpr( nb_mask ) ),
   20816                                mkexpr( current_mem) ) ) );
   20817       }
   20818 
   20819       /* Store the value in 32-byte chunks */
   20820       assign( word0,  binop( Iop_Shr64,
   20821                              unop( Iop_V128HIto64, mkexpr( store_val ) ),
   20822                              mkU8( 32 ) ) );
   20823 
   20824       assign( word1, binop( Iop_And64,
   20825                             unop( Iop_V128HIto64, mkexpr( store_val ) ),
   20826                             mkU64( 0xFFFFFFFF ) ) );
   20827 
   20828       assign( word2, binop( Iop_Shr64,
   20829                             unop( Iop_V128to64, mkexpr( store_val ) ),
   20830                             mkU8( 32 ) ) );
   20831 
   20832       assign( word3, binop( Iop_And64,
   20833                             unop( Iop_V128to64, mkexpr( store_val ) ),
   20834                             mkU64( 0xFFFFFFFF ) ) );
   20835 
   20836       ea_off = 0;
   20837       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20838                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20839 
   20840       store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
   20841 
   20842       ea_off += 4;
   20843       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20844                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20845 
   20846       store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
   20847 
   20848       ea_off += 4;
   20849       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20850                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20851 
   20852       store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
   20853 
   20854       ea_off += 4;
   20855       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20856                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20857 
   20858       store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
   20859       break;
   20860    }
   20861 
   20862    case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
   20863    {
   20864       UInt ea_off = 0;
   20865       IRExpr* irx_addr;
   20866       IRTemp word0[5];
   20867       IRTemp word1[5];
   20868       IRTemp word2[5];
   20869       IRTemp word3[5];
   20870       IRTemp shift = newTemp(Ity_I8);
   20871       IRTemp nb_gt16 = newTemp(Ity_I8);
   20872       IRTemp nb_zero = newTemp(Ity_V128);
   20873       IRTemp nb = newTemp(Ity_I8);
   20874       IRTemp nb_field = newTemp(Ity_I64);
   20875       IRTemp n_bytes = newTemp(Ity_I8);
   20876       IRTemp base_addr = newTemp( ty );
   20877       IRTemp current_mem = newTemp(Ity_V128);
   20878       IRTemp store_val = newTemp(Ity_V128);
   20879       IRTemp nb_mask = newTemp(Ity_V128);
   20880       IRTemp mask = newTemp( Ity_I64 );
   20881       IRTemp byte[16];
   20882       IRTemp tmp_low[9];
   20883       IRTemp tmp_hi[9];
   20884       IRTemp nb_field_compare_zero = newTemp( Ity_I64 );
   20885       Int i;
   20886 
   20887       DIP("stxvll %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   20888 
   20889       assign( nb_field, binop( Iop_Shr64,
   20890                                getIReg(rB_addr),
   20891                                mkU8( 56 ) ) );
   20892       assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
   20893       assign( mask, mkU64( 0xFFFFFFFFFFFFFFFFULL ) );
   20894 
   20895       /* nb_gt16 will be all zeros if nb > 16 */
   20896       assign( nb_gt16, unop( Iop_1Sto8,
   20897                              binop( Iop_CmpLT64U,
   20898                                     binop( Iop_Shr64,
   20899                                            mkexpr( nb_field ),
   20900                                            mkU8( 4 ) ),
   20901                                     mkU64( 1 ) ) ) );
   20902 
   20903       assign( nb_field_compare_zero, unop( Iop_1Sto64,
   20904                                            binop( Iop_CmpEQ64,
   20905                                                   mkexpr( nb_field ),
   20906                                                   mkU64( 0 ) ) ) );
   20907 
   20908       /* nb_zero is 0xFF..FF if the nb_field = 0 */
   20909       assign( nb_zero, binop( Iop_64HLtoV128,
   20910                               mkexpr( nb_field_compare_zero ),
   20911                               mkexpr( nb_field_compare_zero ) ) );
   20912 
   20913 
   20914       /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
   20915       assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
   20916       assign( shift,
   20917               unop( Iop_64to8,
   20918                     binop( Iop_Mul64,
   20919                            binop( Iop_Sub64,
   20920                                   mkU64( 16 ),
   20921                                   unop( Iop_8Uto64, mkexpr( n_bytes ) )),
   20922                            mkU64( 8 ) ) ) );
   20923 
   20924       /* We only have a 32-bit store function. So, need to fetch the
   20925        * contents of memory merge with the store value and do two
   20926        * 32-byte stores so we preserve the contents of memory not
   20927        * addressed by nb.
   20928        */
   20929       assign( base_addr, ea_rAor0( rA_addr ) );
   20930       /* fetch all 16 bytes and store in Big Endian format */
   20931       word0[0] = newTemp(Ity_I64);
   20932       assign( word0[0], mkU64( 0 ) );
   20933 
   20934       word1[0] = newTemp(Ity_I64);
   20935       assign( word1[0], mkU64( 0 ) );
   20936 
   20937       word2[0] = newTemp(Ity_I64);
   20938       assign( word2[0], mkU64( 0 ) );
   20939 
   20940       word3[0] = newTemp(Ity_I64);
   20941       assign( word3[0], mkU64( 0 ) );
   20942 
   20943       for (i = 0; i < 4; i++) {
   20944          word0[i+1] = newTemp(Ity_I64);
   20945 
   20946          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20947                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20948          ea_off += 1;
   20949 
   20950          /* Instruction always loads in Big Endian format */
   20951          assign( word0[i+1],
   20952                  binop( Iop_Or64,
   20953                         binop( Iop_Shl64,
   20954                                unop( Iop_8Uto64,
   20955                                      load( Ity_I8,
   20956                                            irx_addr ) ),
   20957                                mkU8( (3-i)*8 ) ),
   20958                         mkexpr( word0[i] ) ) );
   20959       }
   20960 
   20961       for (i = 0; i < 4; i++) {
   20962          word1[i+1] = newTemp(Ity_I64);
   20963 
   20964          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20965                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20966          ea_off += 1;
   20967 
   20968          /* Instruction always loads in Big Endian format */
   20969          assign( word1[i+1],
   20970                  binop( Iop_Or64,
   20971                         binop( Iop_Shl64,
   20972                                unop( Iop_8Uto64,
   20973                                      load( Ity_I8,
   20974                                            irx_addr ) ),
   20975                                mkU8( (3-i)*8 ) ),
   20976                         mkexpr( word1[i] ) ) );
   20977       }
   20978       for (i = 0; i < 4; i++) {
   20979          word2[i+1] = newTemp(Ity_I64);
   20980 
   20981          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20982                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   20983          ea_off += 1;
   20984 
   20985          /* Instruction always loads in Big Endian format */
   20986          assign( word2[i+1],
   20987                  binop( Iop_Or64,
   20988                         binop( Iop_Shl64,
   20989                                unop( Iop_8Uto64,
   20990                                      load( Ity_I8,
   20991                                            irx_addr ) ),
   20992                                mkU8( (3-i)*8 ) ),
   20993                         mkexpr( word2[i] ) ) );
   20994       }
   20995       for (i = 0; i < 4; i++) {
   20996          word3[i+1] = newTemp(Ity_I64);
   20997 
   20998          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   20999                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21000          ea_off += 1;
   21001 
   21002          /* Instruction always loads in Big Endian format */
   21003          assign( word3[i+1],
   21004                  binop( Iop_Or64,
   21005                         binop( Iop_Shl64,
   21006                                unop( Iop_8Uto64,
   21007                                      load( Ity_I8,
   21008                                            irx_addr ) ),
   21009                                mkU8( (3-i)*8 ) ),
   21010                         mkexpr( word3[i] ) ) );
   21011       }
   21012 
   21013 
   21014       assign( current_mem,
   21015               binop( Iop_64HLtoV128,
   21016                      binop( Iop_Or64,
   21017                             binop( Iop_Shl64,
   21018                                    mkexpr( word0[4] ),
   21019                                    mkU8( 32 ) ),
   21020                             mkexpr( word1[4] ) ),
   21021                      binop( Iop_Or64,
   21022                             binop( Iop_Shl64,
   21023                                    mkexpr( word2[4] ),
   21024                                    mkU8( 32 ) ),
   21025                             mkexpr( word3[4] ) ) ) );
   21026 
   21027       /* Set the nb_mask to all zeros if nb = 0 so the current contents
   21028        * of memory get written back without modifications.
   21029        *
   21030        * The store_val is a combination of the current memory value
   21031        * and the bytes you want to store.  The nb_mask selects the
   21032        * bytes you want stored from Vs.
   21033        */
   21034       /* The instruction always uses Big Endian order */
   21035       assign( nb_mask,
   21036               binop( Iop_OrV128,
   21037                      binop( Iop_AndV128,
   21038                             binop( Iop_ShlV128,
   21039                                    binop( Iop_ShrV128,
   21040                                           binop( Iop_64HLtoV128,
   21041                                                  mkexpr( mask ),
   21042                                                  mkexpr( mask ) ),
   21043                                           mkexpr( shift ) ),
   21044                                    mkexpr( shift ) ),
   21045                             unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
   21046                      binop( Iop_AndV128,
   21047                             mkexpr( nb_zero ),
   21048                             binop( Iop_64HLtoV128,
   21049                                    mkU64( 0x0 ),
   21050                                    mkU64( 0x0 ) ) ) ) );
   21051 
   21052       assign( store_val,
   21053               binop( Iop_OrV128,
   21054                      binop( Iop_AndV128,
   21055                             mkexpr( vS ),
   21056                             mkexpr( nb_mask ) ),
   21057                      binop( Iop_AndV128,
   21058                             unop( Iop_NotV128, mkexpr( nb_mask ) ),
   21059                             mkexpr( current_mem) ) ) );
   21060 
   21061       /* store the merged value in Big Endian format */
   21062       tmp_low[0] = newTemp(Ity_I64);
   21063       tmp_hi[0] = newTemp(Ity_I64);
   21064       assign( tmp_low[0], mkU64( 0 ) );
   21065       assign( tmp_hi[0], mkU64( 0 ) );
   21066 
   21067       for (i = 0; i < 8; i++) {
   21068          byte[i] = newTemp(Ity_I64);
   21069          byte[i+8] = newTemp(Ity_I64);
   21070          tmp_low[i+1] = newTemp(Ity_I64);
   21071          tmp_hi[i+1]  = newTemp(Ity_I64);
   21072 
   21073          assign( byte[i], binop( Iop_And64,
   21074                                  binop( Iop_Shr64,
   21075                                         unop( Iop_V128HIto64,
   21076                                               mkexpr( store_val ) ),
   21077                                         mkU8( (7-i)*8 ) ),
   21078                                  mkU64( 0xFF ) ) );
   21079          assign( byte[i+8], binop( Iop_And64,
   21080                                    binop( Iop_Shr64,
   21081                                           unop( Iop_V128to64,
   21082                                                 mkexpr( store_val ) ),
   21083                                           mkU8( (7-i)*8 ) ),
   21084                                    mkU64( 0xFF ) ) );
   21085 
   21086          assign( tmp_low[i+1],
   21087                  binop( Iop_Or64,
   21088                         mkexpr( tmp_low[i] ),
   21089                         binop( Iop_Shl64, mkexpr( byte[i] ), mkU8( i*8 ) ) ) );
   21090          assign( tmp_hi[i+1],
   21091                  binop( Iop_Or64,
   21092                         mkexpr( tmp_hi[i] ),
   21093                         binop( Iop_Shl64, mkexpr( byte[i+8] ),
   21094                                mkU8( i*8 ) ) ) );
   21095       }
   21096 
   21097       /* Store the value in 32-byte chunks */
   21098       ea_off = 0;
   21099       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   21100                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21101 
   21102       store( irx_addr, unop( Iop_64to32, mkexpr( tmp_low[8] ) ) );
   21103 
   21104       ea_off += 4;
   21105       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   21106                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21107 
   21108       store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_low[8] ) ) );
   21109 
   21110       ea_off += 4;
   21111       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   21112                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21113 
   21114       store( irx_addr, unop( Iop_64to32, mkexpr( tmp_hi[8] ) ) );
   21115 
   21116       ea_off += 4;
   21117       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
   21118                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21119 
   21120       store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_hi[8] ) ) );
   21121 
   21122       break;
   21123       }
   21124 
   21125    case 0x28C:
   21126    {
   21127       IRTemp high64 = newTemp(Ity_F64);
   21128       IRTemp val32  = newTemp(Ity_I32);
   21129       DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21130       assign(high64, unop( Iop_ReinterpI64asF64,
   21131                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
   21132       assign(val32, unop( Iop_ReinterpF32asI32,
   21133                           unop( Iop_TruncF64asF32,
   21134                                 mkexpr(high64) ) ) );
   21135       store( mkexpr( EA ), mkexpr( val32 ) );
   21136       break;
   21137    }
   21138    case 0x2CC:
   21139    {
   21140       IRExpr * high64;
   21141       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21142       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   21143       store( mkexpr( EA ), high64 );
   21144       break;
   21145    }
   21146 
   21147    case 0x38D: // stxsibx
   21148    {
   21149       IRExpr *stored_word;
   21150       IRTemp byte_to_store = newTemp( Ity_I64 );
   21151 
   21152       DIP("stxsibx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21153 
   21154       /* Can't store just a byte, need to fetch the word at EA merge data
   21155        * and store.
   21156        */
   21157       stored_word = load( Ity_I64, mkexpr( EA ) );
   21158       assign( byte_to_store, binop( Iop_And64,
   21159                                     unop( Iop_V128HIto64,
   21160                                           mkexpr( vS ) ),
   21161                                     mkU64( 0xFF ) ) );
   21162 
   21163       store( mkexpr( EA ), binop( Iop_Or64,
   21164                                   binop( Iop_And64,
   21165                                          stored_word,
   21166                                          mkU64( 0xFFFFFFFFFFFFFF00 ) ),
   21167                                   mkexpr( byte_to_store ) ) );
   21168       break;
   21169    }
   21170 
   21171    case 0x3AD: // stxsihx
   21172    {
   21173       IRExpr *stored_word;
   21174       IRTemp byte_to_store = newTemp( Ity_I64 );
   21175 
   21176       DIP("stxsihx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21177 
   21178       /* Can't store just a halfword, need to fetch the word at EA merge data
   21179        * and store.
   21180        */
   21181       stored_word = load( Ity_I64, mkexpr( EA ) );
   21182       assign( byte_to_store, binop( Iop_And64,
   21183                                     unop( Iop_V128HIto64,
   21184                                           mkexpr( vS ) ),
   21185                                     mkU64( 0xFFFF ) ) );
   21186 
   21187       store( mkexpr( EA ), binop( Iop_Or64,
   21188                                   binop( Iop_And64,
   21189                                          stored_word,
   21190                                          mkU64( 0xFFFFFFFFFFFF0000 ) ),
   21191                                   mkexpr( byte_to_store ) ) );
   21192       break;
   21193    }
   21194 
   21195    case 0x3CC:
   21196    {
   21197       IRExpr * high64, *low64;
   21198       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21199       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   21200       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   21201       store( mkexpr( EA ), high64 );
   21202       store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21203                     ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
   21204       break;
   21205    }
   21206    case 0x38C:
   21207    {
   21208       UInt ea_off = 0;
   21209       IRExpr* irx_addr;
   21210       IRTemp hi64 = newTemp( Ity_I64 );
   21211       IRTemp lo64 = newTemp( Ity_I64 );
   21212 
   21213       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21214 
   21215       // This instruction supports word-aligned stores, so EA may not be
   21216       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   21217       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   21218       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   21219       store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   21220       ea_off += 4;
   21221       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21222                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21223       store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   21224       ea_off += 4;
   21225       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21226                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21227       store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   21228       ea_off += 4;
   21229       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21230                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21231       store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   21232 
   21233       break;
   21234    }
   21235    case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
   21236    {
   21237       UInt ea_off = 0;
   21238       IRExpr* irx_addr;
   21239       IRTemp half_word0 = newTemp( Ity_I64 );
   21240       IRTemp half_word1 = newTemp( Ity_I64 );
   21241       IRTemp half_word2 = newTemp( Ity_I64 );
   21242       IRTemp half_word3 = newTemp( Ity_I64 );
   21243       IRTemp half_word4 = newTemp( Ity_I64 );
   21244       IRTemp half_word5 = newTemp( Ity_I64 );
   21245       IRTemp half_word6 = newTemp( Ity_I64 );
   21246       IRTemp half_word7 = newTemp( Ity_I64 );
   21247 
   21248       DIP("stxvb8x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21249 
   21250       assign( half_word0, binop( Iop_Shr64,
   21251                                  unop( Iop_V128HIto64, mkexpr( vS ) ),
   21252                                  mkU8( 48 ) ) );
   21253 
   21254       assign( half_word1, binop( Iop_And64,
   21255                                  binop( Iop_Shr64,
   21256                                         unop( Iop_V128HIto64, mkexpr( vS ) ),
   21257                                         mkU8( 32 ) ),
   21258                                  mkU64( 0xFFFF ) ) );
   21259 
   21260       assign( half_word2, binop( Iop_And64,
   21261                                  binop( Iop_Shr64,
   21262                                         unop( Iop_V128HIto64, mkexpr( vS ) ),
   21263                                         mkU8( 16 ) ),
   21264                                  mkU64( 0xFFFF ) ) );
   21265 
   21266       assign( half_word3, binop( Iop_And64,
   21267                                  unop( Iop_V128HIto64, mkexpr( vS ) ),
   21268                                  mkU64( 0xFFFF ) ) );
   21269 
   21270       assign( half_word4, binop( Iop_Shr64,
   21271                                  unop( Iop_V128to64, mkexpr( vS ) ),
   21272                                  mkU8( 48 ) ) );
   21273 
   21274       assign( half_word5, binop( Iop_And64,
   21275                                  binop( Iop_Shr64,
   21276                                         unop( Iop_V128to64, mkexpr( vS ) ),
   21277                                         mkU8( 32 ) ),
   21278                                  mkU64( 0xFFFF ) ) );
   21279 
   21280       assign( half_word6, binop( Iop_And64,
   21281                                  binop( Iop_Shr64,
   21282                                         unop( Iop_V128to64, mkexpr( vS ) ),
   21283                                         mkU8( 16 ) ),
   21284                                  mkU64( 0xFFFF ) ) );
   21285 
   21286       assign( half_word7, binop( Iop_And64,
   21287                                  unop( Iop_V128to64, mkexpr( vS ) ),
   21288                                  mkU64( 0xFFFF ) ) );
   21289 
   21290       /* Do the 32-bit stores.  The store() does an Endian aware store. */
   21291       if ( host_endness == VexEndnessBE ) {
   21292          store( mkexpr( EA ), unop( Iop_64to32,
   21293                                     binop( Iop_Or64,
   21294                                            mkexpr( half_word1 ),
   21295                                            binop( Iop_Shl64,
   21296                                                   mkexpr( half_word0 ),
   21297                                                   mkU8( 16 ) ) ) ) );
   21298 
   21299          ea_off += 4;
   21300          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21301                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21302 
   21303 
   21304          store( irx_addr, unop( Iop_64to32,
   21305                                 binop( Iop_Or64,
   21306                                        mkexpr( half_word3 ),
   21307                                        binop( Iop_Shl64,
   21308                                               mkexpr( half_word2 ),
   21309                                               mkU8( 16 ) ) ) ) );
   21310 
   21311          ea_off += 4;
   21312          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21313                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21314 
   21315          store( irx_addr, unop( Iop_64to32,
   21316                                 binop( Iop_Or64,
   21317                                        mkexpr( half_word5 ),
   21318                                        binop( Iop_Shl64,
   21319                                               mkexpr( half_word4 ),
   21320                                               mkU8( 16 ) ) ) ) );
   21321          ea_off += 4;
   21322          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21323                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21324 
   21325          store( irx_addr, unop( Iop_64to32,
   21326                                 binop( Iop_Or64,
   21327                                        mkexpr( half_word7 ),
   21328                                        binop( Iop_Shl64,
   21329                                               mkexpr( half_word6 ),
   21330                                               mkU8( 16 ) ) ) ) );
   21331 
   21332       } else {
   21333          store( mkexpr( EA ), unop( Iop_64to32,
   21334                                     binop( Iop_Or64,
   21335                                            mkexpr( half_word0 ),
   21336                                            binop( Iop_Shl64,
   21337                                                   mkexpr( half_word1 ),
   21338                                                   mkU8( 16 ) ) ) ) );
   21339 
   21340          ea_off += 4;
   21341          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21342                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21343 
   21344          store( irx_addr, unop( Iop_64to32,
   21345                                 binop( Iop_Or64,
   21346                                        mkexpr( half_word2 ),
   21347                                        binop( Iop_Shl64,
   21348                                               mkexpr( half_word3 ),
   21349                                               mkU8( 16 ) ) ) ) );
   21350          ea_off += 4;
   21351          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21352                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21353 
   21354          store( irx_addr, unop( Iop_64to32,
   21355                                 binop( Iop_Or64,
   21356                                        mkexpr( half_word4 ),
   21357                                        binop( Iop_Shl64,
   21358                                               mkexpr( half_word5 ),
   21359                                               mkU8( 16 ) ) ) ) );
   21360          ea_off += 4;
   21361          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21362                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21363 
   21364          store( irx_addr, unop( Iop_64to32,
   21365                                 binop( Iop_Or64,
   21366                                        mkexpr( half_word6 ),
   21367                                        binop( Iop_Shl64,
   21368                                               mkexpr( half_word7 ),
   21369                                               mkU8( 16 ) ) ) ) );
   21370       }
   21371       break;
   21372    }
   21373 
   21374    case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
   21375    {
   21376       UInt ea_off = 0;
   21377       int i;
   21378       IRExpr* irx_addr;
   21379       IRTemp byte[16];
   21380 
   21381       DIP("stxvb16x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   21382 
   21383       for ( i = 0; i < 8; i++ ) {
   21384          byte[i] = newTemp( Ity_I64 );
   21385          byte[i+8] = newTemp( Ity_I64 );
   21386 
   21387          assign( byte[i], binop( Iop_And64,
   21388                                binop( Iop_Shr64,
   21389                                       unop( Iop_V128HIto64, mkexpr( vS ) ),
   21390                                       mkU8( 56 - i*8 ) ),
   21391                                mkU64( 0xFF ) ) );
   21392 
   21393          assign( byte[i+8], binop( Iop_And64,
   21394                                binop( Iop_Shr64,
   21395                                       unop( Iop_V128to64, mkexpr( vS ) ),
   21396                                       mkU8( 56 - i*8) ),
   21397                                mkU64( 0xFF ) ) );
   21398       }
   21399 
   21400       if ( host_endness == VexEndnessBE ) {
   21401          for ( i = 0; i < 16; i = i + 4)  {
   21402             irx_addr =
   21403                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21404                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21405 
   21406             store( irx_addr,
   21407                    unop( Iop_64to32,
   21408                          binop( Iop_Or64,
   21409                                 binop( Iop_Or64,
   21410                                        mkexpr( byte[i+3] ),
   21411                                        binop( Iop_Shl64,
   21412                                               mkexpr( byte[i+2] ),
   21413                                               mkU8( 8 ) ) ),
   21414                                 binop( Iop_Or64,
   21415                                        binop( Iop_Shl64,
   21416                                               mkexpr( byte[i+1] ),
   21417                                               mkU8( 16 ) ),
   21418                                        binop( Iop_Shl64,
   21419                                               mkexpr( byte[i] ),
   21420                                               mkU8( 24 ) ) ) ) ) );
   21421             ea_off += 4;
   21422          }
   21423 
   21424       } else {
   21425          for ( i = 0; i < 16; i = i + 4)  {
   21426             irx_addr =
   21427                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   21428                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   21429 
   21430             store( irx_addr,
   21431                    unop( Iop_64to32,
   21432                          binop( Iop_Or64,
   21433                                 binop( Iop_Or64,
   21434                                        mkexpr( byte[i] ),
   21435                                        binop( Iop_Shl64,
   21436                                               mkexpr( byte[i+1] ),
   21437                                               mkU8( 8 ) ) ),
   21438                                 binop( Iop_Or64,
   21439                                        binop( Iop_Shl64,
   21440                                               mkexpr( byte[i+2] ),
   21441                                               mkU8( 16 ) ),
   21442                                        binop( Iop_Shl64,
   21443                                               mkexpr( byte[i+3] ),
   21444                                               mkU8( 24 ) ) ) ) ) );
   21445 
   21446             ea_off += 4;
   21447          }
   21448       }
   21449       break;
   21450    }
   21451 
   21452    default:
   21453       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   21454       return False;
   21455    }
   21456    return True;
   21457 }
   21458 
   21459 static Bool
   21460 dis_vx_Scalar_Round_to_quad_integer( UInt theInstr )
   21461 {
   21462    /* The ISA 3.0 instructions supported in this function require
   21463     * the underlying hardware platform that supports the ISA3.0
   21464     * instruction set.
   21465     */
   21466    /* XX1-Form */
   21467    UChar opc1 = ifieldOPC( theInstr );
   21468    UInt opc2 = IFIELD( theInstr, 1, 8 );
   21469    UChar vT_addr = ifieldRegDS( theInstr );
   21470    UChar vB_addr = ifieldRegB( theInstr );
   21471    IRTemp vB = newTemp( Ity_F128 );
   21472    IRTemp vT = newTemp( Ity_F128 );
   21473    UChar EX = IFIELD( theInstr, 0, 1 );
   21474 
   21475    assign( vB, getF128Reg( vB_addr ) );
   21476    if (opc1 != 0x3F) {
   21477       vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
   21478       return False;
   21479    }
   21480    switch (opc2) {
   21481    case 0x005:     // VSX Scalar Round to Quad-Precision Integer [with Inexact]
   21482       {
   21483          UChar R   = IFIELD( theInstr, 16, 1 );
   21484          UChar RMC = IFIELD( theInstr, 9, 2 );
   21485 
   21486          /* Store the rm specification bits.  Will extract them later when
   21487           * the isntruction is issued.
   21488           */
   21489          IRExpr* rm = mkU32( R << 3 | RMC << 1 | EX);
   21490 
   21491          if ( EX == 0 ) {  // xsrqpi
   21492             DIP("xsrqpi %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
   21493             assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
   21494 
   21495          } else {     // xsrqpix
   21496             DIP("xsrqpix %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC);
   21497             assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
   21498          }
   21499          generate_store_FPRF( Ity_F128, vT );
   21500       }   /* case 0x005 */
   21501       break;
   21502    case 0x025:     // xsrqpxp  VSX Scalar Round Quad-Precision to
   21503                    // Double-Extended Precision
   21504       {
   21505          UChar R   = IFIELD( theInstr, 16, 1 );
   21506          UChar RMC = IFIELD( theInstr, 9, 2 );
   21507 
   21508          /* Store the rm specification bits.  Will extract them later when
   21509           * the isntruction is issued.
   21510           */
   21511          IRExpr* rm = mkU32( R << 3 | RMC << 1 );
   21512 
   21513         DIP("xsrqpxp %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
   21514          assign( vT, binop( Iop_RndF128, rm, mkexpr( vB ) ) );
   21515          generate_store_FPRF( Ity_F128, vT );
   21516       }   /* case 0x025 */
   21517      break;
   21518    default:
   21519       vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
   21520       return False;
   21521    }     /* switch opc2 */
   21522    putF128Reg( vT_addr, mkexpr( vT ) );
   21523    return True;
   21524 }
   21525 
   21526 static Bool
   21527 dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr )
   21528 {
   21529    /* The ISA 3.0 instructions supported in this function require
   21530     * the underlying hardware platform that supports the ISA 3.0
   21531     * instruction set.
   21532     */
   21533    /* XX1-Form */
   21534    UChar opc1 = ifieldOPC( theInstr );
   21535    UInt opc2 = ifieldOPClo10( theInstr );
   21536    UChar vT_addr = ifieldRegDS( theInstr );
   21537    UChar vA_addr = ifieldRegA( theInstr );
   21538    UChar vB_addr = ifieldRegB( theInstr );
   21539    IRTemp vA = newTemp( Ity_F128 );
   21540    IRTemp vB = newTemp( Ity_F128 );
   21541    IRTemp vT = newTemp( Ity_F128 );
   21542    IRExpr* rm = get_IR_roundingmode();
   21543    UChar R0 = IFIELD( theInstr, 0, 1 );
   21544 
   21545    assign( vB, getF128Reg( vB_addr ) );
   21546 
   21547    if ( opc1 != 0x3F ) {
   21548       vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
   21549       return False;
   21550    }
   21551    switch ( opc2 ) {
   21552    case 0x004:     // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
   21553       {
   21554          assign( vA, getF128Reg( vA_addr ) );
   21555 
   21556          if ( R0 == 0 ) {
   21557             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21558             DIP("xsaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21559             assign( vT, triop( Iop_AddF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
   21560 
   21561          } else {
   21562            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21563             DIP("xsaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21564             assign( vT, triop( Iop_AddF128, set_round_to_Oddmode(),
   21565                                mkexpr( vA ), mkexpr( vB ) ) );
   21566          }
   21567          generate_store_FPRF( Ity_F128, vT );
   21568          break;
   21569       }
   21570    case 0x024:     // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
   21571       {
   21572          assign( vA, getF128Reg( vA_addr ) );
   21573 
   21574          if ( R0 == 0 ) {
   21575             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21576             DIP("xsmulqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21577             assign( vT, triop( Iop_MulF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
   21578 
   21579          } else {
   21580             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21581             DIP("xsmulqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21582             assign( vT, triop( Iop_MulF128, set_round_to_Oddmode(), mkexpr( vA ),
   21583                                mkexpr( vB ) ) );
   21584          }
   21585          generate_store_FPRF( Ity_F128, vT );
   21586          break;
   21587       }
   21588    case 0x184:   // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd])
   21589       {
   21590          /* instruction computes (vA * vB) + vC */
   21591          IRTemp vC = newTemp( Ity_F128 );
   21592 
   21593          assign( vA, getF128Reg( vA_addr ) );
   21594          assign( vC, getF128Reg( vT_addr ) );
   21595 
   21596          if ( R0 == 0 ) {
   21597             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21598             DIP("xsmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21599             assign( vT,
   21600                qop( Iop_MAddF128, rm, mkexpr( vA ),
   21601                     mkexpr( vC ), mkexpr( vB ) ) );
   21602 
   21603          } else {
   21604             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21605             DIP("xsmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21606             assign( vT,
   21607                qop( Iop_MAddF128, set_round_to_Oddmode(), mkexpr( vA ),
   21608                     mkexpr( vC ), mkexpr( vB ) ) );
   21609          }
   21610          generate_store_FPRF( Ity_F128, vT );
   21611          break;
   21612       }
   21613    case 0x1A4:   // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd])
   21614       {
   21615          IRTemp vC = newTemp( Ity_F128 );
   21616 
   21617          assign( vA, getF128Reg( vA_addr ) );
   21618          assign( vC, getF128Reg( vT_addr ) );
   21619 
   21620          if ( R0 == 0 ) {
   21621             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21622             DIP("xsmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21623             assign( vT,
   21624                qop( Iop_MSubF128, rm, mkexpr( vA ),
   21625                     mkexpr( vC ), mkexpr( vB ) ) );
   21626 
   21627          } else {
   21628             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21629             DIP("xsmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21630             assign( vT,
   21631                     qop( Iop_MSubF128, set_round_to_Oddmode(),
   21632                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
   21633          }
   21634          generate_store_FPRF( Ity_F128, vT );
   21635          break;
   21636       }
   21637    case 0x1C4:   // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd])
   21638       {
   21639          IRTemp vC = newTemp( Ity_F128 );
   21640 
   21641          assign( vA, getF128Reg( vA_addr ) );
   21642          assign( vC, getF128Reg( vT_addr ) );
   21643 
   21644          if ( R0 == 0 ) {
   21645             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21646             DIP("xsnmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21647             assign( vT,
   21648                qop( Iop_NegMAddF128, rm, mkexpr( vA ),
   21649                     mkexpr( vC ), mkexpr( vB ) ) );
   21650 
   21651          } else {
   21652             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21653             DIP("xsnmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21654             assign( vT,
   21655                     qop( Iop_NegMAddF128, set_round_to_Oddmode(),
   21656                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
   21657          }
   21658          generate_store_FPRF( Ity_F128, vT );
   21659         break;
   21660       }
   21661    case 0x1E4:   // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd])
   21662       {
   21663          IRTemp vC = newTemp( Ity_F128 );
   21664 
   21665          assign( vA, getF128Reg( vA_addr ) );
   21666          assign( vC, getF128Reg( vT_addr ) );
   21667 
   21668          if ( R0 == 0 ) {
   21669             /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21670             DIP("xsnmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21671             assign( vT,
   21672                qop( Iop_NegMSubF128, rm, mkexpr( vA ),
   21673                     mkexpr( vC ), mkexpr( vB ) ) );
   21674 
   21675          } else {
   21676             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21677             DIP("xsnmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21678             assign( vT,
   21679                     qop( Iop_NegMSubF128, set_round_to_Oddmode(),
   21680                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
   21681          }
   21682          generate_store_FPRF( Ity_F128, vT );
   21683          break;
   21684       }
   21685    case 0x204:     // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
   21686       {
   21687          assign( vA, getF128Reg( vA_addr ) );
   21688          if ( R0 == 0 ) {
   21689             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
   21690             DIP("xssubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21691             assign( vT, triop( Iop_SubF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
   21692 
   21693          } else {
   21694             /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21695             DIP("xssubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21696             assign( vT, triop( Iop_SubF128, set_round_to_Oddmode(), mkexpr( vA ),
   21697                                mkexpr( vB ) ) );
   21698          }
   21699          generate_store_FPRF( Ity_F128, vT );
   21700         break;
   21701       }
   21702    case 0x224:     // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
   21703       {
   21704          assign( vA, getF128Reg( vA_addr ) );
   21705          if ( R0 == 0 ) {
   21706             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
   21707             DIP("xsdivqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21708             assign( vT, triop( Iop_DivF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
   21709 
   21710          } else {
   21711             /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
   21712             DIP("xsdivqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21713             assign( vT, triop( Iop_DivF128, set_round_to_Oddmode(), mkexpr( vA ),
   21714                                mkexpr( vB ) ) );
   21715          }
   21716          generate_store_FPRF( Ity_F128, vT );
   21717          break;
   21718       }
   21719    case 0x324:  // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd])
   21720       {
   21721          UInt inst_select = IFIELD( theInstr, 16, 5 );
   21722 
   21723          switch (inst_select) {
   21724          case 27:
   21725             {
   21726                if ( R0 == 0 ) { // xssqrtqp
   21727                   /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21728                   DIP("xssqrtqp v%d,v%d\n",  vT_addr, vB_addr);
   21729                   assign( vT, binop( Iop_SqrtF128, rm, mkexpr( vB ) ) );
   21730 
   21731                } else {      // xssqrtqpo
   21732                   /* rounding mode is Round to odd. Issue inst with R0 = 1 */
   21733                   DIP("xssqrtqpo v%d,v%d\n",  vT_addr, vB_addr);
   21734                   assign( vT, binop( Iop_SqrtF128, set_round_to_Oddmode(),
   21735                                      mkexpr( vB ) ) );
   21736                }
   21737                generate_store_FPRF( Ity_F128, vT );
   21738                break;
   21739             }   /* end case 27 */
   21740          default:
   21741             vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
   21742             return False;
   21743          }  /* end switch inst_select */
   21744          break;
   21745       }   /* end case 0x324 */
   21746 
   21747    case 0x344:
   21748       {
   21749          UInt inst_select = IFIELD( theInstr, 16, 5);
   21750 
   21751          switch (inst_select) {
   21752          case 1:    // xscvqpuwz  VSX Scalar Truncate & Convert Quad-Precision
   21753                     // format to Unsigned Word format
   21754             {
   21755                DIP("xscvqpuwz v%d,v%d\n",  vT_addr, vB_addr);
   21756                assign( vT, unop( Iop_TruncF128toI32U, mkexpr( vB ) ) );
   21757                break;
   21758             }
   21759          case 2:    // xscvudqp  VSX Scalar Convert from Unsigned Doubleword
   21760                     // format to Quad-Precision format
   21761             {
   21762                IRTemp tmp = newTemp( Ity_I64 );
   21763 
   21764                DIP("xscvudqp v%d,v%d\n",  vT_addr, vB_addr);
   21765                assign( tmp, unop( Iop_ReinterpF64asI64,
   21766                                   unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
   21767                assign( vT, unop( Iop_I64UtoF128, mkexpr( tmp ) ) );
   21768                generate_store_FPRF( Ity_F128, vT );
   21769                break;
   21770             }
   21771          case 9:    // xsvqpswz  VSX Scalar Truncate & Convert Quad-Precision
   21772                     // format to Signed Word format
   21773             {
   21774                DIP("xscvqpswz v%d,v%d\n",  vT_addr, vB_addr);
   21775                assign( vT, unop( Iop_TruncF128toI32S, mkexpr( vB ) ) );
   21776                break;
   21777             }
   21778          case 10:   // xscvsdqp  VSX Scalar from Signed Doubleword format
   21779                     // Quad-Precision format
   21780             {
   21781                IRTemp tmp = newTemp( Ity_I64 );
   21782 
   21783                DIP("xscvsdqp v%d,v%d\n",  vT_addr, vB_addr);
   21784 
   21785                assign( tmp, unop( Iop_ReinterpF64asI64,
   21786                                   unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
   21787                assign( vT, unop( Iop_I64StoF128, mkexpr( tmp ) ) );
   21788                generate_store_FPRF( Ity_F128, vT );
   21789                break;
   21790             }
   21791         case 17:    // xsvqpudz  VSX Scalar Truncate & Convert Quad-Precision
   21792                     // format to Unigned Doubleword format
   21793             {
   21794               DIP("xscvqpudz v%d,v%d\n",  vT_addr, vB_addr);
   21795                assign( vT, unop( Iop_TruncF128toI64U, mkexpr( vB ) ) );
   21796                break;
   21797             }
   21798          case 20: //  xscvqpdp  Scalar round & Conver Quad-Precision
   21799                   //  format to Double-Precision format [using round to Odd]
   21800             {
   21801                IRTemp ftmp = newTemp( Ity_F64 );
   21802                IRTemp tmp = newTemp( Ity_I64 );
   21803 
   21804                /* This instruction takes a 128-bit floating point value and
   21805                 * converts it to a 64-bit floating point value.  The 64-bit
   21806                 * result is stored in the upper 64-bit of the 128-bit result
   21807                 * register.  The lower 64-bit are undefined.
   21808                 */
   21809                if (R0 == 0) { //  xscvqpdp
   21810                   /* rounding mode specified by RN. Issue inst with R0 = 0 */
   21811                   DIP("xscvqpdp v%d,v%d\n",  vT_addr, vB_addr);
   21812 
   21813                   assign( ftmp, binop( Iop_F128toF64, rm, mkexpr( vB ) ) );
   21814 
   21815                } else {       //  xscvqpdpo
   21816                   /* rounding mode is Round to odd. Issue inst with R0 = 1 */
   21817                   DIP("xscvqpdpo v%d,v%d\n",  vT_addr, vB_addr);
   21818                   assign( ftmp,
   21819                           binop( Iop_F128toF64,
   21820                                  set_round_to_Oddmode(), mkexpr( vB ) ) );
   21821                }
   21822 
   21823                /* store 64-bit float in upper 64-bits of 128-bit register,
   21824                 * lower 64-bits are zero.
   21825                 */
   21826                if (host_endness == VexEndnessLE)
   21827                   assign( vT,
   21828                           binop( Iop_F64HLtoF128,
   21829                                  mkexpr( ftmp ),
   21830                                  unop( Iop_ReinterpI64asF64, mkU64( 0 ) ) ) );
   21831                else
   21832                   assign( vT,
   21833                           binop( Iop_F64HLtoF128,
   21834                                  unop( Iop_ReinterpI64asF64, mkU64( 0 ) ),
   21835                                  mkexpr( ftmp ) ) );
   21836 
   21837                assign( tmp, unop( Iop_ReinterpF64asI64,
   21838                                   unop( Iop_F128HItoF64, mkexpr( vT ) ) ) );
   21839 
   21840                generate_store_FPRF( Ity_I64, tmp );
   21841                break;
   21842             }
   21843          case 22:    // xscvdpqp VSX Scalar Convert from Double-Precision
   21844                      // format to Quad-Precision format
   21845             {
   21846                DIP("xscvdpqp v%d,v%d\n",  vT_addr, vB_addr);
   21847                /* The 64-bit value is in the upper 64 bit of the src */
   21848                assign( vT, unop( Iop_F64toF128,
   21849                                  unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
   21850 
   21851                generate_store_FPRF( Ity_F128, vT );
   21852                break;
   21853             }
   21854          case 25:    // xsvqpsdz  VSX Scalar Truncate & Convert Quad-Precision
   21855                      // format to Signed Doubleword format
   21856             {
   21857                DIP("xscvqpsdz v%d,v%d\n",  vT_addr, vB_addr);
   21858                assign( vT, unop( Iop_TruncF128toI64S, mkexpr( vB ) ) );
   21859                break;
   21860             }
   21861          default:
   21862            vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
   21863            return False;
   21864          }  /* switch inst_select */
   21865       }   /* end case 0x344 */
   21866       break;
   21867    default:    /* switch opc2 */
   21868       vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
   21869       return False;
   21870    }
   21871    putF128Reg( vT_addr, mkexpr( vT ) );
   21872    return True;
   21873 }
   21874 
   21875 
   21876 /* VSX Scalar Quad-Precision instructions */
   21877 static Bool
   21878 dis_vx_scalar_quad_precision ( UInt theInstr )
   21879 {
   21880    /* This function emulates the 128-bit floating point instructions
   21881     * using existing 128-bit vector instructions (Iops).  The 128-bit
   21882     * floating point instructions use the same 128-bit vector register
   21883     * set.
   21884     */
   21885    /* XX1-Form */
   21886    UChar opc1 = ifieldOPC( theInstr );
   21887    UInt opc2 = ifieldOPClo10( theInstr );
   21888    UChar vT_addr = ifieldRegDS( theInstr ) + 32;
   21889    UChar vA_addr = ifieldRegA( theInstr ) + 32;
   21890    UChar vB_addr = ifieldRegB( theInstr ) + 32;
   21891    IRTemp vA = newTemp( Ity_V128 );
   21892    IRTemp vB = newTemp( Ity_V128 );
   21893    IRTemp vT = newTemp( Ity_V128 );
   21894 
   21895    assign( vB, getVSReg( vB_addr ) );
   21896 
   21897    if (opc1 != 0x3F) {
   21898       vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
   21899       return False;
   21900    }
   21901 
   21902    switch (opc2) {
   21903 
   21904    case 0x064:     // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
   21905       {
   21906          IRTemp sign_vA = newTemp( Ity_I64 );
   21907          IRTemp vB_hi = newTemp( Ity_I64 );
   21908 
   21909          DIP("xscpsgnqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   21910 
   21911          assign( vA, getVSReg(vA_addr) );
   21912 
   21913          assign( sign_vA, binop( Iop_And64,
   21914                                  unop( Iop_V128HIto64,
   21915                                        mkexpr( vA ) ),
   21916                                  mkU64( 0x8000000000000000ULL ) ) );
   21917          assign( vB_hi, binop( Iop_Or64,
   21918                                binop( Iop_And64,
   21919                                       unop( Iop_V128HIto64,
   21920                                             mkexpr( vB ) ),
   21921                                       mkU64( 0x7FFFFFFFFFFFFFFFULL ) ),
   21922                                mkexpr( sign_vA ) ) );
   21923          assign( vT, binop( Iop_64HLtoV128,
   21924                             mkexpr( vB_hi ),
   21925                             unop( Iop_V128to64, mkexpr( vB ) ) ) );
   21926          break;
   21927       }
   21928 
   21929    case 0x084:     // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision)
   21930    case 0x284:     // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision)
   21931       {
   21932          /* Note, only differece between xscmoqp and xscmpuqp is the
   21933             exception flag settings which are not supported anyway. */
   21934          IRExpr *bit4, *bit5, *bit6, *bit7;
   21935          IRExpr *bit_zero, *bit_inf, *same_sign;
   21936          UInt BF = IFIELD( theInstr, 23, 3 );
   21937          IRTemp eq_lt_gt = newTemp( Ity_I32 );
   21938          IRTemp CC = newTemp( Ity_I32 );
   21939 
   21940          if (opc2 == 0x084) {
   21941             DIP("xscmpoqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
   21942          } else {
   21943             DIP("xscmpuqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
   21944          }
   21945 
   21946          assign( vA, getVSReg(vA_addr));
   21947 
   21948          /* A and B have the same sign */
   21949          same_sign =  binop( Iop_CmpEQ64,
   21950                              binop( Iop_Shr64,
   21951                                     unop( Iop_V128HIto64,
   21952                                           mkexpr( vA ) ),
   21953                                     mkU8( 63 ) ),
   21954                              binop( Iop_Shr64,
   21955                                     unop( Iop_V128HIto64,
   21956                                           mkexpr( vB ) ),
   21957                                     mkU8( 63 ) ) );
   21958 
   21959          /* A < B */
   21960          bit4 = Quad_precision_gt( vB, vA );
   21961 
   21962          /*  A > B  */
   21963          bit5 = Quad_precision_gt( vA, vB );
   21964 
   21965          /* A equal B */
   21966          bit6 = mkAND1( binop( Iop_CmpEQ64,
   21967                                unop( Iop_V128HIto64,
   21968                                      mkexpr( vA ) ),
   21969                                unop( Iop_V128HIto64,
   21970                                      mkexpr( vB ) ) ),
   21971                         binop( Iop_CmpEQ64,
   21972                                unop( Iop_V128to64,
   21973                                      mkexpr( vA ) ),
   21974                                unop( Iop_V128to64,
   21975                                      mkexpr( vB ) ) ) );
   21976 
   21977          /* test both zero don't care about sign */
   21978          bit_zero = mkAND1( is_Zero( Ity_V128, vA ), is_Zero( Ity_V128, vB ) );
   21979 
   21980          /* test both for infinity, don't care about sign */
   21981          bit_inf = mkAND1(
   21982                           mkAND1( is_Inf( Ity_V128, vA ), is_Inf( Ity_V128, vB ) ),
   21983                           binop( Iop_CmpEQ64,
   21984                                  binop( Iop_And64,
   21985                                         unop( Iop_V128to64,
   21986                                               mkexpr( vA ) ),
   21987                                         mkU64( 0x80000000) ),
   21988                                  binop( Iop_And64,
   21989                                         unop( Iop_V128to64,
   21990                                               mkexpr( vB ) ),
   21991                                         mkU64( 0x80000000) ) ) );
   21992 
   21993          /* exp A or exp B is NaN */
   21994          bit7 = mkOR1( is_NaN( Ity_V128, vA ),
   21995                        is_NaN( Ity_V128, vB ) );
   21996 
   21997          assign( eq_lt_gt,
   21998                  binop( Iop_Or32,
   21999                         binop( Iop_Or32,
   22000                                binop( Iop_Shl32,
   22001                                       unop( Iop_1Uto32, bit4 ),
   22002                                       mkU8( 3 ) ),
   22003                                binop( Iop_Shl32,
   22004                                       unop( Iop_1Uto32, bit5 ),
   22005                                       mkU8( 2 ) ) ),
   22006                         binop( Iop_Or32,
   22007                                binop( Iop_Shl32,
   22008                                       unop( Iop_1Uto32, bit6 ),
   22009                                       mkU8( 1 ) ),
   22010                                binop( Iop_Or32,
   22011                                       binop( Iop_Shl32,
   22012                                              unop( Iop_1Uto32,
   22013                                                    bit_zero ),
   22014                                              mkU8( 1 ) ),
   22015                                       binop( Iop_Shl32,
   22016                                              unop( Iop_1Uto32,
   22017                                                    mkAND1( bit_inf, same_sign ) ),
   22018                                              mkU8( 1 ) ) ) ) ) );
   22019 
   22020          assign(CC, binop( Iop_Or32,
   22021                            binop( Iop_And32,
   22022                                   unop( Iop_Not32,
   22023                                         unop( Iop_1Sto32, bit7 ) ),
   22024                                   mkexpr( eq_lt_gt ) ),
   22025                            unop( Iop_1Uto32, bit7 ) ) );
   22026 
   22027          /* put result of the comparison into CC and FPCC */
   22028          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
   22029          putFPCC( mkexpr( CC ) );
   22030          return True;
   22031       }
   22032       break;
   22033 
   22034    case 0xA4:     // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision)
   22035       {
   22036          IRExpr *bit4, *bit5, *bit6, *bit7;
   22037          UInt BF = IFIELD( theInstr, 23, 3 );
   22038 
   22039          IRTemp eq_lt_gt = newTemp( Ity_I32 );
   22040          IRTemp CC = newTemp( Ity_I32 );
   22041 
   22042          DIP("xscmpexpqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
   22043 
   22044          assign( vA, getVSReg(vA_addr));
   22045 
   22046          /* A exp < B exp */
   22047          bit4 = binop( Iop_CmpLT64U,
   22048                       binop( Iop_And64,
   22049                              unop( Iop_V128HIto64,
   22050                                    mkexpr( vA ) ),
   22051                              mkU64( 0x7FFF000000000000 ) ),
   22052                       binop( Iop_And64,
   22053                              unop( Iop_V128HIto64,
   22054                                    mkexpr( vB ) ),
   22055                              mkU64( 0x7FFF000000000000 ) ) );
   22056          /*  exp > B exp */
   22057          bit5 = binop( Iop_CmpLT64U,
   22058                       binop( Iop_And64,
   22059                              unop( Iop_V128HIto64,
   22060                                    mkexpr( vB ) ),
   22061                              mkU64( 0x7FFF000000000000 ) ),
   22062                       binop( Iop_And64,
   22063                              unop( Iop_V128HIto64,
   22064                                    mkexpr( vA ) ),
   22065                              mkU64( 0x7FFF000000000000 ) ) );
   22066          /* test equal */
   22067          bit6 = binop( Iop_CmpEQ64,
   22068                       binop( Iop_And64,
   22069                              unop( Iop_V128HIto64,
   22070                                    mkexpr( vA ) ),
   22071                              mkU64( 0x7FFF000000000000 ) ),
   22072                       binop( Iop_And64,
   22073                              unop( Iop_V128HIto64,
   22074                                    mkexpr( vB ) ),
   22075                              mkU64( 0x7FFF000000000000 ) ) );
   22076 
   22077          /* exp A or exp B is NaN */
   22078          bit7 = mkOR1( is_NaN( Ity_V128, vA ),
   22079                        is_NaN( Ity_V128, vB ) );
   22080 
   22081          /* NaN over rules the other comparisons */
   22082          assign( eq_lt_gt, binop( Iop_Or32,
   22083                                   binop( Iop_Shl32,
   22084                                          unop( Iop_1Uto32, bit4 ),
   22085                                          mkU8( 3) ),
   22086                                   binop( Iop_Or32,
   22087                                          binop( Iop_Shl32,
   22088                                                 unop( Iop_1Uto32, bit5 ),
   22089                                                 mkU8( 2) ),
   22090                                          binop( Iop_Shl32,
   22091                                                 unop( Iop_1Uto32, bit6 ),
   22092                                                 mkU8( 1 ) ) ) ) );
   22093          assign(CC, binop( Iop_Or32,
   22094                            binop( Iop_And32,
   22095                                   unop( Iop_Not32,
   22096                                         unop( Iop_1Sto32, bit7 ) ),
   22097                                   mkexpr( eq_lt_gt ) ),
   22098                            unop( Iop_1Uto32, bit7 ) ) );
   22099 
   22100          /* put result of the comparison into CC and FPCC */
   22101          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
   22102          putFPCC( mkexpr( CC ) );
   22103          return True;
   22104       }
   22105       break;
   22106 
   22107    case 0x2C4:    // xststdcqp (VSX Scalar Quad-Precision Test Data Class)
   22108       {
   22109          UInt BF = IFIELD( theInstr, 23, 3 );
   22110          UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
   22111          IRTemp CC = newTemp( Ity_I64 );
   22112          IRTemp NaN = newTemp( Ity_I64 );
   22113          IRTemp inf = newTemp( Ity_I64 );
   22114          IRTemp pos = newTemp( Ity_I64 );
   22115          IRTemp DCM = newTemp( Ity_I64 );
   22116          IRTemp zero = newTemp( Ity_I64 );
   22117          IRTemp dnorm = newTemp( Ity_I64 );
   22118 
   22119          DIP("xststdcqp  %d,v%d,%d\n",  BF, vB_addr, DCMX_mask);
   22120 
   22121          assign( zero, unop( Iop_1Uto64, is_Zero( Ity_V128, vB ) ) );
   22122          assign( pos, unop( Iop_1Uto64,
   22123                             binop( Iop_CmpEQ64,
   22124                                    binop( Iop_Shr64,
   22125                                           unop( Iop_V128HIto64,
   22126                                                 mkexpr( vB ) ),
   22127                                           mkU8( 63 ) ),
   22128                                    mkU64( 0 ) ) ) );
   22129 
   22130          assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_V128, vB ) ) );
   22131          assign( inf, unop( Iop_1Uto64, is_Inf( Ity_V128, vB ) ) );
   22132 
   22133          assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_V128, vB ) ) );
   22134          assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
   22135          assign( CC, binop( Iop_Or64,
   22136                             binop( Iop_And64,    /* vB sign bit */
   22137                                   binop( Iop_Shr64,
   22138                                          unop( Iop_V128HIto64, mkexpr( vB ) ),
   22139                                          mkU8( 60 ) ),
   22140                                   mkU64( 0x8 ) ),
   22141                            binop( Iop_Shl64,
   22142                                   unop( Iop_1Uto64,
   22143                                         binop( Iop_CmpNE64,
   22144                                                binop( Iop_And64,
   22145                                                       mkexpr( DCM ),
   22146                                                       mkU64( DCMX_mask ) ),
   22147                                                mkU64( 0 ) ) ),
   22148                                    mkU8( 1 ) ) ) );
   22149 
   22150          putGST_field( PPC_GST_CR, unop(Iop_64to32, mkexpr( CC ) ), BF );
   22151          putFPCC( unop(Iop_64to32, mkexpr( CC ) ) );
   22152          return True;
   22153       }
   22154       break;
   22155 
   22156    case 0x324:    // xsabsqp  (VSX Scalar Absolute Quad-Precision)
   22157                   // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision)
   22158                   // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision)
   22159                   // xsnegqp  (VSX Scalar Negate Quad-Precision)
   22160                   // xsxsigqp (VSX Scalar Extract Significand Quad-Precision)
   22161       {
   22162          UInt inst_select = IFIELD( theInstr, 16, 5);
   22163 
   22164          switch (inst_select) {
   22165          case 0:
   22166             DIP("xsabsqp  v%d,v%d\n",  vT_addr, vB_addr);
   22167             assign( vT, binop( Iop_AndV128, mkexpr( vB ),
   22168                                binop( Iop_64HLtoV128,
   22169                                       mkU64( 0x7FFFFFFFFFFFFFFF ),
   22170                                       mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
   22171             break;
   22172 
   22173          case 2:
   22174             DIP("xsxexpqp  v%d,v%d\n",  vT_addr, vB_addr);
   22175             assign( vT, binop( Iop_ShrV128,
   22176                                binop( Iop_AndV128, mkexpr( vB ),
   22177                                       binop( Iop_64HLtoV128,
   22178                                              mkU64( 0x7FFF000000000000 ),
   22179                                              mkU64( 0x0000000000000000 ) ) ),
   22180                                mkU8( 48 ) ) );
   22181             break;
   22182 
   22183          case 8:
   22184             DIP("xsnabsqp  v%d,v%d\n",  vT_addr, vB_addr);
   22185             assign( vT, binop( Iop_OrV128, mkexpr( vB ),
   22186                             binop( Iop_64HLtoV128,
   22187                                    mkU64( 0x8000000000000000 ),
   22188                                    mkU64( 0x0000000000000000 ) ) ) );
   22189             break;
   22190 
   22191          case 16:
   22192             DIP("xsnegqp  v%d,v%d\n",  vT_addr, vB_addr);
   22193             assign( vT, binop( Iop_XorV128, mkexpr( vB ),
   22194                             binop( Iop_64HLtoV128,
   22195                                    mkU64( 0x8000000000000000 ),
   22196                                    mkU64( 0x0000000000000000 ) ) ) );
   22197             break;
   22198 
   22199          case 18:
   22200          {
   22201             IRTemp expZero = newTemp( Ity_I64 );
   22202             IRTemp expInfinity = newTemp( Ity_I64 );
   22203 
   22204             DIP("xsxsigqp  v%d,v%d\n",  vT_addr, vB_addr);
   22205 
   22206             assign( expZero, unop( Iop_1Uto64,
   22207                                    binop( Iop_CmpNE64,
   22208                                           binop( Iop_And64,
   22209                                                  unop( Iop_V128HIto64,
   22210                                                        mkexpr( vB ) ),
   22211                                                  mkU64( 0x7FFF000000000000 ) ),
   22212                                           mkU64( 0x0 ) ) ) );
   22213 
   22214             assign( expInfinity,
   22215                     unop( Iop_1Uto64,
   22216                           binop( Iop_CmpNE64,
   22217                                  binop( Iop_And64,
   22218                                         unop( Iop_V128HIto64,
   22219                                               mkexpr( vB ) ),
   22220                                         mkU64( 0x7FFF000000000000 ) ),
   22221                                  mkU64( 0x7FFF000000000000 ) ) ) );
   22222 
   22223             /* Clear upper 16 bits to 0x0000.  If the exp was zero or infinity
   22224              * set bit 48 (lsb = 0) to 0, otherwise  set bit 48 to 1.
   22225              */
   22226             assign( vT,
   22227                     binop( Iop_OrV128,
   22228                            binop( Iop_ShrV128,
   22229                                   binop( Iop_ShlV128,
   22230                                          mkexpr( vB ),
   22231                                          mkU8( 16 ) ),
   22232                                   mkU8( 16 ) ),
   22233                            binop( Iop_64HLtoV128,
   22234                                   binop( Iop_Shl64,
   22235                                          binop( Iop_And64,
   22236                                                 mkexpr( expZero ),
   22237                                                 mkexpr( expInfinity ) ),
   22238                                          mkU8( 48 ) ),
   22239                                   mkU64( 0 ) ) ) );
   22240          }
   22241          break;
   22242 
   22243          default:
   22244             vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
   22245             return False;
   22246          }
   22247       }
   22248       break;
   22249    case 0x364:    // xsiexpqp (VST Scalar Insert Exponent Quad-Precision)
   22250       {
   22251          IRTemp exp = newTemp( Ity_I64 );
   22252 
   22253          DIP("xsiexpqp  v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
   22254 
   22255          assign( vA, getVSReg( vA_addr ) );
   22256          assign( exp, binop( Iop_And64,
   22257                                  unop( Iop_V128HIto64,
   22258                                        mkexpr( vB ) ),
   22259                                  mkU64( 0x7FFFULL ) ) );
   22260          assign( vT, binop( Iop_64HLtoV128,
   22261                             binop( Iop_Or64,
   22262                                    binop( Iop_And64,
   22263                                           unop( Iop_V128HIto64,
   22264                                                 mkexpr( vA ) ),
   22265                                           mkU64( 0x8000FFFFFFFFFFFFULL ) ),
   22266                                    binop( Iop_Shl64,
   22267                                           mkexpr( exp ),
   22268                                           mkU8( 48 ) ) ),
   22269                             unop( Iop_V128to64,
   22270                                   mkexpr( vA ) ) ) );
   22271       }
   22272       break;
   22273 
   22274    default:
   22275       vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
   22276 
   22277       return False;
   22278    }
   22279 
   22280    putVSReg( vT_addr, mkexpr( vT ) );
   22281    return True;
   22282 }
   22283 
   22284 /*
   22285  * VSX permute and other miscealleous instructions
   22286  */
   22287 static Bool
   22288 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   22289 {
   22290    /* XX3-Form */
   22291    UChar opc1 = ifieldOPC( theInstr );
   22292    UChar XT = ifieldRegXT ( theInstr );
   22293    UChar XA = ifieldRegXA ( theInstr );
   22294    UChar XB = ifieldRegXB ( theInstr );
   22295    IRTemp vT = newTemp( Ity_V128 );
   22296    IRTemp vA = newTemp( Ity_V128 );
   22297    IRTemp vB = newTemp( Ity_V128 );
   22298 
   22299    if (opc1 != 0x3C) {
   22300       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   22301       return False;
   22302    }
   22303 
   22304    assign( vA, getVSReg( XA ) );
   22305    assign( vB, getVSReg( XB ) );
   22306 
   22307    switch (opc2) {
   22308       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   22309       {
   22310          UChar SHW = ifieldSHW ( theInstr );
   22311          IRTemp result = newTemp(Ity_V128);
   22312          if ( SHW != 0 ) {
   22313              IRTemp hi = newTemp(Ity_V128);
   22314              IRTemp lo = newTemp(Ity_V128);
   22315              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   22316              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   22317              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   22318          } else
   22319              assign ( result, mkexpr(vA) );
   22320          DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
   22321          putVSReg( XT, mkexpr(result) );
   22322          break;
   22323       }
   22324       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   22325       {
   22326          UChar DM = ifieldDM ( theInstr );
   22327          IRTemp hi = newTemp(Ity_I64);
   22328          IRTemp lo = newTemp(Ity_I64);
   22329 
   22330          if (DM & 0x2)
   22331            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   22332          else
   22333            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   22334 
   22335          if (DM & 0x1)
   22336            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   22337          else
   22338            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   22339 
   22340          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   22341 
   22342          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
   22343          putVSReg( XT, mkexpr( vT ) );
   22344          break;
   22345       }
   22346       case 0x48: // xxmrghw (VSX Merge High Word)
   22347       case 0xc8: // xxmrglw (VSX Merge Low Word)
   22348       {
   22349          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
   22350          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   22351          IRTemp a64 = newTemp(Ity_I64);
   22352          IRTemp ahi32 = newTemp(Ity_I32);
   22353          IRTemp alo32 = newTemp(Ity_I32);
   22354          IRTemp b64 = newTemp(Ity_I64);
   22355          IRTemp bhi32 = newTemp(Ity_I32);
   22356          IRTemp blo32 = newTemp(Ity_I32);
   22357 
   22358          assign( a64, unop(word_op, mkexpr(vA)) );
   22359          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   22360          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   22361 
   22362          assign( b64, unop(word_op, mkexpr(vB)) );
   22363          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   22364          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   22365 
   22366          assign( vT, binop(Iop_64HLtoV128,
   22367                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   22368                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   22369 
   22370          DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
   22371          putVSReg( XT, mkexpr( vT ) );
   22372          break;
   22373       }
   22374       case 0x018: // xxsel (VSX Select)
   22375       {
   22376          UChar XC = ifieldRegXC(theInstr);
   22377          IRTemp vC = newTemp( Ity_V128 );
   22378          assign( vC, getVSReg( XC ) );
   22379          DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
   22380          /* vD = (vA & ~vC) | (vB & vC) */
   22381          putVSReg( XT, binop(Iop_OrV128,
   22382             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   22383             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   22384          break;
   22385       }
   22386 
   22387       case 0x68: // xxperm  (VSX Permute )
   22388       case 0xE8: // xxpermr (VSX Permute right-index )
   22389       {
   22390          int i;
   22391          IRTemp new_Vt[17];
   22392          IRTemp perm_val[16];
   22393          IRTemp perm_val_gt16[16];
   22394          IRTemp tmp_val[16];
   22395          IRTemp perm_idx[16];
   22396          IRTemp perm_mask = newTemp( Ity_V128 );
   22397          IRTemp val_mask  = newTemp( Ity_V128 );
   22398          int    dest_shift_amount = 0;
   22399 
   22400          if ( opc2 == 0x68 ) {
   22401             DIP("xxperm v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   22402 
   22403          } else {
   22404             /* Same as xperm just the index is 31 - idx */
   22405             DIP("xxpermr v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   22406          }
   22407 
   22408          new_Vt[0] = newTemp( Ity_V128 );
   22409 
   22410          assign( vT, getVSReg( XT ) );
   22411 
   22412          assign( new_Vt[0], binop( Iop_64HLtoV128,
   22413                                    mkU64( 0x0 ), mkU64( 0x0 ) ) );
   22414          assign( perm_mask, binop( Iop_64HLtoV128,
   22415                                    mkU64( 0x0 ), mkU64( 0x1F ) ) );
   22416          assign( val_mask, binop( Iop_64HLtoV128,
   22417                                   mkU64( 0x0 ), mkU64( 0xFF ) ) );
   22418 
   22419          /* For each permute index in XB, the permute list, select the byte
   22420           * from XA indexed by the permute index if the permute index is less
   22421           * then 16.  Copy the selected byte to the destination location in
   22422           * the result.
   22423           */
   22424          for ( i = 0; i < 16; i++ ) {
   22425             perm_val_gt16[i] = newTemp( Ity_V128 );
   22426             perm_val[i] = newTemp( Ity_V128 );
   22427             perm_idx[i] = newTemp( Ity_I8 );
   22428             tmp_val[i]  = newTemp( Ity_V128 );
   22429             new_Vt[i+1]  = newTemp( Ity_V128 );
   22430 
   22431             /* create mask to extract the permute index value from vB,
   22432              * store value in least significant bits of perm_val
   22433              */
   22434             if ( opc2 == 0x68 )
   22435                /* xxperm, the perm value is the index value in XB */
   22436                assign( perm_val[i], binop( Iop_ShrV128,
   22437                                            binop( Iop_AndV128,
   22438                                                   mkexpr(vB),
   22439                                                   binop( Iop_ShlV128,
   22440                                                          mkexpr( perm_mask ),
   22441                                                          mkU8( (15 - i) * 8 ) ) ),
   22442                                            mkU8( (15 - i) * 8 ) ) );
   22443 
   22444             else
   22445                /* xxpermr, the perm value is 31 - index value in XB */
   22446                assign( perm_val[i],
   22447                        binop( Iop_Sub8x16,
   22448                               binop( Iop_64HLtoV128,
   22449                                      mkU64( 0 ), mkU64( 31 ) ),
   22450                               binop( Iop_ShrV128,
   22451                                      binop( Iop_AndV128,
   22452                                             mkexpr( vB ),
   22453                                             binop( Iop_ShlV128,
   22454                                                    mkexpr( perm_mask ),
   22455                                                    mkU8( ( 15 - i ) * 8 ) ) ),
   22456                                      mkU8( ( 15 - i ) * 8 ) ) ) );
   22457 
   22458             /* Determine if the perm_val[] > 16.  If it is, then the value
   22459              * will come from xT otherwise it comes from xA.  Either way,
   22460              * create the mask to get the value from the source using the
   22461              * lower 3 bits of perm_val[].  Create a 128 bit mask from the
   22462              * upper bit of perm_val[] to be used to select from xT or xA.
   22463              */
   22464             assign( perm_val_gt16[i],
   22465                     binop(Iop_64HLtoV128,
   22466                           unop( Iop_1Sto64,
   22467                                 unop( Iop_64to1,
   22468                                       unop( Iop_V128to64,
   22469                                             binop( Iop_ShrV128,
   22470                                                    mkexpr( perm_val[i] ),
   22471                                                    mkU8( 4 ) ) ) ) ),
   22472                           unop( Iop_1Sto64,
   22473                                 unop( Iop_64to1,
   22474                                       unop( Iop_V128to64,
   22475                                             binop( Iop_ShrV128,
   22476                                                    mkexpr( perm_val[i] ),
   22477                                                    mkU8( 4 ) ) ) ) ) ) );
   22478 
   22479             assign( perm_idx[i],
   22480                     unop(Iop_32to8,
   22481                          binop( Iop_Mul32,
   22482                                 binop( Iop_Sub32,
   22483                                        mkU32( 15 ),
   22484                                        unop( Iop_64to32,
   22485                                              binop( Iop_And64,
   22486                                                   unop( Iop_V128to64,
   22487                                                        mkexpr( perm_val[i] ) ),
   22488                                                   mkU64( 0xF ) ) ) ),
   22489                                 mkU32( 8 ) ) ) );
   22490 
   22491             dest_shift_amount = ( 15 - i )*8;
   22492 
   22493             /* Use perm_val_gt16 to select value from vA or vT */
   22494             assign( tmp_val[i],
   22495                     binop( Iop_ShlV128,
   22496                            binop( Iop_ShrV128,
   22497                                   binop( Iop_OrV128,
   22498                                          binop( Iop_AndV128,
   22499                                                 mkexpr( vA ),
   22500                                                 binop( Iop_AndV128,
   22501                                                        unop( Iop_NotV128,
   22502                                                              mkexpr( perm_val_gt16[i] ) ),
   22503                                                        binop( Iop_ShlV128,
   22504                                                               mkexpr( val_mask ),
   22505                                                               mkexpr( perm_idx[i] ) ) ) ),
   22506                                          binop( Iop_AndV128,
   22507                                                 mkexpr( vT ),
   22508                                                 binop( Iop_AndV128,
   22509                                                        mkexpr( perm_val_gt16[i] ),
   22510                                                        binop( Iop_ShlV128,
   22511                                                               mkexpr( val_mask ),
   22512                                                               mkexpr( perm_idx[i] ) ) ) ) ),
   22513                                   mkexpr( perm_idx[i] ) ),
   22514                            mkU8( dest_shift_amount ) ) );
   22515 
   22516             assign( new_Vt[i+1], binop( Iop_OrV128,
   22517                                        mkexpr( tmp_val[i] ),
   22518                                        mkexpr( new_Vt[i] ) ) );
   22519          }
   22520          putVSReg( XT, mkexpr( new_Vt[16] ) );
   22521          break;
   22522       }
   22523 
   22524       case 0x148: // xxspltw (VSX Splat Word)
   22525       {
   22526          UChar UIM   = ifieldRegA(theInstr) & 3;
   22527          UChar sh_uim = (3 - (UIM)) * 32;
   22528          DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
   22529          putVSReg( XT,
   22530                    unop( Iop_Dup32x4,
   22531                          unop( Iop_V128to32,
   22532                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   22533          break;
   22534       }
   22535 
   22536       default:
   22537          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   22538          return False;
   22539    }
   22540    return True;
   22541 }
   22542 
   22543 /*
   22544   AltiVec Load Instructions
   22545 */
   22546 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
   22547 {
   22548    /* X-Form */
   22549    UChar opc1     = ifieldOPC(theInstr);
   22550    UChar vD_addr  = ifieldRegDS(theInstr);
   22551    UChar rA_addr  = ifieldRegA(theInstr);
   22552    UChar rB_addr  = ifieldRegB(theInstr);
   22553    UInt  opc2     = ifieldOPClo10(theInstr);
   22554    UChar b0       = ifieldBIT0(theInstr);
   22555 
   22556    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   22557    IRTemp EA         = newTemp(ty);
   22558    IRTemp EA_align16 = newTemp(ty);
   22559 
   22560    if (opc1 != 0x1F || b0 != 0) {
   22561       vex_printf("dis_av_load(ppc)(instr)\n");
   22562       return False;
   22563    }
   22564 
   22565    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   22566    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   22567 
   22568    switch (opc2) {
   22569 
   22570    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   22571       IRDirty* d;
   22572       UInt vD_off = vectorGuestRegOffset(vD_addr);
   22573       IRExpr** args_be = mkIRExprVec_5(
   22574                          IRExpr_GSPTR(),
   22575                          mkU32(vD_off),
   22576                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   22577                                           mkU32(0xF)),
   22578                          mkU32(0)/*left*/,
   22579                          mkU32(1)/*Big Endian*/);
   22580       IRExpr** args_le = mkIRExprVec_5(
   22581                          IRExpr_GSPTR(),
   22582                          mkU32(vD_off),
   22583                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   22584                                           mkU32(0xF)),
   22585                          mkU32(0)/*left*/,
   22586                          mkU32(0)/*Little Endian*/);
   22587       if (!mode64) {
   22588          d = unsafeIRDirty_0_N (
   22589                         0/*regparms*/,
   22590                         "ppc32g_dirtyhelper_LVS",
   22591                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   22592                         args_be );
   22593       } else {
   22594          if (host_endness == VexEndnessBE)
   22595             d = unsafeIRDirty_0_N (
   22596                            0/*regparms*/,
   22597                            "ppc64g_dirtyhelper_LVS",
   22598                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   22599                            args_be );
   22600          else
   22601             d = unsafeIRDirty_0_N (
   22602                            0/*regparms*/,
   22603                            "ppc64g_dirtyhelper_LVS",
   22604                            fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
   22605                            args_le );
   22606       }
   22607       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22608       /* declare guest state effects */
   22609       d->nFxState = 1;
   22610       vex_bzero(&d->fxState, sizeof(d->fxState));
   22611       d->fxState[0].fx     = Ifx_Write;
   22612       d->fxState[0].offset = vD_off;
   22613       d->fxState[0].size   = sizeof(U128);
   22614 
   22615       /* execute the dirty call, side-effecting guest state */
   22616       stmt( IRStmt_Dirty(d) );
   22617       break;
   22618    }
   22619    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   22620       IRDirty* d;
   22621       UInt vD_off = vectorGuestRegOffset(vD_addr);
   22622       IRExpr** args_be = mkIRExprVec_5(
   22623                              IRExpr_GSPTR(),
   22624                              mkU32(vD_off),
   22625                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   22626                                               mkU32(0xF)),
   22627                              mkU32(1)/*right*/,
   22628                              mkU32(1)/*Big Endian*/);
   22629       IRExpr** args_le = mkIRExprVec_5(
   22630                              IRExpr_GSPTR(),
   22631                              mkU32(vD_off),
   22632                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   22633                                               mkU32(0xF)),
   22634                              mkU32(1)/*right*/,
   22635                              mkU32(0)/*Little Endian*/);
   22636 
   22637       if (!mode64) {
   22638          d = unsafeIRDirty_0_N (
   22639                         0/*regparms*/,
   22640                         "ppc32g_dirtyhelper_LVS",
   22641                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   22642                         args_be );
   22643       } else {
   22644          if (host_endness == VexEndnessBE)
   22645             d = unsafeIRDirty_0_N (
   22646                            0/*regparms*/,
   22647                            "ppc64g_dirtyhelper_LVS",
   22648                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   22649                            args_be );
   22650          else
   22651             d = unsafeIRDirty_0_N (
   22652                            0/*regparms*/,
   22653                            "ppc64g_dirtyhelper_LVS",
   22654                            fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
   22655                            args_le );
   22656       }
   22657       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22658       /* declare guest state effects */
   22659       d->nFxState = 1;
   22660       vex_bzero(&d->fxState, sizeof(d->fxState));
   22661       d->fxState[0].fx     = Ifx_Write;
   22662       d->fxState[0].offset = vD_off;
   22663       d->fxState[0].size   = sizeof(U128);
   22664 
   22665       /* execute the dirty call, side-effecting guest state */
   22666       stmt( IRStmt_Dirty(d) );
   22667       break;
   22668    }
   22669    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   22670       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22671       /* loads addressed byte into vector[EA[0:3]
   22672          since all other destination bytes are undefined,
   22673          can simply load entire vector from 16-aligned EA */
   22674       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   22675       break;
   22676 
   22677    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   22678       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22679       /* see note for lvebx */
   22680       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   22681       break;
   22682 
   22683    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   22684       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22685       /* see note for lvebx */
   22686       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   22687       break;
   22688 
   22689    case 0x067: // lvx (Load Vector Indexed, AV p127)
   22690       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22691       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   22692       break;
   22693 
   22694    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   22695       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   22696       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   22697       break;
   22698 
   22699    default:
   22700       vex_printf("dis_av_load(ppc)(opc2)\n");
   22701       return False;
   22702    }
   22703    return True;
   22704 }
   22705 
   22706 /*
   22707   AltiVec Store Instructions
   22708 */
   22709 static Bool dis_av_store ( UInt theInstr )
   22710 {
   22711    /* X-Form */
   22712    UChar opc1     = ifieldOPC(theInstr);
   22713    UChar vS_addr  = ifieldRegDS(theInstr);
   22714    UChar rA_addr  = ifieldRegA(theInstr);
   22715    UChar rB_addr  = ifieldRegB(theInstr);
   22716    UInt  opc2     = ifieldOPClo10(theInstr);
   22717    UChar b0       = ifieldBIT0(theInstr);
   22718 
   22719    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   22720    IRTemp EA           = newTemp(ty);
   22721    IRTemp addr_aligned = newTemp(ty);
   22722    IRTemp vS           = newTemp(Ity_V128);
   22723    IRTemp eb           = newTemp(Ity_I8);
   22724    IRTemp idx          = newTemp(Ity_I8);
   22725 
   22726    if (opc1 != 0x1F || b0 != 0) {
   22727       vex_printf("dis_av_store(ppc)(instr)\n");
   22728       return False;
   22729    }
   22730 
   22731    assign( vS, getVReg(vS_addr));
   22732    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   22733 
   22734    switch (opc2) {
   22735    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   22736       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   22737       assign( eb, binop(Iop_And8, mkU8(0xF),
   22738                         unop(Iop_32to8,
   22739                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   22740      if (host_endness == VexEndnessLE) {
   22741          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   22742       } else {
   22743          assign( idx, binop(Iop_Shl8,
   22744                             binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   22745                             mkU8(3)) );
   22746       }
   22747       store( mkexpr(EA),
   22748              unop( Iop_32to8, unop(Iop_V128to32,
   22749                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   22750       break;
   22751    }
   22752    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   22753       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   22754       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   22755       assign( eb, binop(Iop_And8, mkU8(0xF),
   22756                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   22757       if (host_endness == VexEndnessLE) {
   22758           assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   22759       } else {
   22760          assign( idx, binop(Iop_Shl8,
   22761                             binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   22762                             mkU8(3)) );
   22763       }
   22764       store( mkexpr(addr_aligned),
   22765              unop( Iop_32to16, unop(Iop_V128to32,
   22766                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   22767       break;
   22768    }
   22769    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   22770       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   22771       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   22772       assign( eb, binop(Iop_And8, mkU8(0xF),
   22773                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   22774       if (host_endness == VexEndnessLE) {
   22775          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   22776       } else {
   22777          assign( idx, binop(Iop_Shl8,
   22778                             binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   22779                             mkU8(3)) );
   22780       }
   22781       store( mkexpr( addr_aligned),
   22782              unop( Iop_V128to32,
   22783                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   22784       break;
   22785    }
   22786 
   22787    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   22788       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   22789       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   22790       break;
   22791 
   22792    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   22793       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   22794       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   22795       break;
   22796 
   22797    default:
   22798       vex_printf("dis_av_store(ppc)(opc2)\n");
   22799       return False;
   22800    }
   22801    return True;
   22802 }
   22803 
   22804 /*
   22805   AltiVec Arithmetic Instructions
   22806 */
   22807 static Bool dis_av_arith ( UInt theInstr )
   22808 {
   22809    /* VX-Form */
   22810    UChar opc1     = ifieldOPC(theInstr);
   22811    UChar vD_addr  = ifieldRegDS(theInstr);
   22812    UChar vA_addr  = ifieldRegA(theInstr);
   22813    UChar vB_addr  = ifieldRegB(theInstr);
   22814    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   22815 
   22816    IRTemp vA = newTemp(Ity_V128);
   22817    IRTemp vB = newTemp(Ity_V128);
   22818    IRTemp z3 = newTemp(Ity_I64);
   22819    IRTemp z2 = newTemp(Ity_I64);
   22820    IRTemp z1 = newTemp(Ity_I64);
   22821    IRTemp z0 = newTemp(Ity_I64);
   22822    IRTemp aEvn, aOdd;
   22823    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   22824    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   22825    IRTemp b3, b2, b1, b0;
   22826 
   22827    aEvn = aOdd = IRTemp_INVALID;
   22828    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   22829    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   22830    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   22831 
   22832    assign( vA, getVReg( vA_addr ) );
   22833    assign( vB, getVReg( vB_addr ) );
   22834 
   22835    if (opc1 != 0x4) {
   22836       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   22837       return False;
   22838    }
   22839 
   22840    switch (opc2) {
   22841    /* Add */
   22842    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   22843       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22844       /* unsigned_ov(x+y) = (y >u not(x)) */
   22845       putVReg( vD_addr, binop( Iop_ShrN32x4,
   22846                                binop( Iop_CmpGT32Ux4, mkexpr( vB ),
   22847                                     unop( Iop_NotV128, mkexpr( vA ) ) ),
   22848                               mkU8( 31 ) ) );
   22849       break;
   22850    }
   22851    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   22852       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22853       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   22854       break;
   22855 
   22856    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   22857       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22858       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   22859       break;
   22860 
   22861    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   22862       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22863       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   22864       break;
   22865 
   22866    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
   22867       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22868       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
   22869       break;
   22870 
   22871    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   22872       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22873       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   22874       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   22875       break;
   22876 
   22877    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   22878       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22879       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   22880       // TODO: set VSCR[SAT]
   22881       break;
   22882 
   22883    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   22884       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22885       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   22886       // TODO: set VSCR[SAT]
   22887       break;
   22888 
   22889    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   22890       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22891       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   22892       // TODO: set VSCR[SAT]
   22893       break;
   22894 
   22895    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   22896       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22897       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   22898       // TODO: set VSCR[SAT]
   22899       break;
   22900 
   22901    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   22902       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22903       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   22904       // TODO: set VSCR[SAT]
   22905       break;
   22906 
   22907 
   22908    /* Subtract */
   22909    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   22910       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22911       /* unsigned_ov(x-y) = (y >u x) */
   22912       putVReg( vD_addr, binop(Iop_ShrN32x4,
   22913                               unop(Iop_NotV128,
   22914                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   22915                                          mkexpr(vA))),
   22916                               mkU8(31)) );
   22917       break;
   22918    }
   22919    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   22920       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22921       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   22922       break;
   22923 
   22924    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   22925       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22926       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   22927       break;
   22928 
   22929    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   22930       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22931       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   22932       break;
   22933 
   22934    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
   22935       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22936       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
   22937       break;
   22938 
   22939    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   22940       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22941       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   22942       // TODO: set VSCR[SAT]
   22943       break;
   22944 
   22945    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   22946       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22947       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   22948       // TODO: set VSCR[SAT]
   22949       break;
   22950 
   22951    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   22952       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22953       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   22954       // TODO: set VSCR[SAT]
   22955       break;
   22956 
   22957    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   22958       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22959       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   22960       // TODO: set VSCR[SAT]
   22961       break;
   22962 
   22963    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   22964       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22965       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   22966       // TODO: set VSCR[SAT]
   22967       break;
   22968 
   22969    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   22970       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22971       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   22972       // TODO: set VSCR[SAT]
   22973       break;
   22974 
   22975 
   22976    /* Maximum */
   22977    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   22978       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22979       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   22980       break;
   22981 
   22982    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   22983       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22984       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   22985       break;
   22986 
   22987    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   22988       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22989       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   22990       break;
   22991 
   22992    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
   22993       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22994       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
   22995       break;
   22996 
   22997    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   22998       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   22999       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   23000       break;
   23001 
   23002    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   23003       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23004       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   23005       break;
   23006 
   23007    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   23008       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23009       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   23010       break;
   23011 
   23012    case 0x1C2: // vmaxsd (Maximum Signed Double word)
   23013       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23014       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
   23015       break;
   23016 
   23017    /* Minimum */
   23018    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   23019       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23020       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   23021       break;
   23022 
   23023    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   23024       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23025       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   23026       break;
   23027 
   23028    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   23029       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23030       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   23031       break;
   23032 
   23033    case 0x2C2: // vminud (Minimum Unsigned Double Word)
   23034       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23035       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
   23036       break;
   23037 
   23038    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   23039       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23040       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   23041       break;
   23042 
   23043    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   23044       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23045       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   23046       break;
   23047 
   23048    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   23049       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23050       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   23051       break;
   23052 
   23053    case 0x3C2: // vminsd (Minimum Signed Double Word)
   23054       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23055       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
   23056       break;
   23057 
   23058 
   23059    /* Average */
   23060    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   23061       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23062       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   23063       break;
   23064 
   23065    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   23066       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23067       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   23068       break;
   23069 
   23070    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   23071       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23072       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   23073       break;
   23074 
   23075    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   23076       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23077       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   23078       break;
   23079 
   23080    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   23081       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23082       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   23083       break;
   23084 
   23085    case 0x582: // vavgsw (Average Signed Word, AV p151)
   23086       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23087       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   23088       break;
   23089 
   23090 
   23091    /* Multiply */
   23092    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   23093       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23094       putVReg( vD_addr,
   23095                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   23096       break;
   23097 
   23098    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   23099       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23100       putVReg( vD_addr,
   23101                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   23102       break;
   23103 
   23104    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
   23105       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23106       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
   23107       break;
   23108 
   23109    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
   23110       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23111       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
   23112       break;
   23113 
   23114    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   23115       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23116       putVReg( vD_addr,
   23117                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   23118       break;
   23119 
   23120    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   23121       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23122       putVReg( vD_addr,
   23123                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   23124       break;
   23125 
   23126    case 0x188: // vmulosw (Multiply Odd Signed Word)
   23127       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23128       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
   23129       break;
   23130 
   23131    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   23132       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23133       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   23134       break;
   23135 
   23136    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   23137       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23138       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   23139       break;
   23140 
   23141    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
   23142       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23143       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
   23144       break;
   23145 
   23146    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   23147       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23148       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   23149       break;
   23150 
   23151    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   23152       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23153       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   23154       break;
   23155 
   23156    case 0x388: // vmulesw (Multiply Even Signed Word)
   23157       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23158       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
   23159       break;
   23160 
   23161    /* Sum Across Partial */
   23162    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   23163       IRTemp aEE, aEO, aOE, aOO;
   23164       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   23165       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23166 
   23167       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   23168       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   23169       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   23170       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   23171 
   23172       /* break V128 to 4xI32's, zero-extending to I64's */
   23173       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   23174       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   23175       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   23176       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   23177       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   23178 
   23179       /* add lanes */
   23180       assign( z3, binop(Iop_Add64, mkexpr(b3),
   23181                      binop(Iop_Add64,
   23182                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   23183                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   23184       assign( z2, binop(Iop_Add64, mkexpr(b2),
   23185                      binop(Iop_Add64,
   23186                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   23187                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   23188       assign( z1, binop(Iop_Add64, mkexpr(b1),
   23189                      binop(Iop_Add64,
   23190                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   23191                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   23192       assign( z0, binop(Iop_Add64, mkexpr(b0),
   23193                      binop(Iop_Add64,
   23194                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   23195                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   23196 
   23197       /* saturate-narrow to 32bit, and combine to V128 */
   23198       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   23199                                          mkexpr(z1), mkexpr(z0)) );
   23200       break;
   23201    }
   23202    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   23203       IRTemp aEE, aEO, aOE, aOO;
   23204       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   23205       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23206 
   23207       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   23208       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   23209       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   23210       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   23211 
   23212       /* break V128 to 4xI32's, sign-extending to I64's */
   23213       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   23214       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   23215       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   23216       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   23217       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   23218 
   23219       /* add lanes */
   23220       assign( z3, binop(Iop_Add64, mkexpr(b3),
   23221                      binop(Iop_Add64,
   23222                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   23223                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   23224       assign( z2, binop(Iop_Add64, mkexpr(b2),
   23225                      binop(Iop_Add64,
   23226                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   23227                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   23228       assign( z1, binop(Iop_Add64, mkexpr(b1),
   23229                      binop(Iop_Add64,
   23230                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   23231                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   23232       assign( z0, binop(Iop_Add64, mkexpr(b0),
   23233                      binop(Iop_Add64,
   23234                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   23235                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   23236 
   23237       /* saturate-narrow to 32bit, and combine to V128 */
   23238       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   23239                                          mkexpr(z1), mkexpr(z0)) );
   23240       break;
   23241    }
   23242    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   23243       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23244 
   23245       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   23246       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   23247 
   23248       /* break V128 to 4xI32's, sign-extending to I64's */
   23249       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   23250       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   23251       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   23252 
   23253       /* add lanes */
   23254       assign( z3, binop(Iop_Add64, mkexpr(b3),
   23255                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   23256       assign( z2, binop(Iop_Add64, mkexpr(b2),
   23257                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   23258       assign( z1, binop(Iop_Add64, mkexpr(b1),
   23259                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   23260       assign( z0, binop(Iop_Add64, mkexpr(b0),
   23261                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   23262 
   23263       /* saturate-narrow to 32bit, and combine to V128 */
   23264       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   23265                                          mkexpr(z1), mkexpr(z0)) );
   23266       break;
   23267    }
   23268    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   23269       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23270 
   23271       /* break V128 to 4xI32's, sign-extending to I64's */
   23272       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   23273       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   23274 
   23275       /* add lanes */
   23276       assign( z2, binop(Iop_Add64, mkexpr(b2),
   23277                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   23278       assign( z0, binop(Iop_Add64, mkexpr(b0),
   23279                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   23280 
   23281       /* saturate-narrow to 32bit, and combine to V128 */
   23282       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   23283                                          mkU64(0), mkexpr(z0)) );
   23284       break;
   23285    }
   23286    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   23287       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23288 
   23289       /* break V128 to 4xI32's, sign-extending to I64's */
   23290       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   23291       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   23292 
   23293       /* add lanes */
   23294       assign( z0, binop(Iop_Add64, mkexpr(b0),
   23295                      binop(Iop_Add64,
   23296                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   23297                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   23298 
   23299       /* saturate-narrow to 32bit, and combine to V128 */
   23300       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   23301                                          mkU64(0), mkexpr(z0)) );
   23302       break;
   23303    }
   23304    default:
   23305       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   23306       return False;
   23307    }
   23308    return True;
   23309 }
   23310 
   23311 /*
   23312   AltiVec Logic Instructions
   23313 */
   23314 static Bool dis_av_logic ( UInt theInstr )
   23315 {
   23316    /* VX-Form */
   23317    UChar opc1    = ifieldOPC(theInstr);
   23318    UChar vD_addr = ifieldRegDS(theInstr);
   23319    UChar vA_addr = ifieldRegA(theInstr);
   23320    UChar vB_addr = ifieldRegB(theInstr);
   23321    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   23322 
   23323    IRTemp vA = newTemp(Ity_V128);
   23324    IRTemp vB = newTemp(Ity_V128);
   23325    assign( vA, getVReg(vA_addr));
   23326    assign( vB, getVReg(vB_addr));
   23327 
   23328    if (opc1 != 0x4) {
   23329       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   23330       return False;
   23331    }
   23332 
   23333    switch (opc2) {
   23334    case 0x404: // vand (And, AV p147)
   23335       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23336       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   23337       break;
   23338 
   23339    case 0x444: // vandc (And, AV p148)
   23340       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23341       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   23342                               unop(Iop_NotV128, mkexpr(vB))) );
   23343       break;
   23344 
   23345    case 0x484: // vor (Or, AV p217)
   23346       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23347       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   23348       break;
   23349 
   23350    case 0x4C4: // vxor (Xor, AV p282)
   23351       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23352       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   23353       break;
   23354 
   23355    case 0x504: // vnor (Nor, AV p216)
   23356       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23357       putVReg( vD_addr,
   23358          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   23359       break;
   23360 
   23361    case 0x544: // vorc (vA Or'd with complement of vb)
   23362       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23363       putVReg( vD_addr, binop( Iop_OrV128,
   23364                                mkexpr( vA ),
   23365                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
   23366       break;
   23367 
   23368    case 0x584: // vnand (Nand)
   23369       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23370       putVReg( vD_addr, unop( Iop_NotV128,
   23371                               binop(Iop_AndV128, mkexpr( vA ),
   23372                               mkexpr( vB ) ) ) );
   23373       break;
   23374 
   23375    case 0x684: // veqv (complemented XOr)
   23376       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23377       putVReg( vD_addr, unop( Iop_NotV128,
   23378                               binop( Iop_XorV128, mkexpr( vA ),
   23379                               mkexpr( vB ) ) ) );
   23380       break;
   23381 
   23382    default:
   23383       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   23384       return False;
   23385    }
   23386    return True;
   23387 }
   23388 
   23389 /*
   23390   AltiVec Compare Instructions
   23391 */
   23392 static Bool dis_av_cmp ( UInt theInstr )
   23393 {
   23394    /* VXR-Form */
   23395    UChar opc1     = ifieldOPC(theInstr);
   23396    UChar vD_addr  = ifieldRegDS(theInstr);
   23397    UChar vA_addr  = ifieldRegA(theInstr);
   23398    UChar vB_addr  = ifieldRegB(theInstr);
   23399    UChar flag_rC  = ifieldBIT10(theInstr);
   23400    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   23401 
   23402    IRTemp vA = newTemp(Ity_V128);
   23403    IRTemp vB = newTemp(Ity_V128);
   23404    IRTemp vD = newTemp(Ity_V128);
   23405    assign( vA, getVReg(vA_addr));
   23406    assign( vB, getVReg(vB_addr));
   23407 
   23408    if (opc1 != 0x4) {
   23409       vex_printf("dis_av_cmp(ppc)(instr)\n");
   23410       return False;
   23411    }
   23412 
   23413    switch (opc2) {
   23414    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   23415       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23416                                       vD_addr, vA_addr, vB_addr);
   23417       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   23418       break;
   23419 
   23420    case 0x007: // vcmpneb (Compare Not Equal byte)
   23421       DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23422                                       vD_addr, vA_addr, vB_addr);
   23423       assign( vD, unop( Iop_NotV128,
   23424                         binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( vB ) ) ) );
   23425       break;
   23426 
   23427    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   23428       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23429                                       vD_addr, vA_addr, vB_addr);
   23430       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   23431       break;
   23432 
   23433    case 0x047: // vcmpneh (Compare Not Equal-to  Halfword)
   23434       DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23435                                       vD_addr, vA_addr, vB_addr);
   23436       assign( vD, unop( Iop_NotV128,
   23437                         binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( vB ) ) ) );
   23438       break;
   23439 
   23440    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   23441       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23442                                       vD_addr, vA_addr, vB_addr);
   23443       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   23444       break;
   23445 
   23446    case 0x087: // vcmpnew (Compare Not Equal-to Word)
   23447       DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23448                                       vD_addr, vA_addr, vB_addr);
   23449       assign( vD, unop( Iop_NotV128,
   23450                         binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( vB ) ) ) );
   23451       break;
   23452 
   23453    case 0x107: // vcmpnezb (Compare Not Equal or Zero byte)
   23454       {
   23455          IRTemp vAeqvB = newTemp( Ity_V128 );
   23456          IRTemp vAeq0  = newTemp( Ity_V128 );
   23457          IRTemp vBeq0  = newTemp( Ity_V128 );
   23458          IRTemp zero   = newTemp( Ity_V128 );
   23459 
   23460          DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23461                                          vD_addr, vA_addr, vB_addr);
   23462 
   23463          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
   23464          assign( vAeq0, binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( zero ) ) );
   23465          assign( vBeq0, binop( Iop_CmpEQ8x16, mkexpr( vB ), mkexpr( zero ) ) );
   23466          assign( vAeqvB, unop( Iop_NotV128,
   23467                                binop( Iop_CmpEQ8x16, mkexpr( vA ),
   23468                                       mkexpr( vB ) ) ) );
   23469 
   23470          assign( vD, mkOr3_V128( vAeqvB, vAeq0, vBeq0  ) );
   23471       }
   23472       break;
   23473 
   23474    case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword)
   23475       {
   23476          IRTemp vAeqvB = newTemp( Ity_V128 );
   23477          IRTemp vAeq0  = newTemp( Ity_V128 );
   23478          IRTemp vBeq0  = newTemp( Ity_V128 );
   23479          IRTemp zero   = newTemp( Ity_V128 );
   23480 
   23481          DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23482                                          vD_addr, vA_addr, vB_addr);
   23483 
   23484          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
   23485          assign( vAeq0, binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( zero ) ) );
   23486          assign( vBeq0, binop( Iop_CmpEQ16x8, mkexpr( vB ), mkexpr( zero ) ) );
   23487          assign( vAeqvB, unop( Iop_NotV128,
   23488                                binop(Iop_CmpEQ16x8, mkexpr( vA ),
   23489                                      mkexpr( vB ) ) ) );
   23490 
   23491          assign( vD, binop( Iop_OrV128,
   23492                             binop( Iop_OrV128,
   23493                                    mkexpr( vAeq0 ),
   23494                                    mkexpr( vBeq0 ) ),
   23495                             mkexpr( vAeqvB ) ) );
   23496       }
   23497       break;
   23498 
   23499    case 0x187: // vcmpnezw (Compare Not Equal or Zero Word)
   23500       {
   23501          IRTemp vAeqvB = newTemp( Ity_V128 );
   23502          IRTemp vAeq0  = newTemp( Ity_V128 );
   23503          IRTemp vBeq0  = newTemp( Ity_V128 );
   23504          IRTemp zero   = newTemp( Ity_V128 );
   23505 
   23506          DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23507                                          vD_addr, vA_addr, vB_addr);
   23508 
   23509          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
   23510          assign( vAeq0, binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( zero ) ) );
   23511          assign( vBeq0, binop( Iop_CmpEQ32x4, mkexpr( vB ), mkexpr( zero ) ) );
   23512          assign( vAeqvB, unop( Iop_NotV128,
   23513                                binop(Iop_CmpEQ32x4, mkexpr( vA ),
   23514                                      mkexpr( vB ) ) ) );
   23515 
   23516          assign( vD, binop( Iop_OrV128,
   23517                             binop( Iop_OrV128,
   23518                                    mkexpr( vAeq0 ),
   23519                                    mkexpr( vBeq0 ) ),
   23520                             mkexpr( vAeqvB ) ) );
   23521       }
   23522       break;
   23523 
   23524    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
   23525       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23526                                       vD_addr, vA_addr, vB_addr);
   23527       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
   23528       break;
   23529 
   23530    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   23531       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23532                                       vD_addr, vA_addr, vB_addr);
   23533       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   23534       break;
   23535 
   23536    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   23537       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23538                                       vD_addr, vA_addr, vB_addr);
   23539       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   23540       break;
   23541 
   23542    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   23543       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23544                                        vD_addr, vA_addr, vB_addr);
   23545       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   23546       break;
   23547 
   23548    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
   23549       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23550                                       vD_addr, vA_addr, vB_addr);
   23551       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
   23552       break;
   23553 
   23554    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   23555       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23556                                        vD_addr, vA_addr, vB_addr);
   23557       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   23558       break;
   23559 
   23560    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   23561       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23562                                       vD_addr, vA_addr, vB_addr);
   23563       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   23564       break;
   23565 
   23566    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   23567       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23568                                       vD_addr, vA_addr, vB_addr);
   23569       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   23570       break;
   23571 
   23572    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
   23573       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   23574                                       vD_addr, vA_addr, vB_addr);
   23575       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
   23576       break;
   23577 
   23578    default:
   23579       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   23580       return False;
   23581    }
   23582 
   23583    putVReg( vD_addr, mkexpr(vD) );
   23584 
   23585    if (flag_rC) {
   23586       set_AV_CR6( mkexpr(vD), True );
   23587    }
   23588    return True;
   23589 }
   23590 
   23591 /*
   23592   AltiVec Multiply-Sum Instructions
   23593 */
   23594 static Bool dis_av_multarith ( UInt theInstr )
   23595 {
   23596    /* VA-Form */
   23597    UChar opc1     = ifieldOPC(theInstr);
   23598    UChar vD_addr  = ifieldRegDS(theInstr);
   23599    UChar vA_addr  = ifieldRegA(theInstr);
   23600    UChar vB_addr  = ifieldRegB(theInstr);
   23601    UChar vC_addr  = ifieldRegC(theInstr);
   23602    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   23603 
   23604    IRTemp vA    = newTemp(Ity_V128);
   23605    IRTemp vB    = newTemp(Ity_V128);
   23606    IRTemp vC    = newTemp(Ity_V128);
   23607    IRTemp zeros = newTemp(Ity_V128);
   23608    IRTemp aLo   = newTemp(Ity_V128);
   23609    IRTemp bLo   = newTemp(Ity_V128);
   23610    IRTemp cLo   = newTemp(Ity_V128);
   23611    IRTemp zLo   = newTemp(Ity_V128);
   23612    IRTemp aHi   = newTemp(Ity_V128);
   23613    IRTemp bHi   = newTemp(Ity_V128);
   23614    IRTemp cHi   = newTemp(Ity_V128);
   23615    IRTemp zHi   = newTemp(Ity_V128);
   23616    IRTemp abEvn = newTemp(Ity_V128);
   23617    IRTemp abOdd = newTemp(Ity_V128);
   23618    IRTemp z3    = newTemp(Ity_I64);
   23619    IRTemp z2    = newTemp(Ity_I64);
   23620    IRTemp z1    = newTemp(Ity_I64);
   23621    IRTemp z0    = newTemp(Ity_I64);
   23622    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   23623    IRTemp c3, c2, c1, c0;
   23624 
   23625    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   23626    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   23627 
   23628    assign( vA, getVReg(vA_addr));
   23629    assign( vB, getVReg(vB_addr));
   23630    assign( vC, getVReg(vC_addr));
   23631    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   23632 
   23633    if (opc1 != 0x4) {
   23634       vex_printf("dis_av_multarith(ppc)(instr)\n");
   23635       return False;
   23636    }
   23637 
   23638    switch (opc2) {
   23639    /* Multiply-Add */
   23640    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   23641       IRTemp cSigns = newTemp(Ity_V128);
   23642       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   23643           vD_addr, vA_addr, vB_addr, vC_addr);
   23644       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   23645       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   23646       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   23647       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   23648       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   23649       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   23650       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   23651 
   23652       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   23653                          binop(Iop_SarN32x4,
   23654                                binop(Iop_MullEven16Sx8,
   23655                                      mkexpr(aLo), mkexpr(bLo)),
   23656                                mkU8(15))) );
   23657 
   23658       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   23659                          binop(Iop_SarN32x4,
   23660                                binop(Iop_MullEven16Sx8,
   23661                                      mkexpr(aHi), mkexpr(bHi)),
   23662                                mkU8(15))) );
   23663 
   23664       putVReg( vD_addr,
   23665                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   23666       break;
   23667    }
   23668    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   23669       IRTemp zKonst = newTemp(Ity_V128);
   23670       IRTemp cSigns = newTemp(Ity_V128);
   23671       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   23672           vD_addr, vA_addr, vB_addr, vC_addr);
   23673       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   23674       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   23675       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   23676       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   23677       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   23678       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   23679       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   23680 
   23681       /* shifting our const avoids store/load version of Dup */
   23682       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   23683                             mkU8(14)) );
   23684 
   23685       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   23686                          binop(Iop_SarN32x4,
   23687                                binop(Iop_Add32x4, mkexpr(zKonst),
   23688                                      binop(Iop_MullEven16Sx8,
   23689                                            mkexpr(aLo), mkexpr(bLo))),
   23690                                mkU8(15))) );
   23691 
   23692       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   23693                          binop(Iop_SarN32x4,
   23694                                binop(Iop_Add32x4, mkexpr(zKonst),
   23695                                      binop(Iop_MullEven16Sx8,
   23696                                            mkexpr(aHi), mkexpr(bHi))),
   23697                                mkU8(15))) );
   23698 
   23699       putVReg( vD_addr,
   23700                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   23701       break;
   23702    }
   23703    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   23704       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   23705           vD_addr, vA_addr, vB_addr, vC_addr);
   23706       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   23707       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   23708       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   23709       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   23710       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   23711       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   23712       assign(zLo, binop(Iop_Add32x4,
   23713                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   23714                      mkexpr(cLo)) );
   23715       assign(zHi, binop(Iop_Add32x4,
   23716                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   23717                      mkexpr(cHi)));
   23718       putVReg( vD_addr,
   23719                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   23720       break;
   23721    }
   23722 
   23723    case 0x23: { // vmsumudm
   23724       DIP("vmsumudm v%d,v%d,v%d,v%d\n",
   23725           vD_addr, vA_addr, vB_addr, vC_addr);
   23726       /* This instruction takes input vectors VA, VB consisting of 2 usigned
   23727          64-bit integer elements and a 128 bit unsigned input U128_C.  The
   23728          instruction performs the following operation:
   23729 
   23730             VA[0] * VB[0] -> U128_mul_result0;
   23731             VA[1] * VB[1] -> U128_mul_result1;
   23732             U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum;
   23733             carry out and overflow is discarded.
   23734       */
   23735 
   23736       /* The Iop_MulI128low assumes the upper 64-bits in the two input operands
   23737          are zero. */
   23738       IRTemp mul_result0 = newTemp( Ity_I128 );
   23739       IRTemp mul_result1 = newTemp( Ity_I128 );
   23740       IRTemp partial_sum_hi = newTemp( Ity_I64 );
   23741       IRTemp partial_sum_low = newTemp( Ity_I64 );
   23742       IRTemp result_hi  = newTemp( Ity_I64 );
   23743       IRTemp result_low = newTemp( Ity_I64 );
   23744       IRExpr *ca_sum, *ca_result;
   23745 
   23746 
   23747       /* Do multiplications */
   23748       assign ( mul_result0, binop( Iop_MullU64,
   23749                                    unop( Iop_V128to64, mkexpr( vA ) ),
   23750                                    unop( Iop_V128to64, mkexpr( vB) ) ) );
   23751 
   23752       assign ( mul_result1, binop( Iop_MullU64,
   23753                                    unop( Iop_V128HIto64, mkexpr( vA ) ),
   23754                                    unop( Iop_V128HIto64, mkexpr( vB) ) ) );
   23755 
   23756       /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry
   23757          from low 64-bits add into sum of upper 64-bits.  Throw away carry out
   23758          of the upper 64-bit sum. */
   23759       assign ( partial_sum_low, binop( Iop_Add64,
   23760                                        unop( Iop_128to64, mkexpr( mul_result0 ) ),
   23761                                        unop( Iop_128to64, mkexpr( mul_result1 ) )
   23762                                        ) );
   23763 
   23764       /* ca_sum is type U32 */
   23765       ca_sum =  calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD,
   23766                                       mkexpr(partial_sum_low ),
   23767                                       unop( Iop_128to64, mkexpr( mul_result0 ) ),
   23768                                       unop( Iop_128to64, mkexpr( mul_result1 ) ),
   23769                                       mkU64( 0 ) );
   23770 
   23771       assign ( partial_sum_hi,
   23772                binop( Iop_Add64,
   23773                       binop( Iop_Add64,
   23774                              unop( Iop_128HIto64, mkexpr( mul_result0 ) ),
   23775                              unop( Iop_128HIto64, mkexpr( mul_result1 ) ) ),
   23776                       binop( Iop_32HLto64, mkU32( 0 ), ca_sum ) ) );
   23777 
   23778       /* Now add in the value of C */
   23779       assign ( result_low, binop( Iop_Add64,
   23780                                   mkexpr( partial_sum_low ),
   23781                                   unop( Iop_V128to64, mkexpr( vC ) ) ) );
   23782 
   23783       /* ca_result is type U32 */
   23784       ca_result =  calculate_XER_CA_64(  PPCG_FLAG_OP_ADD,
   23785                                          mkexpr( result_low ),
   23786                                          mkexpr( partial_sum_low ),
   23787                                          unop( Iop_V128to64,
   23788                                                mkexpr( vC ) ),
   23789                                          mkU64( 0 ) );
   23790 
   23791       assign ( result_hi,
   23792                binop( Iop_Add64,
   23793                       binop( Iop_Add64,
   23794                              mkexpr( partial_sum_hi ),
   23795                              unop( Iop_V128HIto64, mkexpr( vC ) ) ),
   23796                       binop( Iop_32HLto64, mkU32( 0 ), ca_result ) ) );
   23797 
   23798       putVReg( vD_addr, binop( Iop_64HLtoV128,
   23799                                mkexpr( result_hi ), mkexpr ( result_low ) ) );
   23800       break;
   23801    }
   23802 
   23803    /* Multiply-Sum */
   23804    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   23805       IRTemp abEE, abEO, abOE, abOO;
   23806       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   23807       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   23808           vD_addr, vA_addr, vB_addr, vC_addr);
   23809 
   23810       /* multiply vA,vB (unsigned, widening) */
   23811       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   23812       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   23813 
   23814       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   23815       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   23816       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   23817 
   23818       putVReg( vD_addr,
   23819          binop(Iop_Add32x4, mkexpr(vC),
   23820                binop(Iop_Add32x4,
   23821                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   23822                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   23823       break;
   23824    }
   23825    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   23826       IRTemp aEvn, aOdd, bEvn, bOdd;
   23827       IRTemp abEE = newTemp(Ity_V128);
   23828       IRTemp abEO = newTemp(Ity_V128);
   23829       IRTemp abOE = newTemp(Ity_V128);
   23830       IRTemp abOO = newTemp(Ity_V128);
   23831       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   23832       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   23833           vD_addr, vA_addr, vB_addr, vC_addr);
   23834 
   23835       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   23836          (separating out adjacent lanes to different vectors) */
   23837       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   23838       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   23839 
   23840       /* multiply vA, vB, again separating adjacent lanes */
   23841       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   23842       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   23843       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   23844       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   23845 
   23846       /* add results together, + vC */
   23847       putVReg( vD_addr,
   23848          binop(Iop_QAdd32Sx4, mkexpr(vC),
   23849                binop(Iop_QAdd32Sx4,
   23850                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   23851                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   23852       break;
   23853    }
   23854    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   23855       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   23856           vD_addr, vA_addr, vB_addr, vC_addr);
   23857       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   23858       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   23859       putVReg( vD_addr,
   23860          binop(Iop_Add32x4, mkexpr(vC),
   23861                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   23862       break;
   23863    }
   23864    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   23865       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   23866           vD_addr, vA_addr, vB_addr, vC_addr);
   23867       /* widening multiply, separating lanes */
   23868       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   23869       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   23870 
   23871       /* break V128 to 4xI32's, zero-extending to I64's */
   23872       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   23873       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   23874       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   23875 
   23876       /* add lanes */
   23877       assign( z3, binop(Iop_Add64, mkexpr(c3),
   23878                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   23879       assign( z2, binop(Iop_Add64, mkexpr(c2),
   23880                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   23881       assign( z1, binop(Iop_Add64, mkexpr(c1),
   23882                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   23883       assign( z0, binop(Iop_Add64, mkexpr(c0),
   23884                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   23885 
   23886       /* saturate-narrow to 32bit, and combine to V128 */
   23887       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   23888                                          mkexpr(z1), mkexpr(z0)) );
   23889 
   23890       break;
   23891    }
   23892    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   23893       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   23894           vD_addr, vA_addr, vB_addr, vC_addr);
   23895       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   23896       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   23897       putVReg( vD_addr,
   23898          binop(Iop_Add32x4, mkexpr(vC),
   23899                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   23900       break;
   23901    }
   23902    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   23903       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   23904           vD_addr, vA_addr, vB_addr, vC_addr);
   23905       /* widening multiply, separating lanes */
   23906       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   23907       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   23908 
   23909       /* break V128 to 4xI32's, sign-extending to I64's */
   23910       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   23911       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   23912       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   23913 
   23914       /* add lanes */
   23915       assign( z3, binop(Iop_Add64, mkexpr(c3),
   23916                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   23917       assign( z2, binop(Iop_Add64, mkexpr(c2),
   23918                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   23919       assign( z1, binop(Iop_Add64, mkexpr(c1),
   23920                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   23921       assign( z0, binop(Iop_Add64, mkexpr(c0),
   23922                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   23923 
   23924       /* saturate-narrow to 32bit, and combine to V128 */
   23925       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   23926                                          mkexpr(z1), mkexpr(z0)) );
   23927       break;
   23928    }
   23929    default:
   23930       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   23931       return False;
   23932    }
   23933    return True;
   23934 }
   23935 
   23936 /*
   23937   AltiVec Polynomial Multiply-Sum Instructions
   23938 */
   23939 static Bool dis_av_polymultarith ( UInt theInstr )
   23940 {
   23941    /* VA-Form */
   23942    UChar opc1     = ifieldOPC(theInstr);
   23943    UChar vD_addr  = ifieldRegDS(theInstr);
   23944    UChar vA_addr  = ifieldRegA(theInstr);
   23945    UChar vB_addr  = ifieldRegB(theInstr);
   23946    UChar vC_addr  = ifieldRegC(theInstr);
   23947    UInt  opc2     = IFIELD(theInstr, 0, 11);
   23948    IRTemp vA    = newTemp(Ity_V128);
   23949    IRTemp vB    = newTemp(Ity_V128);
   23950    IRTemp vC    = newTemp(Ity_V128);
   23951 
   23952    assign( vA, getVReg(vA_addr));
   23953    assign( vB, getVReg(vB_addr));
   23954    assign( vC, getVReg(vC_addr));
   23955 
   23956    if (opc1 != 0x4) {
   23957       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
   23958       return False;
   23959    }
   23960 
   23961    switch (opc2) {
   23962       /* Polynomial Multiply-Add */
   23963       case 0x408:  // vpmsumb   Vector Polynomial Multiply-sum Byte
   23964          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23965          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
   23966                                  mkexpr(vA), mkexpr(vB)) );
   23967          break;
   23968       case 0x448:  // vpmsumd   Vector Polynomial Multiply-sum Double Word
   23969          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23970          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
   23971                                  mkexpr(vA), mkexpr(vB)) );
   23972          break;
   23973       case 0x488:  // vpmsumw   Vector Polynomial Multiply-sum Word
   23974          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23975          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
   23976                                  mkexpr(vA), mkexpr(vB)) );
   23977          break;
   23978       case 0x4C8:  // vpmsumh   Vector Polynomial Multiply-sum Half Word
   23979          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   23980          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
   23981                                  mkexpr(vA), mkexpr(vB)) );
   23982          break;
   23983       default:
   23984          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
   23985          return False;
   23986    }
   23987    return True;
   23988 }
   23989 
   23990 /*
   23991   AltiVec Shift/Rotate Instructions
   23992 */
   23993 static Bool dis_av_shift ( UInt theInstr )
   23994 {
   23995    /* VX-Form */
   23996    UChar opc1    = ifieldOPC(theInstr);
   23997    UChar vD_addr = ifieldRegDS(theInstr);
   23998    UChar vA_addr = ifieldRegA(theInstr);
   23999    UChar vB_addr = ifieldRegB(theInstr);
   24000    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   24001 
   24002    IRTemp vA = newTemp(Ity_V128);
   24003    IRTemp vB = newTemp(Ity_V128);
   24004    assign( vA, getVReg(vA_addr));
   24005    assign( vB, getVReg(vB_addr));
   24006 
   24007    if (opc1 != 0x4){
   24008       vex_printf("dis_av_shift(ppc)(instr)\n");
   24009       return False;
   24010    }
   24011 
   24012    switch (opc2) {
   24013    /* Rotate */
   24014    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   24015       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24016       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   24017       break;
   24018 
   24019    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   24020       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24021       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   24022       break;
   24023 
   24024    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   24025       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24026       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   24027       break;
   24028 
   24029    case 0x0C4: // vrld (Rotate Left Integer Double Word)
   24030       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24031       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
   24032       break;
   24033 
   24034 
   24035    /* Shift Left */
   24036    case 0x104: // vslb (Shift Left Integer B, AV p240)
   24037       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24038       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   24039       break;
   24040 
   24041    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   24042       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24043       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   24044       break;
   24045 
   24046    case 0x184: // vslw (Shift Left Integer W, AV p244)
   24047       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24048       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   24049       break;
   24050 
   24051    case 0x5C4: // vsld (Shift Left Integer Double Word)
   24052       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24053       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
   24054       break;
   24055 
   24056    case 0x1C4: { // vsl (Shift Left, AV p239)
   24057       IRTemp sh = newTemp(Ity_I8);
   24058       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24059       assign( sh, binop(Iop_And8, mkU8(0x7),
   24060                         unop(Iop_32to8,
   24061                              unop(Iop_V128to32, mkexpr(vB)))) );
   24062       putVReg( vD_addr,
   24063                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   24064       break;
   24065    }
   24066    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   24067       IRTemp sh = newTemp(Ity_I8);
   24068       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24069       assign( sh, binop(Iop_And8, mkU8(0x78),
   24070                         unop(Iop_32to8,
   24071                              unop(Iop_V128to32, mkexpr(vB)))) );
   24072       putVReg( vD_addr,
   24073                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   24074       break;
   24075    }
   24076 
   24077 
   24078    /* Shift Right */
   24079    case 0x204: // vsrb (Shift Right B, AV p256)
   24080       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24081       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   24082       break;
   24083 
   24084    case 0x244: // vsrh (Shift Right HW, AV p257)
   24085       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24086       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   24087       break;
   24088 
   24089    case 0x284: // vsrw (Shift Right W, AV p259)
   24090       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24091       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   24092       break;
   24093 
   24094    case 0x2C4: { // vsr (Shift Right, AV p251)
   24095       IRTemp sh = newTemp(Ity_I8);
   24096       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24097       assign( sh, binop(Iop_And8, mkU8(0x7),
   24098                         unop(Iop_32to8,
   24099                              unop(Iop_V128to32, mkexpr(vB)))) );
   24100       putVReg( vD_addr,
   24101                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   24102       break;
   24103    }
   24104    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   24105       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24106       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   24107       break;
   24108 
   24109    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   24110       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24111       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   24112       break;
   24113 
   24114    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   24115       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24116       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   24117       break;
   24118 
   24119    case 0x3C4: // vsrad (Shift Right Alg Double Word)
   24120       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24121       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
   24122       break;
   24123 
   24124    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   24125       IRTemp sh = newTemp(Ity_I8);
   24126       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24127       assign( sh, binop(Iop_And8, mkU8(0x78),
   24128                         unop(Iop_32to8,
   24129                              unop(Iop_V128to32, mkexpr(vB)))) );
   24130       putVReg( vD_addr,
   24131                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   24132       break;
   24133    }
   24134 
   24135    case 0x6C4: // vsrd (Shift Right Double Word)
   24136       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24137       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
   24138       break;
   24139 
   24140 
   24141    default:
   24142       vex_printf("dis_av_shift(ppc)(opc2)\n");
   24143       return False;
   24144    }
   24145    return True;
   24146 }
   24147 
   24148 /*
   24149   AltiVec Permute Instructions
   24150 */
   24151 static Bool dis_av_permute ( UInt theInstr )
   24152 {
   24153    /* VA-Form, VX-Form */
   24154    UChar opc1      = ifieldOPC(theInstr);
   24155    UChar vD_addr   = ifieldRegDS(theInstr);
   24156    UChar vA_addr   = ifieldRegA(theInstr);
   24157    UChar UIMM_5    = vA_addr;
   24158    UChar vB_addr   = ifieldRegB(theInstr);
   24159    UChar vC_addr   = ifieldRegC(theInstr);
   24160    UChar b10       = ifieldBIT10(theInstr);
   24161    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   24162    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   24163 
   24164    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   24165 
   24166    IRTemp vA = newTemp(Ity_V128);
   24167    IRTemp vB = newTemp(Ity_V128);
   24168    IRTemp vC = newTemp(Ity_V128);
   24169    assign( vA, getVReg(vA_addr));
   24170    assign( vB, getVReg(vB_addr));
   24171    assign( vC, getVReg(vC_addr));
   24172 
   24173    if (opc1 != 0x4) {
   24174       vex_printf("dis_av_permute(ppc)(instr)\n");
   24175       return False;
   24176    }
   24177 
   24178    switch (opc2) {
   24179    case 0x2A: // vsel (Conditional Select, AV p238)
   24180       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   24181       /* vD = (vA & ~vC) | (vB & vC) */
   24182       putVReg( vD_addr, binop(Iop_OrV128,
   24183          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   24184          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   24185       return True;
   24186 
   24187    case 0x2B: { // vperm (Permute, AV p218)
   24188       /* limited to two args for IR, so have to play games... */
   24189       IRTemp a_perm  = newTemp(Ity_V128);
   24190       IRTemp b_perm  = newTemp(Ity_V128);
   24191       IRTemp mask    = newTemp(Ity_V128);
   24192       IRTemp vC_andF = newTemp(Ity_V128);
   24193       DIP("vperm v%d,v%d,v%d,v%d\n",
   24194           vD_addr, vA_addr, vB_addr, vC_addr);
   24195       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   24196          IR specifies, and also to hide irrelevant bits from
   24197          memcheck */
   24198       assign( vC_andF,
   24199               binop(Iop_AndV128, mkexpr(vC),
   24200                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   24201       assign( a_perm,
   24202               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   24203       assign( b_perm,
   24204               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   24205       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   24206       assign( mask, binop(Iop_SarN8x16,
   24207                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   24208                           mkU8(7)) );
   24209       // dst = (a & ~mask) | (b & mask)
   24210       putVReg( vD_addr, binop(Iop_OrV128,
   24211                               binop(Iop_AndV128, mkexpr(a_perm),
   24212                                     unop(Iop_NotV128, mkexpr(mask))),
   24213                               binop(Iop_AndV128, mkexpr(b_perm),
   24214                                     mkexpr(mask))) );
   24215       return True;
   24216    }
   24217    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   24218       if (b10 != 0) {
   24219          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   24220          return False;
   24221       }
   24222       DIP("vsldoi v%d,v%d,v%d,%d\n",
   24223           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   24224       if (SHB_uimm4 == 0)
   24225          putVReg( vD_addr, mkexpr(vA) );
   24226       else
   24227          putVReg( vD_addr,
   24228             binop(Iop_OrV128,
   24229                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   24230                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   24231       return True;
   24232    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
   24233       IRTemp a_perm  = newTemp(Ity_V128);
   24234       IRTemp b_perm  = newTemp(Ity_V128);
   24235       IRTemp vrc_a   = newTemp(Ity_V128);
   24236       IRTemp vrc_b   = newTemp(Ity_V128);
   24237 
   24238       DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   24239 
   24240       /* IBM index  is 0:7, Change index value to index 7:0 */
   24241       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
   24242                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
   24243       assign( vrc_a, binop( Iop_ShrV128,
   24244                             binop( Iop_AndV128, mkexpr( vC ),
   24245                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
   24246                             mkU8 ( 4 ) ) );
   24247       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
   24248       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
   24249       putVReg( vD_addr, binop( Iop_XorV128,
   24250                                mkexpr( a_perm ), mkexpr( b_perm) ) );
   24251       return True;
   24252    }
   24253 
   24254    case 0x3B: {  // vpermr (Vector Permute Right-indexed)
   24255       int i;
   24256       IRTemp new_Vt[17];
   24257       IRTemp tmp[16];
   24258       IRTemp index[16];
   24259       IRTemp index_gt16[16];
   24260       IRTemp mask[16];
   24261 
   24262       DIP("vpermr v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   24263 
   24264       new_Vt[0] = newTemp( Ity_V128 );
   24265       assign( new_Vt[0], binop( Iop_64HLtoV128,
   24266                                 mkU64( 0x0 ),
   24267                                 mkU64( 0x0 ) ) );
   24268 
   24269       for ( i = 0; i < 16; i++ ) {
   24270          index_gt16[i] = newTemp( Ity_V128 );
   24271          mask[i]  = newTemp( Ity_V128 );
   24272          index[i] = newTemp( Ity_I32 );
   24273          tmp[i]   = newTemp( Ity_V128 );
   24274          new_Vt[i+1] = newTemp( Ity_V128 );
   24275 
   24276          assign( index[i],
   24277                  binop( Iop_Sub32,
   24278                         mkU32( 31 ),
   24279                         unop( Iop_64to32,
   24280                               unop( Iop_V128to64,
   24281                                     binop( Iop_ShrV128,
   24282                                            binop( Iop_AndV128,
   24283                                                   binop( Iop_ShlV128,
   24284                                                          binop( Iop_64HLtoV128,
   24285                                                                 mkU64( 0x0 ),
   24286                                                                 mkU64( 0x3F ) ),
   24287                                                          mkU8(  (15 - i) * 8 ) ),
   24288                                                   mkexpr( vC ) ),
   24289                                            mkU8( (15 - i) * 8 ) ) ) ) ) );
   24290 
   24291          /* Determine if index < 16, src byte is vA[index], otherwise
   24292           * vB[31-index]. Check if msb of index is 1 or not.
   24293           */
   24294          assign( index_gt16[i],
   24295                  binop( Iop_64HLtoV128,
   24296                         unop( Iop_1Sto64,
   24297                               unop( Iop_32to1,
   24298                                     binop( Iop_Shr32,
   24299                                            mkexpr( index[i] ),
   24300                                            mkU8( 4 ) ) ) ),
   24301                         unop( Iop_1Sto64,
   24302                               unop( Iop_32to1,
   24303                                     binop( Iop_Shr32,
   24304                                            mkexpr( index[i] ),
   24305                                            mkU8( 4 ) ) ) ) ) );
   24306          assign( mask[i],
   24307                  binop( Iop_ShlV128,
   24308                         binop( Iop_64HLtoV128,
   24309                                mkU64( 0x0 ),
   24310                                mkU64( 0xFF ) ),
   24311                         unop( Iop_32to8,
   24312                               binop( Iop_Mul32,
   24313                                      binop( Iop_Sub32,
   24314                                             mkU32( 15 ),
   24315                                             binop( Iop_And32,
   24316                                                    mkexpr( index[i] ),
   24317                                                    mkU32( 0xF ) ) ),
   24318                                      mkU32( 8 ) ) ) ) );
   24319 
   24320          /* Extract the indexed byte from vA and vB using the lower 4-bits
   24321           * of the index. Then use the index_gt16 mask to select vA if the
   24322           * index < 16 or vB if index > 15.  Put the selected byte in the
   24323           * least significant byte.
   24324           */
   24325          assign( tmp[i],
   24326                  binop( Iop_ShrV128,
   24327                         binop( Iop_OrV128,
   24328                                binop( Iop_AndV128,
   24329                                       binop( Iop_AndV128,
   24330                                              mkexpr( mask[i] ),
   24331                                              mkexpr( vA ) ),
   24332                                       unop( Iop_NotV128,
   24333                                             mkexpr( index_gt16[i] ) ) ),
   24334                                binop( Iop_AndV128,
   24335                                       binop( Iop_AndV128,
   24336                                              mkexpr( mask[i] ),
   24337                                              mkexpr( vB ) ),
   24338                                       mkexpr( index_gt16[i] ) ) ),
   24339                         unop( Iop_32to8,
   24340                               binop( Iop_Mul32,
   24341                                      binop( Iop_Sub32,
   24342                                             mkU32( 15 ),
   24343                                             binop( Iop_And32,
   24344                                                    mkexpr( index[i] ),
   24345                                                    mkU32( 0xF ) ) ),
   24346                                      mkU32( 8 ) ) ) ) );
   24347 
   24348          /* Move the selected byte to the position to store in the result */
   24349          assign( new_Vt[i+1], binop( Iop_OrV128,
   24350                                      binop( Iop_ShlV128,
   24351                                             mkexpr( tmp[i] ),
   24352                                             mkU8(  (15 - i) * 8 ) ),
   24353                                      mkexpr( new_Vt[i] ) ) );
   24354          }
   24355       putVReg( vD_addr, mkexpr( new_Vt[16] ) );
   24356       return True;
   24357    }
   24358 
   24359    default:
   24360      break; // Fall through...
   24361    }
   24362 
   24363    opc2 = IFIELD( theInstr, 0, 11 );
   24364    switch (opc2) {
   24365 
   24366    /* Merge */
   24367    case 0x00C: // vmrghb (Merge High B, AV p195)
   24368       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24369       putVReg( vD_addr,
   24370                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   24371       break;
   24372 
   24373    case 0x04C: // vmrghh (Merge High HW, AV p196)
   24374       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24375       putVReg( vD_addr,
   24376                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   24377       break;
   24378 
   24379    case 0x08C: // vmrghw (Merge High W, AV p197)
   24380       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24381       putVReg( vD_addr,
   24382                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   24383       break;
   24384 
   24385    case 0x10C: // vmrglb (Merge Low B, AV p198)
   24386       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24387       putVReg( vD_addr,
   24388                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   24389       break;
   24390 
   24391    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   24392       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24393       putVReg( vD_addr,
   24394                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   24395       break;
   24396 
   24397    case 0x18C: // vmrglw (Merge Low W, AV p200)
   24398       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24399       putVReg( vD_addr,
   24400                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   24401       break;
   24402 
   24403    /* Extract instructions */
   24404    case 0x20D: // vextractub  (Vector Extract Unsigned Byte)
   24405    {
   24406       UChar uim = IFIELD( theInstr, 16, 4 );
   24407 
   24408       DIP("vextractub v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24409 
   24410       putVReg( vD_addr, binop( Iop_ShlV128,
   24411                                binop( Iop_AndV128,
   24412                                       binop( Iop_ShrV128,
   24413                                              mkexpr( vB ),
   24414                                              unop( Iop_32to8,
   24415                                                    binop( Iop_Mul32,
   24416                                                           mkU32( 8 ),
   24417                                                           mkU32( 31 - uim ) ) ) ),
   24418                                       binop( Iop_64HLtoV128,
   24419                                              mkU64( 0x0ULL ),
   24420                                              mkU64( 0xFFULL ) ) ),
   24421                                mkU8( 64 ) ) );
   24422    }
   24423    break;
   24424 
   24425    case 0x24D: // vextractuh  (Vector Extract Unsigned Halfword)
   24426    {
   24427       UChar uim = IFIELD( theInstr, 16, 4 );
   24428 
   24429       DIP("vextractuh v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24430 
   24431       putVReg( vD_addr, binop( Iop_ShlV128,
   24432                                binop( Iop_AndV128,
   24433                                       binop( Iop_ShrV128,
   24434                                              mkexpr( vB ),
   24435                                              unop( Iop_32to8,
   24436                                                    binop( Iop_Mul32,
   24437                                                           mkU32( 8 ),
   24438                                                           mkU32( 30 - uim ) ) ) ),
   24439                                       binop( Iop_64HLtoV128,
   24440                                              mkU64( 0x0ULL ),
   24441                                              mkU64( 0xFFFFULL ) ) ),
   24442                                mkU8( 64 ) ) );
   24443    }
   24444    break;
   24445 
   24446    case 0x28D: // vextractuw  (Vector Extract Unsigned Word)
   24447    {
   24448       UChar uim = IFIELD( theInstr, 16, 4 );
   24449 
   24450       DIP("vextractuw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24451 
   24452       putVReg( vD_addr,
   24453                binop( Iop_ShlV128,
   24454                       binop( Iop_AndV128,
   24455                              binop( Iop_ShrV128,
   24456                                     mkexpr( vB ),
   24457                                     unop( Iop_32to8,
   24458                                           binop( Iop_Mul32,
   24459                                                  mkU32( 8 ),
   24460                                                  mkU32( 28 - uim ) ) ) ),
   24461                              binop( Iop_64HLtoV128,
   24462                                     mkU64( 0x0ULL ),
   24463                                     mkU64( 0xFFFFFFFFULL ) ) ),
   24464                       mkU8( 64 ) ) );
   24465    }
   24466    break;
   24467 
   24468    case 0x2CD: // vextractd  (Vector Extract Double Word)
   24469    {
   24470       UChar uim = IFIELD( theInstr, 16, 4 );
   24471 
   24472       DIP("vextractd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24473 
   24474       putVReg( vD_addr,
   24475                binop( Iop_ShlV128,
   24476                       binop( Iop_AndV128,
   24477                              binop( Iop_ShrV128,
   24478                                     mkexpr( vB ),
   24479                                     unop( Iop_32to8,
   24480                                           binop( Iop_Mul32,
   24481                                                  mkU32( 8 ),
   24482                                                  mkU32( 24 - uim ) ) ) ),
   24483                              binop( Iop_64HLtoV128,
   24484                                     mkU64( 0x0ULL ),
   24485                                     mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
   24486                       mkU8( 64 ) ) );
   24487    }
   24488    break;
   24489 
   24490    /* Insert instructions */
   24491    case 0x30D:  // vinsertb  (Vector insert Unsigned Byte)
   24492    {
   24493       UChar uim = IFIELD( theInstr, 16, 4 );
   24494       IRTemp shift = newTemp( Ity_I8 );
   24495       IRTemp vD = newTemp( Ity_V128 );
   24496 
   24497       DIP("vinsertb v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24498 
   24499       assign( vD, getVReg( vD_addr ) );
   24500 
   24501       assign( shift, unop( Iop_32to8,
   24502                            binop( Iop_Mul32,
   24503                                   mkU32( 8 ),
   24504                                   mkU32( 15 - ( uim + 0 ) ) ) ) );
   24505 
   24506       putVReg( vD_addr,
   24507                binop( Iop_OrV128,
   24508                       binop( Iop_ShlV128,
   24509                              binop( Iop_AndV128,
   24510                                     binop( Iop_ShrV128,
   24511                                            mkexpr( vB ),
   24512                                            mkU8( ( 15 - 7 )*8 ) ),
   24513                                     binop( Iop_64HLtoV128,
   24514                                            mkU64( 0x0ULL ),
   24515                                            mkU64( 0xFFULL ) ) ),
   24516                              mkexpr( shift ) ),
   24517                       binop( Iop_AndV128,
   24518                              unop( Iop_NotV128,
   24519                                    binop( Iop_ShlV128,
   24520                                           binop( Iop_64HLtoV128,
   24521                                                  mkU64( 0x0ULL ),
   24522                                                  mkU64( 0xFFULL ) ),
   24523                                           mkexpr( shift ) ) ),
   24524                              mkexpr( vD ) ) ) );
   24525    }
   24526    break;
   24527 
   24528    case 0x34D: // vinserth  (Vector insert Halfword)
   24529    {
   24530       UChar uim = IFIELD( theInstr, 16, 4 );
   24531       IRTemp shift = newTemp( Ity_I8 );
   24532       IRTemp vD = newTemp( Ity_V128 );
   24533 
   24534       DIP("vinserth v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24535 
   24536       assign( vD, getVReg( vD_addr ) );
   24537 
   24538       assign( shift, unop( Iop_32to8,
   24539                            binop( Iop_Mul32,
   24540                                   mkU32( 8 ),
   24541                                   mkU32( 15 - ( uim + 1 ) ) ) ) );
   24542 
   24543       putVReg( vD_addr,
   24544                binop( Iop_OrV128,
   24545                       binop( Iop_ShlV128,
   24546                              binop( Iop_AndV128,
   24547                                     binop( Iop_ShrV128,
   24548                                            mkexpr( vB ),
   24549                                            mkU8( (7 - 3)*16 ) ),
   24550                                     binop( Iop_64HLtoV128,
   24551                                            mkU64( 0x0ULL ),
   24552                                            mkU64( 0xFFFFULL ) ) ),
   24553                              mkexpr( shift ) ),
   24554                       binop( Iop_AndV128,
   24555                              unop( Iop_NotV128,
   24556                                    binop( Iop_ShlV128,
   24557                                           binop( Iop_64HLtoV128,
   24558                                                  mkU64( 0x0ULL ),
   24559                                                  mkU64( 0xFFFFULL ) ),
   24560                                           mkexpr( shift ) ) ),
   24561                              mkexpr( vD ) ) ) );
   24562    }
   24563    break;
   24564 
   24565    case 0x38D: // vinsertw  (Vector insert Word)
   24566    {
   24567       UChar uim = IFIELD( theInstr, 16, 4 );
   24568       IRTemp shift = newTemp( Ity_I8 );
   24569       IRTemp vD = newTemp( Ity_V128 );
   24570 
   24571       DIP("vinsertw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24572 
   24573       assign( vD, getVReg( vD_addr ) );
   24574 
   24575       assign( shift, unop( Iop_32to8,
   24576                            binop( Iop_Mul32,
   24577                                   mkU32( 8 ),
   24578                                   mkU32( 15 - ( uim + 3 ) ) ) ) );
   24579 
   24580       putVReg( vD_addr,
   24581                binop( Iop_OrV128,
   24582                       binop( Iop_ShlV128,
   24583                              binop( Iop_AndV128,
   24584                                     binop( Iop_ShrV128,
   24585                                            mkexpr( vB ),
   24586                                            mkU8( (3 - 1) * 32 ) ),
   24587                                     binop( Iop_64HLtoV128,
   24588                                            mkU64( 0x0ULL ),
   24589                                            mkU64( 0xFFFFFFFFULL ) ) ),
   24590                              mkexpr( shift ) ),
   24591                       binop( Iop_AndV128,
   24592                              unop( Iop_NotV128,
   24593                                    binop( Iop_ShlV128,
   24594                                           binop( Iop_64HLtoV128,
   24595                                                  mkU64( 0x0ULL ),
   24596                                                  mkU64( 0xFFFFFFFFULL ) ),
   24597                                           mkexpr( shift ) ) ),
   24598                              mkexpr( vD ) ) ) );
   24599    }
   24600    break;
   24601 
   24602    case 0x3CD: // vinsertd  (Vector insert Doubleword)
   24603    {
   24604       UChar uim = IFIELD( theInstr, 16, 4 );
   24605       IRTemp shift = newTemp( Ity_I8 );
   24606       IRTemp vD = newTemp( Ity_V128 );
   24607 
   24608       DIP("vinsertd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
   24609 
   24610       assign( vD, getVReg( vD_addr ) );
   24611 
   24612       assign( shift, unop( Iop_32to8,
   24613                            binop( Iop_Mul32,
   24614                                   mkU32( 8 ),
   24615                                   mkU32( 15 - ( uim + 7 ) ) ) ) );
   24616 
   24617       putVReg( vD_addr,
   24618                binop( Iop_OrV128,
   24619                       binop( Iop_ShlV128,
   24620                              binop( Iop_AndV128,
   24621                                     binop( Iop_ShrV128,
   24622                                            mkexpr( vB ),
   24623                                            mkU8( ( 1 - 0 ) * 64 ) ),
   24624                                     binop( Iop_64HLtoV128,
   24625                                            mkU64( 0x0ULL ),
   24626                                            mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
   24627                              mkexpr( shift ) ),
   24628                       binop( Iop_AndV128,
   24629                              unop( Iop_NotV128,
   24630                                    binop( Iop_ShlV128,
   24631                                           binop( Iop_64HLtoV128,
   24632                                                  mkU64( 0x0ULL ),
   24633                                                  mkU64( 0xFFFFFFFFFFFFFFFFULL ) ),
   24634                                           mkexpr( shift ) ) ),
   24635                              mkexpr( vD ) ) ) );
   24636    }
   24637    break;
   24638 
   24639    /* Splat */
   24640    case 0x20C: { // vspltb (Splat Byte, AV p245)
   24641       /* vD = Dup8x16( vB[UIMM_5] ) */
   24642       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   24643       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   24644       putVReg( vD_addr, unop(Iop_Dup8x16,
   24645            unop(Iop_32to8, unop(Iop_V128to32,
   24646                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   24647       break;
   24648    }
   24649    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   24650       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   24651       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   24652       putVReg( vD_addr, unop(Iop_Dup16x8,
   24653            unop(Iop_32to16, unop(Iop_V128to32,
   24654                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   24655       break;
   24656    }
   24657    case 0x28C: { // vspltw (Splat Word, AV p250)
   24658       /* vD = Dup32x4( vB[UIMM_5] ) */
   24659       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   24660       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   24661       putVReg( vD_addr, unop(Iop_Dup32x4,
   24662          unop(Iop_V128to32,
   24663               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   24664       break;
   24665    }
   24666    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   24667       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   24668       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   24669       break;
   24670 
   24671    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   24672       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   24673       putVReg( vD_addr,
   24674                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   24675       break;
   24676 
   24677    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   24678       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   24679       putVReg( vD_addr,
   24680                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   24681       break;
   24682 
   24683    case 0x68C: // vmrgow (Merge Odd Word)
   24684      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24685       /*   VD[0] <- VA[1]
   24686            VD[1] <- VB[1]
   24687            VD[2] <- VA[3]
   24688            VD[3] <- VB[3]
   24689       */
   24690       putVReg( vD_addr,
   24691                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   24692       break;
   24693 
   24694    case 0x78C: // vmrgew (Merge Even Word)
   24695       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24696       /*   VD[0] <- VA[0]
   24697            VD[1] <- VB[0]
   24698            VD[2] <- VA[2]
   24699            VD[3] <- VB[2]
   24700       */
   24701       putVReg( vD_addr,
   24702                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   24703       break;
   24704 
   24705    default:
   24706       vex_printf("dis_av_permute(ppc)(opc2)\n");
   24707       return False;
   24708    }
   24709    return True;
   24710 }
   24711 
   24712 /*
   24713   Vector Integer Absolute Difference
   24714 */
   24715 static Bool dis_abs_diff ( UInt theInstr )
   24716 {
   24717    /* VX-Form */
   24718    UChar opc1     = ifieldOPC( theInstr );
   24719    UChar vT_addr  = ifieldRegDS( theInstr );
   24720    UChar vA_addr  = ifieldRegA( theInstr );
   24721    UChar vB_addr  = ifieldRegB( theInstr );
   24722    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   24723 
   24724    IRTemp vA    = newTemp( Ity_V128 );
   24725    IRTemp vB    = newTemp( Ity_V128 );
   24726    IRTemp vT    = newTemp( Ity_V128 );
   24727 
   24728    IRTemp vAminusB = newTemp( Ity_V128 );
   24729    IRTemp vBminusA = newTemp( Ity_V128 );
   24730    IRTemp vMask    = newTemp( Ity_V128 );
   24731 
   24732    assign( vA, getVReg( vA_addr ) );
   24733    assign( vB, getVReg( vB_addr ) );
   24734 
   24735    if ( opc1 != 0x4 ) {
   24736       vex_printf("dis_abs_diff(ppc)(instr)\n");
   24737       return False;
   24738    }
   24739 
   24740    switch ( opc2 ) {
   24741    case 0x403: // vabsdub  Vector absolute difference Unsigned Byte
   24742    {
   24743       DIP("vabsdub v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
   24744 
   24745       /* Determine which of the corresponding bytes is larger,
   24746        * create mask with 1's in byte positions where vA[i] > vB[i]
   24747        */
   24748       assign( vMask, binop( Iop_CmpGT8Ux16, mkexpr( vA ), mkexpr( vB ) ) );
   24749 
   24750       assign( vAminusB,
   24751               binop( Iop_AndV128,
   24752                      binop( Iop_Sub8x16, mkexpr( vA ), mkexpr( vB ) ),
   24753                      mkexpr( vMask ) ) );
   24754 
   24755       assign( vBminusA,
   24756               binop( Iop_AndV128,
   24757                      binop( Iop_Sub8x16, mkexpr( vB ), mkexpr( vA ) ),
   24758                      unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
   24759 
   24760       assign( vT, binop( Iop_OrV128,
   24761                          mkexpr( vAminusB ),
   24762                          mkexpr( vBminusA ) ) );
   24763    }
   24764    break;
   24765 
   24766    case 0x443: // vabsduh  Vector absolute difference Unsigned Halfword
   24767    {
   24768       DIP("vabsduh v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
   24769 
   24770       /* Determine which of the corresponding halfwords is larger,
   24771        * create mask with 1's in halfword positions where vA[i] > vB[i]
   24772        */
   24773       assign( vMask, binop( Iop_CmpGT16Ux8, mkexpr( vA ), mkexpr( vB ) ) );
   24774 
   24775       assign( vAminusB,
   24776               binop( Iop_AndV128,
   24777                      binop( Iop_Sub16x8, mkexpr( vA ), mkexpr( vB ) ),
   24778                      mkexpr( vMask ) ) );
   24779 
   24780       assign( vBminusA,
   24781               binop( Iop_AndV128,
   24782                      binop( Iop_Sub16x8, mkexpr( vB ), mkexpr( vA ) ),
   24783                      unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
   24784 
   24785       assign( vT, binop( Iop_OrV128,
   24786                          mkexpr( vAminusB ),
   24787                          mkexpr( vBminusA ) ) );
   24788    }
   24789    break;
   24790 
   24791    case 0x483: // vabsduw  Vector absolute difference Unsigned Word
   24792    {
   24793          DIP("vabsduw v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
   24794 
   24795          /* Determine which of the corresponding words is larger,
   24796           * create mask with 1's in word positions where vA[i] > vB[i]
   24797           */
   24798          assign( vMask, binop( Iop_CmpGT32Ux4, mkexpr( vA ), mkexpr( vB ) ) );
   24799 
   24800          assign( vAminusB,
   24801                  binop( Iop_AndV128,
   24802                         binop( Iop_Sub32x4, mkexpr( vA ), mkexpr( vB ) ),
   24803                         mkexpr( vMask ) ) );
   24804 
   24805          assign( vBminusA,
   24806                  binop( Iop_AndV128,
   24807                         binop( Iop_Sub32x4, mkexpr( vB ), mkexpr( vA ) ),
   24808                         unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
   24809 
   24810          assign( vT, binop( Iop_OrV128,
   24811                             mkexpr( vAminusB ),
   24812                             mkexpr( vBminusA ) ) );
   24813    }
   24814    break;
   24815 
   24816    default:
   24817       return False;
   24818    }
   24819 
   24820    putVReg( vT_addr, mkexpr( vT ) );
   24821 
   24822   return True;
   24823 }
   24824 
   24825 /*
   24826   AltiVec 128 bit integer multiply by 10 Instructions
   24827 */
   24828 static Bool dis_av_mult10 ( UInt theInstr )
   24829 {
   24830    /* VX-Form */
   24831    UChar opc1     = ifieldOPC(theInstr);
   24832    UChar vT_addr  = ifieldRegDS(theInstr);
   24833    UChar vA_addr  = ifieldRegA(theInstr);
   24834    UChar vB_addr  = ifieldRegB(theInstr);
   24835    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   24836 
   24837    IRTemp vA    = newTemp(Ity_V128);
   24838    assign( vA, getVReg(vA_addr));
   24839 
   24840    if (opc1 != 0x4) {
   24841       vex_printf("dis_av_mult10(ppc)(instr)\n");
   24842       return False;
   24843    }
   24844    switch (opc2) {
   24845    case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
   24846       DIP("vmul10cuq v%d,v%d\n", vT_addr, vA_addr);
   24847       putVReg( vT_addr,
   24848                unop( Iop_MulI128by10Carry, mkexpr( vA ) ) );
   24849       break;
   24850   }
   24851    case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry
   24852                  //           Unsigned Quadword VX form)
   24853       IRTemp vB    = newTemp(Ity_V128);
   24854       assign( vB, getVReg(vB_addr));
   24855       DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
   24856       putVReg( vT_addr,
   24857                binop( Iop_MulI128by10ECarry, mkexpr( vA ), mkexpr( vB ) ) );
   24858       break;
   24859    }
   24860    case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
   24861       DIP("vmul10uq v%d,v%d\n", vT_addr, vA_addr);
   24862       putVReg( vT_addr,
   24863                unop( Iop_MulI128by10, mkexpr( vA ) ) );
   24864       break;
   24865    }
   24866   case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended
   24867                 //           Unsigned Quadword VX form)
   24868       IRTemp vB    = newTemp(Ity_V128);
   24869       assign( vB, getVReg(vB_addr));
   24870       DIP("vmul10euq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
   24871       putVReg( vT_addr,
   24872                binop( Iop_MulI128by10E, mkexpr( vA ), mkexpr( vB ) ) );
   24873       break;
   24874    }
   24875    default:
   24876       vex_printf("dis_av_mult10(ppc)(opc2)\n");
   24877       return False;
   24878    }
   24879    return True;
   24880 }
   24881 
   24882 /*
   24883   AltiVec Pack/Unpack Instructions
   24884 */
   24885 static Bool dis_av_pack ( UInt theInstr )
   24886 {
   24887    /* VX-Form */
   24888    UChar opc1     = ifieldOPC(theInstr);
   24889    UChar vD_addr  = ifieldRegDS(theInstr);
   24890    UChar vA_addr  = ifieldRegA(theInstr);
   24891    UChar vB_addr  = ifieldRegB(theInstr);
   24892    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   24893 
   24894    IRTemp signs = IRTemp_INVALID;
   24895    IRTemp zeros = IRTemp_INVALID;
   24896    IRTemp vA    = newTemp(Ity_V128);
   24897    IRTemp vB    = newTemp(Ity_V128);
   24898    assign( vA, getVReg(vA_addr));
   24899    assign( vB, getVReg(vB_addr));
   24900 
   24901    if (opc1 != 0x4) {
   24902       vex_printf("dis_av_pack(ppc)(instr)\n");
   24903       return False;
   24904    }
   24905    switch (opc2) {
   24906    /* Packing */
   24907    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   24908       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24909       putVReg( vD_addr,
   24910                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   24911       return True;
   24912 
   24913    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   24914       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24915       putVReg( vD_addr,
   24916                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   24917       return True;
   24918 
   24919    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   24920       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24921       putVReg( vD_addr,
   24922                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   24923       // TODO: set VSCR[SAT]
   24924       return True;
   24925 
   24926    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   24927       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24928       putVReg( vD_addr,
   24929                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   24930       // TODO: set VSCR[SAT]
   24931       return True;
   24932 
   24933    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   24934       // This insn does a signed->unsigned saturating conversion.
   24935       // Conversion done here, then uses unsigned->unsigned vpk insn:
   24936       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   24937       IRTemp vA_tmp = newTemp(Ity_V128);
   24938       IRTemp vB_tmp = newTemp(Ity_V128);
   24939       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24940       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   24941                             unop(Iop_NotV128,
   24942                                  binop(Iop_SarN16x8,
   24943                                        mkexpr(vA), mkU8(15)))) );
   24944       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   24945                             unop(Iop_NotV128,
   24946                                  binop(Iop_SarN16x8,
   24947                                        mkexpr(vB), mkU8(15)))) );
   24948       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   24949                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   24950       // TODO: set VSCR[SAT]
   24951       return True;
   24952    }
   24953    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   24954       // This insn does a signed->unsigned saturating conversion.
   24955       // Conversion done here, then uses unsigned->unsigned vpk insn:
   24956       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   24957       IRTemp vA_tmp = newTemp(Ity_V128);
   24958       IRTemp vB_tmp = newTemp(Ity_V128);
   24959       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24960       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   24961                             unop(Iop_NotV128,
   24962                                  binop(Iop_SarN32x4,
   24963                                        mkexpr(vA), mkU8(31)))) );
   24964       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   24965                             unop(Iop_NotV128,
   24966                                  binop(Iop_SarN32x4,
   24967                                        mkexpr(vB), mkU8(31)))) );
   24968       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   24969                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   24970       // TODO: set VSCR[SAT]
   24971       return True;
   24972    }
   24973    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   24974       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24975       putVReg( vD_addr,
   24976                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   24977       // TODO: set VSCR[SAT]
   24978       return True;
   24979 
   24980    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   24981       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24982       putVReg( vD_addr,
   24983                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   24984       // TODO: set VSCR[SAT]
   24985       return True;
   24986 
   24987    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   24988       /* CAB: Worth a new primop? */
   24989       /* Using shifts to compact pixel elements, then packing them */
   24990       IRTemp a1 = newTemp(Ity_V128);
   24991       IRTemp a2 = newTemp(Ity_V128);
   24992       IRTemp a3 = newTemp(Ity_V128);
   24993       IRTemp a_tmp = newTemp(Ity_V128);
   24994       IRTemp b1 = newTemp(Ity_V128);
   24995       IRTemp b2 = newTemp(Ity_V128);
   24996       IRTemp b3 = newTemp(Ity_V128);
   24997       IRTemp b_tmp = newTemp(Ity_V128);
   24998       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   24999       assign( a1, binop(Iop_ShlN16x8,
   25000                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   25001                         mkU8(10)) );
   25002       assign( a2, binop(Iop_ShlN16x8,
   25003                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   25004                         mkU8(5)) );
   25005       assign( a3,  binop(Iop_ShrN16x8,
   25006                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   25007                          mkU8(11)) );
   25008       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   25009                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   25010 
   25011       assign( b1, binop(Iop_ShlN16x8,
   25012                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   25013                         mkU8(10)) );
   25014       assign( b2, binop(Iop_ShlN16x8,
   25015                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   25016                         mkU8(5)) );
   25017       assign( b3,  binop(Iop_ShrN16x8,
   25018                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   25019                          mkU8(11)) );
   25020       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   25021                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   25022 
   25023       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   25024                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   25025       return True;
   25026    }
   25027 
   25028    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
   25029       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25030       putVReg( vD_addr,
   25031                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
   25032       return True;
   25033 
   25034    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
   25035       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25036       putVReg( vD_addr,
   25037                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
   25038       // TODO: set VSCR[SAT]
   25039       return True;
   25040 
   25041    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
   25042       // This insn does a doubled signed->double unsigned saturating conversion
   25043       // Conversion done here, then uses unsigned->unsigned vpk insn:
   25044       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   25045       // This is similar to the technique used for vpkswus, except done
   25046       // with double word integers versus word integers.
   25047       IRTemp vA_tmp = newTemp(Ity_V128);
   25048       IRTemp vB_tmp = newTemp(Ity_V128);
   25049       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25050       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   25051                             unop(Iop_NotV128,
   25052                                  binop(Iop_SarN64x2,
   25053                                        mkexpr(vA), mkU8(63)))) );
   25054       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   25055                             unop(Iop_NotV128,
   25056                                  binop(Iop_SarN64x2,
   25057                                        mkexpr(vB), mkU8(63)))) );
   25058       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
   25059                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   25060       // TODO: set VSCR[SAT]
   25061       return True;
   25062    }
   25063 
   25064    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
   25065       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25066       putVReg( vD_addr,
   25067                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
   25068       // TODO: set VSCR[SAT]
   25069       return True;
   25070    default:
   25071       break; // Fall through...
   25072    }
   25073 
   25074 
   25075    if (vA_addr != 0) {
   25076       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   25077       return False;
   25078    }
   25079 
   25080    signs = newTemp(Ity_V128);
   25081    zeros = newTemp(Ity_V128);
   25082    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   25083 
   25084    switch (opc2) {
   25085    /* Unpacking */
   25086    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   25087       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   25088       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   25089       putVReg( vD_addr,
   25090                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   25091       break;
   25092    }
   25093    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   25094       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   25095       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   25096       putVReg( vD_addr,
   25097                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   25098       break;
   25099    }
   25100    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   25101       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   25102       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   25103       putVReg( vD_addr,
   25104                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   25105       break;
   25106    }
   25107    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   25108       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   25109       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   25110       putVReg( vD_addr,
   25111                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   25112       break;
   25113    }
   25114    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   25115       /* CAB: Worth a new primop? */
   25116       /* Using shifts to isolate pixel elements, then expanding them */
   25117       IRTemp z0  = newTemp(Ity_V128);
   25118       IRTemp z1  = newTemp(Ity_V128);
   25119       IRTemp z01 = newTemp(Ity_V128);
   25120       IRTemp z2  = newTemp(Ity_V128);
   25121       IRTemp z3  = newTemp(Ity_V128);
   25122       IRTemp z23 = newTemp(Ity_V128);
   25123       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   25124       assign( z0,  binop(Iop_ShlN16x8,
   25125                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   25126                          mkU8(8)) );
   25127       assign( z1,  binop(Iop_ShrN16x8,
   25128                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   25129                          mkU8(11)) );
   25130       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   25131                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   25132       assign( z2,  binop(Iop_ShrN16x8,
   25133                          binop(Iop_ShlN16x8,
   25134                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   25135                                mkU8(11)),
   25136                          mkU8(3)) );
   25137       assign( z3,  binop(Iop_ShrN16x8,
   25138                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   25139                          mkU8(11)) );
   25140       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   25141                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   25142       putVReg( vD_addr,
   25143                binop(Iop_OrV128,
   25144                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   25145                      mkexpr(z23)) );
   25146       break;
   25147    }
   25148    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   25149       /* identical to vupkhpx, except interleaving LO */
   25150       IRTemp z0  = newTemp(Ity_V128);
   25151       IRTemp z1  = newTemp(Ity_V128);
   25152       IRTemp z01 = newTemp(Ity_V128);
   25153       IRTemp z2  = newTemp(Ity_V128);
   25154       IRTemp z3  = newTemp(Ity_V128);
   25155       IRTemp z23 = newTemp(Ity_V128);
   25156       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   25157       assign( z0,  binop(Iop_ShlN16x8,
   25158                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   25159                          mkU8(8)) );
   25160       assign( z1,  binop(Iop_ShrN16x8,
   25161                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   25162                          mkU8(11)) );
   25163       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   25164                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   25165       assign( z2,  binop(Iop_ShrN16x8,
   25166                          binop(Iop_ShlN16x8,
   25167                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   25168                                mkU8(11)),
   25169                          mkU8(3)) );
   25170       assign( z3,  binop(Iop_ShrN16x8,
   25171                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   25172                          mkU8(11)) );
   25173       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   25174                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   25175       putVReg( vD_addr,
   25176                binop(Iop_OrV128,
   25177                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   25178                      mkexpr(z23)) );
   25179       break;
   25180    }
   25181    case 0x64E: { // vupkhsw (Unpack High Signed Word)
   25182       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
   25183       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   25184       putVReg( vD_addr,
   25185                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
   25186       break;
   25187    }
   25188    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
   25189       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
   25190       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   25191       putVReg( vD_addr,
   25192                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
   25193       break;
   25194    }
   25195    default:
   25196       vex_printf("dis_av_pack(ppc)(opc2)\n");
   25197       return False;
   25198    }
   25199    return True;
   25200 }
   25201 
   25202 /*
   25203   AltiVec Cipher Instructions
   25204 */
   25205 static Bool dis_av_cipher ( UInt theInstr )
   25206 {
   25207    /* VX-Form */
   25208    UChar opc1     = ifieldOPC(theInstr);
   25209    UChar vD_addr  = ifieldRegDS(theInstr);
   25210    UChar vA_addr  = ifieldRegA(theInstr);
   25211    UChar vB_addr  = ifieldRegB(theInstr);
   25212    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   25213 
   25214    IRTemp vA    = newTemp(Ity_V128);
   25215    IRTemp vB    = newTemp(Ity_V128);
   25216    assign( vA, getVReg(vA_addr));
   25217    assign( vB, getVReg(vB_addr));
   25218 
   25219    if (opc1 != 0x4) {
   25220       vex_printf("dis_av_cipher(ppc)(instr)\n");
   25221       return False;
   25222    }
   25223    switch (opc2) {
   25224       case 0x508: // vcipher (Vector Inverser Cipher)
   25225          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25226          putVReg( vD_addr,
   25227                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
   25228          return True;
   25229 
   25230       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
   25231          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25232          putVReg( vD_addr,
   25233                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
   25234          return True;
   25235 
   25236       case 0x548: // vncipher (Vector Inverser Cipher)
   25237          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25238          putVReg( vD_addr,
   25239                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
   25240          return True;
   25241 
   25242       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
   25243          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   25244          putVReg( vD_addr,
   25245                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
   25246          return True;
   25247 
   25248       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
   25249        * subBytes transform)
   25250        */
   25251          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
   25252          putVReg( vD_addr,
   25253                   unop(Iop_CipherSV128, mkexpr(vA) ) );
   25254          return True;
   25255 
   25256       default:
   25257          vex_printf("dis_av_cipher(ppc)(opc2)\n");
   25258          return False;
   25259    }
   25260    return True;
   25261 }
   25262 
   25263 /*
   25264   AltiVec Secure Hash Instructions
   25265 */
   25266 static Bool dis_av_hash ( UInt theInstr )
   25267 {
   25268    /* VX-Form */
   25269    UChar opc1     = ifieldOPC(theInstr);
   25270    UChar vRT_addr = ifieldRegDS(theInstr);
   25271    UChar vRA_addr  = ifieldRegA(theInstr);
   25272    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
   25273    UChar st       = IFIELD( theInstr, 15, 1 );  // st
   25274    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
   25275    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   25276 
   25277    IRTemp vA    = newTemp(Ity_V128);
   25278    IRTemp dst    = newTemp(Ity_V128);
   25279    assign( vA, getVReg(vRA_addr));
   25280 
   25281    if (opc1 != 0x4) {
   25282       vex_printf("dis_av_hash(ppc)(instr)\n");
   25283       return False;
   25284    }
   25285 
   25286    switch (opc2) {
   25287       case 0x682:  // vshasigmaw
   25288          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   25289          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
   25290          putVReg( vRT_addr, mkexpr(dst));
   25291          return True;
   25292 
   25293       case 0x6C2:  // vshasigmad,
   25294          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   25295          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
   25296          return True;
   25297 
   25298       default:
   25299          vex_printf("dis_av_hash(ppc)(opc2)\n");
   25300          return False;
   25301    }
   25302    return True;
   25303 }
   25304 
   25305 /*
   25306  * This function is used by the Vector add/subtract [extended] modulo/carry
   25307  * instructions.
   25308  *   - For the non-extended add instructions, the cin arg is set to zero.
   25309  *   - For the extended add instructions, cin is the integer value of
   25310  *     src3.bit[127].
   25311  *   - For the non-extended subtract instructions, src1 is added to the one's
   25312  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
   25313  *     value for this operation.
   25314  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
   25315  */
   25316 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
   25317                                         IRExpr * cin, Bool modulo)
   25318 {
   25319    IRTemp _vecA_32   = IRTemp_INVALID;
   25320    IRTemp _vecB_32   = IRTemp_INVALID;
   25321    IRTemp res_32     = IRTemp_INVALID;
   25322    IRTemp res_64     = IRTemp_INVALID;
   25323    IRTemp result     = IRTemp_INVALID;
   25324    IRTemp tmp_result = IRTemp_INVALID;
   25325    IRTemp carry      = IRTemp_INVALID;
   25326    Int i;
   25327    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
   25328    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
   25329    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
   25330    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
   25331 
   25332    carry = newTemp(Ity_I32);
   25333    assign( carry, cin );
   25334 
   25335    for (i = 0; i < 4; i++) {
   25336       _vecA_32 = newTemp(Ity_I32);
   25337       _vecB_32 = newTemp(Ity_I32);
   25338       res_32   = newTemp(Ity_I32);
   25339       res_64   = newTemp(Ity_I64);
   25340 
   25341       switch (i) {
   25342       case 0:
   25343          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
   25344          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
   25345          break;
   25346       case 1:
   25347          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
   25348          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
   25349          break;
   25350       case 2:
   25351          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
   25352          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
   25353          break;
   25354       case 3:
   25355          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
   25356          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
   25357          break;
   25358       }
   25359 
   25360       assign( res_64, binop( Iop_Add64,
   25361                              binop ( Iop_Add64,
   25362                                      binop( Iop_32HLto64,
   25363                                             mkU32( 0 ),
   25364                                             mkexpr(_vecA_32) ),
   25365                                      binop( Iop_32HLto64,
   25366                                             mkU32( 0 ),
   25367                                             mkexpr(_vecB_32) ) ),
   25368                              binop( Iop_32HLto64,
   25369                                     mkU32( 0 ),
   25370                                     mkexpr( carry ) ) ) );
   25371 
   25372       /* Calculate the carry to the next higher 32 bits. */
   25373       carry = newTemp(Ity_I32);
   25374       assign(carry, unop( Iop_64HIto32, mkexpr( res_64 ) ) );
   25375 
   25376       /* result is the lower 32-bits */
   25377       assign(res_32, unop( Iop_64to32, mkexpr( res_64 ) ) );
   25378 
   25379       if (modulo) {
   25380          result = newTemp(Ity_V128);
   25381          assign(result, binop( Iop_OrV128,
   25382                               (i == 0) ? binop( Iop_64HLtoV128,
   25383                                                 mkU64(0),
   25384                                                 mkU64(0) ) : mkexpr(tmp_result),
   25385                               binop( Iop_ShlV128,
   25386                                      binop( Iop_64HLtoV128,
   25387                                             mkU64(0),
   25388                                             binop( Iop_32HLto64,
   25389                                                    mkU32(0),
   25390                                                    mkexpr(res_32) ) ),
   25391                                      mkU8(i * 32) ) ) );
   25392          tmp_result = newTemp(Ity_V128);
   25393          assign(tmp_result, mkexpr(result));
   25394       }
   25395    }
   25396    if (modulo)
   25397       return result;
   25398    else
   25399       return carry;
   25400 }
   25401 
   25402 
   25403 static Bool dis_av_quad ( UInt theInstr )
   25404 {
   25405    /* VX-Form */
   25406    UChar opc1     = ifieldOPC(theInstr);
   25407    UChar vRT_addr = ifieldRegDS(theInstr);
   25408    UChar vRA_addr = ifieldRegA(theInstr);
   25409    UChar vRB_addr = ifieldRegB(theInstr);
   25410    UChar vRC_addr;
   25411    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   25412 
   25413    IRTemp vA    = newTemp(Ity_V128);
   25414    IRTemp vB    = newTemp(Ity_V128);
   25415    IRTemp vC    = IRTemp_INVALID;
   25416    IRTemp cin    = IRTemp_INVALID;
   25417    assign( vA, getVReg(vRA_addr));
   25418    assign( vB, getVReg(vRB_addr));
   25419 
   25420    if (opc1 != 0x4) {
   25421       vex_printf("dis_av_quad(ppc)(instr)\n");
   25422       return False;
   25423    }
   25424 
   25425    switch (opc2) {
   25426    case 0x140:  // vaddcuq
   25427      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25428      putVReg( vRT_addr, unop( Iop_32UtoV128,
   25429                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25430                                                                mkexpr(vB),
   25431                                                                mkU32(0), False) ) ) );
   25432      return True;
   25433    case 0x100: // vadduqm
   25434       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25435       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25436                                                           mkexpr(vB), mkU32(0), True) ) );
   25437       return True;
   25438    case 0x540: // vsubcuq
   25439       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25440       putVReg( vRT_addr,
   25441                unop( Iop_32UtoV128,
   25442                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25443                                                       unop( Iop_NotV128,
   25444                                                             mkexpr(vB) ),
   25445                                                       mkU32(1), False) ) ) );
   25446       return True;
   25447    case 0x500: // vsubuqm
   25448       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25449       putVReg( vRT_addr,
   25450                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25451                                                 unop( Iop_NotV128, mkexpr(vB) ),
   25452                                                 mkU32(1), True) ) );
   25453       return True;
   25454    case 0x054C: // vbpermq
   25455    {
   25456 #define BPERMD_IDX_MASK 0x00000000000000FFULL
   25457 #define BPERMD_BIT_MASK 0x8000000000000000ULL
   25458       int i;
   25459       IRExpr * vB_expr = mkexpr(vB);
   25460       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
   25461       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25462       for (i = 0; i < 16; i++) {
   25463          IRTemp idx_tmp = newTemp( Ity_V128 );
   25464          IRTemp perm_bit = newTemp( Ity_V128 );
   25465          IRTemp idx = newTemp( Ity_I8 );
   25466          IRTemp idx_LT127 = newTemp( Ity_I1 );
   25467          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
   25468 
   25469          assign( idx_tmp,
   25470                  binop( Iop_AndV128,
   25471                         binop( Iop_64HLtoV128,
   25472                                mkU64(0),
   25473                                mkU64(BPERMD_IDX_MASK) ),
   25474                         vB_expr ) );
   25475          assign( idx_LT127,
   25476                  binop( Iop_CmpEQ32,
   25477                         unop ( Iop_64to32,
   25478                                unop( Iop_V128to64, binop( Iop_ShrV128,
   25479                                                           mkexpr(idx_tmp),
   25480                                                           mkU8(7) ) ) ),
   25481                         mkU32(0) ) );
   25482 
   25483          /* Below, we set idx to determine which bit of vA to use for the
   25484           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
   25485           */
   25486          assign( idx,
   25487                  binop( Iop_And8,
   25488                         unop( Iop_1Sto8,
   25489                               mkexpr(idx_LT127) ),
   25490                         unop( Iop_32to8,
   25491                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
   25492 
   25493          assign( idx_LT127_ity128,
   25494                  binop( Iop_64HLtoV128,
   25495                         mkU64(0),
   25496                         unop( Iop_32Uto64,
   25497                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
   25498          assign( perm_bit,
   25499                  binop( Iop_AndV128,
   25500                         mkexpr( idx_LT127_ity128 ),
   25501                         binop( Iop_ShrV128,
   25502                                binop( Iop_AndV128,
   25503                                       binop (Iop_64HLtoV128,
   25504                                              mkU64( BPERMD_BIT_MASK ),
   25505                                              mkU64(0)),
   25506                                       binop( Iop_ShlV128,
   25507                                              mkexpr( vA ),
   25508                                              mkexpr( idx ) ) ),
   25509                                mkU8( 127 ) ) ) );
   25510          res = binop( Iop_OrV128,
   25511                       res,
   25512                       binop( Iop_ShlV128,
   25513                              mkexpr( perm_bit ),
   25514                              mkU8( i + 64 ) ) );
   25515          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
   25516       }
   25517       putVReg( vRT_addr, res);
   25518       return True;
   25519 #undef BPERMD_IDX_MASK
   25520 #undef BPERMD_BIT_MASK
   25521    }
   25522 
   25523    default:
   25524       break;  // fall through
   25525    }
   25526 
   25527    opc2     = IFIELD( theInstr, 0, 6 );
   25528    vRC_addr = ifieldRegC(theInstr);
   25529    vC = newTemp(Ity_V128);
   25530    cin = newTemp(Ity_I32);
   25531    switch (opc2) {
   25532       case 0x3D: // vaddecuq
   25533          assign( vC, getVReg(vRC_addr));
   25534          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   25535              vRC_addr);
   25536          assign(cin, binop( Iop_And32,
   25537                             unop( Iop_64to32,
   25538                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   25539                             mkU32(1) ) );
   25540          putVReg( vRT_addr,
   25541                   unop( Iop_32UtoV128,
   25542                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   25543                                                          mkexpr(cin),
   25544                                                          False) ) ) );
   25545          return True;
   25546       case 0x3C: // vaddeuqm
   25547          assign( vC, getVReg(vRC_addr));
   25548          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   25549              vRC_addr);
   25550          assign(cin, binop( Iop_And32,
   25551                             unop( Iop_64to32,
   25552                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   25553                             mkU32(1) ) );
   25554          putVReg( vRT_addr,
   25555                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   25556                                                    mkexpr(cin),
   25557                                                    True) ) );
   25558          return True;
   25559       case 0x3F: // vsubecuq
   25560          assign( vC, getVReg(vRC_addr));
   25561          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   25562              vRC_addr);
   25563          assign(cin, binop( Iop_And32,
   25564                             unop( Iop_64to32,
   25565                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   25566                             mkU32(1) ) );
   25567          putVReg( vRT_addr,
   25568                   unop( Iop_32UtoV128,
   25569                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25570                                                          unop( Iop_NotV128,
   25571                                                                mkexpr(vB) ),
   25572                                                          mkexpr(cin),
   25573                                                          False) ) ) );
   25574          return True;
   25575       case 0x3E: // vsubeuqm
   25576          assign( vC, getVReg(vRC_addr));
   25577          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   25578              vRC_addr);
   25579          assign(cin, binop( Iop_And32,
   25580                             unop( Iop_64to32,
   25581                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   25582                             mkU32(1) ) );
   25583          putVReg( vRT_addr,
   25584                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   25585                                                    unop( Iop_NotV128, mkexpr(vB) ),
   25586                                                    mkexpr(cin),
   25587                                                    True) ) );
   25588          return True;
   25589       default:
   25590          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
   25591          return False;
   25592    }
   25593 
   25594    return True;
   25595 }
   25596 
   25597 static IRExpr * bcd_sign_code_adjust( UInt ps, IRExpr * tmp)
   25598 {
   25599    /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
   25600     * instruction being issued with ps = 0.  If ps = 1, the sign code, which
   25601     * is in the least significant four bits of the result, needs to be updated
   25602     * per the ISA:
   25603     *
   25604     *    If PS=0, the sign code of the result is set to 0b1100.
   25605     *    If PS=1, the sign code of the result is set to 0b1111.
   25606     *
   25607     * Note, the ps value is NOT being passed down to the instruction issue
   25608     * because passing a constant via triop() breaks the vbit-test test.  The
   25609     * vbit-tester assumes it can set non-zero shadow bits for the triop()
   25610     * arguments.  Thus they have to be expressions not a constant.
   25611     * Use 32-bit compare instructiions as 64-bit compares are not supported
   25612     * in 32-bit mode.
   25613     */
   25614    IRTemp mask  = newTemp(Ity_I64);
   25615    IRExpr *rtn;
   25616 
   25617    if ( ps == 0 ) {
   25618       /* sign code is correct, just return it.  */
   25619       rtn = tmp;
   25620 
   25621    } else {
   25622       /* Check if lower four bits are 0b1100, if so, change to 0b1111 */
   25623       /* Make this work in 32-bit mode using only 32-bit compares */
   25624       assign( mask, unop( Iop_1Sto64,
   25625                           binop( Iop_CmpEQ32, mkU32( 0xC ),
   25626                                  binop( Iop_And32, mkU32( 0xF ),
   25627                                         unop( Iop_64to32,
   25628                                               unop( Iop_V128to64, tmp )
   25629                                               ) ) ) ) );
   25630       rtn = binop( Iop_64HLtoV128,
   25631                    unop( Iop_V128HIto64, tmp ),
   25632                    binop( Iop_Or64,
   25633                           binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ),
   25634                           unop( Iop_V128to64, tmp ) ) );
   25635    }
   25636 
   25637    return rtn;
   25638 }
   25639 
   25640 /*
   25641   AltiVec BCD Arithmetic instructions.
   25642   These instructions modify CR6 for various conditions in the result,
   25643   including when an overflow occurs.  We could easily detect all conditions
   25644   except when an overflow occurs.  But since we can't be 100% accurate
   25645   in our emulation of CR6, it seems best to just not support it all.
   25646 */
   25647 static Bool dis_av_bcd_misc ( UInt theInstr, const VexAbiInfo* vbi )
   25648 {
   25649    UChar opc1     = ifieldOPC(theInstr);
   25650    UChar vRT_addr = ifieldRegDS(theInstr);
   25651    UChar vRA_addr = ifieldRegA(theInstr);
   25652    UChar vRB_addr = ifieldRegB(theInstr);
   25653    IRTemp vA      = newTemp(Ity_V128);
   25654    IRTemp vB      = newTemp(Ity_V128);
   25655    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   25656    IRExpr *pos, *neg, *valid, *zero, *sign;
   25657    IRTemp eq_lt_gt = newTemp( Ity_I32 );
   25658 
   25659    assign( vA, getVReg(vRA_addr));
   25660    assign( vB, getVReg(vRB_addr));
   25661 
   25662    if (opc1 != 0x4) {
   25663       vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
   25664       return False;
   25665    }
   25666 
   25667    switch (opc2) {
   25668    case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form
   25669       {
   25670          IRExpr *sign_vb, *value_va;
   25671          DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   25672 
   25673          zero =
   25674             BCDstring_zero( binop( Iop_AndV128,
   25675                                    binop( Iop_64HLtoV128,
   25676                                           mkU64( 0xFFFFFFFFFFFFFFFF ),
   25677                                           mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   25678                                    mkexpr( vA ) ) );
   25679 
   25680          /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   25681           * codes 0xB and 0xD are negative.
   25682           */
   25683          sign = binop( Iop_And64, mkU64( 0xF ),
   25684                        unop( Iop_V128to64, mkexpr( vB ) ) );
   25685 
   25686          neg = mkOR1( binop( Iop_CmpEQ64,
   25687                              sign,
   25688                              mkU64 ( 0xB ) ),
   25689                       binop( Iop_CmpEQ64,
   25690                              sign,
   25691                              mkU64 ( 0xD ) ) );
   25692 
   25693          pos = mkNOT1( neg );
   25694 
   25695          /* invalid if vA or vB is not valid */
   25696          valid =
   25697             unop( Iop_64to32,
   25698                   binop( Iop_And64,
   25699                          is_BCDstring128( vbi,
   25700                                           /*Signed*/True, mkexpr( vA ) ),
   25701                          is_BCDstring128( vbi,
   25702                                           /*Signed*/True, mkexpr( vB ) ) ) );
   25703 
   25704          sign_vb = binop( Iop_AndV128,
   25705                           binop( Iop_64HLtoV128,
   25706                                  mkU64( 0 ),
   25707                                  mkU64( 0xF ) ),
   25708                           mkexpr( vB ) );
   25709 
   25710          value_va = binop( Iop_AndV128,
   25711                            binop( Iop_64HLtoV128,
   25712                                   mkU64( 0xFFFFFFFFFFFFFFFF ),
   25713                                   mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   25714                            mkexpr( vA ) );
   25715          putVReg( vRT_addr, binop( Iop_OrV128, sign_vb, value_va ) );
   25716       }
   25717       break;
   25718 
   25719    default:
   25720       vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
   25721       return False;
   25722    }
   25723 
   25724    /* set CR field 6 to:
   25725     *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
   25726     *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
   25727     *    0b1000  if vB equals 0,
   25728     *    0b0001  if vB is invalid  over rules lt, gt, eq
   25729     */
   25730    assign( eq_lt_gt,
   25731            binop( Iop_Or32,
   25732                   binop( Iop_Shl32,
   25733                          unop( Iop_1Uto32,
   25734                                mkAND1( neg,
   25735                                        mkNOT1( zero ) ) ),
   25736                          mkU8( 3 ) ),
   25737                   binop( Iop_Or32,
   25738                          binop( Iop_Shl32,
   25739                                 unop( Iop_1Uto32,
   25740                                       mkAND1( pos,
   25741                                               mkNOT1( zero ) ) ),
   25742                                 mkU8( 2 ) ),
   25743                          binop( Iop_Shl32,
   25744                                 unop( Iop_1Uto32, zero ),
   25745                                 mkU8( 1 ) ) ) ) );
   25746 
   25747    IRTemp valid_mask = newTemp( Ity_I32 );
   25748 
   25749    assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
   25750 
   25751    putGST_field( PPC_GST_CR,
   25752                  binop( Iop_Or32,
   25753                         binop( Iop_And32,
   25754                                mkexpr( valid_mask ),
   25755                                mkexpr( eq_lt_gt ) ),
   25756                         binop( Iop_And32,
   25757                                unop( Iop_Not32, mkexpr( valid_mask ) ),
   25758                                mkU32( 1 ) ) ),
   25759                  6 );
   25760    return True;
   25761 }
   25762 
   25763 static Bool dis_av_bcd ( UInt theInstr, const VexAbiInfo* vbi )
   25764 {
   25765    /* VX-Form */
   25766    UChar opc1     = ifieldOPC(theInstr);
   25767    UChar vRT_addr = ifieldRegDS(theInstr);
   25768    UChar vRA_addr = ifieldRegA(theInstr);
   25769    UChar vRB_addr = ifieldRegB(theInstr);
   25770    UChar ps       = IFIELD( theInstr, 9, 1 );
   25771    UInt  opc2     = IFIELD( theInstr, 0, 9 );
   25772    IRTemp vA    = newTemp(Ity_V128);
   25773    IRTemp vB    = newTemp(Ity_V128);
   25774    IRTemp dst    = newTemp(Ity_V128);
   25775    IRExpr *pos, *neg, *valid, *zero, *sign_digit, *in_range;
   25776    IRTemp eq_lt_gt = newTemp( Ity_I32 );
   25777    IRExpr *overflow, *value;
   25778 
   25779    assign( vA, getVReg(vRA_addr));
   25780    assign( vB, getVReg(vRB_addr));
   25781 
   25782    if (opc1 != 0x4) {
   25783       vex_printf("dis_av_bcd(ppc)(instr)\n");
   25784       return False;
   25785    }
   25786 
   25787    switch (opc2) {
   25788    case 0x1:   // bcdadd.
   25789    case 0x41:  // bcdsub.
   25790       {
   25791          /* NOTE 64 bit compares are not supported in 32-bit mode.  Use
   25792           * 32-bit compares only.
   25793           */
   25794 
   25795          IRExpr *sign, *res_smaller;
   25796          IRExpr *signA, *signB, *sign_digitA, *sign_digitB;
   25797          IRExpr *zeroA, *zeroB, *posA, *posB, *negA, *negB;
   25798 
   25799          if ( opc2 == 0x1 ) {
   25800             DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   25801             assign( dst, bcd_sign_code_adjust( ps,
   25802                                                binop( Iop_BCDAdd,
   25803                                                       mkexpr( vA ),
   25804                                                       mkexpr( vB ) ) ) );
   25805          } else {
   25806             DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   25807             assign( dst, bcd_sign_code_adjust( ps,
   25808                                                binop( Iop_BCDSub,
   25809                                                       mkexpr( vA ),
   25810                                                       mkexpr( vB ) ) ) );
   25811          }
   25812 
   25813          putVReg( vRT_addr, mkexpr( dst ) );
   25814          /* set CR field 6 */
   25815          /* result */
   25816          zero = BCDstring_zero( binop( Iop_AndV128,
   25817                                        binop( Iop_64HLtoV128,
   25818                                               mkU64( 0xFFFFFFFFFFFFFFFF ),
   25819                                               mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   25820                                        mkexpr(dst) ) );  // ignore sign
   25821 
   25822          sign_digit = binop( Iop_And32, mkU32( 0xF ),
   25823                              unop( Iop_64to32,
   25824                                    unop( Iop_V128to64, mkexpr( dst ) ) ) );
   25825 
   25826          sign = mkOR1( binop( Iop_CmpEQ32,
   25827                               sign_digit,
   25828                               mkU32 ( 0xB ) ),
   25829                        binop( Iop_CmpEQ32,
   25830                               sign_digit,
   25831                               mkU32 ( 0xD ) ) );
   25832          neg = mkAND1( sign, mkNOT1( zero ) );
   25833 
   25834          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
   25835          pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   25836          valid =  unop( Iop_64to32,
   25837                         binop( Iop_And64,
   25838                                is_BCDstring128( vbi,
   25839                                                 /*Signed*/True, mkexpr( vA ) ),
   25840                                is_BCDstring128( vbi,
   25841                                                 /*Signed*/True, mkexpr( vB ) )
   25842                                                 ) );
   25843 
   25844          /* src A */
   25845          zeroA = BCDstring_zero( binop( Iop_AndV128,
   25846                                         binop( Iop_64HLtoV128,
   25847                                                mkU64( 0xFFFFFFFFFFFFFFFF ),
   25848                                                mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   25849                                         mkexpr( vA ) ) );  // ignore sign
   25850          sign_digitA = binop( Iop_And32, mkU32( 0xF ),
   25851                               unop( Iop_64to32,
   25852                                     unop( Iop_V128to64, mkexpr( vA ) ) ) );
   25853 
   25854          signA = mkOR1( binop( Iop_CmpEQ32,
   25855                                sign_digitA,
   25856                                mkU32 ( 0xB ) ),
   25857                         binop( Iop_CmpEQ32,
   25858                                sign_digitA,
   25859                                mkU32 ( 0xD ) ) );
   25860          negA = mkAND1( signA, mkNOT1( zeroA ) );
   25861          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
   25862          posA = mkAND1( mkNOT1( signA ), mkNOT1( zeroA ) );
   25863 
   25864          /* src B */
   25865          zeroB = BCDstring_zero( binop( Iop_AndV128,
   25866                                         binop( Iop_64HLtoV128,
   25867                                                mkU64( 0xFFFFFFFFFFFFFFFF ),
   25868                                                mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   25869                                         mkexpr( vB ) ) );  // ignore sign
   25870          sign_digitB = binop( Iop_And32, mkU32( 0xF ),
   25871                               unop( Iop_64to32,
   25872                                     unop( Iop_V128to64, mkexpr( vB ) ) ) );
   25873 
   25874          signB = mkOR1( binop( Iop_CmpEQ32,
   25875                                sign_digitB,
   25876                                mkU32 ( 0xB ) ),
   25877                         binop( Iop_CmpEQ32,
   25878                                sign_digitB,
   25879                                mkU32 ( 0xD ) ) );
   25880          negB = mkAND1( signB, mkNOT1( zeroB ) );
   25881 
   25882 
   25883          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
   25884          posB = mkAND1( mkNOT1( signB ), mkNOT1( zeroB ) );
   25885 
   25886 
   25887          if (mode64) {
   25888 	    res_smaller = mkAND1( CmpGT128U( mkexpr( vA ), mkexpr( dst ) ),
   25889 				  CmpGT128U( mkexpr( vB ), mkexpr( dst ) ) );
   25890 
   25891          } else {
   25892             /* Have to do this with 32-bit compares, expensive */
   25893             res_smaller = mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA ),
   25894                                                         mkexpr( dst ) ),
   25895                                   UNSIGNED_CMP_GT_V128( mkexpr( vB ),
   25896                                                         mkexpr( dst ) ) );
   25897          }
   25898 
   25899          if ( opc2 == 0x1) {
   25900             /* Overflow for Add can only occur if the signs of the operands
   25901              * are the same and the two operands are non-zero.  On overflow,
   25902              * the PPC hardware produces a result consisting of just the lower
   25903              * digits of the result.  So, if the result is less then both
   25904              * operands and the sign of the operands are the same overflow
   25905              * occured.
   25906              */
   25907             overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, negB ) ),
   25908                               mkAND1( res_smaller, mkAND1( posA, posB ) ) );
   25909          } else {
   25910             /* Overflow for Add can only occur if the signs of the operands
   25911              * are the different and the two operands are non-zero.  On overflow,
   25912              * the PPC hardware produces a result consisting of just the lower
   25913              * digits of the result.  So, if the result is less then both
   25914              * operands and the sign of the operands are different overflow
   25915              * occured.
   25916              */
   25917             overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, posB ) ),
   25918                               mkAND1( res_smaller, mkAND1( posA, negB ) ) );
   25919          }
   25920       }
   25921      break;
   25922 
   25923    case 0x081: // bcdus.  Decimal Unsigned Shift VX-form
   25924    case 0x0C1: // bcds.   Decimal Shift VX-form
   25925    case 0x1C1: // bcdsr.  Decimal Shift and Round VX-form
   25926       {
   25927          IRExpr *shift_dir;
   25928          IRExpr *shift_mask, *result, *new_sign_val, *sign;
   25929          IRExpr *not_excess_shift, *not_excess_shift_mask;
   25930          IRTemp shift_dir_mask = newTemp( Ity_I64 );
   25931          IRTemp shift_by = newTemp( Ity_I64 );
   25932          IRTemp shift_field = newTemp( Ity_I64 );
   25933          IRTemp shifted_out = newTemp( Ity_V128 );
   25934          IRTemp value_shl = newTemp( Ity_V128 );
   25935          IRTemp value_shr = newTemp( Ity_V128 );
   25936          IRTemp round = newTemp( Ity_I32);
   25937 
   25938          ULong value_mask_low = 0;
   25939          UInt max_shift = 0;
   25940 
   25941          if (opc2 == 0x0C1) {
   25942             DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
   25943             value_mask_low = 0xFFFFFFFFFFFFFFF0;
   25944             max_shift = 30 * 4; /* maximum without shifting all digits out */
   25945 
   25946          }  else if (opc2 == 0x1C1) {
   25947             DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
   25948 
   25949             value_mask_low = 0xFFFFFFFFFFFFFFF0;
   25950             max_shift = 30 * 4; /* maximum without shifting all digits out */
   25951 
   25952          } else {
   25953             DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr,
   25954                 vRB_addr, ps);
   25955             value_mask_low = 0xFFFFFFFFFFFFFFFF;
   25956             max_shift = 31 * 4; /* maximum without shifting all digits out */
   25957          }
   25958 
   25959          value = binop( Iop_AndV128,
   25960                         binop( Iop_64HLtoV128,
   25961                                mkU64( 0xFFFFFFFFFFFFFFFF ),
   25962                                mkU64( value_mask_low ) ),
   25963                         mkexpr( vB ) );
   25964 
   25965          zero = BCDstring_zero( value );
   25966 
   25967          /* Shift field is 2's complement value */
   25968          assign( shift_field, unop( Iop_V128to64,
   25969                                     binop( Iop_ShrV128,
   25970                                            binop( Iop_AndV128,
   25971                                                   binop( Iop_64HLtoV128,
   25972                                                          mkU64( 0xFF ),
   25973                                                          mkU64( 0x0) ),
   25974                                                   mkexpr( vA ) ),
   25975                                            mkU8( 64 ) ) ) );
   25976 
   25977          /* if shift_dir = 0 shift left, otherwise shift right */
   25978          shift_dir = binop( Iop_CmpEQ64,
   25979                             binop( Iop_Shr64,
   25980                                    mkexpr( shift_field ),
   25981                                    mkU8( 7 ) ),
   25982                             mkU64( 1 ) );
   25983 
   25984          assign( shift_dir_mask, unop( Iop_1Sto64, shift_dir ) );
   25985 
   25986          /* Shift field is stored in 2's complement form */
   25987          assign(shift_by,
   25988                 binop( Iop_Mul64,
   25989                        binop( Iop_Or64,
   25990                               binop( Iop_And64,
   25991                                      unop( Iop_Not64,
   25992                                            mkexpr( shift_dir_mask ) ),
   25993                                      mkexpr( shift_field ) ),
   25994                               binop( Iop_And64,
   25995                                      mkexpr( shift_dir_mask ),
   25996                                      binop( Iop_And64,
   25997                                             binop( Iop_Add64,
   25998                                                    mkU64( 1 ),
   25999                                                    unop( Iop_Not64,
   26000                                                          mkexpr( shift_field ) ) ),
   26001                                             mkU64( 0xFF ) ) ) ),
   26002                        mkU64( 4 ) ) );
   26003 
   26004          /* If the shift exceeds 128 bits, we need to force the result
   26005           * to zero because Valgrind shift amount is only 7-bits. Otherwise,
   26006           * we get a shift amount of mod(shift_by, 127)
   26007           */
   26008          not_excess_shift = unop( Iop_1Sto64,
   26009                                   binop( Iop_CmpLE64U,
   26010                                          mkexpr( shift_by ),
   26011                                          mkU64( max_shift ) ) );
   26012 
   26013          not_excess_shift_mask = binop( Iop_64HLtoV128,
   26014                                         not_excess_shift,
   26015                                         not_excess_shift );
   26016 
   26017          assign( value_shl,
   26018                  binop( Iop_ShlV128, value, unop( Iop_64to8,
   26019                                                   mkexpr( shift_by) ) ) );
   26020          assign( value_shr,
   26021                  binop( Iop_AndV128,
   26022                         binop( Iop_64HLtoV128,
   26023                                mkU64( 0xFFFFFFFFFFFFFFFF ),
   26024                                mkU64( value_mask_low) ),
   26025                         binop( Iop_ShrV128,
   26026                                value,
   26027                                unop( Iop_64to8,
   26028                                      mkexpr( shift_by ) )  ) ) );
   26029 
   26030          /* Overflow occurs if the shift amount is greater than zero, the
   26031           * operation is a left shift and any non-zero digits are left
   26032           * shifted out.
   26033           */
   26034          assign( shifted_out,
   26035                  binop( Iop_OrV128,
   26036                         binop( Iop_ShrV128,
   26037                                value,
   26038                                unop( Iop_64to8,
   26039                                      binop( Iop_Sub64,
   26040                                             mkU64( 32*4 ),
   26041                                             mkexpr( shift_by ) ) ) ),
   26042                         binop( Iop_AndV128,
   26043                                unop( Iop_NotV128,
   26044                                      not_excess_shift_mask ),
   26045                                value ) ) );
   26046 
   26047          overflow = mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out ) ) ),
   26048                             mkAND1( mkNOT1( shift_dir ),
   26049                                     binop( Iop_CmpNE64,
   26050                                            mkexpr( shift_by ),
   26051                                            mkU64( 0 ) ) ) );
   26052 
   26053          if ((opc2 == 0xC1) || (opc2 == 0x1C1)) {
   26054             /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   26055              * codes 0xB and 0xD are negative.
   26056              */
   26057             sign_digit = binop( Iop_And64, mkU64( 0xF ),
   26058                                 unop( Iop_V128to64, mkexpr( vB ) ) );
   26059 
   26060             sign = mkOR1( binop( Iop_CmpEQ64,
   26061                                  sign_digit,
   26062                                  mkU64 ( 0xB ) ),
   26063                           binop( Iop_CmpEQ64,
   26064                                  sign_digit,
   26065                                  mkU64 ( 0xD ) ) );
   26066             neg = mkAND1( sign, mkNOT1( zero ) );
   26067 
   26068             /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
   26069             pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26070 
   26071             valid =
   26072                unop( Iop_64to32,
   26073                      is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
   26074 
   26075          } else {
   26076             /* string is an unsigned BCD value */
   26077             pos = mkU1( 1 );
   26078             neg = mkU1( 0 );
   26079             sign = mkU1( 0 );
   26080 
   26081             valid =
   26082                unop( Iop_64to32,
   26083                      is_BCDstring128( vbi, /* Unsigned */False,
   26084                                       mkexpr( vB ) ) );
   26085          }
   26086 
   26087          /* if PS = 0
   26088                   vB positive, sign is C
   26089                   vB negative, sign is D
   26090             if PS = 1
   26091                   vB positive, sign is F
   26092                   vB negative, sign is D
   26093             Note can't use pos or neg here since they are ANDed with zero,
   26094             use sign instead.
   26095          */
   26096          if (ps == 0) {
   26097             new_sign_val = binop( Iop_Or64,
   26098                                   unop( Iop_1Uto64, sign ),
   26099                                   mkU64( 0xC ) );
   26100 
   26101          } else {
   26102             new_sign_val = binop( Iop_Xor64,
   26103                                   binop( Iop_Shl64,
   26104                                          unop( Iop_1Uto64, sign ),
   26105                                          mkU8( 1 ) ),
   26106                                   mkU64( 0xF ) );
   26107          }
   26108 
   26109          shift_mask = binop( Iop_64HLtoV128,
   26110                              unop( Iop_1Sto64, shift_dir ),
   26111                              unop( Iop_1Sto64, shift_dir ) );
   26112 
   26113          result = binop( Iop_OrV128,
   26114                          binop( Iop_AndV128, mkexpr( value_shr ), shift_mask ),
   26115                          binop( Iop_AndV128,
   26116                                 mkexpr( value_shl ),
   26117                                 unop( Iop_NotV128, shift_mask ) ) );
   26118 
   26119          if (opc2 == 0xC1) {    // bcds.
   26120             putVReg( vRT_addr, binop( Iop_OrV128,
   26121                                       binop( Iop_64HLtoV128,
   26122                                              mkU64( 0 ),
   26123                                              new_sign_val ),
   26124                                       binop( Iop_AndV128,
   26125                                              not_excess_shift_mask,
   26126                                              result ) ) );
   26127          } else if (opc2 == 0x1C1) {  //bcdsr.
   26128             /* If shifting right, need to round up if needed */
   26129             assign( round, unop( Iop_1Uto32,
   26130                                  mkAND1( shift_dir,
   26131                                          check_BCD_round( value,
   26132                                                           shift_by ) ) ) );
   26133 
   26134             putVReg( vRT_addr,
   26135                      binop( Iop_OrV128,
   26136                             binop( Iop_64HLtoV128,
   26137                                    mkU64( 0 ),
   26138                                    new_sign_val ),
   26139                             binop( Iop_AndV128,
   26140                                    not_excess_shift_mask,
   26141                                    mkexpr( increment_BCDstring( vbi, result,
   26142                                                                 mkexpr( round)
   26143                                                                 ) ) ) ) );
   26144          } else {  // bcdus.
   26145             putVReg( vRT_addr, binop( Iop_AndV128,
   26146                                       not_excess_shift_mask,
   26147                                       result ) );
   26148          }
   26149       }
   26150       break;
   26151 
   26152    case 0x101:  // bcdtrunc.   Decimal Truncate VX-form
   26153    case 0x141:  // bcdutrunc.  Decimal Unsigned Truncate VX-form
   26154       {
   26155          IRTemp length = newTemp( Ity_I64 );
   26156          IRTemp masked_out = newTemp( Ity_V128 );
   26157          IRExpr *new_sign_val, *result, *shift;
   26158          IRExpr *length_neq_128, *sign;
   26159          ULong value_mask_low;
   26160          Int max_digits;
   26161 
   26162          if ( opc2 == 0x101) {     // bcdtrunc.
   26163             value_mask_low = 0xFFFFFFFFFFFFFFF0;
   26164             max_digits = 31;
   26165          } else {
   26166             value_mask_low = 0xFFFFFFFFFFFFFFFF;
   26167             max_digits = 32;
   26168          }
   26169 
   26170          assign( length, binop( Iop_And64,
   26171                                      unop( Iop_V128HIto64,
   26172                                            mkexpr( vA ) ),
   26173                                      mkU64( 0xFFFF ) ) );
   26174          shift = unop( Iop_64to8,
   26175                        binop( Iop_Mul64,
   26176                               binop( Iop_Sub64,
   26177                                      mkU64( max_digits ),
   26178                                      mkexpr( length ) ),
   26179                               mkU64( 4 ) ) );
   26180 
   26181          /* Note ShrV128 gets masked by 127 so a shift of 128 results in
   26182           * the value not being shifted.  A shift of 128 sets the register
   26183           * zero.  So if length+1 = 128, just set the value to 0.
   26184          */
   26185          length_neq_128 = mkNOT1( binop( Iop_CmpEQ64,
   26186                                          mkexpr( length),
   26187                                          mkU64( 0x1F ) ) );
   26188 
   26189          assign( masked_out,
   26190                  binop( Iop_AndV128,
   26191                         binop( Iop_64HLtoV128,
   26192                                unop( Iop_1Sto64, length_neq_128 ),
   26193                                unop( Iop_1Sto64, length_neq_128 ) ),
   26194                         binop( Iop_ShrV128,
   26195                                mkexpr( vB ),
   26196                                unop( Iop_64to8,
   26197                                      binop( Iop_Mul64,
   26198                                             mkU64( 4 ),
   26199                                             binop( Iop_Add64,
   26200                                                    mkU64( 1 ),
   26201                                                    mkexpr( length ) ) ) ) )
   26202                         ) );
   26203 
   26204          /* Overflow occurs if any of the left most 31-length digits of vB
   26205           * are non-zero.
   26206           */
   26207          overflow = mkNOT1( BCDstring_zero( mkexpr( masked_out ) ) );
   26208 
   26209          value = binop( Iop_AndV128,
   26210                         binop( Iop_64HLtoV128,
   26211                                mkU64( 0xFFFFFFFFFFFFFFFF ),
   26212                                mkU64( value_mask_low ) ),
   26213                         mkexpr( vB ) );
   26214 
   26215 
   26216          if ( opc2 == 0x101 ) {     // bcdtrunc.
   26217             /* Check if all of the non-sign digits are zero */
   26218             zero = BCDstring_zero( binop( Iop_AndV128,
   26219                                           binop( Iop_64HLtoV128,
   26220                                                  mkU64( 0xFFFFFFFFFFFFFFFF ),
   26221                                                  mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   26222                                           value ) );
   26223 
   26224             /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   26225              * codes 0xB and 0xD are negative.
   26226              */
   26227             sign_digit = binop( Iop_And64, mkU64( 0xF ),
   26228                                 unop( Iop_V128to64, mkexpr( vB ) ) );
   26229 
   26230             sign = mkOR1( binop( Iop_CmpEQ64,
   26231                                  sign_digit,
   26232                                  mkU64 ( 0xB ) ),
   26233                           binop( Iop_CmpEQ64,
   26234                                  sign_digit,
   26235                                  mkU64 ( 0xD ) ) );
   26236             neg = mkAND1( sign, mkNOT1( zero ) );
   26237 
   26238             /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
   26239             pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26240 
   26241             /* Note can't use pos or neg here since they are ANDed with zero,
   26242                use sign instead.
   26243             */
   26244             if (ps == 0) {
   26245                new_sign_val = binop( Iop_Or64,
   26246                                      unop( Iop_1Uto64, sign ),
   26247                                      mkU64( 0xC ) );
   26248             } else {
   26249                new_sign_val = binop( Iop_Xor64,
   26250                                      binop( Iop_Shl64,
   26251                                             unop( Iop_1Uto64, sign ),
   26252                                             mkU8 ( 1 ) ),
   26253                                      mkU64( 0xF ) );
   26254             }
   26255             valid =
   26256                unop( Iop_64to32,
   26257                      is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
   26258 
   26259          } else {   // bcdutrunc.
   26260             /* Check if all of the digits are zero */
   26261             zero = BCDstring_zero( value );
   26262 
   26263             /* unsigned value, need to make CC code happy */
   26264             neg = mkU1( 0 );
   26265 
   26266             /* Pos position AKA gt = 1 if (not eq zero) */
   26267             pos = mkNOT1( zero );
   26268             valid =
   26269                unop( Iop_64to32,
   26270                      is_BCDstring128( vbi, /* Unsigned */False,
   26271                                       mkexpr( vB ) ) );
   26272          }
   26273 
   26274          /* If vB is not valid, the result is undefined, but we need to
   26275           * match the hardware so the output of the test suite will match.
   26276           * Hardware sets result to 0x0.
   26277           */
   26278          result = binop( Iop_AndV128,
   26279                          mkV128( 0xFFFF ),
   26280                          binop( Iop_ShrV128,
   26281                                 binop( Iop_ShlV128, value, shift ),
   26282                                 shift ) );
   26283 
   26284          if ( opc2 == 0x101) {     // bcdtrunc.
   26285             putVReg( vRT_addr, binop( Iop_OrV128,
   26286                                       binop( Iop_64HLtoV128,
   26287                                              mkU64( 0 ),
   26288                                              new_sign_val ),
   26289                                       result ) );
   26290          } else {
   26291             putVReg( vRT_addr, result );
   26292          }
   26293       }
   26294       break;
   26295 
   26296    case 0x181:   // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn.,
   26297                  // bcdcfsq., bcdctsq.
   26298       {
   26299          UInt inst_select = IFIELD( theInstr, 16, 5);
   26300 
   26301          switch (inst_select) {
   26302          case 0:  // bcdctsq.  (Decimal Convert to Signed Quadword VX-form)
   26303             {
   26304                IRExpr *sign;
   26305 
   26306                /* The instruction takes a 32-bit integer in a vector source
   26307                 * register and returns the signed packed decimal number
   26308                 * in a vector register.  The source integer needs to be moved
   26309                 * from the V128 to an I32 for the Iop.
   26310                 */
   26311 
   26312                DIP("bcdctsq v%d, v%d\n", vRT_addr, vRB_addr);
   26313 
   26314                putVReg( vRT_addr, unop( Iop_BCD128toI128S, mkexpr( vB ) ) );
   26315 
   26316                sign =  binop( Iop_And64,
   26317                               unop( Iop_V128to64, mkexpr( vB ) ),
   26318                               mkU64( 0xF ) );
   26319                zero = mkAND1( binop( Iop_CmpEQ64,
   26320                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
   26321                                      mkU64( 0x0 ) ),
   26322                               binop( Iop_CmpEQ64,
   26323                                      binop( Iop_And64,
   26324                                             unop( Iop_V128to64, mkexpr( vB ) ),
   26325                                             mkU64( 0xFFFFFFF0 ) ),
   26326                                      mkU64( 0x0 ) ) );
   26327                pos = mkAND1( mkNOT1( zero ),
   26328                              mkOR1( mkOR1( binop( Iop_CmpEQ64,
   26329                                                   sign, mkU64( 0xA ) ),
   26330                                            binop( Iop_CmpEQ64,
   26331                                                   sign, mkU64( 0xC ) ) ),
   26332                                     mkOR1( binop( Iop_CmpEQ64,
   26333                                                   sign, mkU64( 0xE ) ),
   26334                                            binop( Iop_CmpEQ64,
   26335                                                   sign, mkU64( 0xF ) ) ) ) );
   26336                neg = mkAND1( mkNOT1( zero ),
   26337                              mkOR1( binop( Iop_CmpEQ64, sign, mkU64( 0xB ) ),
   26338                                     binop( Iop_CmpEQ64, sign, mkU64( 0xD ) ) ) );
   26339 
   26340                /* Check each of the nibbles for a valid digit 0 to 9 */
   26341                valid =
   26342                   unop( Iop_64to32,
   26343                         is_BCDstring128( vbi, /* Signed */True,
   26344                                          mkexpr( vB ) ) );
   26345                overflow = mkU1( 0 );  // not used
   26346             }
   26347             break;
   26348 
   26349          case 2:  // bcdcfsq. (Decimal Convert from Signed Quadword VX-form)
   26350             {
   26351                IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt;
   26352                IRExpr *neg_upper_lt, *neg_upper_eq, *neg_lower_lt;
   26353 
   26354                DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr, vRB_addr, ps);
   26355 
   26356                /* The instruction takes a signed packed decimal number and
   26357                 * returns the integer value in the vector register.  The Iop
   26358                 * returns an I32 which needs to be moved to the destination
   26359                 * vector register.
   26360                 */
   26361                putVReg( vRT_addr,
   26362                         binop( Iop_I128StoBCD128, mkexpr( vB ), mkU8( ps ) ) );
   26363 
   26364                zero = mkAND1( binop( Iop_CmpEQ64, mkU64( 0 ),
   26365                                      unop( Iop_V128to64, mkexpr( vB ) ) ),
   26366                               binop( Iop_CmpEQ64, mkU64( 0 ),
   26367                                      unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   26368                pos = mkAND1( mkNOT1 ( zero ),
   26369                              binop( Iop_CmpEQ64, mkU64( 0 ),
   26370                                     binop( Iop_And64,
   26371                                            unop( Iop_V128HIto64,
   26372                                                  mkexpr( vB ) ),
   26373                                            mkU64( 0x8000000000000000UL ) ) ) );
   26374                neg = mkAND1( mkNOT1 ( zero ),
   26375                              binop( Iop_CmpEQ64, mkU64( 0x8000000000000000UL ),
   26376                                     binop( Iop_And64,
   26377                                            unop( Iop_V128HIto64,
   26378                                                  mkexpr( vB ) ),
   26379                                            mkU64( 0x8000000000000000UL ) ) ) );
   26380 
   26381                /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1
   26382                 * do not have a 128 bit compare.  Will have to compare the
   26383                 * upper 64 bit and athe lower 64 bits.  If the upper 64-bits
   26384                 * are equal then overflow if the lower 64 bits of vB is greater
   26385                 * otherwise if the upper bits of vB is greater then the max
   26386                 * for the upper 64-bits then overflow
   26387                 *
   26388                 *     10^31-1 = 0x7E37BE2022C0914B267FFFFFFF
   26389                 */
   26390                pos_upper_gt = binop( Iop_CmpLT64U,
   26391                                      mkU64( 0x7E37BE2022 ),
   26392                                      unop( Iop_V128HIto64, mkexpr( vB ) ) );
   26393                pos_upper_eq = binop( Iop_CmpEQ64,
   26394                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
   26395                                      mkU64( 0x7E37BE2022 ) );
   26396                pos_lower_gt = binop( Iop_CmpLT64U,
   26397                                      mkU64( 0x0914B267FFFFFFF ),
   26398                                      unop( Iop_V128to64, mkexpr( vB ) ) );
   26399                /* -10^31-1 =  0X81C841DFDD3F6EB4D97FFFFFFF */
   26400                neg_upper_lt = binop( Iop_CmpLT64U,
   26401                                      mkU64( 0X81C841DFDD ),
   26402                                      unop( Iop_V128HIto64, mkexpr( vB ) ) );
   26403                neg_upper_eq = binop( Iop_CmpEQ64,
   26404                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
   26405                                      mkU64( 0X81C841DFDD ) );
   26406                neg_lower_lt = binop( Iop_CmpLT64U,
   26407                                      mkU64( 0x3F6EB4D97FFFFFFF ),
   26408                                      unop( Iop_V128to64, mkexpr( vB ) ) );
   26409 
   26410                /* calculate overflow, masking for positive and negative */
   26411                overflow = mkOR1( mkAND1( pos,
   26412                                          mkOR1( pos_upper_gt,
   26413                                                 mkAND1( pos_upper_eq,
   26414                                                         pos_lower_gt ) ) ),
   26415                                  mkAND1( neg,
   26416                                          mkOR1( neg_upper_lt,
   26417                                                 mkAND1( neg_upper_eq,
   26418                                                         neg_lower_lt )
   26419                                                 ) ) );
   26420                valid = mkU32( 1 );
   26421             }
   26422             break;
   26423 
   26424          case 4:  // bcdctz. (Decimal Convert to Zoned VX-form)
   26425             {
   26426                IRExpr *ox_flag, *sign, *vrb_nibble30;
   26427                int neg_bit_shift;
   26428                unsigned int upper_byte, sign_byte;
   26429                IRTemp tmp = newTemp( Ity_V128 );
   26430 
   26431                DIP("bcdctz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
   26432 
   26433                if (ps == 0) {
   26434                   upper_byte = 0x30;
   26435                   sign_byte = 0x30;
   26436                   neg_bit_shift = 4+2;  /* sign byte is in bits [7:4] */
   26437                } else {
   26438                   upper_byte = 0xF0;
   26439                   sign_byte = 0xC0;
   26440                   neg_bit_shift = 4+0;
   26441                }
   26442 
   26443                /* Grab vB bits[7:4].  It goes into bits [3:0] of the
   26444                 * result.
   26445                 */
   26446                vrb_nibble30 = binop( Iop_Shr64,
   26447                                      binop( Iop_And64,
   26448                                             unop( Iop_V128to64, mkexpr( vB ) ),
   26449                                             mkU64( 0xF0 ) ),
   26450                                      mkU8( 4 ) );
   26451 
   26452                /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23],
   26453                 * must be zero for the value to be zero.  This goes
   26454                 * in the overflow position of the condition code register.
   26455                 */
   26456                ox_flag = binop( Iop_CmpEQ64,
   26457                                      binop( Iop_And64,
   26458                                             unop( Iop_V128to64, mkexpr( vB ) ),
   26459                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
   26460                                 mkU64( 0 ) );
   26461 
   26462                /* zero is the same as eq_flag */
   26463                zero = mkAND1( binop( Iop_CmpEQ64,
   26464                                      binop( Iop_And64,
   26465                                             unop( Iop_V128HIto64, mkexpr( vB ) ),
   26466                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
   26467                                      mkU64( 0 ) ),
   26468                               binop( Iop_CmpEQ64,
   26469                                      binop( Iop_And64,
   26470                                             unop( Iop_V128to64, mkexpr( vB ) ),
   26471                                             mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   26472                                      mkU64( 0 ) ) );
   26473 
   26474                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   26475                 * codes 0xB and 0xD are negative.
   26476                 */
   26477                sign_digit = binop( Iop_And64, mkU64( 0xF ),
   26478                                    unop( Iop_V128to64, mkexpr( vB ) ) );
   26479 
   26480                /* The negative value goes in the LT bit position of the
   26481                 * condition code register. Set neg if the sign of vB
   26482                 * is negative and zero is true.
   26483                 */
   26484                sign = mkOR1( binop( Iop_CmpEQ64,
   26485                                     sign_digit,
   26486                                     mkU64 ( 0xB ) ),
   26487                              binop( Iop_CmpEQ64,
   26488                                     sign_digit,
   26489                                     mkU64 ( 0xD ) ) );
   26490                neg = mkAND1( sign, mkNOT1( zero ) );
   26491 
   26492                /* The positive value goes in the LT bit position of the
   26493                 * condition code register. Set positive if the sign of the
   26494                 * value is not negative.
   26495                 */
   26496                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26497 
   26498                assign( tmp,
   26499                        convert_to_zoned( vbi, mkexpr( vB ),
   26500                                          mkU64( upper_byte ) ) );
   26501 
   26502                /* Insert the sign based on ps and sign of vB
   26503                 * in the lower byte.
   26504                 */
   26505                putVReg( vRT_addr,
   26506                         binop( Iop_OrV128,
   26507                                binop( Iop_64HLtoV128,
   26508                                       mkU64( 0 ),
   26509                                       vrb_nibble30 ),
   26510                                binop( Iop_OrV128,
   26511                                       mkexpr( tmp ),
   26512                                       binop( Iop_64HLtoV128,
   26513                                              mkU64( 0 ),
   26514                                              binop( Iop_Or64,
   26515                                                     mkU64( sign_byte ),
   26516                                                     binop( Iop_Shl64,
   26517                                                            unop( Iop_1Uto64,
   26518                                                                  sign ),
   26519                                                            mkU8( neg_bit_shift)
   26520                                ) ) ) ) ) );
   26521 
   26522                /* A valid number must have a value that is less then or
   26523                 * equal to 10^16 - 1.  This is checked by making sure
   26524                 * bytes [31:16] of vB are zero.
   26525                 */
   26526                in_range = binop( Iop_CmpEQ64,
   26527                                  binop( Iop_And64,
   26528                                         mkU64( 0xFFFFFFFFFFFFFFF0 ),
   26529                                         unop( Iop_V128HIto64, mkexpr( vB ) ) ),
   26530                                  mkU64( 0 ) );
   26531 
   26532                /* overflow is set if ox_flag or not in_inrange.  Setting is
   26533                 * ORed with the other condition code values.
   26534                 */
   26535                overflow = mkOR1( ox_flag, mkNOT1( in_range ) );
   26536 
   26537                /* The sign code must be between 0xA and 0xF and all digits are
   26538                 * between 0x0 and 0x9. The vB must be in range to be valid.
   26539                 * If not valid, condition code set to 0x0001.
   26540                 */
   26541                valid =
   26542                   unop( Iop_64to32,
   26543                         is_BCDstring128( vbi, /* Signed */True,
   26544                                          mkexpr( vB ) ) );
   26545             }
   26546             break;
   26547 
   26548          case 5:  // bcdctn. (Decimal Convert to National VX-form)
   26549             {
   26550                IRExpr *ox_flag, *sign;
   26551                IRTemp tmp = newTemp( Ity_V128 );;
   26552 
   26553                DIP("bcdctn. v%d,v%d\n", vRT_addr, vRB_addr);
   26554 
   26555                value = binop( Iop_And64,
   26556                               mkU64( 0xFFFFFFFF ),
   26557                               unop( Iop_V128to64, mkexpr( vB ) ) );
   26558 
   26559                /* A valid number must have a value that is less then or
   26560                 * equal to 10^7 - 1.  This is checked by making sure
   26561                 * bytes [31:8] of vB are zero.
   26562                 */
   26563                in_range = mkAND1( binop( Iop_CmpEQ64,
   26564                                          unop( Iop_V128HIto64, mkexpr( vB ) ),
   26565                                          mkU64( 0 ) ),
   26566                                   binop( Iop_CmpEQ64,
   26567                                          binop( Iop_Shr64,
   26568                                                 unop( Iop_V128to64,
   26569                                                       mkexpr( vB ) ),
   26570                                                 mkU8( 32 ) ),
   26571                                          mkU64( 0 ) ) );
   26572 
   26573                /* The sign code must be between 0xA and 0xF and all digits are
   26574                 *  between 0x0 and 0x9.
   26575                 */
   26576                valid =
   26577                   unop( Iop_64to32,
   26578                         is_BCDstring128( vbi, /* Signed */True,
   26579                                          mkexpr( vB ) ) );
   26580 
   26581                /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23],
   26582                 * must be zero for the ox_flag to be zero.  This goes
   26583                 * in the LSB position (variable overflow) of the
   26584                 * condition code register.
   26585                 */
   26586                ox_flag =
   26587                   mkNOT1( mkAND1( binop( Iop_CmpEQ64,
   26588                                          binop( Iop_And64,
   26589                                                 unop( Iop_V128HIto64,
   26590                                                       mkexpr( vB ) ),
   26591                                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
   26592                                          mkU64( 0 ) ),
   26593                                   binop( Iop_CmpEQ64,
   26594                                          binop( Iop_And64,
   26595                                                 unop( Iop_V128to64,
   26596                                                       mkexpr( vB ) ),
   26597                                                 mkU64( 0xFFFFFFFF00000000 ) ),
   26598                                          mkU64( 0 ) ) ) );
   26599 
   26600                /* Set zero to 1 if all of the bytes in vB are zero.  This is
   26601                 * used when setting the lt_flag (variable neg) and the gt_flag
   26602                 * (variable pos).
   26603                 */
   26604                zero = mkAND1( binop( Iop_CmpEQ64,
   26605                                      binop( Iop_And64,
   26606                                             unop( Iop_V128HIto64,
   26607                                                   mkexpr( vB ) ),
   26608                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
   26609                                          mkU64( 0 ) ),
   26610                               binop( Iop_CmpEQ64,
   26611                                       binop( Iop_And64,
   26612                                              unop( Iop_V128to64, mkexpr( vB ) ),
   26613                                              mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   26614                                       mkU64( 0 ) ) );
   26615 
   26616                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   26617                 * codes 0xB and 0xD are negative.
   26618                 */
   26619                sign_digit = binop( Iop_And64, mkU64( 0xF ), value );
   26620 
   26621                /* The negative value goes in the LT bit position of the
   26622                 * condition code register. Set neg if the sign of the
   26623                 * value is negative and the value is zero.
   26624                 */
   26625                sign = mkOR1( binop( Iop_CmpEQ64,
   26626                                     sign_digit,
   26627                                     mkU64 ( 0xB ) ),
   26628                              binop( Iop_CmpEQ64,
   26629                                     sign_digit,
   26630                                     mkU64 ( 0xD ) ) );
   26631                neg = mkAND1( sign, mkNOT1( zero ) );
   26632 
   26633                /* The positive value goes in the LT bit position of the
   26634                 * condition code register. Set neg if the sign of the
   26635                 * value is not negative and the value is zero.
   26636                 */
   26637                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26638 
   26639                assign( tmp,
   26640                        convert_to_national( vbi, mkexpr( vB ) ) );
   26641 
   26642                /* If vB is positive insert sign value 0x002B, otherwise
   26643                 * insert 0x002D for negative. Have to use sign not neg
   26644                 * because neg has been ANDed with zero.  This is 0x29
   26645                 * OR'd with (sign << 1 | NOT sign) << 1.
   26646                 * sign = 1 if vB is negative.
   26647                 */
   26648                putVReg( vRT_addr,
   26649                         binop( Iop_OrV128,
   26650                                mkexpr( tmp ),
   26651                                binop( Iop_64HLtoV128,
   26652                                       mkU64( 0 ),
   26653                                       binop( Iop_Or64,
   26654                                              mkU64( 0x29 ),
   26655                                              binop( Iop_Or64,
   26656                                                     binop( Iop_Shl64,
   26657                                                            unop( Iop_1Uto64,
   26658                                                                  sign ),
   26659                                                            mkU8( 2 ) ),
   26660                                                     binop( Iop_Shl64,
   26661                                                            unop( Iop_1Uto64,
   26662                                                                  mkNOT1(sign)),
   26663                                                            mkU8( 1 ) )
   26664                                                     ) ) ) ) );
   26665 
   26666 
   26667                /* The sign code must be between 0xA and 0xF and all digits are
   26668                 *  between 0x0 and 0x9. The vB must be in range to be valid.
   26669                 */
   26670                valid =
   26671                   unop( Iop_64to32,
   26672                         is_BCDstring128( vbi, /* Signed */True,
   26673                                          mkexpr( vB ) ) );
   26674 
   26675                overflow = ox_flag;
   26676             }
   26677             break;
   26678 
   26679          case 6:  // bcdcfz. (Decimal Convert From Zoned VX-form)
   26680             {
   26681                IRExpr *sign;
   26682                IRTemp tmp = newTemp( Ity_V128 );;
   26683 
   26684                DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
   26685 
   26686                valid = unop( Iop_1Uto32, is_Zoned_decimal( vB, ps ) );
   26687 
   26688                assign( tmp,
   26689                        convert_from_zoned( vbi, mkexpr( vB ) ) );
   26690 
   26691                /* If the result of checking the lower 4 bits of each 8-bit
   26692                 * value is zero, then the "number" was zero.
   26693                 */
   26694                zero =
   26695                   binop( Iop_CmpEQ64,
   26696                   binop( Iop_Or64,
   26697                      binop( Iop_And64,
   26698                                           unop( Iop_V128to64, mkexpr( vB ) ),
   26699                                           mkU64( 0x0F0F0F0F0F0F0F0FULL ) ),
   26700                                    binop( Iop_And64,
   26701                                           unop( Iop_V128to64, mkexpr( vB ) ),
   26702                   mkU64( 0x0F0F0F0F0F0F0F0FULL ) ) ),
   26703                   mkU64( 0 ) );
   26704 
   26705                /* Sign bit is in bit 6 of vB. */
   26706                sign_digit = binop( Iop_And64, mkU64( 0xF0 ),
   26707                                    unop( Iop_V128to64,  mkexpr( vB ) ) );
   26708 
   26709                if ( ps == 0 ) {
   26710                   /* sign will be equal to 0 for positive number */
   26711                   sign = binop( Iop_CmpEQ64,
   26712                                 binop( Iop_And64,
   26713                                        sign_digit,
   26714                                        mkU64( 0x40 ) ),
   26715                                 mkU64( 0x40 ) );
   26716                } else {
   26717                   sign = mkOR1(
   26718                                binop( Iop_CmpEQ64, sign_digit, mkU64( 0xB0 ) ),
   26719                                binop( Iop_CmpEQ64, sign_digit, mkU64( 0xD0 ) ) );
   26720                }
   26721 
   26722                /* The negative value goes in the LT bit position of the
   26723                 * condition code register. Set neg if the sign of the
   26724                 * value is negative and the value is zero.
   26725                 */
   26726                neg = mkAND1( sign, mkNOT1( zero ) );
   26727 
   26728                /* The positive value goes in the GT bit position of the
   26729                 * condition code register. Set neg if the sign of the
   26730                 * value is not negative and the value is zero.
   26731                 */
   26732                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26733 
   26734                /* sign of the result is 0xC for positive, 0xD for negative */
   26735                putVReg( vRT_addr,
   26736                                binop( Iop_OrV128,
   26737                                       mkexpr( tmp ),
   26738                                       binop( Iop_64HLtoV128,
   26739                                              mkU64( 0 ),
   26740                                              binop( Iop_Or64,
   26741                                                     mkU64( 0xC ),
   26742                                                     unop( Iop_1Uto64, sign )
   26743                                                     ) ) ) );
   26744                /* For this instructions the LSB position in the CC
   26745                 * field, the overflow position in the other instructions,
   26746                 * is given by 0.  There is nothing to or with LT, EQ or GT.
   26747                 */
   26748                overflow = mkU1( 0 );
   26749             }
   26750             break;
   26751 
   26752          case 7:  // bcdcfn. (Decimal Convert From National VX-form)
   26753             {
   26754                IRTemp hword_7 = newTemp( Ity_I64 );
   26755                IRExpr *sign;
   26756                IRTemp tmp = newTemp( Ity_I64 );;
   26757 
   26758                DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
   26759 
   26760                /* check that the value is valid */
   26761                valid = unop( Iop_1Uto32, is_National_decimal( vB ) );
   26762 
   26763                assign( hword_7, binop( Iop_And64,
   26764                                        unop( Iop_V128to64, mkexpr( vB ) ),
   26765                                        mkU64( 0xFFF ) ) );
   26766                /* sign = 1 if vB is negative */
   26767                sign = binop( Iop_CmpEQ64, mkexpr( hword_7 ), mkU64( 0x002D ) );
   26768 
   26769                assign( tmp, convert_from_national( vbi, mkexpr( vB ) ) );
   26770 
   26771                /* If the result of checking the lower 4 bits of each 16-bit
   26772                 * value is zero, then the "number" was zero.
   26773                 */
   26774                zero =
   26775                   binop( Iop_CmpEQ64,
   26776                          binop( Iop_Or64,
   26777                                 binop( Iop_And64,
   26778                                        unop( Iop_V128HIto64, mkexpr( vB ) ),
   26779                                        mkU64( 0x000F000F000F000FULL ) ),
   26780                                 binop( Iop_And64,
   26781                                        unop( Iop_V128to64, mkexpr( vB ) ),
   26782                                        mkU64( 0x000F000F000F0000ULL ) ) ),
   26783                          mkU64( 0 ) );
   26784 
   26785 
   26786                /* The negative value goes in the LT bit position of the
   26787                 * condition code register. Set neg if the sign of the
   26788                * value is negative and the value is zero.
   26789                 */
   26790                neg = mkAND1( sign, mkNOT1( zero ) );
   26791 
   26792                /* The positive value goes in the GT bit position of the
   26793                 * condition code register. Set neg if the sign of the
   26794                 * value is not negative and the value is zero.
   26795                 */
   26796                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26797 
   26798                /* For this instructions the LSB position in the CC
   26799                 * field, the overflow position in the other instructions,
   26800                 * is given by invalid.  There is nothing to OR with the valid
   26801                 * flag.
   26802                 */
   26803                overflow = mkU1( 0 );
   26804 
   26805                /* sign of the result is:
   26806                   ( 0b1100 OR neg) OR (ps OR  (ps AND pos) << 1 )
   26807                */
   26808 
   26809                putVReg( vRT_addr,
   26810                         binop( Iop_64HLtoV128,
   26811                                mkU64( 0 ),
   26812                                binop( Iop_Or64,
   26813                                       binop( Iop_Or64,
   26814                                              binop( Iop_Shl64,
   26815                                                     binop( Iop_And64,
   26816                                                            mkU64( ps ),
   26817                                                            unop( Iop_1Uto64,
   26818                                                                  mkNOT1(sign))),
   26819                                                     mkU8( 1 ) ),
   26820                                              mkU64( ps ) ),
   26821                                       binop( Iop_Or64,
   26822                                              binop( Iop_Or64,
   26823                                                     mkU64( 0xC ),
   26824                                                     unop( Iop_1Uto64, sign ) ),
   26825                                              mkexpr( tmp ) ) ) ) );
   26826 
   26827             }
   26828             break;
   26829 
   26830          case 31:  // bcdsetsgn. (BCD set sign)
   26831             {
   26832                IRExpr *new_sign_val, *sign;
   26833 
   26834                DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
   26835 
   26836                value = binop( Iop_AndV128,
   26837                               binop( Iop_64HLtoV128,
   26838                                      mkU64( 0xFFFFFFFFFFFFFFFF ),
   26839                                      mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
   26840                               mkexpr( vB ) );
   26841                zero = BCDstring_zero( value );
   26842 
   26843                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
   26844                 * codes 0xB and 0xD are negative.
   26845                 */
   26846                sign_digit = binop( Iop_And64, mkU64( 0xF ),
   26847                                    unop( Iop_V128to64, mkexpr( vB ) ) );
   26848 
   26849                sign = mkOR1( binop( Iop_CmpEQ64,
   26850                                     sign_digit,
   26851                                     mkU64 ( 0xB ) ),
   26852                              binop( Iop_CmpEQ64,
   26853                                     sign_digit,
   26854                                     mkU64 ( 0xD ) ) );
   26855                neg = mkAND1( sign, mkNOT1( zero ) );
   26856 
   26857                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
   26858 
   26859                valid =
   26860                   unop( Iop_64to32,
   26861                         is_BCDstring128( vbi, /* Signed */True,
   26862                                          mkexpr( vB ) ) );
   26863 
   26864                /* if PS = 0
   26865                      vB positive, sign is C
   26866                      vB negative, sign is D
   26867                   if PS = 1
   26868                      vB positive, sign is F
   26869                      vB negative, sign is D
   26870                   Note can't use pos or neg here since they are ANDed with
   26871                   zero, use sign instead.
   26872                */
   26873                if (ps == 0) {
   26874                   new_sign_val = binop( Iop_Or64,
   26875                                         unop( Iop_1Uto64, sign ),
   26876                                         mkU64( 0xC ) );
   26877 
   26878                } else {
   26879                   new_sign_val = binop( Iop_Xor64,
   26880                                         binop( Iop_Shl64,
   26881                                                unop( Iop_1Uto64, sign ),
   26882                                                mkU8( 1 ) ),
   26883                                         mkU64( 0xF ) );
   26884                }
   26885 
   26886                putVReg( vRT_addr, binop( Iop_OrV128,
   26887                                          binop( Iop_64HLtoV128,
   26888                                                 mkU64( 0 ),
   26889                                                 new_sign_val ),
   26890                                          value ) );
   26891                /* For this instructions the LSB position in the CC
   26892                 * field, the overflow position in the other instructions,
   26893                 * is given by invalid.
   26894                 */
   26895                overflow = unop( Iop_32to1, unop( Iop_Not32, valid ) );
   26896             }
   26897             break;
   26898 
   26899          default:
   26900             vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
   26901             return False;
   26902          }
   26903       }
   26904       break;
   26905 
   26906    default:
   26907       vex_printf("dis_av_bcd(ppc)(opc2)\n");
   26908       return False;
   26909    }
   26910 
   26911    IRTemp valid_mask = newTemp( Ity_I32 );
   26912 
   26913    assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
   26914 
   26915    /* set CR field 6 to:
   26916     *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
   26917     *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
   26918     *    0b0010  if vB equals 0,
   26919     *    0b0001  if vB is invalid  over rules lt, gt, eq
   26920     */
   26921    assign( eq_lt_gt,
   26922            binop( Iop_Or32,
   26923                   binop( Iop_Shl32,
   26924                          unop( Iop_1Uto32, neg ),
   26925                          mkU8( 3 ) ),
   26926                   binop( Iop_Or32,
   26927                          binop( Iop_Shl32,
   26928                                 unop( Iop_1Uto32, pos ),
   26929                                 mkU8( 2 ) ),
   26930                          binop( Iop_Shl32,
   26931                                unop( Iop_1Uto32, zero ),
   26932                                 mkU8( 1 ) ) ) ) );
   26933    /* valid is 1 if it is a valid number, complement and put in the
   26934     * invalid bit location, overriding ls, eq, gt, overflow.
   26935     */
   26936    putGST_field( PPC_GST_CR,
   26937                  binop( Iop_Or32,
   26938                         binop( Iop_And32,
   26939                                mkexpr( valid_mask ),
   26940                                binop( Iop_Or32,
   26941                                       mkexpr( eq_lt_gt ),
   26942                                       unop( Iop_1Uto32, overflow ) ) ),
   26943                         binop( Iop_And32,
   26944                                unop( Iop_Not32, mkexpr( valid_mask ) ),
   26945                                mkU32( 1 ) ) ),
   26946                  6 );
   26947    return True;
   26948 }
   26949 
   26950 /*
   26951   AltiVec Floating Point Arithmetic Instructions
   26952 */
   26953 static Bool dis_av_fp_arith ( UInt theInstr )
   26954 {
   26955    /* VA-Form */
   26956    UChar opc1     = ifieldOPC(theInstr);
   26957    UChar vD_addr  = ifieldRegDS(theInstr);
   26958    UChar vA_addr  = ifieldRegA(theInstr);
   26959    UChar vB_addr  = ifieldRegB(theInstr);
   26960    UChar vC_addr  = ifieldRegC(theInstr);
   26961    UInt  opc2=0;
   26962 
   26963    IRTemp vA = newTemp(Ity_V128);
   26964    IRTemp vB = newTemp(Ity_V128);
   26965    IRTemp vC = newTemp(Ity_V128);
   26966    assign( vA, getVReg(vA_addr));
   26967    assign( vB, getVReg(vB_addr));
   26968    assign( vC, getVReg(vC_addr));
   26969 
   26970    if (opc1 != 0x4) {
   26971       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   26972       return False;
   26973    }
   26974 
   26975    IRTemp rm = newTemp(Ity_I32);
   26976    assign(rm, get_IR_roundingmode());
   26977 
   26978    opc2 = IFIELD( theInstr, 0, 6 );
   26979    switch (opc2) {
   26980    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   26981       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   26982           vD_addr, vA_addr, vC_addr, vB_addr);
   26983       putVReg( vD_addr,
   26984                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
   26985                      mkexpr(vB),
   26986                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   26987                            mkexpr(vA), mkexpr(vC))) );
   26988       return True;
   26989 
   26990    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   26991       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   26992           vD_addr, vA_addr, vC_addr, vB_addr);
   26993       putVReg( vD_addr,
   26994                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   26995                      mkexpr(vB),
   26996                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   26997                            mkexpr(vA), mkexpr(vC))) );
   26998       return True;
   26999    }
   27000 
   27001    default:
   27002      break; // Fall through...
   27003    }
   27004 
   27005    opc2 = IFIELD( theInstr, 0, 11 );
   27006    switch (opc2) {
   27007    case 0x00A: // vaddfp (Add FP, AV p137)
   27008       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   27009       putVReg( vD_addr, triop(Iop_Add32Fx4,
   27010                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   27011       return True;
   27012 
   27013   case 0x04A: // vsubfp (Subtract FP, AV p261)
   27014       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   27015       putVReg( vD_addr, triop(Iop_Sub32Fx4,
   27016                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   27017       return True;
   27018 
   27019    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   27020       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   27021       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   27022       return True;
   27023 
   27024    case 0x44A: // vminfp (Minimum FP, AV p187)
   27025       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   27026       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   27027       return True;
   27028 
   27029    default:
   27030       break; // Fall through...
   27031    }
   27032 
   27033 
   27034    if (vA_addr != 0) {
   27035       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   27036       return False;
   27037    }
   27038 
   27039    switch (opc2) {
   27040    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   27041       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   27042       putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
   27043       return True;
   27044 
   27045    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   27046       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   27047       putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
   27048       return True;
   27049 
   27050    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   27051       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   27052       DIP(" => not implemented\n");
   27053       return False;
   27054 
   27055    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   27056       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   27057       DIP(" => not implemented\n");
   27058       return False;
   27059 
   27060    default:
   27061       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   27062       return False;
   27063    }
   27064    return True;
   27065 }
   27066 
   27067 /*
   27068   AltiVec Floating Point Compare Instructions
   27069 */
   27070 static Bool dis_av_fp_cmp ( UInt theInstr )
   27071 {
   27072    /* VXR-Form */
   27073    UChar opc1     = ifieldOPC(theInstr);
   27074    UChar vD_addr  = ifieldRegDS(theInstr);
   27075    UChar vA_addr  = ifieldRegA(theInstr);
   27076    UChar vB_addr  = ifieldRegB(theInstr);
   27077    UChar flag_rC  = ifieldBIT10(theInstr);
   27078    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   27079 
   27080    Bool cmp_bounds = False;
   27081 
   27082    IRTemp vA = newTemp(Ity_V128);
   27083    IRTemp vB = newTemp(Ity_V128);
   27084    IRTemp vD = newTemp(Ity_V128);
   27085    assign( vA, getVReg(vA_addr));
   27086    assign( vB, getVReg(vB_addr));
   27087 
   27088    if (opc1 != 0x4) {
   27089       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   27090       return False;
   27091    }
   27092 
   27093    switch (opc2) {
   27094    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   27095       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   27096                                       vD_addr, vA_addr, vB_addr);
   27097       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   27098       break;
   27099 
   27100    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   27101       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   27102                                       vD_addr, vA_addr, vB_addr);
   27103       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   27104       break;
   27105 
   27106    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   27107       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   27108                                       vD_addr, vA_addr, vB_addr);
   27109       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   27110       break;
   27111 
   27112    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   27113       IRTemp gt      = newTemp(Ity_V128);
   27114       IRTemp lt      = newTemp(Ity_V128);
   27115       IRTemp zeros   = newTemp(Ity_V128);
   27116       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   27117                                      vD_addr, vA_addr, vB_addr);
   27118       cmp_bounds = True;
   27119       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   27120 
   27121       /* Note: making use of fact that the ppc backend for compare insns
   27122          return zero'd lanes if either of the corresponding arg lanes is
   27123          a nan.
   27124 
   27125          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   27126          need this for the other compares too (vcmpeqfp etc)...
   27127          Better still, tighten down the spec for compare irops.
   27128        */
   27129       assign( gt, unop(Iop_NotV128,
   27130                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   27131       assign( lt, unop(Iop_NotV128,
   27132                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   27133                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   27134                                    mkexpr(zeros),
   27135                                    mkexpr(vB)))) );
   27136 
   27137       // finally, just shift gt,lt to correct position
   27138       assign( vD, binop(Iop_ShlN32x4,
   27139                         binop(Iop_OrV128,
   27140                               binop(Iop_AndV128, mkexpr(gt),
   27141                                     unop(Iop_Dup32x4, mkU32(0x2))),
   27142                               binop(Iop_AndV128, mkexpr(lt),
   27143                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   27144                         mkU8(30)) );
   27145       break;
   27146    }
   27147 
   27148    default:
   27149       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   27150       return False;
   27151    }
   27152 
   27153    putVReg( vD_addr, mkexpr(vD) );
   27154 
   27155    if (flag_rC) {
   27156       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   27157    }
   27158    return True;
   27159 }
   27160 
   27161 /*
   27162   AltiVec Floating Point Convert/Round Instructions
   27163 */
   27164 static Bool dis_av_fp_convert ( UInt theInstr )
   27165 {
   27166    /* VX-Form */
   27167    UChar opc1     = ifieldOPC(theInstr);
   27168    UChar vD_addr  = ifieldRegDS(theInstr);
   27169    UChar UIMM_5   = ifieldRegA(theInstr);
   27170    UChar vB_addr  = ifieldRegB(theInstr);
   27171    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   27172 
   27173    IRTemp vB        = newTemp(Ity_V128);
   27174    IRTemp vScale    = newTemp(Ity_V128);
   27175    IRTemp vInvScale = newTemp(Ity_V128);
   27176 
   27177    float scale, inv_scale;
   27178 
   27179    assign( vB, getVReg(vB_addr));
   27180 
   27181    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   27182    scale = (float)( (unsigned int) 1<<UIMM_5 );
   27183    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   27184    inv_scale = 1/scale;
   27185    assign( vInvScale,
   27186            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   27187 
   27188    if (opc1 != 0x4) {
   27189       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   27190       return False;
   27191    }
   27192 
   27193    switch (opc2) {
   27194    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   27195       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   27196       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   27197                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   27198                               mkexpr(vInvScale)) );
   27199       return True;
   27200 
   27201    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   27202       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   27203 
   27204       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   27205                               unop(Iop_I32StoFx4, mkexpr(vB)),
   27206                               mkexpr(vInvScale)) );
   27207       return True;
   27208 
   27209    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   27210       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   27211       putVReg( vD_addr,
   27212                unop(Iop_QFtoI32Ux4_RZ,
   27213                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   27214                           mkexpr(vB), mkexpr(vScale))) );
   27215       return True;
   27216 
   27217    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   27218       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   27219       putVReg( vD_addr,
   27220                unop(Iop_QFtoI32Sx4_RZ,
   27221                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   27222                            mkexpr(vB), mkexpr(vScale))) );
   27223       return True;
   27224 
   27225    default:
   27226      break;    // Fall through...
   27227    }
   27228 
   27229    if (UIMM_5 != 0) {
   27230       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   27231       return False;
   27232    }
   27233 
   27234    switch (opc2) {
   27235    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   27236       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   27237       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   27238       break;
   27239 
   27240    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   27241       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   27242       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   27243       break;
   27244 
   27245    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   27246       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   27247       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   27248       break;
   27249 
   27250    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   27251       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   27252       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   27253       break;
   27254 
   27255    default:
   27256       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   27257       return False;
   27258    }
   27259    return True;
   27260 }
   27261 
   27262 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
   27263                                        const VexAbiInfo* vbi,
   27264                                        /*OUT*/DisResult* dres,
   27265                                        Bool (*resteerOkFn)(void*,Addr),
   27266                                        void* callback_opaque )
   27267 {
   27268    UInt   opc2      = IFIELD( theInstr, 1, 10 );
   27269 
   27270    switch (opc2) {
   27271    case 0x28E: {        //tbegin.
   27272       /* The current implementation is to just fail the tbegin and execute
   27273        * the failure path.  The failure path is assumed to be functionaly
   27274        * equivalent to the transactional path with the needed data locking
   27275        * to ensure correctness.  The tend is just a noop and shouldn't
   27276        * actually get executed.
   27277        *   1) set cr0 to 0x2
   27278        *   2) Initialize TFHAR to CIA+4
   27279        *   3) Initialize TEXASR
   27280        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
   27281        *   5) Continue executing at the next instruction.
   27282        */
   27283       UInt R = IFIELD( theInstr, 21, 1 );
   27284 
   27285       ULong tm_reason;
   27286       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
   27287                                * or treclaim.
   27288                                */
   27289       UInt persistant = 1;    /* set persistant since we are always failing
   27290                                * the tbegin.
   27291                                */
   27292       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
   27293                                  as the reason for failing the trasaction */
   27294       UInt tm_exact   = 1;    /* have exact address for failure */
   27295 
   27296       DIP("tbegin. %u\n", R);
   27297 
   27298       /* Set the CR0 field to indicate the tbegin failed.  Then let
   27299        * the code do the branch to the failure path.
   27300        *
   27301        * 000 || 0  Transaction initiation successful,
   27302        *           unnested (Transaction state of
   27303        *           Non-transactional prior to tbegin.)
   27304        * 010 || 0  Transaction initiation successful, nested
   27305        *           (Transaction state of Transactional
   27306        *           prior to tbegin.)
   27307        * 001 || 0  Transaction initiation unsuccessful,
   27308        *           (Transaction state of Suspended prior
   27309        *           to tbegin.)
   27310        */
   27311       putCR321( 0, mkU8( 0x2 ) );
   27312 
   27313       tm_reason = generate_TMreason( failure_code, persistant,
   27314                                      nest_overflow, tm_exact );
   27315 
   27316       storeTMfailure( guest_CIA_curr_instr, tm_reason,
   27317                       guest_CIA_curr_instr+4 );
   27318 
   27319       return True;
   27320 
   27321       break;
   27322    }
   27323 
   27324    case 0x2AE: {        //tend.
   27325       /* The tend. is just a noop.  Do nothing */
   27326       UInt A = IFIELD( theInstr, 25, 1 );
   27327 
   27328       DIP("tend. %u\n", A);
   27329       break;
   27330    }
   27331 
   27332    case 0x2EE: {        //tsr.
   27333       /* The tsr. is just a noop.  Do nothing */
   27334       UInt L = IFIELD( theInstr, 21, 1 );
   27335 
   27336       DIP("tsr. %u\n", L);
   27337       break;
   27338    }
   27339 
   27340    case 0x2CE: {        //tcheck.
   27341       /* The tcheck. is just a noop.  Do nothing */
   27342       UInt BF = IFIELD( theInstr, 25, 1 );
   27343 
   27344       DIP("tcheck. %u\n", BF);
   27345       break;
   27346    }
   27347 
   27348    case 0x30E: {        //tbortwc.
   27349       /* The tabortwc. is just a noop.  Do nothing */
   27350       UInt TO = IFIELD( theInstr, 25, 1 );
   27351       UInt RA = IFIELD( theInstr, 16, 5 );
   27352       UInt RB = IFIELD( theInstr, 11, 5 );
   27353 
   27354       DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
   27355       break;
   27356    }
   27357 
   27358    case 0x32E: {        //tbortdc.
   27359       /* The tabortdc. is just a noop.  Do nothing */
   27360       UInt TO = IFIELD( theInstr, 25, 1 );
   27361       UInt RA = IFIELD( theInstr, 16, 5 );
   27362       UInt RB = IFIELD( theInstr, 11, 5 );
   27363 
   27364       DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
   27365       break;
   27366    }
   27367 
   27368    case 0x34E: {        //tbortwci.
   27369       /* The tabortwci. is just a noop.  Do nothing */
   27370       UInt TO = IFIELD( theInstr, 25, 1 );
   27371       UInt RA = IFIELD( theInstr, 16, 5 );
   27372       UInt SI = IFIELD( theInstr, 11, 5 );
   27373 
   27374       DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
   27375       break;
   27376    }
   27377 
   27378    case 0x36E: {        //tbortdci.
   27379       /* The tabortdci. is just a noop.  Do nothing */
   27380       UInt TO = IFIELD( theInstr, 25, 1 );
   27381       UInt RA = IFIELD( theInstr, 16, 5 );
   27382       UInt SI = IFIELD( theInstr, 11, 5 );
   27383 
   27384       DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
   27385       break;
   27386    }
   27387 
   27388    case 0x38E: {        //tbort.
   27389       /* The tabort. is just a noop.  Do nothing */
   27390       UInt RA = IFIELD( theInstr, 16, 5 );
   27391 
   27392       DIP("tabort. %u\n", RA);
   27393       break;
   27394    }
   27395 
   27396    case 0x3AE: {        //treclaim.
   27397       /* The treclaim. is just a noop.  Do nothing */
   27398       UInt RA = IFIELD( theInstr, 16, 5 );
   27399 
   27400       DIP("treclaim. %u\n", RA);
   27401       break;
   27402    }
   27403 
   27404    case 0x3EE: {        //trechkpt.
   27405       /* The trechkpt. is just a noop.  Do nothing */
   27406       DIP("trechkpt.\n");
   27407       break;
   27408    }
   27409 
   27410    default:
   27411       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
   27412       return False;
   27413    }
   27414 
   27415    return True;
   27416 }
   27417 
   27418 
   27419 /* The 0x3C primary opcode (VSX category) uses several different forms of
   27420  * extended opcodes:
   27421  *   o XX2-form:
   27422  *      - [10:2] (IBM notation [21:29])
   27423  *   o XX3-form variants:
   27424  *       - variant 1: [10:3] (IBM notation [21:28])
   27425  *       - variant 2: [9:3] (IBM notation [22:28])
   27426  *       - variant 3: [7:3] (IBM notation [24:28])
   27427  *   o XX-4 form:
   27428  *      - [10:6] (IBM notation [21:25])
   27429  *
   27430  * The XX2-form needs bit 0 masked from the standard extended opcode
   27431  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   27432  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   27433  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   27434  * front end since their encoding does not begin at bit 21 like the standard
   27435  * format.
   27436  *
   27437  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   27438  * secondary opcode for such VSX instructions.
   27439  *
   27440 */
   27441 
   27442 
   27443 struct vsx_insn {
   27444    UInt opcode;
   27445    const HChar * name;
   27446 };
   27447 
   27448 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   27449 static struct vsx_insn vsx_xx2[] = {
   27450       { 0x14, "xsrsqrtesp" },
   27451       { 0x16, "xssqrtsp" },
   27452       { 0x18, "xxsel" },
   27453       { 0x34, "xsresp" },
   27454       { 0x90, "xscvdpuxws" },
   27455       { 0x92, "xsrdpi" },
   27456       { 0x94, "xsrsqrtedp" },
   27457       { 0x96, "xssqrtdp" },
   27458       { 0xb0, "xscvdpsxws" },
   27459       { 0xb2, "xsrdpiz" },
   27460       { 0xb4, "xsredp" },
   27461       { 0xd2, "xsrdpip" },
   27462       { 0xd4, "xstsqrtdp" },
   27463       { 0xd6, "xsrdpic" },
   27464       { 0xf2, "xsrdpim" },
   27465       { 0x112, "xvrspi" },
   27466       { 0x116, "xvsqrtsp" },
   27467       { 0x130, "xvcvspsxws" },
   27468       { 0x132, "xvrspiz" },
   27469       { 0x134, "xvresp" },
   27470       { 0x148, "xxspltw" },
   27471       { 0x14A, "xxextractuw" },
   27472       { 0x150, "xvcvuxwsp" },
   27473       { 0x152, "xvrspip" },
   27474       { 0x154, "xvtsqrtsp" },
   27475       { 0x156, "xvrspic" },
   27476       { 0x16A, "xxinsertw" },
   27477       { 0x170, "xvcvsxwsp" },
   27478       { 0x172, "xvrspim" },
   27479       { 0x190, "xvcvdpuxws" },
   27480       { 0x192, "xvrdpi" },
   27481       { 0x194, "xvrsqrtedp" },
   27482       { 0x196, "xvsqrtdp" },
   27483       { 0x1b0, "xvcvdpsxws" },
   27484       { 0x1b2, "xvrdpiz" },
   27485       { 0x1b4, "xvredp" },
   27486       { 0x1d0, "xvcvuxwdp" },
   27487       { 0x1d2, "xvrdpip" },
   27488       { 0x1d4, "xvtsqrtdp" },
   27489       { 0x1d6, "xvrdpic" },
   27490       { 0x1f0, "xvcvsxwdp" },
   27491       { 0x1f2, "xvrdpim" },
   27492       { 0x212, "xscvdpsp" },
   27493       { 0x216, "xscvdpspn" },
   27494       { 0x232, "xxrsp" },
   27495       { 0x250, "xscvuxdsp" },
   27496       { 0x254, "xststdcsp" },
   27497       { 0x270, "xscvsxdsp" },
   27498       { 0x290, "xscvdpuxds" },
   27499       { 0x292, "xscvspdp" },
   27500       { 0x296, "xscvspdpn" },
   27501       { 0x2b0, "xscvdpsxds" },
   27502       { 0x2b2, "xsabsdp" },
   27503       { 0x2b6, "xsxexpdp_xsxigdp" },
   27504       { 0x2d0, "xscvuxddp" },
   27505       { 0x2d2, "xsnabsdp" },
   27506       { 0x2d4, "xststdcdp" },
   27507       { 0x2e4, "xsnmsubmdp" },
   27508       { 0x2f0, "xscvsxddp" },
   27509       { 0x2f2, "xsnegdp" },
   27510       { 0x310, "xvcvspuxds" },
   27511       { 0x312, "xvcvdpsp" },
   27512       { 0x330, "xvcvspsxds" },
   27513       { 0x332, "xvabssp" },
   27514       { 0x350, "xvcvuxdsp" },
   27515       { 0x352, "xvnabssp" },
   27516       { 0x370, "xvcvsxdsp" },
   27517       { 0x372, "xvnegsp" },
   27518       { 0x390, "xvcvdpuxds" },
   27519       { 0x392, "xvcvspdp" },
   27520       { 0x3b0, "xvcvdpsxds" },
   27521       { 0x3b2, "xvabsdp" },
   27522       { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp" },
   27523       { 0x3d0, "xvcvuxddp" },
   27524       { 0x3d2, "xvnabsdp" },
   27525       { 0x3f2, "xvnegdp" }
   27526 };
   27527 #define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2)
   27528 
   27529 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   27530 static struct vsx_insn vsx_xx3[] = {
   27531       { 0x0,  "xsaddsp" },
   27532       { 0x4,  "xsmaddasp" },
   27533       { 0x9,  "xsmaddmsp" },
   27534       { 0x20, "xssubsp" },
   27535       { 0x24, "xsmaddmsp" },
   27536       { 0x3A, "xxpermr" },
   27537       { 0x40, "xsmulsp" },
   27538       { 0x44, "xsmsubasp" },
   27539       { 0x48, "xxmrghw" },
   27540       { 0x60, "xsdivsp" },
   27541       { 0x64, "xsmsubmsp" },
   27542       { 0x68, "xxperm" },
   27543       { 0x80, "xsadddp" },
   27544       { 0x84, "xsmaddadp" },
   27545       { 0x8c, "xscmpudp" },
   27546       { 0xa0, "xssubdp" },
   27547       { 0xa4, "xsmaddmdp" },
   27548       { 0xac, "xscmpodp" },
   27549       { 0xc0, "xsmuldp" },
   27550       { 0xc4, "xsmsubadp" },
   27551       { 0xc8, "xxmrglw" },
   27552       { 0xd4, "xstsqrtdp" },
   27553       { 0xe0, "xsdivdp" },
   27554       { 0xe4, "xsmsubmdp" },
   27555       { 0xe8, "xxpermr" },
   27556       { 0xeC, "xscmpexpdp" },
   27557       { 0xf4, "xstdivdp" },
   27558       { 0x100, "xvaddsp" },
   27559       { 0x104, "xvmaddasp" },
   27560       { 0x10C, "xvcmpeqsp" },
   27561       { 0x110, "xvcvspuxws" },
   27562       { 0x114, "xvrsqrtesp" },
   27563       { 0x120, "xvsubsp" },
   27564       { 0x124, "xvmaddmsp" },
   27565       { 0x130, "xvcvspsxws" },
   27566       { 0x140, "xvmulsp" },
   27567       { 0x144, "xvmsubasp" },
   27568       { 0x14C, "xvcmpgesp", },
   27569       { 0x160, "xvdivsp" },
   27570       { 0x164, "xvmsubmsp" },
   27571       { 0x174, "xvtdivsp" },
   27572       { 0x180, "xvadddp" },
   27573       { 0x184, "xvmaddadp" },
   27574       { 0x18C, "xvcmpeqdp" },
   27575       { 0x1a0, "xvsubdp" },
   27576       { 0x1a4, "xvmaddmdp" },
   27577       { 0x1aC, "xvcmpgtdp" },
   27578       { 0x1c0, "xvmuldp" },
   27579       { 0x1c4, "xvmsubadp" },
   27580       { 0x1cc, "xvcmpgedp" },
   27581       { 0x1e0, "xvdivdp" },
   27582       { 0x1e4, "xvmsubmdp" },
   27583       { 0x1f4, "xvtdivdp" },
   27584       { 0x204, "xsnmaddasp" },
   27585       { 0x208, "xxland" },
   27586       { 0x224, "xsnmaddmsp" },
   27587       { 0x228, "xxlandc" },
   27588       { 0x244, "xsnmsubasp" },
   27589       { 0x248, "xxlor" },
   27590       { 0x264, "xsnmsubmsp" },
   27591       { 0x268, "xxlxor" },
   27592       { 0x280, "xsmaxdp" },
   27593       { 0x284, "xsnmaddadp" },
   27594       { 0x288, "xxlnor" },
   27595       { 0x2a0, "xsmindp" },
   27596       { 0x2a4, "xsnmaddmdp" },
   27597       { 0x2a8, "xxlorc" },
   27598       { 0x2c0, "xscpsgndp" },
   27599       { 0x2c4, "xsnmsubadp" },
   27600       { 0x2c8, "xxlnand" },
   27601       { 0x2e4, "xsnmsubmdp" },
   27602       { 0x2e8, "xxleqv" },
   27603       { 0x300, "xvmaxsp" },
   27604       { 0x304, "xvnmaddasp" },
   27605       { 0x320, "xvminsp" },
   27606       { 0x324, "xvnmaddmsp" },
   27607       { 0x340, "xvcpsgnsp" },
   27608       { 0x344, "xvnmsubasp" },
   27609       { 0x360, "xviexpsp" },
   27610       { 0x364, "xvnmsubmsp" },
   27611       { 0x380, "xvmaxdp" },
   27612       { 0x384, "xvnmaddadp" },
   27613       { 0x3a0, "xvmindp" },
   27614       { 0x3a4, "xvnmaddmdp" },
   27615       { 0x3c0, "xvcpsgndp" },
   27616       { 0x3c4, "xvnmsubadp" },
   27617       { 0x3e0, "xviexpdp" },
   27618       { 0x3e4, "xvnmsubmdp" },
   27619       { 0x3f0, "xvcvsxddp" },
   27620 };
   27621 #define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3)
   27622 
   27623 
   27624 /* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays
   27625  * are sorted.
   27626  */
   27627 static Int findVSXextOpCode_xx2(UInt opcode)
   27628 {
   27629    Int low, mid, high;
   27630    low = 0;
   27631    high = VSX_XX2_LEN - 1;
   27632    while (low <= high) {
   27633       mid = (low + high)/2;
   27634       if (opcode < vsx_xx2[mid].opcode)
   27635          high = mid - 1;
   27636       else if (opcode > vsx_xx2[mid].opcode)
   27637          low = mid + 1;
   27638       else
   27639          return mid;
   27640    }
   27641    return -1;
   27642 }
   27643 
   27644 static Int findVSXextOpCode_xx3(UInt opcode)
   27645 {
   27646    Int low, mid, high;
   27647    low = 0;
   27648    high = VSX_XX3_LEN - 1;
   27649    while (low <= high) {
   27650       mid = (low + high)/2;
   27651       if (opcode < vsx_xx3[mid].opcode)
   27652          high = mid - 1;
   27653       else if (opcode > vsx_xx3[mid].opcode)
   27654          low = mid + 1;
   27655       else
   27656          return mid;
   27657    }
   27658    return -1;
   27659 }
   27660 
   27661 
   27662 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   27663  * passed, and we then try to match it up with one of the VSX forms
   27664  * below.
   27665  */
   27666 static UInt get_VSX60_opc2(UInt opc2_full, UInt theInstr)
   27667 {
   27668 #define XX2_1_MASK 0x000003FF    // xsiexpdp specific
   27669 #define XX2_2_MASK 0x000003FE
   27670 #define XX3_1_MASK 0x000003FC
   27671 #define XX3_2_MASK 0x000001FC
   27672 #define XX3_4_MASK 0x0000027C
   27673 #define XX3_5_MASK 0x000003DC
   27674 #define XX4_MASK   0x00000018
   27675 
   27676    Int ret;
   27677    UInt vsxExtOpcode = 0;
   27678 
   27679    if (( ret = findVSXextOpCode_xx2(opc2_full & XX2_2_MASK)) >= 0)
   27680       return vsx_xx2[ret].opcode;
   27681    else if ((opc2_full & XX2_1_MASK) == 0x396 )   // xsiexpdp
   27682       return 0x396;
   27683    else if (( ret = findVSXextOpCode_xx3(opc2_full & XX3_1_MASK)) >= 0)
   27684       return vsx_xx3[ret].opcode;
   27685    else {
   27686 
   27687       /* There are only a few codes in each of these cases it is
   27688        * probably faster to check for the codes then do the array lookups.
   27689        */
   27690       vsxExtOpcode = opc2_full & XX3_2_MASK;
   27691 
   27692       switch (vsxExtOpcode) {
   27693       case 0x10C: return vsxExtOpcode;   // xvcmpeqsp
   27694       case 0x12C: return vsxExtOpcode;   // xvcmpgtsp, xvcmpgtsp.
   27695       case 0x14C: return vsxExtOpcode;   // xvcmpgesp, xvcmpgesp.
   27696       case 0x18C: return vsxExtOpcode;   // xvcmpeqdp, xvcmpeqdp.
   27697       case 0x1AC: return vsxExtOpcode;   // xvcmpgtdp, xvcmpgtdp.
   27698       case 0x1CC: return vsxExtOpcode;   // xvcmpgedp, xvcmpgedp.
   27699       default:  break;
   27700       }
   27701 
   27702       vsxExtOpcode = opc2_full & XX3_4_MASK;
   27703 
   27704       switch (vsxExtOpcode) {
   27705       case 0x8:   return vsxExtOpcode;   // xxsldwi
   27706       case 0x28:  return vsxExtOpcode;   // xxpermdi
   27707       default:  break;
   27708       }
   27709 
   27710       vsxExtOpcode = opc2_full & XX3_5_MASK;
   27711 
   27712       switch (vsxExtOpcode) {
   27713       case 0x354:  return vsxExtOpcode;   // xvtstdcsp
   27714       case 0x3D4:  return vsxExtOpcode;   // xvtstdcdp
   27715       default:  break;
   27716       }
   27717 
   27718       if (( opc2_full & XX4_MASK ) == XX4_MASK ) {   // xxsel
   27719          vsxExtOpcode = 0x18;
   27720          return vsxExtOpcode;
   27721       }
   27722    }
   27723 
   27724    vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n",
   27725                opc2_full, theInstr );
   27726    vpanic( "ERROR: get_VSX60_opc2()\n" );
   27727    return 0;
   27728 }
   27729 
   27730 /*------------------------------------------------------------*/
   27731 /*--- Disassemble a single instruction                     ---*/
   27732 /*------------------------------------------------------------*/
   27733 
   27734 /* Disassemble a single instruction into IR.  The instruction
   27735    is located in host memory at &guest_code[delta]. */
   27736 
   27737 static
   27738 DisResult disInstr_PPC_WRK (
   27739              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
   27740              Bool         resteerCisOk,
   27741              void*        callback_opaque,
   27742              Long         delta64,
   27743              const VexArchInfo* archinfo,
   27744              const VexAbiInfo*  abiinfo,
   27745              Bool         sigill_diag
   27746           )
   27747 {
   27748    UChar     opc1;
   27749    UInt      opc2;
   27750    DisResult dres;
   27751    UInt      theInstr;
   27752    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   27753    UInt      hwcaps = archinfo->hwcaps;
   27754    Long      delta;
   27755    Bool      allow_F  = False;
   27756    Bool      allow_V  = False;
   27757    Bool      allow_FX = False;
   27758    Bool      allow_GX = False;
   27759    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   27760    Bool      allow_DFP = False;
   27761    Bool      allow_isa_2_07 = False;
   27762    Bool      allow_isa_3_0  = False;
   27763 
   27764    /* What insn variants are we supporting today? */
   27765    if (mode64) {
   27766       allow_F  = True;
   27767       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   27768       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   27769       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   27770       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   27771       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
   27772       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
   27773       allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_0));
   27774    } else {
   27775       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   27776       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   27777       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   27778       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   27779       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   27780       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
   27781       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
   27782       allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_0));
   27783    }
   27784 
   27785    /* Enable writting the OV32 and CA32 bits added with ISA3.0 */
   27786    OV32_CA32_supported = allow_isa_3_0;
   27787 
   27788    /* The running delta */
   27789    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   27790 
   27791    /* Set result defaults. */
   27792    dres.whatNext    = Dis_Continue;
   27793    dres.len         = 0;
   27794    dres.continueAt  = 0;
   27795    dres.jk_StopHere = Ijk_INVALID;
   27796    dres.hint        = Dis_HintNone;
   27797 
   27798    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   27799       4-aligned.  So just fish the whole thing out of memory right now
   27800       and have done. */
   27801    theInstr = getUIntPPCendianly( &guest_code[delta] );
   27802 
   27803    if (0) vex_printf("insn: 0x%x\n", theInstr);
   27804 
   27805    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   27806 
   27807    /* Spot "Special" instructions (see comment at top of file). */
   27808    {
   27809       const UChar* code = guest_code + delta;
   27810       /* Spot the 16-byte preamble:
   27811          32-bit mode:
   27812             5400183E  rlwinm 0,0,3,0,31
   27813             5400683E  rlwinm 0,0,13,0,31
   27814             5400E83E  rlwinm 0,0,29,0,31
   27815             5400983E  rlwinm 0,0,19,0,31
   27816          64-bit mode:
   27817             78001800  rotldi 0,0,3
   27818             78006800  rotldi 0,0,13
   27819             7800E802  rotldi 0,0,61
   27820             78009802  rotldi 0,0,51
   27821       */
   27822       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
   27823       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
   27824       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
   27825       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
   27826       Bool is_special_preamble = False;
   27827       if (getUIntPPCendianly(code+ 0) == word1 &&
   27828           getUIntPPCendianly(code+ 4) == word2 &&
   27829           getUIntPPCendianly(code+ 8) == word3 &&
   27830           getUIntPPCendianly(code+12) == word4) {
   27831          is_special_preamble = True;
   27832       } else if (! mode64 &&
   27833                  getUIntPPCendianly(code+ 0) == 0x54001800 &&
   27834                  getUIntPPCendianly(code+ 4) == 0x54006800 &&
   27835                  getUIntPPCendianly(code+ 8) == 0x5400E800 &&
   27836                  getUIntPPCendianly(code+12) == 0x54009800) {
   27837          static Bool reported = False;
   27838          if (!reported) {
   27839             vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
   27840             vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
   27841             reported = True;
   27842          }
   27843          is_special_preamble = True;
   27844       }
   27845       if (is_special_preamble) {
   27846          /* Got a "Special" instruction preamble.  Which one is it? */
   27847          if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   27848             /* %R3 = client_request ( %R4 ) */
   27849             DIP("r3 = client_request ( %%r4 )\n");
   27850             delta += 20;
   27851             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   27852             dres.jk_StopHere = Ijk_ClientReq;
   27853             dres.whatNext    = Dis_StopHere;
   27854             goto decode_success;
   27855          }
   27856          else
   27857          if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   27858             /* %R3 = guest_NRADDR */
   27859             DIP("r3 = guest_NRADDR\n");
   27860             delta += 20;
   27861             dres.len = 20;
   27862             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   27863             goto decode_success;
   27864          }
   27865          else
   27866          if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   27867             delta += 20;
   27868             if (host_endness == VexEndnessLE) {
   27869                 /*  branch-and-link-to-noredir %R12 */
   27870                 DIP("branch-and-link-to-noredir r12\n");
   27871                 putGST( PPC_GST_LR,
   27872                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   27873                 putGST( PPC_GST_CIA, getIReg(12));
   27874             } else {
   27875                 /*  branch-and-link-to-noredir %R11 */
   27876                 DIP("branch-and-link-to-noredir r11\n");
   27877                 putGST( PPC_GST_LR,
   27878                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   27879                 putGST( PPC_GST_CIA, getIReg(11));
   27880             }
   27881             dres.jk_StopHere = Ijk_NoRedir;
   27882             dres.whatNext    = Dis_StopHere;
   27883             goto decode_success;
   27884          }
   27885          else
   27886          if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   27887             /* %R3 = guest_NRADDR_GPR2 */
   27888             DIP("r3 = guest_NRADDR_GPR2\n");
   27889             delta += 20;
   27890             dres.len = 20;
   27891             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   27892             goto decode_success;
   27893          }
   27894          else
   27895          if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
   27896             DIP("IR injection\n");
   27897             if (host_endness == VexEndnessBE)
   27898                vex_inject_ir(irsb, Iend_BE);
   27899             else
   27900                vex_inject_ir(irsb, Iend_LE);
   27901 
   27902             delta += 20;
   27903             dres.len = 20;
   27904 
   27905             // Invalidate the current insn. The reason is that the IRop we're
   27906             // injecting here can change. In which case the translation has to
   27907             // be redone. For ease of handling, we simply invalidate all the
   27908             // time.
   27909 
   27910             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
   27911             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
   27912 
   27913             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   27914             dres.whatNext    = Dis_StopHere;
   27915             dres.jk_StopHere = Ijk_InvalICache;
   27916             goto decode_success;
   27917          }
   27918          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   27919             can print the insn following the Special-insn preamble. */
   27920          theInstr = getUIntPPCendianly(code+16);
   27921          opc1     = ifieldOPC(theInstr);
   27922          opc2     = ifieldOPClo10(theInstr);
   27923          goto decode_failure;
   27924          /*NOTREACHED*/
   27925       }
   27926    }
   27927 
   27928    opc1 = ifieldOPC(theInstr);
   27929    opc2 = ifieldOPClo10(theInstr);
   27930 
   27931    // Note: all 'reserved' bits must be cleared, else invalid
   27932    switch (opc1) {
   27933 
   27934    /* Integer Arithmetic Instructions */
   27935    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   27936    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   27937       if (dis_int_arith( theInstr )) goto decode_success;
   27938       goto decode_failure;
   27939 
   27940    /* Integer Compare Instructions */
   27941    case 0x0B: case 0x0A: // cmpi, cmpli
   27942       if (dis_int_cmp( theInstr )) goto decode_success;
   27943       goto decode_failure;
   27944 
   27945    /* Integer Logical Instructions */
   27946    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   27947    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   27948       if (dis_int_logic( theInstr )) goto decode_success;
   27949       goto decode_failure;
   27950 
   27951    /* Integer Rotate Instructions */
   27952    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   27953       if (dis_int_rot( theInstr )) goto decode_success;
   27954       goto decode_failure;
   27955 
   27956    /* 64bit Integer Rotate Instructions */
   27957    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   27958       if (!mode64) goto decode_failure;
   27959       if (dis_int_rot( theInstr )) goto decode_success;
   27960       goto decode_failure;
   27961 
   27962    /* Integer Load Instructions */
   27963    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   27964    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   27965    case 0x20: case 0x21:            // lwz,  lwzu
   27966       if (dis_int_load( theInstr )) goto decode_success;
   27967       goto decode_failure;
   27968 
   27969    /* Integer Store Instructions */
   27970    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   27971    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   27972       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   27973       goto decode_failure;
   27974 
   27975    /* Integer Load and Store Multiple Instructions */
   27976    case 0x2E: case 0x2F: // lmw, stmw
   27977       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   27978       goto decode_failure;
   27979 
   27980    /* Branch Instructions */
   27981    case 0x12: case 0x10: // b, bc
   27982       if (dis_branch(theInstr, abiinfo, &dres,
   27983                                resteerOkFn, callback_opaque))
   27984          goto decode_success;
   27985       goto decode_failure;
   27986 
   27987    /* System Linkage Instructions */
   27988    case 0x11: // sc
   27989       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   27990       goto decode_failure;
   27991 
   27992    /* Trap Instructions */
   27993    case 0x02:    // tdi
   27994       if (!mode64) goto decode_failure;
   27995       if (dis_trapi(theInstr, &dres)) goto decode_success;
   27996       goto decode_failure;
   27997 
   27998    case 0x03:   // twi
   27999       if (dis_trapi(theInstr, &dres)) goto decode_success;
   28000       goto decode_failure;
   28001 
   28002    /* Floating Point Load Instructions */
   28003    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   28004    case 0x33:                       // lfdu
   28005       if (!allow_F) goto decode_noF;
   28006       if (dis_fp_load( theInstr )) goto decode_success;
   28007       goto decode_failure;
   28008 
   28009    /* Floating Point Store Instructions */
   28010    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   28011    case 0x37:                       // stfdux
   28012       if (!allow_F) goto decode_noF;
   28013       if (dis_fp_store( theInstr )) goto decode_success;
   28014       goto decode_failure;
   28015 
   28016       /* Floating Point Load Double Pair Instructions */
   28017    case 0x39: case 0x3D:    // lfdp, lxsd, lxssp, lxv
   28018                             // stfdp, stxsd, stxssp, stxv
   28019       if (!allow_F) goto decode_noF;
   28020       if (dis_fp_pair( theInstr )) goto decode_success;
   28021       goto decode_failure;
   28022 
   28023    /* 128-bit Integer Load */
   28024    case 0x38:  // lq
   28025       if (dis_int_load( theInstr )) goto decode_success;
   28026       goto decode_failure;
   28027 
   28028    /* 64bit Integer Loads */
   28029    case 0x3A:  // ld, ldu, lwa
   28030       if (!mode64) goto decode_failure;
   28031       if (dis_int_load( theInstr )) goto decode_success;
   28032       goto decode_failure;
   28033 
   28034    case 0x3B:
   28035       if (!allow_F) goto decode_noF;
   28036       opc2 = ifieldOPClo10(theInstr);
   28037 
   28038       switch (opc2) {
   28039          case 0x2:    // dadd - DFP Add
   28040          case 0x202:  // dsub - DFP Subtract
   28041          case 0x22:   // dmul - DFP Mult
   28042          case 0x222:  // ddiv - DFP Divide
   28043             if (!allow_DFP) goto decode_noDFP;
   28044             if (dis_dfp_arith( theInstr ))
   28045                goto decode_success;
   28046          case 0x82:   // dcmpo, DFP comparison ordered instruction
   28047          case 0x282:  // dcmpu, DFP comparison unordered instruction
   28048             if (!allow_DFP) goto decode_noDFP;
   28049             if (dis_dfp_compare( theInstr ) )
   28050                goto decode_success;
   28051             goto decode_failure;
   28052          case 0x102: // dctdp  - DFP convert to DFP long
   28053          case 0x302: // drsp   - DFP round to dfp short
   28054          case 0x122: // dctfix - DFP convert to fixed
   28055             if (!allow_DFP) goto decode_noDFP;
   28056             if (dis_dfp_fmt_conv( theInstr ))
   28057                goto decode_success;
   28058             goto decode_failure;
   28059          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
   28060             if (!allow_VX)
   28061                goto decode_failure;
   28062             if (!allow_DFP) goto decode_noDFP;
   28063             if (dis_dfp_fmt_conv( theInstr ))
   28064                goto decode_success;
   28065             goto decode_failure;
   28066          case 0x2A2: // dtstsf  - DFP number of significant digits
   28067          case 0x2A3: // dtstsfi - DFP number of significant digits Immediate
   28068             if (!allow_DFP) goto decode_noDFP;
   28069             if (dis_dfp_significant_digits(theInstr))
   28070                goto decode_success;
   28071             goto decode_failure;
   28072          case 0x142: // ddedpd   DFP Decode DPD to BCD
   28073          case 0x342: // denbcd   DFP Encode BCD to DPD
   28074             if (!allow_DFP) goto decode_noDFP;
   28075             if (dis_dfp_bcd(theInstr))
   28076                goto decode_success;
   28077             goto decode_failure;
   28078          case 0x162:  // dxex - Extract exponent
   28079          case 0x362:  // diex - Insert exponent
   28080             if (!allow_DFP) goto decode_noDFP;
   28081             if (dis_dfp_extract_insert( theInstr ) )
   28082                goto decode_success;
   28083             goto decode_failure;
   28084          case 0x3CE: // fcfidus (implemented as native insn)
   28085             if (!allow_VX)
   28086                goto decode_noVX;
   28087             if (dis_fp_round( theInstr ))
   28088                goto decode_success;
   28089             goto decode_failure;
   28090          case 0x34E: // fcfids
   28091             if (dis_fp_round( theInstr ))
   28092                goto decode_success;
   28093             goto decode_failure;
   28094       }
   28095 
   28096       opc2 = ifieldOPClo9( theInstr );
   28097       switch (opc2) {
   28098       case 0x42: // dscli, DFP shift left
   28099       case 0x62: // dscri, DFP shift right
   28100          if (!allow_DFP) goto decode_noDFP;
   28101          if (dis_dfp_shift( theInstr ))
   28102             goto decode_success;
   28103          goto decode_failure;
   28104       case 0xc2:  // dtstdc, DFP test data class
   28105       case 0xe2:  // dtstdg, DFP test data group
   28106          if (!allow_DFP) goto decode_noDFP;
   28107          if (dis_dfp_class_test( theInstr ))
   28108             goto decode_success;
   28109          goto decode_failure;
   28110       }
   28111 
   28112       opc2 = ifieldOPClo8( theInstr );
   28113       switch (opc2) {
   28114       case 0x3:   // dqua  - DFP Quantize
   28115       case 0x23:  // drrnd - DFP Reround
   28116       case 0x43:  // dquai - DFP Quantize immediate
   28117          if (!allow_DFP) goto decode_noDFP;
   28118          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
   28119             goto decode_success;
   28120          goto decode_failure;
   28121       case 0xA2: // dtstex - DFP Test exponent
   28122          if (!allow_DFP) goto decode_noDFP;
   28123          if (dis_dfp_exponent_test( theInstr ) )
   28124             goto decode_success;
   28125          goto decode_failure;
   28126       case 0x63: // drintx - Round to an integer value
   28127       case 0xE3: // drintn - Round to an integer value
   28128          if (!allow_DFP) goto decode_noDFP;
   28129          if (dis_dfp_round( theInstr ) ) {
   28130             goto decode_success;
   28131          }
   28132          goto decode_failure;
   28133       default:
   28134          break;  /* fall through to next opc2 check */
   28135       }
   28136 
   28137       opc2 = IFIELD(theInstr, 1, 5);
   28138       switch (opc2) {
   28139       /* Floating Point Arith Instructions */
   28140       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   28141       case 0x19:                       // fmuls
   28142          if (dis_fp_arith(theInstr)) goto decode_success;
   28143          goto decode_failure;
   28144       case 0x16:                       // fsqrts
   28145          if (!allow_FX) goto decode_noFX;
   28146          if (dis_fp_arith(theInstr)) goto decode_success;
   28147          goto decode_failure;
   28148       case 0x18:                       // fres
   28149          if (!allow_GX) goto decode_noGX;
   28150          if (dis_fp_arith(theInstr)) goto decode_success;
   28151          goto decode_failure;
   28152 
   28153       /* Floating Point Mult-Add Instructions */
   28154       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   28155       case 0x1F:                       // fnmadds
   28156          if (dis_fp_multadd(theInstr)) goto decode_success;
   28157          goto decode_failure;
   28158 
   28159       case 0x1A:                       // frsqrtes
   28160          if (!allow_GX) goto decode_noGX;
   28161          if (dis_fp_arith(theInstr)) goto decode_success;
   28162          goto decode_failure;
   28163 
   28164       default:
   28165          goto decode_failure;
   28166       }
   28167       break;
   28168 
   28169    case 0x3C: // VSX instructions (except load/store)
   28170    {
   28171       // All of these VSX instructions use some VMX facilities, so
   28172       // if allow_V is not set, we'll skip trying to decode.
   28173       if (!allow_V) goto decode_noVX;
   28174       /* The xvtstdcdp and xvtstdcsp instructions do not have a
   28175          contiguous opc2 field.  The following vsxOpc2 = get_VSX60_opc2()
   28176          doesn't correctly match these instructions for dc != 0.  So,
   28177          we will explicitly look for the two instructions. */
   28178       opc2 = ifieldOPClo10(theInstr);
   28179       UInt opc2hi = IFIELD(theInstr, 7, 4);
   28180       UInt opc2lo = IFIELD(theInstr, 3, 3);
   28181       UInt vsxOpc2;
   28182 
   28183       if (( opc2hi == 13 ) && ( opc2lo == 5)) { //xvtstdcsp
   28184          if (dis_vxs_misc(theInstr, 0x354, allow_isa_3_0))
   28185             goto decode_success;
   28186          goto decode_failure;
   28187       }
   28188 
   28189       if (( opc2hi == 15 ) && ( opc2lo == 5)) { //xvtstdcdp
   28190          if (dis_vxs_misc(theInstr, 0x3D4, allow_isa_3_0))
   28191                goto decode_success;
   28192             goto decode_failure;
   28193       }
   28194 
   28195       /* The vsxOpc2 returned is the "normalized" value, representing the
   28196        * instructions secondary opcode as taken from the standard secondary
   28197        * opcode field [21:30] (IBM notatition), even if the actual field
   28198        * is non-standard.  These normalized values are given in the opcode
   28199        * appendices of the ISA 2.06 document.
   28200        */
   28201       if ( ( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )// xxspltib
   28202       {
   28203          /* This is a special case of the XX1 form where the  RA, RB
   28204           * fields hold an immediate value.
   28205           */
   28206          if (dis_vxs_misc(theInstr, opc2, allow_isa_3_0)) goto decode_success;
   28207          goto decode_failure;
   28208       }
   28209 
   28210       vsxOpc2 = get_VSX60_opc2(opc2, theInstr);
   28211 
   28212       switch (vsxOpc2) {
   28213          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   28214          case 0x068: case 0xE8:  // xxperm, xxpermr
   28215          case 0x018: case 0x148: // xxsel, xxspltw
   28216             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   28217             goto decode_failure;
   28218          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
   28219          case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
   28220          case 0x2C8: case 0x2E8: // xxlnand, xxleqv
   28221             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   28222             goto decode_failure;
   28223          case 0x0ec:             // xscmpexpdp
   28224          case 0x14A: case 0x16A: // xxextractuw, xxinsertw
   28225          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   28226          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   28227          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   28228          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   28229          case 0x034: case 0x014: // xsresp, xsrsqrtesp
   28230          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   28231          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   28232          case 0x092: case 0x232: // xsrdpi, xsrsp
   28233          case 0x3B6:             // xxbrh, xvxexpdp, xvxexpsp, xvxsigdp
   28234                                  // xvxsigsp, xvcvhpsp
   28235          case 0x2b6:             // xsxexpdp, xsxsigdp
   28236          case 0x254: case 0x2d4: // xststdcsp, xststdcdp
   28237          case 0x354:             // xvtstdcsp
   28238          case 0x360:case 0x396:  // xviexpsp, xsiexpdp
   28239          case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp
   28240             if (dis_vxs_misc(theInstr, vsxOpc2, allow_isa_3_0))
   28241                goto decode_success;
   28242             goto decode_failure;
   28243          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   28244             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   28245             goto decode_failure;
   28246          case 0x0:   case 0x020: // xsaddsp, xssubsp
   28247          case 0x080:             // xsadddp
   28248          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
   28249          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
   28250          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   28251          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
   28252          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   28253          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
   28254          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   28255          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
   28256          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   28257          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
   28258          case 0x0A0:             // xssubdp
   28259          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
   28260          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
   28261             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   28262             goto decode_failure;
   28263          case 0x180: // xvadddp
   28264          case 0x1E0: // xvdivdp
   28265          case 0x1C0: // xvmuldp
   28266          case 0x1A0: // xvsubdp
   28267          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   28268          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   28269          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   28270          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   28271          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   28272          case 0x196: // xvsqrtdp
   28273             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   28274             goto decode_failure;
   28275          case 0x100: // xvaddsp
   28276          case 0x160: // xvdivsp
   28277          case 0x140: // xvmulsp
   28278          case 0x120: // xvsubsp
   28279          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   28280          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   28281          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   28282          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   28283          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   28284          case 0x116: // xvsqrtsp
   28285             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   28286             goto decode_failure;
   28287 
   28288          case 0x250:             // xscvuxdsp
   28289          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
   28290          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
   28291          case 0x090: // xscvdpuxws
   28292             // The above VSX conversion instructions employ some ISA 2.06
   28293             // floating point conversion instructions under the covers,
   28294             // so if allow_VX (which means "supports ISA 2.06") is not set,
   28295             // we'll skip the decode.
   28296             if (!allow_VX) goto decode_noVX;
   28297             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   28298             goto decode_failure;
   28299 
   28300          case 0x2B0: // xscvdpsxds
   28301          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
   28302          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   28303          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   28304          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
   28305          case 0x292: case 0x296: // xscvspdp, xscvspdpn
   28306          case 0x312: // xvcvdpsp
   28307          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   28308          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   28309          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   28310          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   28311          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   28312          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   28313             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   28314             goto decode_failure;
   28315 
   28316          case 0x18C:             // xvcmpeqdp[.]
   28317          case 0x10C:             // xvcmpeqsp[.]
   28318          case 0x14C:             // xvcmpgesp[.]
   28319          case 0x12C:             // xvcmpgtsp[.]
   28320          case 0x1CC:             // xvcmpgedp[.]
   28321          case 0x1AC:             // xvcmpgtdp[.]
   28322              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   28323              goto decode_failure;
   28324 
   28325          case 0x134:  // xvresp
   28326          case 0x1B4:  // xvredp
   28327          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   28328          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   28329          case 0x300: case 0x320: // xvmaxsp, xvminsp
   28330          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   28331          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   28332          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   28333          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   28334          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   28335          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   28336          case 0x112: case 0x156: // xvrspi, xvrspic
   28337          case 0x172: case 0x152: // xvrspim, xvrspip
   28338          case 0x132: // xvrspiz
   28339             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   28340             goto decode_failure;
   28341 
   28342          default:
   28343             goto decode_failure;
   28344       }
   28345       break;
   28346    }
   28347 
   28348    /* 64bit Integer Stores */
   28349    case 0x3E:  // std, stdu, stq
   28350       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   28351       goto decode_failure;
   28352 
   28353    case 0x3F:
   28354       if (!allow_F) goto decode_noF;
   28355       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   28356          so we can simply fall through the first switch statement */
   28357 
   28358       opc2 = IFIELD(theInstr, 1, 5);
   28359       switch (opc2) {
   28360       /* Floating Point Arith Instructions */
   28361       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   28362       case 0x19:                       // fmul
   28363          if (dis_fp_arith(theInstr)) goto decode_success;
   28364          goto decode_failure;
   28365       case 0x16:                       // fsqrt
   28366          if (!allow_FX) goto decode_noFX;
   28367          if (dis_fp_arith(theInstr)) goto decode_success;
   28368          goto decode_failure;
   28369       case 0x17: case 0x1A:            // fsel, frsqrte
   28370          if (!allow_GX) goto decode_noGX;
   28371          if (dis_fp_arith(theInstr)) goto decode_success;
   28372          goto decode_failure;
   28373 
   28374       /* Floating Point Mult-Add Instructions */
   28375       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   28376       case 0x1F:                       // fnmadd
   28377          if (dis_fp_multadd(theInstr)) goto decode_success;
   28378          goto decode_failure;
   28379 
   28380       case 0x18:                       // fre
   28381          if (!allow_GX) goto decode_noGX;
   28382          if (dis_fp_arith(theInstr)) goto decode_success;
   28383          goto decode_failure;
   28384 
   28385       default:
   28386          break; // Fall through
   28387       }
   28388 
   28389       opc2 = IFIELD(theInstr, 1, 8);
   28390       switch (opc2) {
   28391       case 0x5: // xsrqpi, xsrqpix
   28392       case 0x25: // xsrqpxp
   28393          if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
   28394          if ( dis_vx_Scalar_Round_to_quad_integer( theInstr ) )
   28395             goto decode_success;
   28396          goto decode_failure;
   28397       default:
   28398          break; // Fall through
   28399       }
   28400 
   28401       opc2 = IFIELD(theInstr, 1, 10);
   28402       UInt inst_select = IFIELD( theInstr, 16, 5 );
   28403 
   28404       switch (opc2) {
   28405       /* 128-bit DFP instructions */
   28406       case 0x2:    // daddq - DFP Add
   28407       case 0x202:  // dsubq - DFP Subtract
   28408       case 0x22:   // dmulq - DFP Mult
   28409       case 0x222:  // ddivq - DFP Divide
   28410          if (!allow_DFP) goto decode_noDFP;
   28411          if (dis_dfp_arithq( theInstr ))
   28412             goto decode_success;
   28413          goto decode_failure;
   28414       case 0x162:  // dxexq - DFP Extract exponent
   28415       case 0x362:  // diexq - DFP Insert exponent
   28416          if (!allow_DFP) goto decode_noDFP;
   28417          if (dis_dfp_extract_insertq( theInstr ))
   28418             goto decode_success;
   28419          goto decode_failure;
   28420 
   28421       case 0x82:   // dcmpoq, DFP comparison ordered instruction
   28422       case 0x282:  // dcmpuq, DFP comparison unordered instruction
   28423          if (!allow_DFP) goto decode_noDFP;
   28424          if (dis_dfp_compare( theInstr ) )
   28425             goto decode_success;
   28426          goto decode_failure;
   28427 
   28428       case 0x102: // dctqpq  - DFP convert to DFP extended
   28429       case 0x302: // drdpq   - DFP round to dfp Long
   28430       case 0x122: // dctfixq - DFP convert to fixed quad
   28431       case 0x322: // dcffixq - DFP convert from fixed quad
   28432          if (!allow_DFP) goto decode_noDFP;
   28433          if (dis_dfp_fmt_convq( theInstr ))
   28434             goto decode_success;
   28435          goto decode_failure;
   28436 
   28437       case 0x2A2: // dtstsfq  - DFP number of significant digits
   28438       case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate
   28439          if (!allow_DFP) goto decode_noDFP;
   28440          if (dis_dfp_significant_digits(theInstr))
   28441             goto decode_success;
   28442          goto decode_failure;
   28443 
   28444       case 0x142: // ddedpdq   DFP Decode DPD to BCD
   28445       case 0x342: // denbcdq   DFP Encode BCD to DPD
   28446          if (!allow_DFP) goto decode_noDFP;
   28447          if (dis_dfp_bcdq(theInstr))
   28448             goto decode_success;
   28449          goto decode_failure;
   28450 
   28451       /* Floating Point Compare Instructions */
   28452       case 0x000: // fcmpu
   28453       case 0x020: // fcmpo
   28454          if (dis_fp_cmp(theInstr)) goto decode_success;
   28455          goto decode_failure;
   28456 
   28457       case 0x080: // ftdiv
   28458       case 0x0A0: // ftsqrt
   28459          if (dis_fp_tests(theInstr)) goto decode_success;
   28460          goto decode_failure;
   28461 
   28462       /* Floating Point Rounding/Conversion Instructions */
   28463       case 0x00C: // frsp
   28464       case 0x00E: // fctiw
   28465       case 0x00F: // fctiwz
   28466       case 0x32E: // fctid
   28467       case 0x32F: // fctidz
   28468       case 0x34E: // fcfid
   28469          if (dis_fp_round(theInstr)) goto decode_success;
   28470          goto decode_failure;
   28471       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   28472       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   28473          if (!allow_VX) goto decode_noVX;
   28474          if (dis_fp_round(theInstr)) goto decode_success;
   28475          goto decode_failure;
   28476 
   28477       /* Power6 rounding stuff */
   28478       case 0x1E8: // frim
   28479       case 0x1C8: // frip
   28480       case 0x188: // frin
   28481       case 0x1A8: // friz
   28482          /* A hack to check for P6 capability . . . */
   28483          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   28484              (dis_fp_round(theInstr)))
   28485             goto decode_success;
   28486          goto decode_failure;
   28487 
   28488       /* Floating Point Move Instructions */
   28489       case 0x008: // fcpsgn
   28490       case 0x028: // fneg
   28491       case 0x048: // fmr
   28492       case 0x088: // fnabs
   28493       case 0x108: // fabs
   28494          if (dis_fp_move( theInstr )) goto decode_success;
   28495          goto decode_failure;
   28496 
   28497       case 0x3c6: case 0x346:          // fmrgew, fmrgow
   28498          if (dis_fp_merge( theInstr )) goto decode_success;
   28499          goto decode_failure;
   28500 
   28501       /* Floating Point Status/Control Register Instructions */
   28502       case 0x026: // mtfsb1
   28503       case 0x040: // mcrfs
   28504       case 0x046: // mtfsb0
   28505       case 0x086: // mtfsfi
   28506       case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni,
   28507                   // mffscrn, mffscrn, mffscri, mffsl
   28508       case 0x2C7: // mtfsf
   28509          // Some of the above instructions need to know more about the
   28510          // ISA level supported by the host.
   28511          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
   28512          goto decode_failure;
   28513 
   28514       case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp
   28515          if ( inst_select == 27 ) {    // xssqrtqp
   28516             if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) )
   28517                goto decode_success;
   28518          }
   28519 
   28520          /* Instructions implemented with Pre ISA 3.0 Iops */
   28521          /* VSX Scalar Quad-Precision instructions */
   28522       case 0x064: // xscpsgnqp
   28523       case 0x0A4: // xscmpexpqp
   28524       case 0x084: // xscmpoqp
   28525       case 0x284: // xscmpuqp
   28526       case 0x2C4: // xststdcqp
   28527       case 0x364: // xsiexpqp
   28528          if (dis_vx_scalar_quad_precision( theInstr )) goto decode_success;
   28529          goto decode_failure;
   28530 
   28531       /* Instructions implemented using ISA 3.0 instructions */
   28532                   // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD]
   28533       case 0x004: // xsaddqp  (VSX Scalar Add Quad-Precision [using RN mode]
   28534                   // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD]
   28535       case 0x024: // xsmulqp  (VSX Scalar Multiply Quad-Precision [using RN mode]
   28536                   // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD]
   28537       case 0x184: // xsmaddqp  (VSX Scalar Multiply Add Quad-Precision [using RN mode]
   28538                   // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD]
   28539       case 0x1A4: // xsmsubqp  (VSX Scalar Multiply Sub Quad-Precision [using RN mode]
   28540                   // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD]
   28541       case 0x1C4: // xsnmaddqp  (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode]
   28542                   // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD]
   28543       case 0x1E4: // xsnmsubqp  (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode]
   28544                   // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD]
   28545       case 0x204: // xssubqp  (VSX Scalar Subrtact Quad-Precision [using RN mode]
   28546                   // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD]
   28547       case 0x224: // xsdivqp  (VSX Scalar Divde Quad-Precision [using RN mode]
   28548       case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp
   28549                   // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz
   28550          if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
   28551          if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr ) )
   28552             goto decode_success;
   28553          goto decode_failure;
   28554 
   28555       default:
   28556          break; // Fall through...
   28557       }
   28558 
   28559       opc2 = ifieldOPClo9( theInstr );
   28560       switch (opc2) {
   28561       case 0x42: // dscli, DFP shift left
   28562       case 0x62: // dscri, DFP shift right
   28563          if (!allow_DFP) goto decode_noDFP;
   28564          if (dis_dfp_shiftq( theInstr ))
   28565             goto decode_success;
   28566          goto decode_failure;
   28567       case 0xc2:  // dtstdc, DFP test data class
   28568       case 0xe2:  // dtstdg, DFP test data group
   28569          if (!allow_DFP) goto decode_noDFP;
   28570          if (dis_dfp_class_test( theInstr ))
   28571             goto decode_success;
   28572          goto decode_failure;
   28573       default:
   28574          break;
   28575       }
   28576 
   28577       opc2 = ifieldOPClo8( theInstr );
   28578       switch (opc2) {
   28579       case 0x3:   // dquaq  - DFP Quantize Quad
   28580       case 0x23:  // drrndq - DFP Reround Quad
   28581       case 0x43:  // dquaiq - DFP Quantize immediate Quad
   28582          if (!allow_DFP) goto decode_noDFP;
   28583          if (dis_dfp_quantize_sig_rrndq( theInstr ))
   28584             goto decode_success;
   28585          goto decode_failure;
   28586       case 0xA2: // dtstexq - DFP Test exponent Quad
   28587          if (!allow_DFP) goto decode_noDFP;
   28588          if (dis_dfp_exponent_test( theInstr ) )
   28589             goto decode_success;
   28590          goto decode_failure;
   28591       case 0x63:  // drintxq - DFP Round to an integer value
   28592       case 0xE3:  // drintnq - DFP Round to an integer value
   28593          if (!allow_DFP) goto decode_noDFP;
   28594          if (dis_dfp_roundq( theInstr ))
   28595             goto decode_success;
   28596          goto decode_failure;
   28597 
   28598       default:
   28599          goto decode_failure;
   28600       }
   28601       break;
   28602 
   28603    case 0x13:
   28604 
   28605       opc2 = ifieldOPClo5(theInstr);
   28606       switch (opc2) {
   28607 
   28608       /* PC relative load/store */
   28609       case 0x002:       // addpcis
   28610          if (dis_pc_relative(theInstr)) goto decode_success;
   28611          goto decode_failure;
   28612 
   28613       /* fall through to the next opc2 field size */
   28614       }
   28615 
   28616       opc2 = ifieldOPClo10(theInstr);
   28617       switch (opc2) {
   28618 
   28619       /* Condition Register Logical Instructions */
   28620       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   28621       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   28622       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   28623          if (dis_cond_logic( theInstr )) goto decode_success;
   28624          goto decode_failure;
   28625 
   28626       /* Branch Instructions */
   28627       case 0x210: case 0x010: // bcctr, bclr
   28628          if (dis_branch(theInstr, abiinfo, &dres,
   28629                                   resteerOkFn, callback_opaque))
   28630             goto decode_success;
   28631          goto decode_failure;
   28632 
   28633       /* Memory Synchronization Instructions */
   28634       case 0x096: // isync
   28635          if (dis_memsync( theInstr )) goto decode_success;
   28636          goto decode_failure;
   28637 
   28638       default:
   28639          goto decode_failure;
   28640       }
   28641       break;
   28642 
   28643 
   28644    case 0x1F:
   28645 
   28646       /* For arith instns, bit10 is the OE flag (overflow enable) */
   28647 
   28648       opc2 = IFIELD(theInstr, 1, 9);
   28649       switch (opc2) {
   28650       /* Integer Arithmetic Instructions */
   28651       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   28652       case 0x0AA:                         // addex
   28653       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   28654       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   28655       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   28656       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   28657       case 0x0C8: // subfze
   28658          if (dis_int_arith( theInstr )) goto decode_success;
   28659          goto decode_failure;
   28660 
   28661       case 0x18B: // divweu (implemented as native insn)
   28662       case 0x1AB: // divwe (implemented as native insn)
   28663          if (!allow_VX) goto decode_noVX;
   28664          if (dis_int_arith( theInstr )) goto decode_success;
   28665          goto decode_failure;
   28666 
   28667       /* 64bit Integer Arithmetic */
   28668       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   28669       case 0x1C9: case 0x1E9: // divdu, divd
   28670          if (!mode64) goto decode_failure;
   28671          if (dis_int_arith( theInstr )) goto decode_success;
   28672          goto decode_failure;
   28673 
   28674       case 0x1A9: //  divde (implemented as native insn)
   28675       case 0x189: //  divdeuo (implemented as native insn)
   28676          if (!allow_VX) goto decode_noVX;
   28677          if (!mode64) goto decode_failure;
   28678          if (dis_int_arith( theInstr )) goto decode_success;
   28679          goto decode_failure;
   28680 
   28681       case 0x1FC:                         // cmpb
   28682          if (dis_int_logic( theInstr )) goto decode_success;
   28683          goto decode_failure;
   28684 
   28685       default:
   28686          break;  // Fall through...
   28687       }
   28688 
   28689       /* All remaining opcodes use full 10 bits. */
   28690 
   28691       opc2 = IFIELD(theInstr, 1, 10);
   28692       switch (opc2) {
   28693 
   28694       /* Integer miscellaneous instructions */
   28695       case 0x01E:  // wait  RFC 2500
   28696          if (dis_int_misc( theInstr )) goto decode_success;
   28697          goto decode_failure;
   28698 
   28699 
   28700       /* Integer Compare Instructions  */
   28701       case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb
   28702          if (dis_int_cmp( theInstr )) goto decode_success;
   28703          goto decode_failure;
   28704 
   28705       case 0x0C0: case 0x0E0:   // cmprb, cmpeqb
   28706          if (dis_byte_cmp( theInstr )) goto decode_success;
   28707          goto decode_failure;
   28708 
   28709       case 0x10B: case 0x30B: // moduw, modsw
   28710       case 0x109: case 0x309: // modsd, modud
   28711       case 0x21A: case 0x23A: // cnttzw, cnttzd
   28712          if (dis_modulo_int( theInstr )) goto decode_success;
   28713          goto decode_failure;
   28714 
   28715       /* Integer Logical Instructions */
   28716       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   28717       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   28718       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   28719       case 0x19C: case 0x13C:             // orc,  xor
   28720       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   28721          if (dis_int_logic( theInstr )) goto decode_success;
   28722          goto decode_failure;
   28723 
   28724       case 0x28E: case 0x2AE:             // tbegin., tend.
   28725       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
   28726       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
   28727       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
   28728       if (dis_transactional_memory( theInstr,
   28729                                     getUIntPPCendianly( &guest_code[delta + 4]),
   28730                                     abiinfo, &dres,
   28731                                     resteerOkFn, callback_opaque))
   28732             goto decode_success;
   28733          goto decode_failure;
   28734 
   28735       /* 64bit Integer Logical Instructions */
   28736       case 0x3DA: case 0x03A: // extsw, cntlzd
   28737          if (!mode64) goto decode_failure;
   28738          if (dis_int_logic( theInstr )) goto decode_success;
   28739          goto decode_failure;
   28740 
   28741          /* 64bit Integer Parity Instructions */
   28742       case 0xba: // prtyd
   28743          if (!mode64) goto decode_failure;
   28744          if (dis_int_parity( theInstr )) goto decode_success;
   28745          goto decode_failure;
   28746 
   28747       case 0x9a: // prtyw
   28748          if (dis_int_parity( theInstr )) goto decode_success;
   28749          goto decode_failure;
   28750 
   28751       /* Integer Shift Instructions */
   28752       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   28753       case 0x218:                         // srw
   28754          if (dis_int_shift( theInstr )) goto decode_success;
   28755          goto decode_failure;
   28756 
   28757       /* 64bit Integer Shift Instructions */
   28758       case 0x01B: case 0x31A: // sld, srad
   28759       case 0x33A: case 0x33B: // sradi
   28760       case 0x21B:             // srd
   28761          if (!mode64) goto decode_failure;
   28762          if (dis_int_shift( theInstr )) goto decode_success;
   28763          goto decode_failure;
   28764 
   28765       /* Integer Load Instructions */
   28766       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   28767       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   28768       case 0x017: case 0x037:             // lwzx,  lwzux
   28769          if (dis_int_load( theInstr )) goto decode_success;
   28770          goto decode_failure;
   28771 
   28772       /* 64bit Integer Load Instructions */
   28773       case 0x035: case 0x015:             // ldux,  ldx
   28774       case 0x175: case 0x155:             // lwaux, lwax
   28775          if (!mode64) goto decode_failure;
   28776          if (dis_int_load( theInstr )) goto decode_success;
   28777          goto decode_failure;
   28778 
   28779       /* Integer Store Instructions */
   28780       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   28781       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   28782          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   28783          goto decode_failure;
   28784 
   28785       /* 64bit Integer Store Instructions */
   28786       case 0x0B5: case 0x095: // stdux, stdx
   28787          if (!mode64) goto decode_failure;
   28788          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   28789          goto decode_failure;
   28790 
   28791       /* Integer Load and Store with Byte Reverse Instructions */
   28792       case 0x214: case 0x294: // ldbrx, stdbrx
   28793          if (!mode64) goto decode_failure;
   28794          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   28795          goto decode_failure;
   28796 
   28797       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
   28798       case 0x396:                            // sthbrx
   28799          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   28800          goto decode_failure;
   28801 
   28802       /* Integer Load and Store String Instructions */
   28803       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   28804       case 0x295: {                       // stswx
   28805          Bool stopHere = False;
   28806          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   28807          if (!ok) goto decode_failure;
   28808          if (stopHere) {
   28809             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
   28810             dres.jk_StopHere = Ijk_Boring;
   28811             dres.whatNext    = Dis_StopHere;
   28812          }
   28813          goto decode_success;
   28814       }
   28815 
   28816       /* Memory Synchronization Instructions */
   28817       case 0x034: case 0x074:             // lbarx, lharx
   28818       case 0x2B6: case 0x2D6:             // stbcx, sthcx
   28819          if (!allow_isa_2_07) goto decode_noP8;
   28820          if (dis_memsync( theInstr )) goto decode_success;
   28821          goto decode_failure;
   28822 
   28823       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   28824       case 0x256:                         // sync
   28825          if (dis_memsync( theInstr )) goto decode_success;
   28826          goto decode_failure;
   28827 
   28828       /* 64bit Memory Synchronization Instructions */
   28829       case 0x054: case 0x0D6: // ldarx, stdcx.
   28830          if (!mode64) goto decode_failure;
   28831          if (dis_memsync( theInstr )) goto decode_success;
   28832          goto decode_failure;
   28833 
   28834       case 0x114: case 0x0B6: // lqarx, stqcx.
   28835          if (dis_memsync( theInstr )) goto decode_success;
   28836          goto decode_failure;
   28837 
   28838       /* Processor Control Instructions */
   28839       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
   28840       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
   28841       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   28842       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   28843       case 0x220:                         // mcrxrt
   28844          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   28845          goto decode_failure;
   28846 
   28847       /* Cache Management Instructions */
   28848       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   28849       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   28850       case 0x3D6:                         // icbi
   28851          if (dis_cache_manage( theInstr, &dres, archinfo ))
   28852             goto decode_success;
   28853          goto decode_failure;
   28854 
   28855 //zz       /* External Control Instructions */
   28856 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   28857 //zz          DIP("external control op => not implemented\n");
   28858 //zz          goto decode_failure;
   28859 
   28860       /* Trap Instructions */
   28861       case 0x004:             // tw
   28862          if (dis_trap(theInstr, &dres)) goto decode_success;
   28863          goto decode_failure;
   28864 
   28865       case 0x044:             // td
   28866          if (!mode64) goto decode_failure;
   28867          if (dis_trap(theInstr, &dres)) goto decode_success;
   28868          goto decode_failure;
   28869 
   28870       /* Floating Point Load Instructions */
   28871       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   28872       case 0x277:                         // lfdux
   28873          if (!allow_F) goto decode_noF;
   28874          if (dis_fp_load( theInstr )) goto decode_success;
   28875          goto decode_failure;
   28876 
   28877       /* Floating Point Store Instructions */
   28878       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   28879       case 0x2F7:                         // stfdu, stfiwx
   28880          if (!allow_F) goto decode_noF;
   28881          if (dis_fp_store( theInstr )) goto decode_success;
   28882          goto decode_failure;
   28883       case 0x3D7:                         // stfiwx
   28884          if (!allow_F) goto decode_noF;
   28885          if (!allow_GX) goto decode_noGX;
   28886          if (dis_fp_store( theInstr )) goto decode_success;
   28887          goto decode_failure;
   28888 
   28889          /* Floating Point Double Pair Indexed Instructions */
   28890       case 0x317: // lfdpx (Power6)
   28891       case 0x397: // stfdpx (Power6)
   28892          if (!allow_F) goto decode_noF;
   28893          if (dis_fp_pair(theInstr)) goto decode_success;
   28894          goto decode_failure;
   28895 
   28896       case 0x357:                         // lfiwax
   28897          if (!allow_F) goto decode_noF;
   28898          if (dis_fp_load( theInstr )) goto decode_success;
   28899          goto decode_failure;
   28900 
   28901       case 0x377:                         // lfiwzx
   28902          if (!allow_F) goto decode_noF;
   28903          if (dis_fp_load( theInstr )) goto decode_success;
   28904          goto decode_failure;
   28905 
   28906       /* AltiVec instructions */
   28907 
   28908       /* AV Cache Control - Data streams */
   28909       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   28910          if (!allow_V) goto decode_noV;
   28911          if (dis_av_datastream( theInstr )) goto decode_success;
   28912          goto decode_failure;
   28913 
   28914       /* AV Load */
   28915       case 0x006: case 0x026:             // lvsl, lvsr
   28916       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   28917       case 0x067: case 0x167:             // lvx, lvxl
   28918          if (!allow_V) goto decode_noV;
   28919          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   28920          goto decode_failure;
   28921 
   28922       /* AV Store */
   28923       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   28924       case 0x0E7: case 0x1E7:             // stvx, stvxl
   28925          if (!allow_V) goto decode_noV;
   28926          if (dis_av_store( theInstr )) goto decode_success;
   28927          goto decode_failure;
   28928 
   28929       /* VSX Load */
   28930       case 0x00C: // lxsiwzx
   28931       case 0x04C: // lxsiwax
   28932       case 0x10C: // lxvx
   28933       case 0x10D: // lxvl
   28934       case 0x12D: // lxvll
   28935       case 0x16C: // lxvwsx
   28936       case 0x20C: // lxsspx
   28937       case 0x24C: // lxsdx
   28938       case 0x32C: // lxvh8x
   28939       case 0x30D: // lxsibzx
   28940       case 0x32D: // lxsihzx
   28941       case 0x34C: // lxvd2x
   28942       case 0x36C: // lxvb16x
   28943       case 0x14C: // lxvdsx
   28944       case 0x30C: // lxvw4x
   28945         // All of these VSX load instructions use some VMX facilities, so
   28946         // if allow_V is not set, we'll skip trying to decode.
   28947         if (!allow_V) goto decode_noV;
   28948 
   28949 	if (dis_vx_load( theInstr )) goto decode_success;
   28950           goto decode_failure;
   28951 
   28952       /* VSX Store */
   28953       case 0x08C: // stxsiwx
   28954       case 0x18C: // stxvx
   28955       case 0x18D: // stxvl
   28956       case 0x1AD: // stxvll
   28957       case 0x28C: // stxsspx
   28958       case 0x2CC: // stxsdx
   28959       case 0x38C: // stxvw4x
   28960       case 0x3CC: // stxvd2x
   28961       case 0x38D: // stxsibx
   28962       case 0x3AD: // stxsihx
   28963       case 0x3AC: // stxvh8x
   28964       case 0x3EC: // stxvb16x
   28965         // All of these VSX store instructions use some VMX facilities, so
   28966         // if allow_V is not set, we'll skip trying to decode.
   28967         if (!allow_V) goto decode_noV;
   28968 
   28969 	if (dis_vx_store( theInstr )) goto decode_success;
   28970     	  goto decode_failure;
   28971 
   28972       case 0x133: case 0x193: case 0x1B3:  // mfvsrld, mfvsrdd, mtvsrws
   28973         // The move from/to VSX instructions use some VMX facilities, so
   28974         // if allow_V is not set, we'll skip trying to decode.
   28975         if (!allow_V) goto decode_noV;
   28976         if (dis_vx_move( theInstr )) goto decode_success;
   28977         goto decode_failure;
   28978 
   28979       /* Miscellaneous ISA 2.06 instructions */
   28980       case 0x1FA: // popcntd
   28981       case 0x17A: // popcntw
   28982       case 0x7A:  // popcntb
   28983 	  if (dis_int_logic( theInstr )) goto decode_success;
   28984     	  goto decode_failure;
   28985 
   28986       case 0x0FC: // bpermd
   28987          if (!mode64) goto decode_failure;
   28988          if (dis_int_logic( theInstr )) goto decode_success;
   28989          goto decode_failure;
   28990 
   28991       default:
   28992          /* Deal with some other cases that we would otherwise have
   28993             punted on. */
   28994          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   28995          /* only decode this insn when reserved bit 0 (31 in IBM's
   28996             notation) is zero */
   28997          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   28998             UInt rT = ifieldRegDS( theInstr );
   28999             UInt rA = ifieldRegA( theInstr );
   29000             UInt rB = ifieldRegB( theInstr );
   29001             UInt bi = ifieldRegC( theInstr );
   29002             putIReg(
   29003                rT,
   29004                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
   29005                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   29006                                    : getIReg(rA),
   29007                            getIReg(rB))
   29008 
   29009             );
   29010             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   29011             goto decode_success;
   29012          }
   29013       }
   29014 
   29015       opc2 = IFIELD(theInstr, 2, 9);
   29016       switch (opc2) {
   29017       case 0x1BD:
   29018          if (!mode64) goto decode_failure;
   29019          if (dis_int_logic( theInstr )) goto decode_success;
   29020          goto decode_failure;
   29021 
   29022       default:
   29023          goto decode_failure;
   29024       }
   29025       break;
   29026 
   29027 
   29028    case 0x04:
   29029       /* AltiVec instructions */
   29030 
   29031       opc2 = IFIELD(theInstr, 0, 6);
   29032       switch (opc2) {
   29033       /* AV Mult-Add, Mult-Sum */
   29034       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   29035       case 0x23:                       // vmsumudm
   29036       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   29037       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   29038          if (!allow_V) goto decode_noV;
   29039          if (dis_av_multarith( theInstr )) goto decode_success;
   29040          goto decode_failure;
   29041 
   29042       case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld
   29043          if (!mode64) goto decode_failure;
   29044          if (dis_int_mult_add( theInstr )) goto decode_success;
   29045          goto decode_failure;
   29046 
   29047       /* AV Permutations */
   29048       case 0x2A:                       // vsel
   29049       case 0x2B:                       // vperm
   29050       case 0x2C:                       // vsldoi
   29051          if (!allow_V) goto decode_noV;
   29052          if (dis_av_permute( theInstr )) goto decode_success;
   29053          goto decode_failure;
   29054 
   29055       case 0x2D:                       // vpermxor
   29056       case 0x3B:                       // vpermr
   29057          if (!allow_isa_2_07) goto decode_noP8;
   29058          if (dis_av_permute( theInstr )) goto decode_success;
   29059          goto decode_failure;
   29060 
   29061       /* AV Floating Point Mult-Add/Sub */
   29062       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   29063          if (!allow_V) goto decode_noV;
   29064          if (dis_av_fp_arith( theInstr )) goto decode_success;
   29065          goto decode_failure;
   29066 
   29067       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
   29068       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
   29069          if (!allow_V) goto decode_noV;
   29070          if (dis_av_quad( theInstr)) goto decode_success;
   29071          goto decode_failure;
   29072 
   29073       default:
   29074          break;  // Fall through...
   29075       }
   29076 
   29077       opc2 = IFIELD(theInstr, 0, 9);
   29078       if (IFIELD(theInstr, 10, 1) == 1) {
   29079          /* The following instructions have bit 21 set and a PS bit (bit 22)
   29080           * Bit 21 distinquishes them from instructions with an 11 bit opc2
   29081           * field.
   29082           */
   29083          switch (opc2) {
   29084             /* BCD arithmetic */
   29085             case 0x001: case 0x041:             // bcdadd, bcdsub
   29086             case 0x101: case 0x141:             // bcdtrunc., bcdutrunc.
   29087             case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr.
   29088             case 0x181:                         // bcdcfn., bcdcfz.
   29089                                                 // bcdctz., bcdcfsq., bcdctsq.
   29090                if (!allow_isa_2_07) goto decode_noP8;
   29091                if (dis_av_bcd( theInstr, abiinfo )) goto decode_success;
   29092               goto decode_failure;
   29093          default:
   29094               break;  // Fall through...
   29095             }
   29096       }
   29097 
   29098       opc2 = IFIELD(theInstr, 0, 11);
   29099       switch (opc2) {
   29100       /* BCD manipulation */
   29101       case 0x341:                  // bcdcpsgn
   29102 
   29103          if (!allow_isa_2_07) goto decode_noP8;
   29104          if (dis_av_bcd_misc( theInstr, abiinfo )) goto decode_success;
   29105          goto decode_failure;
   29106 
   29107 
   29108       /* AV Arithmetic */
   29109       case 0x180:                         // vaddcuw
   29110       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   29111       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   29112       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   29113       case 0x580:                         // vsubcuw
   29114       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   29115       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   29116       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   29117       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   29118       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   29119       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   29120       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   29121       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   29122       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   29123       case 0x008: case 0x048:             // vmuloub, vmulouh
   29124       case 0x108: case 0x148:             // vmulosb, vmulosh
   29125       case 0x208: case 0x248:             // vmuleub, vmuleuh
   29126       case 0x308: case 0x348:             // vmulesb, vmulesh
   29127       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   29128       case 0x688: case 0x788:             // vsum2sws, vsumsws
   29129          if (!allow_V) goto decode_noV;
   29130          if (dis_av_arith( theInstr )) goto decode_success;
   29131          goto decode_failure;
   29132 
   29133       case 0x088: case 0x089:             // vmulouw, vmuluwm
   29134       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
   29135       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
   29136       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
   29137       case 0x4C0:                         // vsubudm
   29138          if (!allow_isa_2_07) goto decode_noP8;
   29139          if (dis_av_arith( theInstr )) goto decode_success;
   29140          goto decode_failure;
   29141 
   29142       /* AV Polynomial Vector Multiply Add */
   29143       case 0x408: case 0x448:            // vpmsumb, vpmsumd
   29144       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
   29145          if (!allow_isa_2_07) goto decode_noP8;
   29146          if (dis_av_polymultarith( theInstr )) goto decode_success;
   29147          goto decode_failure;
   29148 
   29149       /* AV Rotate, Shift */
   29150       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   29151       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   29152       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   29153       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   29154       case 0x1C4: case 0x2C4:             // vsl, vsr
   29155       case 0x40C: case 0x44C:             // vslo, vsro
   29156          if (!allow_V) goto decode_noV;
   29157          if (dis_av_shift( theInstr )) goto decode_success;
   29158          goto decode_failure;
   29159 
   29160       case 0x0C4:                         // vrld
   29161       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
   29162           if (!allow_isa_2_07) goto decode_noP8;
   29163           if (dis_av_shift( theInstr )) goto decode_success;
   29164           goto decode_failure;
   29165 
   29166       /* AV Logic */
   29167       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   29168       case 0x4C4: case 0x504:             // vxor, vnor
   29169          if (!allow_V) goto decode_noV;
   29170          if (dis_av_logic( theInstr )) goto decode_success;
   29171          goto decode_failure;
   29172 
   29173       case 0x544:                         // vorc
   29174       case 0x584: case 0x684:             // vnand, veqv
   29175          if (!allow_isa_2_07) goto decode_noP8;
   29176          if (dis_av_logic( theInstr )) goto decode_success;
   29177          goto decode_failure;
   29178 
   29179       /* AV Rotate */
   29180       case 0x085: case 0x185:             // vrlwmi, vrlwnm
   29181       case 0x0C5: case 0x1C5:             // vrldmi, vrldnm
   29182          if (!allow_V) goto decode_noV;
   29183          if (dis_av_rotate( theInstr )) goto decode_success;
   29184          goto decode_failure;
   29185 
   29186       /* AV Processor Control */
   29187       case 0x604: case 0x644:             // mfvscr, mtvscr
   29188          if (!allow_V) goto decode_noV;
   29189          if (dis_av_procctl( theInstr )) goto decode_success;
   29190          goto decode_failure;
   29191 
   29192       /* AV Vector Extract Element instructions */
   29193       case 0x60D: case 0x64D: case 0x68D:   // vextublx, vextuhlx, vextuwlx
   29194       case 0x70D: case 0x74D: case 0x78D:   // vextubrx, vextuhrx, vextuwrx
   29195          if (!allow_V) goto decode_noV;
   29196          if (dis_av_extract_element( theInstr )) goto decode_success;
   29197          goto decode_failure;
   29198 
   29199 
   29200       /* AV Floating Point Arithmetic */
   29201       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   29202       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   29203       case 0x1CA:                         // vlogefp
   29204       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   29205          if (!allow_V) goto decode_noV;
   29206          if (dis_av_fp_arith( theInstr )) goto decode_success;
   29207          goto decode_failure;
   29208 
   29209       /* AV Floating Point Round/Convert */
   29210       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   29211       case 0x2CA:                         // vrfim
   29212       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   29213       case 0x3CA:                         // vctsxs
   29214          if (!allow_V) goto decode_noV;
   29215          if (dis_av_fp_convert( theInstr )) goto decode_success;
   29216          goto decode_failure;
   29217 
   29218       /* AV Merge, Splat, Extract, Insert */
   29219       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   29220       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   29221       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   29222       case 0x20D: case 0x24D:             // vextractub, vextractuh,
   29223       case 0x28D: case 0x2CD:             // vextractuw, vextractd,
   29224       case 0x30D: case 0x34D:             // vinsertb, vinserth
   29225       case 0x38D: case 0x3CD:             // vinsertw, vinsertd
   29226       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   29227          if (!allow_V) goto decode_noV;
   29228          if (dis_av_permute( theInstr )) goto decode_success;
   29229          goto decode_failure;
   29230 
   29231       case 0x68C: case 0x78C:             // vmrgow, vmrgew
   29232           if (!allow_isa_2_07) goto decode_noP8;
   29233           if (dis_av_permute( theInstr )) goto decode_success;
   29234           goto decode_failure;
   29235 
   29236       /* AltiVec 128 bit integer multiply by 10 Instructions */
   29237       case 0x201: case 0x001:               //vmul10uq, vmul10cuq
   29238       case 0x241: case 0x041:               //vmul10euq, vmul10ceuq
   29239           if (!allow_V) goto decode_noV;
   29240           if (!allow_isa_3_0) goto decode_noP9;
   29241           if (dis_av_mult10( theInstr )) goto decode_success;
   29242           goto decode_failure;
   29243 
   29244       /* AV Pack, Unpack */
   29245       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   29246       case 0x0CE:                         // vpkuwus
   29247       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   29248       case 0x1CE:                         // vpkswss
   29249       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   29250       case 0x2CE:                         // vupklsh
   29251       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   29252           if (!allow_V) goto decode_noV;
   29253           if (dis_av_pack( theInstr )) goto decode_success;
   29254           goto decode_failure;
   29255 
   29256       case 0x403: case 0x443: case 0x483:  // vabsdub, vabsduh, vabsduw
   29257           if (!allow_V) goto decode_noV;
   29258           if (dis_abs_diff( theInstr )) goto decode_success;
   29259           goto decode_failure;
   29260 
   29261       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
   29262       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
   29263          if (!allow_isa_2_07) goto decode_noP8;
   29264          if (dis_av_pack( theInstr )) goto decode_success;
   29265          goto decode_failure;
   29266 
   29267       case 0x508: case 0x509:             // vcipher, vcipherlast
   29268       case 0x548: case 0x549:             // vncipher, vncipherlast
   29269       case 0x5C8:                         // vsbox
   29270          if (!allow_isa_2_07) goto decode_noP8;
   29271          if (dis_av_cipher( theInstr )) goto decode_success;
   29272          goto decode_failure;
   29273 
   29274      /* AV Vector Extend Sign Instructions and
   29275       * Vector Count Leading/Trailing zero Least-Significant bits Byte.
   29276       * Vector Integer Negate Instructions
   29277       */
   29278       case 0x602:   // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d
   29279                     // vclzlsbb and vctzlsbb
   29280                     // vnegw, vnegd
   29281                     // vprtybw, vprtybd, vprtybq
   29282                     // vctzb, vctzh, vctzw, vctzd
   29283          if (!allow_V) goto decode_noV;
   29284          if (dis_av_extend_sign_count_zero( theInstr, allow_isa_3_0 ))
   29285             goto decode_success;
   29286          goto decode_failure;
   29287 
   29288       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
   29289          if (!allow_isa_2_07) goto decode_noP8;
   29290          if (dis_av_hash( theInstr )) goto decode_success;
   29291          goto decode_failure;
   29292 
   29293       case 0x702: case 0x742:             // vclzb, vclzh
   29294       case 0x782: case 0x7c2:             // vclzw, vclzd
   29295          if (!allow_isa_2_07) goto decode_noP8;
   29296          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   29297          goto decode_failure;
   29298 
   29299       case 0x703: case 0x743:             // vpopcntb, vpopcnth
   29300       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
   29301          if (!allow_isa_2_07) goto decode_noP8;
   29302          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   29303          goto decode_failure;
   29304 
   29305       case 0x50c:                         // vgbbd
   29306       case 0x5cc:                         // vbpermd
   29307          if (!allow_isa_2_07) goto decode_noP8;
   29308          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   29309          goto decode_failure;
   29310 
   29311       case 0x140: case 0x100:             // vaddcuq, vadduqm
   29312       case 0x540: case 0x500:             // vsubcuq, vsubuqm
   29313       case 0x54C:                         // vbpermq
   29314          if (!allow_V) goto decode_noV;
   29315          if (dis_av_quad( theInstr)) goto decode_success;
   29316          goto decode_failure;
   29317 
   29318       default:
   29319          break;  // Fall through...
   29320       }
   29321 
   29322       opc2 = IFIELD(theInstr, 0, 10);
   29323       switch (opc2) {
   29324 
   29325       /* AV Compare */
   29326       case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb
   29327       case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh
   29328       case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw
   29329       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   29330       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   29331          if (!allow_V) goto decode_noV;
   29332          if (dis_av_cmp( theInstr )) goto decode_success;
   29333          goto decode_failure;
   29334 
   29335       case 0x0C7:                         // vcmpequd
   29336       case 0x2C7:                         // vcmpgtud
   29337       case 0x3C7:                         // vcmpgtsd
   29338           if (!allow_isa_2_07) goto decode_noP8;
   29339           if (dis_av_cmp( theInstr )) goto decode_success;
   29340           goto decode_failure;
   29341 
   29342       /* AV Floating Point Compare */
   29343       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   29344       case 0x3C6:                         // vcmpbfp
   29345          if (!allow_V) goto decode_noV;
   29346          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   29347          goto decode_failure;
   29348 
   29349       default:
   29350          goto decode_failure;
   29351       }
   29352       break;
   29353 
   29354    default:
   29355       goto decode_failure;
   29356 
   29357    decode_noF:
   29358       vassert(!allow_F);
   29359       vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
   29360 		 "can't be handled by Valgrind on this host.  This instruction\n"
   29361 		 "requires a host that supports Floating Point instructions.\n",
   29362 		 theInstr);
   29363       goto not_supported;
   29364    decode_noV:
   29365       vassert(!allow_V);
   29366       vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
   29367 		 "that can't be handled by Valgrind.  If this instruction is an\n"
   29368 		 "Altivec instruction, Valgrind must be run on a host that supports"
   29369 		 "AltiVec instructions.  If the application was compiled for e500, then\n"
   29370 		 "unfortunately Valgrind does not yet support e500 instructions.\n",
   29371 		 theInstr);
   29372       goto not_supported;
   29373    decode_noVX:
   29374       vassert(!allow_VX);
   29375       vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
   29376 		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
   29377 		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
   29378 		 theInstr);
   29379       goto not_supported;
   29380    decode_noFX:
   29381       vassert(!allow_FX);
   29382       vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
   29383 		 "that can't be handled by Valgrind on this host. This instruction\n"
   29384 		 "requires a host that supports the General Purpose-Optional instructions.\n",
   29385 		 theInstr);
   29386       goto not_supported;
   29387    decode_noGX:
   29388       vassert(!allow_GX);
   29389       vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
   29390 		 "that can't be handled by Valgrind on this host. This instruction\n"
   29391 		 "requires a host that supports the Graphic-Optional instructions.\n",
   29392 		 theInstr);
   29393       goto not_supported;
   29394    decode_noDFP:
   29395       vassert(!allow_DFP);
   29396       vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
   29397 		 "that can't be handled by Valgrind on this host.  This instruction\n"
   29398 		 "requires a host that supports DFP instructions.\n",
   29399 		 theInstr);
   29400       goto not_supported;
   29401    decode_noP8:
   29402       vassert(!allow_isa_2_07);
   29403       vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
   29404 		 "by Valgrind on this host.  This instruction requires a host that\n"
   29405 		 "supports Power 8 instructions.\n",
   29406 		 theInstr);
   29407       goto not_supported;
   29408 
   29409    decode_noP9:
   29410       vassert(!allow_isa_3_0);
   29411       vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n"
   29412                  "by Valgrind on this host.  This instruction requires a host that\n"
   29413 		 "supports Power 9 instructions.\n",
   29414 		 theInstr);
   29415       goto not_supported;
   29416 
   29417    decode_failure:
   29418    /* All decode failures end up here. */
   29419    opc2 = (theInstr) & 0x7FF;
   29420    if (sigill_diag) {
   29421       vex_printf("disInstr(ppc): unhandled instruction: "
   29422                  "0x%x\n", theInstr);
   29423       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   29424                  opc1, opc1, opc2, opc2);
   29425    }
   29426 
   29427    not_supported:
   29428    /* Tell the dispatcher that this insn cannot be decoded, and so has
   29429       not been executed, and (is currently) the next to be executed.
   29430       CIA should be up-to-date since it made so at the start of each
   29431       insn, but nevertheless be paranoid and update it again right
   29432       now. */
   29433    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   29434    dres.len         = 0;
   29435    dres.whatNext    = Dis_StopHere;
   29436    dres.jk_StopHere = Ijk_NoDecode;
   29437    dres.continueAt  = 0;
   29438    return dres;
   29439    } /* switch (opc) for the main (primary) opcode switch. */
   29440 
   29441   decode_success:
   29442    /* All decode successes end up here. */
   29443    switch (dres.whatNext) {
   29444       case Dis_Continue:
   29445          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
   29446          break;
   29447       case Dis_ResteerU:
   29448       case Dis_ResteerC:
   29449          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
   29450          break;
   29451       case Dis_StopHere:
   29452          break;
   29453       default:
   29454          vassert(0);
   29455    }
   29456    DIP("\n");
   29457 
   29458    if (dres.len == 0) {
   29459       dres.len = 4;
   29460    } else {
   29461       vassert(dres.len == 20);
   29462    }
   29463    return dres;
   29464 }
   29465 
   29466 #undef DIP
   29467 #undef DIS
   29468 
   29469 
   29470 /*------------------------------------------------------------*/
   29471 /*--- Top-level fn                                         ---*/
   29472 /*------------------------------------------------------------*/
   29473 
   29474 /* Disassemble a single instruction into IR.  The instruction
   29475    is located in host memory at &guest_code[delta]. */
   29476 
   29477 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   29478                          Bool         (*resteerOkFn) ( void*, Addr ),
   29479                          Bool         resteerCisOk,
   29480                          void*        callback_opaque,
   29481                          const UChar* guest_code_IN,
   29482                          Long         delta,
   29483                          Addr         guest_IP,
   29484                          VexArch      guest_arch,
   29485                          const VexArchInfo* archinfo,
   29486                          const VexAbiInfo*  abiinfo,
   29487                          VexEndness   host_endness_IN,
   29488                          Bool         sigill_diag_IN )
   29489 {
   29490    IRType     ty;
   29491    DisResult  dres;
   29492    UInt       mask32, mask64;
   29493    UInt hwcaps_guest = archinfo->hwcaps;
   29494 
   29495    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   29496 
   29497    /* global -- ick */
   29498    mode64 = guest_arch == VexArchPPC64;
   29499    ty = mode64 ? Ity_I64 : Ity_I32;
   29500    if (!mode64 && (host_endness_IN == VexEndnessLE)) {
   29501       vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
   29502       dres.len         = 0;
   29503       dres.whatNext    = Dis_StopHere;
   29504       dres.jk_StopHere = Ijk_NoDecode;
   29505       dres.continueAt   = 0;
   29506       dres.hint        = Dis_HintNone;
   29507       return dres;
   29508    }
   29509 
   29510    /* do some sanity checks */
   29511    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   29512             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   29513             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
   29514 
   29515    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   29516             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
   29517             | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0;
   29518 
   29519    if (mode64) {
   29520       vassert((hwcaps_guest & mask32) == 0);
   29521    } else {
   29522       vassert((hwcaps_guest & mask64) == 0);
   29523    }
   29524 
   29525    /* Set globals (see top of this file) */
   29526    guest_code           = guest_code_IN;
   29527    irsb                 = irsb_IN;
   29528    host_endness         = host_endness_IN;
   29529 
   29530    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   29531    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   29532 
   29533    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
   29534                              delta, archinfo, abiinfo, sigill_diag_IN);
   29535 
   29536    return dres;
   29537 }
   29538 
   29539 
   29540 /*------------------------------------------------------------*/
   29541 /*--- Unused stuff                                         ---*/
   29542 /*------------------------------------------------------------*/
   29543 
   29544 ///* A potentially more memcheck-friendly implementation of Clz32, with
   29545 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   29546 //
   29547 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   29548 //{
   29549 //   /* Welcome ... to SSA R Us. */
   29550 //   IRTemp n1  = newTemp(Ity_I32);
   29551 //   IRTemp n2  = newTemp(Ity_I32);
   29552 //   IRTemp n3  = newTemp(Ity_I32);
   29553 //   IRTemp n4  = newTemp(Ity_I32);
   29554 //   IRTemp n5  = newTemp(Ity_I32);
   29555 //   IRTemp n6  = newTemp(Ity_I32);
   29556 //   IRTemp n7  = newTemp(Ity_I32);
   29557 //   IRTemp n8  = newTemp(Ity_I32);
   29558 //   IRTemp n9  = newTemp(Ity_I32);
   29559 //   IRTemp n10 = newTemp(Ity_I32);
   29560 //   IRTemp n11 = newTemp(Ity_I32);
   29561 //   IRTemp n12 = newTemp(Ity_I32);
   29562 //
   29563 //   /* First, propagate the most significant 1-bit into all lower
   29564 //      positions in the word. */
   29565 //   /* unsigned int clz ( unsigned int n )
   29566 //      {
   29567 //         n |= (n >> 1);
   29568 //         n |= (n >> 2);
   29569 //         n |= (n >> 4);
   29570 //         n |= (n >> 8);
   29571 //         n |= (n >> 16);
   29572 //         return bitcount(~n);
   29573 //      }
   29574 //   */
   29575 //   assign(n1, mkexpr(arg));
   29576 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   29577 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   29578 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   29579 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   29580 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   29581 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   29582 //      a word of the form 1---10---0, then do a population-count idiom
   29583 //      (to count the 1s, which is the number of leading zeroes, or 32
   29584 //      if the original word was 0. */
   29585 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   29586 //
   29587 //   /* unsigned int bitcount ( unsigned int n )
   29588 //      {
   29589 //         n = n - ((n >> 1) & 0x55555555);
   29590 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   29591 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   29592 //         n = n + (n >> 8);
   29593 //         n = (n + (n >> 16)) & 0x3F;
   29594 //         return n;
   29595 //      }
   29596 //   */
   29597 //   assign(n8,
   29598 //          binop(Iop_Sub32,
   29599 //                mkexpr(n7),
   29600 //                binop(Iop_And32,
   29601 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   29602 //                      mkU32(0x55555555))));
   29603 //   assign(n9,
   29604 //          binop(Iop_Add32,
   29605 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   29606 //                binop(Iop_And32,
   29607 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   29608 //                      mkU32(0x33333333))));
   29609 //   assign(n10,
   29610 //          binop(Iop_And32,
   29611 //                binop(Iop_Add32,
   29612 //                      mkexpr(n9),
   29613 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   29614 //                mkU32(0x0F0F0F0F)));
   29615 //   assign(n11,
   29616 //          binop(Iop_Add32,
   29617 //                mkexpr(n10),
   29618 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   29619 //   assign(n12,
   29620 //          binop(Iop_Add32,
   29621 //                mkexpr(n11),
   29622 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   29623 //   return
   29624 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   29625 //}
   29626 
   29627 /*--------------------------------------------------------------------*/
   29628 /*--- end                                         guest_ppc_toIR.c ---*/
   29629 /*--------------------------------------------------------------------*/
   29630