Home | History | Annotate | Download | only in priv
      1 
      2 
      3 /*--------------------------------------------------------------------*/
      4 /*--- begin                                       guest_ppc_toIR.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2004-2013 OpenWorks LLP
     12       info (at) open-works.net
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     27    02110-1301, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 
     31    Neither the names of the U.S. Department of Energy nor the
     32    University of California nor the names of its contributors may be
     33    used to endorse or promote products derived from this software
     34    without prior written permission.
     35 */
     36 
     37 /* TODO 18/Nov/05:
     38 
     39    Spot rld... cases which are simply left/right shifts and emit
     40    Shl64/Shr64 accordingly.
     41 
     42    Altivec
     43    - datastream insns
     44    - lvxl,stvxl: load/store with 'least recently used' hint
     45    - vexptefp, vlogefp
     46 
     47    LIMITATIONS:
     48 
     49    Various, including:
     50 
     51    - Some invalid forms of lswi and lswx are accepted when they should
     52      not be.
     53 
     54    - Floating Point:
     55      - All exceptions disabled in FPSCR
     56      - condition codes not set in FPSCR
     57 
     58    - Altivec floating point:
     59      - vmaddfp, vnmsubfp
     60        Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
     61        system default of Non-Java mode, we get some small errors
     62        (lowest bit only).
     63        This is because Non-Java mode brutally hacks denormalised results
     64        to zero, whereas we keep maximum accuracy.  However, using
     65        Non-Java mode would give us more inaccuracy, as our intermediate
     66        results would then be zeroed, too.
     67 
     68    - AbiHints for the stack red zone are only emitted for
     69        unconditional calls and returns (bl, blr).  They should also be
     70        emitted for conditional calls and returns, but we don't have a
     71        way to express that right now.  Ah well.
     72 
     73    - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
     74        ignores the rounding mode, and generates code that assumes
     75        round-to-nearest.  This means V will compute incorrect results
     76        for uses of these IROps when the rounding mode (first) arg is
     77        not mkU32(Irrm_NEAREST).
     78 */
     79 
     80 /* "Special" instructions.
     81 
     82    This instruction decoder can decode four special instructions
     83    which mean nothing natively (are no-ops as far as regs/mem are
     84    concerned) but have meaning for supporting Valgrind.  A special
     85    instruction is flagged by a 16-byte preamble:
     86 
     87       32-bit mode: 5400183E 5400683E 5400E83E 5400983E
     88                    (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
     89                     rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
     90 
     91       64-bit mode: 78001800 78006800 7800E802 78009802
     92                    (rotldi 0,0,3; rotldi 0,0,13;
     93                     rotldi 0,0,61; rotldi 0,0,51)
     94 
     95    Following that, one of the following 3 are allowed
     96    (standard interpretation in parentheses):
     97 
     98       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
     99       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
    100       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
    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 
    111 /* Translates PPC32/64 code to IR. */
    112 
    113 /* References
    114 
    115 #define PPC32
    116    "PowerPC Microprocessor Family:
    117     The Programming Environments Manual for 32-Bit Microprocessors"
    118     02/21/2000
    119     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
    120 
    121 #define PPC64
    122    "PowerPC Microprocessor Family:
    123     Programming Environments Manual for 64-Bit Microprocessors"
    124     06/10/2003
    125    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
    126 
    127 #define AV
    128    "PowerPC Microprocessor Family:
    129     AltiVec(TM) Technology Programming Environments Manual"
    130     07/10/2003
    131    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
    132 */
    133 
    134 #include "libvex_basictypes.h"
    135 #include "libvex_ir.h"
    136 #include "libvex.h"
    137 #include "libvex_emnote.h"
    138 #include "libvex_guest_ppc32.h"
    139 #include "libvex_guest_ppc64.h"
    140 
    141 #include "main_util.h"
    142 #include "main_globals.h"
    143 #include "guest_generic_bb_to_IR.h"
    144 #include "guest_ppc_defs.h"
    145 
    146 
    147 /*------------------------------------------------------------*/
    148 /*--- Globals                                              ---*/
    149 /*------------------------------------------------------------*/
    150 
    151 /* These are set at the start of the translation of an insn, right
    152    down in disInstr_PPC, so that we don't have to pass them around
    153    endlessly.  They are all constant during the translation of any
    154    given insn. */
    155 
    156 /* We need to know this to do sub-register accesses correctly. */
    157 static Bool host_is_bigendian;
    158 
    159 /* Pointer to the guest code area. */
    160 static UChar* guest_code;
    161 
    162 /* The guest address corresponding to guest_code[0]. */
    163 static Addr64 guest_CIA_bbstart;
    164 
    165 /* The guest address for the instruction currently being
    166    translated. */
    167 static Addr64 guest_CIA_curr_instr;
    168 
    169 /* The IRSB* into which we're generating code. */
    170 static IRSB* irsb;
    171 
    172 /* Is our guest binary 32 or 64bit?  Set at each call to
    173    disInstr_PPC below. */
    174 static Bool mode64 = False;
    175 
    176 // Given a pointer to a function as obtained by "& functionname" in C,
    177 // produce a pointer to the actual entry point for the function.  For
    178 // most platforms it's the identity function.  Unfortunately, on
    179 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
    180 // ppc64-aix5.
    181 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
    182 {
    183    if (vbi->host_ppc_calls_use_fndescrs) {
    184       /* f is a pointer to a 3-word function descriptor, of which the
    185          first word is the entry address. */
    186       /* note, this is correct even with cross-jitting, since this is
    187          purely a host issue, not a guest one. */
    188       HWord* fdescr = (HWord*)f;
    189       return (void*)(fdescr[0]);
    190    } else {
    191       /* Simple; "& f" points directly at the code for f. */
    192       return f;
    193    }
    194 }
    195 
    196 #define SIGN_BIT  0x8000000000000000ULL
    197 #define SIGN_MASK 0x7fffffffffffffffULL
    198 #define SIGN_BIT32  0x80000000
    199 #define SIGN_MASK32 0x7fffffff
    200 
    201 
    202 /*------------------------------------------------------------*/
    203 /*--- Debugging output                                     ---*/
    204 /*------------------------------------------------------------*/
    205 
    206 #define DIP(format, args...)           \
    207    if (vex_traceflags & VEX_TRACE_FE)  \
    208       vex_printf(format, ## args)
    209 
    210 #define DIS(buf, format, args...)      \
    211    if (vex_traceflags & VEX_TRACE_FE)  \
    212       vex_sprintf(buf, format, ## args)
    213 
    214 
    215 /*------------------------------------------------------------*/
    216 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
    217 /*------------------------------------------------------------*/
    218 
    219 #define offsetofPPCGuestState(_x) \
    220    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
    221              offsetof(VexGuestPPC32State, _x))
    222 
    223 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
    224 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
    225 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
    226 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
    227 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
    228 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
    229 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
    230 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
    231 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
    232 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
    233 #define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
    234 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
    235 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
    236 #define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
    237 #define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
    238 #define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
    239 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
    240 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
    241 #define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
    242 #define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
    243 #define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
    244 
    245 
    246 /*------------------------------------------------------------*/
    247 /*--- Extract instruction fields                          --- */
    248 /*------------------------------------------------------------*/
    249 
    250 /* Extract field from insn, given idx (zero = lsb) and field length */
    251 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    252 
    253 /* Extract primary opcode, instr[31:26] */
    254 static UChar ifieldOPC( UInt instr ) {
    255    return toUChar( IFIELD( instr, 26, 6 ) );
    256 }
    257 
    258 /* Extract 10-bit secondary opcode, instr[10:1] */
    259 static UInt ifieldOPClo10 ( UInt instr) {
    260    return IFIELD( instr, 1, 10 );
    261 }
    262 
    263 /* Extract 9-bit secondary opcode, instr[9:1] */
    264 static UInt ifieldOPClo9 ( UInt instr) {
    265    return IFIELD( instr, 1, 9 );
    266 }
    267 
    268 /* Extract 8-bit secondary opcode, instr[8:1] */
    269 static UInt ifieldOPClo8 ( UInt instr) {
    270    return IFIELD( instr, 1, 8 );
    271 }
    272 
    273 /* Extract 5-bit secondary opcode, instr[5:1] */
    274 static UInt ifieldOPClo5 ( UInt instr) {
    275    return IFIELD( instr, 1, 5 );
    276 }
    277 
    278 /* Extract RD (destination register) field, instr[25:21] */
    279 static UChar ifieldRegDS( UInt instr ) {
    280    return toUChar( IFIELD( instr, 21, 5 ) );
    281 }
    282 
    283 /* Extract XT (destination register) field, instr[0,25:21] */
    284 static UChar ifieldRegXT ( UInt instr )
    285 {
    286   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
    287   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
    288   return (upper_bit << 5) | lower_bits;
    289 }
    290 
    291 /* Extract XS (store source register) field, instr[0,25:21] */
    292 static inline UChar ifieldRegXS ( UInt instr )
    293 {
    294   return ifieldRegXT ( instr );
    295 }
    296 
    297 /* Extract RA (1st source register) field, instr[20:16] */
    298 static UChar ifieldRegA ( UInt instr ) {
    299    return toUChar( IFIELD( instr, 16, 5 ) );
    300 }
    301 
    302 /* Extract XA (1st source register) field, instr[2,20:16] */
    303 static UChar ifieldRegXA ( UInt instr )
    304 {
    305   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
    306   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
    307   return (upper_bit << 5) | lower_bits;
    308 }
    309 
    310 /* Extract RB (2nd source register) field, instr[15:11] */
    311 static UChar ifieldRegB ( UInt instr ) {
    312    return toUChar( IFIELD( instr, 11, 5 ) );
    313 }
    314 
    315 /* Extract XB (2nd source register) field, instr[1,15:11] */
    316 static UChar ifieldRegXB ( UInt instr )
    317 {
    318   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
    319   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
    320   return (upper_bit << 5) | lower_bits;
    321 }
    322 
    323 /* Extract RC (3rd source register) field, instr[10:6] */
    324 static UChar ifieldRegC ( UInt instr ) {
    325    return toUChar( IFIELD( instr, 6, 5 ) );
    326 }
    327 
    328 /* Extract XC (3rd source register) field, instr[3,10:6] */
    329 static UChar ifieldRegXC ( UInt instr )
    330 {
    331   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
    332   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
    333   return (upper_bit << 5) | lower_bits;
    334 }
    335 
    336 /* Extract bit 10, instr[10] */
    337 static UChar ifieldBIT10 ( UInt instr ) {
    338    return toUChar( IFIELD( instr, 10, 1 ) );
    339 }
    340 
    341 /* Extract 2nd lowest bit, instr[1] */
    342 static UChar ifieldBIT1 ( UInt instr ) {
    343    return toUChar( IFIELD( instr, 1, 1 ) );
    344 }
    345 
    346 /* Extract lowest bit, instr[0] */
    347 static UChar ifieldBIT0 ( UInt instr ) {
    348    return toUChar( instr & 0x1 );
    349 }
    350 
    351 /* Extract unsigned bottom half, instr[15:0] */
    352 static UInt ifieldUIMM16 ( UInt instr ) {
    353    return instr & 0xFFFF;
    354 }
    355 
    356 /* Extract unsigned bottom 26 bits, instr[25:0] */
    357 static UInt ifieldUIMM26 ( UInt instr ) {
    358    return instr & 0x3FFFFFF;
    359 }
    360 
    361 /* Extract DM field, instr[9:8] */
    362 static UChar ifieldDM ( UInt instr ) {
    363    return toUChar( IFIELD( instr, 8, 2 ) );
    364 }
    365 
    366 /* Extract SHW field, instr[9:8] */
    367 static inline UChar ifieldSHW ( UInt instr )
    368 {
    369   return ifieldDM ( instr );
    370 }
    371 
    372 /*------------------------------------------------------------*/
    373 /*--- Guest-state identifiers                              ---*/
    374 /*------------------------------------------------------------*/
    375 
    376 typedef enum {
    377     PPC_GST_CIA,    // Current Instruction Address
    378     PPC_GST_LR,     // Link Register
    379     PPC_GST_CTR,    // Count Register
    380     PPC_GST_XER,    // Overflow, carry flags, byte count
    381     PPC_GST_CR,     // Condition Register
    382     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    383     PPC_GST_VRSAVE, // Vector Save/Restore Register
    384     PPC_GST_VSCR,   // Vector Status and Control Register
    385     PPC_GST_EMWARN, // Emulation warnings
    386     PPC_GST_CMSTART,// For icbi: start of area to invalidate
    387     PPC_GST_CMLEN,  // For icbi: length of area to invalidate
    388     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    389     PPC_GST_SPRG3_RO, // SPRG3
    390     PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
    391     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
    392     PPC_GST_TEXASR, // Transactional EXception And Summary Register
    393     PPC_GST_MAX
    394 } PPC_GST;
    395 
    396 #define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
    397 #define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
    398 #define MASK_VSCR_VALID 0x00010001
    399 
    400 
    401 /*------------------------------------------------------------*/
    402 /*---  FP Helpers                                          ---*/
    403 /*------------------------------------------------------------*/
    404 
    405 /* Produce the 32-bit pattern corresponding to the supplied
    406    float. */
    407 static UInt float_to_bits ( Float f )
    408 {
    409    union { UInt i; Float f; } u;
    410    vassert(4 == sizeof(UInt));
    411    vassert(4 == sizeof(Float));
    412    vassert(4 == sizeof(u));
    413    u.f = f;
    414    return u.i;
    415 }
    416 
    417 
    418 /*------------------------------------------------------------*/
    419 /*--- Misc Helpers                                         ---*/
    420 /*------------------------------------------------------------*/
    421 
    422 /* Generate mask with 1's from 'begin' through 'end',
    423    wrapping if begin > end.
    424    begin->end works from right to left, 0=lsb
    425 */
    426 static UInt MASK32( UInt begin, UInt end )
    427 {
    428    UInt m1, m2, mask;
    429    vassert(begin < 32);
    430    vassert(end < 32);
    431    m1   = ((UInt)(-1)) << begin;
    432    m2   = ((UInt)(-1)) << end << 1;
    433    mask = m1 ^ m2;
    434    if (begin > end) mask = ~mask;  // wrap mask
    435    return mask;
    436 }
    437 
    438 static ULong MASK64( UInt begin, UInt end )
    439 {
    440    ULong m1, m2, mask;
    441    vassert(begin < 64);
    442    vassert(end < 64);
    443    m1   = ((ULong)(-1)) << begin;
    444    m2   = ((ULong)(-1)) << end << 1;
    445    mask = m1 ^ m2;
    446    if (begin > end) mask = ~mask;  // wrap mask
    447    return mask;
    448 }
    449 
    450 static Addr64 nextInsnAddr( void )
    451 {
    452    return guest_CIA_curr_instr + 4;
    453 }
    454 
    455 
    456 /*------------------------------------------------------------*/
    457 /*--- Helper bits and pieces for deconstructing the        ---*/
    458 /*--- ppc32/64 insn stream.                                ---*/
    459 /*------------------------------------------------------------*/
    460 
    461 /* Add a statement to the list held by "irsb". */
    462 static void stmt ( IRStmt* st )
    463 {
    464    addStmtToIRSB( irsb, st );
    465 }
    466 
    467 /* Generate a new temporary of the given type. */
    468 static IRTemp newTemp ( IRType ty )
    469 {
    470    vassert(isPlausibleIRType(ty));
    471    return newIRTemp( irsb->tyenv, ty );
    472 }
    473 
    474 /* Various simple conversions */
    475 
    476 static UChar extend_s_5to8 ( UChar x )
    477 {
    478    return toUChar((((Int)x) << 27) >> 27);
    479 }
    480 
    481 static UInt extend_s_8to32( UChar x )
    482 {
    483    return (UInt)((((Int)x) << 24) >> 24);
    484 }
    485 
    486 static UInt extend_s_16to32 ( UInt x )
    487 {
    488    return (UInt)((((Int)x) << 16) >> 16);
    489 }
    490 
    491 static ULong extend_s_16to64 ( UInt x )
    492 {
    493    return (ULong)((((Long)x) << 48) >> 48);
    494 }
    495 
    496 static ULong extend_s_26to64 ( UInt x )
    497 {
    498    return (ULong)((((Long)x) << 38) >> 38);
    499 }
    500 
    501 static ULong extend_s_32to64 ( UInt x )
    502 {
    503    return (ULong)((((Long)x) << 32) >> 32);
    504 }
    505 
    506 /* Do a big-endian load of a 32-bit word, regardless of the endianness
    507    of the underlying host. */
    508 static UInt getUIntBigendianly ( UChar* p )
    509 {
    510    UInt w = 0;
    511    w = (w << 8) | p[0];
    512    w = (w << 8) | p[1];
    513    w = (w << 8) | p[2];
    514    w = (w << 8) | p[3];
    515    return w;
    516 }
    517 
    518 
    519 /*------------------------------------------------------------*/
    520 /*--- Helpers for constructing IR.                         ---*/
    521 /*------------------------------------------------------------*/
    522 
    523 static void assign ( IRTemp dst, IRExpr* e )
    524 {
    525    stmt( IRStmt_WrTmp(dst, e) );
    526 }
    527 
    528 /* This generates a normal (non store-conditional) store. */
    529 static void storeBE ( IRExpr* addr, IRExpr* data )
    530 {
    531    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    532    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    533    stmt( IRStmt_Store(Iend_BE, addr, data) );
    534 }
    535 
    536 static IRExpr* unop ( IROp op, IRExpr* a )
    537 {
    538    return IRExpr_Unop(op, a);
    539 }
    540 
    541 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    542 {
    543    return IRExpr_Binop(op, a1, a2);
    544 }
    545 
    546 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    547 {
    548    return IRExpr_Triop(op, a1, a2, a3);
    549 }
    550 
    551 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    552                               IRExpr* a3, IRExpr* a4 )
    553 {
    554    return IRExpr_Qop(op, a1, a2, a3, a4);
    555 }
    556 
    557 static IRExpr* mkexpr ( IRTemp tmp )
    558 {
    559    return IRExpr_RdTmp(tmp);
    560 }
    561 
    562 static IRExpr* mkU8 ( UChar i )
    563 {
    564    return IRExpr_Const(IRConst_U8(i));
    565 }
    566 
    567 static IRExpr* mkU16 ( UInt i )
    568 {
    569    return IRExpr_Const(IRConst_U16(i));
    570 }
    571 
    572 static IRExpr* mkU32 ( UInt i )
    573 {
    574    return IRExpr_Const(IRConst_U32(i));
    575 }
    576 
    577 static IRExpr* mkU64 ( ULong i )
    578 {
    579    return IRExpr_Const(IRConst_U64(i));
    580 }
    581 
    582 static IRExpr* mkV128 ( UShort i )
    583 {
    584    vassert(i == 0 || i == 0xffff);
    585    return IRExpr_Const(IRConst_V128(i));
    586 }
    587 
    588 /* This generates a normal (non load-linked) load. */
    589 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
    590 {
    591    return IRExpr_Load(Iend_BE, ty, addr);
    592 }
    593 
    594 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    595 {
    596    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    597    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    598    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    599                                           unop(Iop_1Uto32, arg2)));
    600 }
    601 
    602 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    603 {
    604    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    605    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    606    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    607                                            unop(Iop_1Uto32, arg2)));
    608 }
    609 
    610 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    611 static void expand8Ux16( IRExpr* vIn,
    612                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    613 {
    614    IRTemp ones8x16 = newTemp(Ity_V128);
    615 
    616    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    617    vassert(vEvn && *vEvn == IRTemp_INVALID);
    618    vassert(vOdd && *vOdd == IRTemp_INVALID);
    619    *vEvn = newTemp(Ity_V128);
    620    *vOdd = newTemp(Ity_V128);
    621 
    622    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    623    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    624    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    625                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    626 }
    627 
    628 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    629 static void expand8Sx16( IRExpr* vIn,
    630                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    631 {
    632    IRTemp ones8x16 = newTemp(Ity_V128);
    633 
    634    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    635    vassert(vEvn && *vEvn == IRTemp_INVALID);
    636    vassert(vOdd && *vOdd == IRTemp_INVALID);
    637    *vEvn = newTemp(Ity_V128);
    638    *vOdd = newTemp(Ity_V128);
    639 
    640    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    641    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    642    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    643                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    644 }
    645 
    646 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    647 static void expand16Ux8( IRExpr* vIn,
    648                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    649 {
    650    IRTemp ones16x8 = newTemp(Ity_V128);
    651 
    652    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    653    vassert(vEvn && *vEvn == IRTemp_INVALID);
    654    vassert(vOdd && *vOdd == IRTemp_INVALID);
    655    *vEvn = newTemp(Ity_V128);
    656    *vOdd = newTemp(Ity_V128);
    657 
    658    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    659    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    660    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    661                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    662 }
    663 
    664 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    665 static void expand16Sx8( IRExpr* vIn,
    666                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    667 {
    668    IRTemp ones16x8 = newTemp(Ity_V128);
    669 
    670    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    671    vassert(vEvn && *vEvn == IRTemp_INVALID);
    672    vassert(vOdd && *vOdd == IRTemp_INVALID);
    673    *vEvn = newTemp(Ity_V128);
    674    *vOdd = newTemp(Ity_V128);
    675 
    676    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    677    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    678    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    679                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    680 }
    681 
    682 /* break V128 to 4xF64's*/
    683 static void breakV128to4xF64( IRExpr* t128,
    684                               /*OUTs*/
    685                               IRTemp* t3, IRTemp* t2,
    686                               IRTemp* t1, IRTemp* t0 )
    687 {
    688    IRTemp hi64 = newTemp(Ity_I64);
    689    IRTemp lo64 = newTemp(Ity_I64);
    690 
    691    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    692    vassert(t0 && *t0 == IRTemp_INVALID);
    693    vassert(t1 && *t1 == IRTemp_INVALID);
    694    vassert(t2 && *t2 == IRTemp_INVALID);
    695    vassert(t3 && *t3 == IRTemp_INVALID);
    696    *t0 = newTemp(Ity_F64);
    697    *t1 = newTemp(Ity_F64);
    698    *t2 = newTemp(Ity_F64);
    699    *t3 = newTemp(Ity_F64);
    700 
    701    assign( hi64, unop(Iop_V128HIto64, t128) );
    702    assign( lo64, unop(Iop_V128to64,   t128) );
    703    assign( *t3,
    704            unop( Iop_F32toF64,
    705                  unop( Iop_ReinterpI32asF32,
    706                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
    707    assign( *t2,
    708            unop( Iop_F32toF64,
    709                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
    710    assign( *t1,
    711            unop( Iop_F32toF64,
    712                  unop( Iop_ReinterpI32asF32,
    713                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
    714    assign( *t0,
    715            unop( Iop_F32toF64,
    716                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
    717 }
    718 
    719 
    720 /* break V128 to 4xI32's, then sign-extend to I64's */
    721 static void breakV128to4x64S( IRExpr* t128,
    722                               /*OUTs*/
    723                               IRTemp* t3, IRTemp* t2,
    724                               IRTemp* t1, IRTemp* t0 )
    725 {
    726    IRTemp hi64 = newTemp(Ity_I64);
    727    IRTemp lo64 = newTemp(Ity_I64);
    728 
    729    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    730    vassert(t0 && *t0 == IRTemp_INVALID);
    731    vassert(t1 && *t1 == IRTemp_INVALID);
    732    vassert(t2 && *t2 == IRTemp_INVALID);
    733    vassert(t3 && *t3 == IRTemp_INVALID);
    734    *t0 = newTemp(Ity_I64);
    735    *t1 = newTemp(Ity_I64);
    736    *t2 = newTemp(Ity_I64);
    737    *t3 = newTemp(Ity_I64);
    738 
    739    assign( hi64, unop(Iop_V128HIto64, t128) );
    740    assign( lo64, unop(Iop_V128to64,   t128) );
    741    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    742    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    743    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    744    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    745 }
    746 
    747 /* break V128 to 4xI32's, then zero-extend to I64's */
    748 static void breakV128to4x64U ( IRExpr* t128,
    749                                /*OUTs*/
    750                                IRTemp* t3, IRTemp* t2,
    751                                IRTemp* t1, IRTemp* t0 )
    752 {
    753    IRTemp hi64 = newTemp(Ity_I64);
    754    IRTemp lo64 = newTemp(Ity_I64);
    755 
    756    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    757    vassert(t0 && *t0 == IRTemp_INVALID);
    758    vassert(t1 && *t1 == IRTemp_INVALID);
    759    vassert(t2 && *t2 == IRTemp_INVALID);
    760    vassert(t3 && *t3 == IRTemp_INVALID);
    761    *t0 = newTemp(Ity_I64);
    762    *t1 = newTemp(Ity_I64);
    763    *t2 = newTemp(Ity_I64);
    764    *t3 = newTemp(Ity_I64);
    765 
    766    assign( hi64, unop(Iop_V128HIto64, t128) );
    767    assign( lo64, unop(Iop_V128to64,   t128) );
    768    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    769    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    770    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    771    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    772 }
    773 
    774 static void breakV128to4x32( IRExpr* t128,
    775                               /*OUTs*/
    776                               IRTemp* t3, IRTemp* t2,
    777                               IRTemp* t1, IRTemp* t0 )
    778 {
    779    IRTemp hi64 = newTemp(Ity_I64);
    780    IRTemp lo64 = newTemp(Ity_I64);
    781 
    782    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    783    vassert(t0 && *t0 == IRTemp_INVALID);
    784    vassert(t1 && *t1 == IRTemp_INVALID);
    785    vassert(t2 && *t2 == IRTemp_INVALID);
    786    vassert(t3 && *t3 == IRTemp_INVALID);
    787    *t0 = newTemp(Ity_I32);
    788    *t1 = newTemp(Ity_I32);
    789    *t2 = newTemp(Ity_I32);
    790    *t3 = newTemp(Ity_I32);
    791 
    792    assign( hi64, unop(Iop_V128HIto64, t128) );
    793    assign( lo64, unop(Iop_V128to64,   t128) );
    794    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
    795    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
    796    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
    797    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
    798 }
    799 
    800 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
    801                                IRTemp t1, IRTemp t0 )
    802 {
    803    return
    804       binop( Iop_64HLtoV128,
    805              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
    806              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
    807    );
    808 }
    809 
    810 
    811 /* Signed saturating narrow 64S to 32 */
    812 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    813 {
    814    IRTemp hi32 = newTemp(Ity_I32);
    815    IRTemp lo32 = newTemp(Ity_I32);
    816 
    817    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    818 
    819    assign( hi32, unop(Iop_64HIto32, t64));
    820    assign( lo32, unop(Iop_64to32,   t64));
    821 
    822    return IRExpr_ITE(
    823              /* if (hi32 == (lo32 >>s 31)) */
    824              binop(Iop_CmpEQ32, mkexpr(hi32),
    825                    binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
    826              /* then: within signed-32 range: lo half good enough */
    827              mkexpr(lo32),
    828              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    829              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    830                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
    831 }
    832 
    833 /* Unsigned saturating narrow 64S to 32 */
    834 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    835 {
    836    IRTemp hi32 = newTemp(Ity_I32);
    837    IRTemp lo32 = newTemp(Ity_I32);
    838 
    839    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    840 
    841    assign( hi32, unop(Iop_64HIto32, t64));
    842    assign( lo32, unop(Iop_64to32,   t64));
    843 
    844    return IRExpr_ITE(
    845             /* if (top 32 bits of t64 are 0) */
    846             binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
    847             /* then: within unsigned-32 range: lo half good enough */
    848             mkexpr(lo32),
    849             /* else: positive saturate -> 0xFFFFFFFF */
    850             mkU32(0xFFFFFFFF));
    851 }
    852 
    853 /* Signed saturate narrow 64->32, combining to V128 */
    854 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    855                                  IRExpr* t1, IRExpr* t0 )
    856 {
    857    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    858    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    859    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    860    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    861    return binop(Iop_64HLtoV128,
    862                 binop(Iop_32HLto64,
    863                       mkQNarrow64Sto32( t3 ),
    864                       mkQNarrow64Sto32( t2 )),
    865                 binop(Iop_32HLto64,
    866                       mkQNarrow64Sto32( t1 ),
    867                       mkQNarrow64Sto32( t0 )));
    868 }
    869 
    870 /* Unsigned saturate narrow 64->32, combining to V128 */
    871 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    872                                  IRExpr* t1, IRExpr* t0 )
    873 {
    874    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    875    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    876    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    877    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    878    return binop(Iop_64HLtoV128,
    879                 binop(Iop_32HLto64,
    880                       mkQNarrow64Uto32( t3 ),
    881                       mkQNarrow64Uto32( t2 )),
    882                 binop(Iop_32HLto64,
    883                       mkQNarrow64Uto32( t1 ),
    884                       mkQNarrow64Uto32( t0 )));
    885 }
    886 
    887 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    888 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    889       binop(Iop_MullEven8Ux16, \
    890             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    891             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    892 
    893 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    894       binop(Iop_MullEven8Sx16, \
    895             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    896             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    897 
    898 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    899       binop(Iop_MullEven16Ux8, \
    900             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    901             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    902 
    903 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
    904       binop(Iop_MullEven32Ux4, \
    905             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    906             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    907 
    908 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    909       binop(Iop_MullEven16Sx8, \
    910             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    911             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    912 
    913 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
    914       binop(Iop_MullEven32Sx4, \
    915             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    916             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    917 
    918 
    919 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
    920 {
    921    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    922    return unop(Iop_32Sto64, unop(Iop_64to32, src));
    923 }
    924 
    925 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
    926 {
    927    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    928    return unop(Iop_32Uto64, unop(Iop_64to32, src));
    929 }
    930 
    931 static IROp mkSzOp ( IRType ty, IROp op8 )
    932 {
    933    Int adj;
    934    vassert(ty == Ity_I8  || ty == Ity_I16 ||
    935            ty == Ity_I32 || ty == Ity_I64);
    936    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
    937            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
    938            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
    939            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
    940            op8 == Iop_Not8 );
    941    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
    942    return adj + op8;
    943 }
    944 
    945 /* Make sure we get valid 32 and 64bit addresses */
    946 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
    947 {
    948    vassert(ty == Ity_I32 || ty == Ity_I64);
    949    return ( ty == Ity_I64 ?
    950             (Addr64)addr :
    951             (Addr64)extend_s_32to64( toUInt(addr) ) );
    952 }
    953 
    954 /* sz, ULong -> IRExpr */
    955 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
    956 {
    957    vassert(ty == Ity_I32 || ty == Ity_I64);
    958    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
    959 }
    960 
    961 /* sz, ULong -> IRConst */
    962 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
    963 {
    964    vassert(ty == Ity_I32 || ty == Ity_I64);
    965    return ( ty == Ity_I64 ?
    966             IRConst_U64(imm64) :
    967             IRConst_U32((UInt)imm64) );
    968 }
    969 
    970 /* Sign extend imm16 -> IRExpr* */
    971 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
    972 {
    973    vassert(ty == Ity_I32 || ty == Ity_I64);
    974    return ( ty == Ity_I64 ?
    975             mkU64(extend_s_16to64(imm16)) :
    976             mkU32(extend_s_16to32(imm16)) );
    977 }
    978 
    979 /* Sign extend imm32 -> IRExpr* */
    980 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
    981 {
    982    vassert(ty == Ity_I32 || ty == Ity_I64);
    983    return ( ty == Ity_I64 ?
    984             mkU64(extend_s_32to64(imm32)) :
    985             mkU32(imm32) );
    986 }
    987 
    988 /* IR narrows I32/I64 -> I8/I16/I32 */
    989 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
    990 {
    991    vassert(ty == Ity_I32 || ty == Ity_I64);
    992    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
    993 }
    994 
    995 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
    996 {
    997    vassert(ty == Ity_I32 || ty == Ity_I64);
    998    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
    999 }
   1000 
   1001 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
   1002 {
   1003    vassert(ty == Ity_I32 || ty == Ity_I64);
   1004    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
   1005 }
   1006 
   1007 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
   1008 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
   1009 {
   1010    IROp op;
   1011    vassert(ty == Ity_I32 || ty == Ity_I64);
   1012    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
   1013    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
   1014    return unop(op, src);
   1015 }
   1016 
   1017 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
   1018 {
   1019    IROp op;
   1020    vassert(ty == Ity_I32 || ty == Ity_I64);
   1021    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
   1022    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
   1023    return unop(op, src);
   1024 }
   1025 
   1026 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
   1027 {
   1028    vassert(ty == Ity_I32 || ty == Ity_I64);
   1029    if (ty == Ity_I32)
   1030       return src;
   1031    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
   1032 }
   1033 
   1034 
   1035 static Int integerGuestRegOffset ( UInt archreg )
   1036 {
   1037    vassert(archreg < 32);
   1038 
   1039    // jrs: probably not necessary; only matters if we reference sub-parts
   1040    // of the ppc registers, but that isn't the case
   1041    // later: this might affect Altivec though?
   1042    vassert(host_is_bigendian);
   1043 
   1044    switch (archreg) {
   1045    case  0: return offsetofPPCGuestState(guest_GPR0);
   1046    case  1: return offsetofPPCGuestState(guest_GPR1);
   1047    case  2: return offsetofPPCGuestState(guest_GPR2);
   1048    case  3: return offsetofPPCGuestState(guest_GPR3);
   1049    case  4: return offsetofPPCGuestState(guest_GPR4);
   1050    case  5: return offsetofPPCGuestState(guest_GPR5);
   1051    case  6: return offsetofPPCGuestState(guest_GPR6);
   1052    case  7: return offsetofPPCGuestState(guest_GPR7);
   1053    case  8: return offsetofPPCGuestState(guest_GPR8);
   1054    case  9: return offsetofPPCGuestState(guest_GPR9);
   1055    case 10: return offsetofPPCGuestState(guest_GPR10);
   1056    case 11: return offsetofPPCGuestState(guest_GPR11);
   1057    case 12: return offsetofPPCGuestState(guest_GPR12);
   1058    case 13: return offsetofPPCGuestState(guest_GPR13);
   1059    case 14: return offsetofPPCGuestState(guest_GPR14);
   1060    case 15: return offsetofPPCGuestState(guest_GPR15);
   1061    case 16: return offsetofPPCGuestState(guest_GPR16);
   1062    case 17: return offsetofPPCGuestState(guest_GPR17);
   1063    case 18: return offsetofPPCGuestState(guest_GPR18);
   1064    case 19: return offsetofPPCGuestState(guest_GPR19);
   1065    case 20: return offsetofPPCGuestState(guest_GPR20);
   1066    case 21: return offsetofPPCGuestState(guest_GPR21);
   1067    case 22: return offsetofPPCGuestState(guest_GPR22);
   1068    case 23: return offsetofPPCGuestState(guest_GPR23);
   1069    case 24: return offsetofPPCGuestState(guest_GPR24);
   1070    case 25: return offsetofPPCGuestState(guest_GPR25);
   1071    case 26: return offsetofPPCGuestState(guest_GPR26);
   1072    case 27: return offsetofPPCGuestState(guest_GPR27);
   1073    case 28: return offsetofPPCGuestState(guest_GPR28);
   1074    case 29: return offsetofPPCGuestState(guest_GPR29);
   1075    case 30: return offsetofPPCGuestState(guest_GPR30);
   1076    case 31: return offsetofPPCGuestState(guest_GPR31);
   1077    default: break;
   1078    }
   1079    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
   1080 }
   1081 
   1082 static IRExpr* getIReg ( UInt archreg )
   1083 {
   1084    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1085    vassert(archreg < 32);
   1086    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
   1087 }
   1088 
   1089 /* Ditto, but write to a reg instead. */
   1090 static void putIReg ( UInt archreg, IRExpr* e )
   1091 {
   1092    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1093    vassert(archreg < 32);
   1094    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
   1095    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
   1096 }
   1097 
   1098 
   1099 /* Floating point egisters are mapped to VSX registers[0..31]. */
   1100 static Int floatGuestRegOffset ( UInt archreg )
   1101 {
   1102    vassert(archreg < 32);
   1103 
   1104    switch (archreg) {
   1105    case  0: return offsetofPPCGuestState(guest_VSR0);
   1106    case  1: return offsetofPPCGuestState(guest_VSR1);
   1107    case  2: return offsetofPPCGuestState(guest_VSR2);
   1108    case  3: return offsetofPPCGuestState(guest_VSR3);
   1109    case  4: return offsetofPPCGuestState(guest_VSR4);
   1110    case  5: return offsetofPPCGuestState(guest_VSR5);
   1111    case  6: return offsetofPPCGuestState(guest_VSR6);
   1112    case  7: return offsetofPPCGuestState(guest_VSR7);
   1113    case  8: return offsetofPPCGuestState(guest_VSR8);
   1114    case  9: return offsetofPPCGuestState(guest_VSR9);
   1115    case 10: return offsetofPPCGuestState(guest_VSR10);
   1116    case 11: return offsetofPPCGuestState(guest_VSR11);
   1117    case 12: return offsetofPPCGuestState(guest_VSR12);
   1118    case 13: return offsetofPPCGuestState(guest_VSR13);
   1119    case 14: return offsetofPPCGuestState(guest_VSR14);
   1120    case 15: return offsetofPPCGuestState(guest_VSR15);
   1121    case 16: return offsetofPPCGuestState(guest_VSR16);
   1122    case 17: return offsetofPPCGuestState(guest_VSR17);
   1123    case 18: return offsetofPPCGuestState(guest_VSR18);
   1124    case 19: return offsetofPPCGuestState(guest_VSR19);
   1125    case 20: return offsetofPPCGuestState(guest_VSR20);
   1126    case 21: return offsetofPPCGuestState(guest_VSR21);
   1127    case 22: return offsetofPPCGuestState(guest_VSR22);
   1128    case 23: return offsetofPPCGuestState(guest_VSR23);
   1129    case 24: return offsetofPPCGuestState(guest_VSR24);
   1130    case 25: return offsetofPPCGuestState(guest_VSR25);
   1131    case 26: return offsetofPPCGuestState(guest_VSR26);
   1132    case 27: return offsetofPPCGuestState(guest_VSR27);
   1133    case 28: return offsetofPPCGuestState(guest_VSR28);
   1134    case 29: return offsetofPPCGuestState(guest_VSR29);
   1135    case 30: return offsetofPPCGuestState(guest_VSR30);
   1136    case 31: return offsetofPPCGuestState(guest_VSR31);
   1137    default: break;
   1138    }
   1139    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
   1140 }
   1141 
   1142 static IRExpr* getFReg ( UInt archreg )
   1143 {
   1144    vassert(archreg < 32);
   1145    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
   1146 }
   1147 
   1148 /* Ditto, but write to a reg instead. */
   1149 static void putFReg ( UInt archreg, IRExpr* e )
   1150 {
   1151    vassert(archreg < 32);
   1152    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1153    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
   1154 }
   1155 
   1156 /* get Decimal float value.  Note, they share floating point register file. */
   1157 static IRExpr* getDReg(UInt archreg) {
   1158    IRExpr *e;
   1159    vassert( archreg < 32 );
   1160    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
   1161    return e;
   1162 }
   1163 static IRExpr* getDReg32(UInt archreg) {
   1164    IRExpr *e;
   1165    vassert( archreg < 32 );
   1166    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
   1167    return e;
   1168 }
   1169 
   1170 /* Read a floating point register pair and combine their contents into a
   1171  128-bit value */
   1172 static IRExpr *getDReg_pair(UInt archreg) {
   1173    IRExpr *high = getDReg( archreg );
   1174    IRExpr *low = getDReg( archreg + 1 );
   1175 
   1176    return binop( Iop_D64HLtoD128, high, low );
   1177 }
   1178 
   1179 /* Ditto, but write to a reg instead. */
   1180 static void putDReg32(UInt archreg, IRExpr* e) {
   1181    vassert( archreg < 32 );
   1182    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
   1183    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1184 }
   1185 
   1186 static void putDReg(UInt archreg, IRExpr* e) {
   1187    vassert( archreg < 32 );
   1188    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
   1189    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1190 }
   1191 
   1192 /* Write a 128-bit floating point value into a register pair. */
   1193 static void putDReg_pair(UInt archreg, IRExpr *e) {
   1194    IRTemp low = newTemp( Ity_D64 );
   1195    IRTemp high = newTemp( Ity_D64 );
   1196 
   1197    vassert( archreg < 32 );
   1198    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
   1199 
   1200    assign( low, unop( Iop_D128LOtoD64, e ) );
   1201    assign( high, unop( Iop_D128HItoD64, e ) );
   1202 
   1203    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
   1204    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
   1205 }
   1206 
   1207 static Int vsxGuestRegOffset ( UInt archreg )
   1208 {
   1209    vassert(archreg < 64);
   1210    switch (archreg) {
   1211    case  0: return offsetofPPCGuestState(guest_VSR0);
   1212    case  1: return offsetofPPCGuestState(guest_VSR1);
   1213    case  2: return offsetofPPCGuestState(guest_VSR2);
   1214    case  3: return offsetofPPCGuestState(guest_VSR3);
   1215    case  4: return offsetofPPCGuestState(guest_VSR4);
   1216    case  5: return offsetofPPCGuestState(guest_VSR5);
   1217    case  6: return offsetofPPCGuestState(guest_VSR6);
   1218    case  7: return offsetofPPCGuestState(guest_VSR7);
   1219    case  8: return offsetofPPCGuestState(guest_VSR8);
   1220    case  9: return offsetofPPCGuestState(guest_VSR9);
   1221    case 10: return offsetofPPCGuestState(guest_VSR10);
   1222    case 11: return offsetofPPCGuestState(guest_VSR11);
   1223    case 12: return offsetofPPCGuestState(guest_VSR12);
   1224    case 13: return offsetofPPCGuestState(guest_VSR13);
   1225    case 14: return offsetofPPCGuestState(guest_VSR14);
   1226    case 15: return offsetofPPCGuestState(guest_VSR15);
   1227    case 16: return offsetofPPCGuestState(guest_VSR16);
   1228    case 17: return offsetofPPCGuestState(guest_VSR17);
   1229    case 18: return offsetofPPCGuestState(guest_VSR18);
   1230    case 19: return offsetofPPCGuestState(guest_VSR19);
   1231    case 20: return offsetofPPCGuestState(guest_VSR20);
   1232    case 21: return offsetofPPCGuestState(guest_VSR21);
   1233    case 22: return offsetofPPCGuestState(guest_VSR22);
   1234    case 23: return offsetofPPCGuestState(guest_VSR23);
   1235    case 24: return offsetofPPCGuestState(guest_VSR24);
   1236    case 25: return offsetofPPCGuestState(guest_VSR25);
   1237    case 26: return offsetofPPCGuestState(guest_VSR26);
   1238    case 27: return offsetofPPCGuestState(guest_VSR27);
   1239    case 28: return offsetofPPCGuestState(guest_VSR28);
   1240    case 29: return offsetofPPCGuestState(guest_VSR29);
   1241    case 30: return offsetofPPCGuestState(guest_VSR30);
   1242    case 31: return offsetofPPCGuestState(guest_VSR31);
   1243    case 32: return offsetofPPCGuestState(guest_VSR32);
   1244    case 33: return offsetofPPCGuestState(guest_VSR33);
   1245    case 34: return offsetofPPCGuestState(guest_VSR34);
   1246    case 35: return offsetofPPCGuestState(guest_VSR35);
   1247    case 36: return offsetofPPCGuestState(guest_VSR36);
   1248    case 37: return offsetofPPCGuestState(guest_VSR37);
   1249    case 38: return offsetofPPCGuestState(guest_VSR38);
   1250    case 39: return offsetofPPCGuestState(guest_VSR39);
   1251    case 40: return offsetofPPCGuestState(guest_VSR40);
   1252    case 41: return offsetofPPCGuestState(guest_VSR41);
   1253    case 42: return offsetofPPCGuestState(guest_VSR42);
   1254    case 43: return offsetofPPCGuestState(guest_VSR43);
   1255    case 44: return offsetofPPCGuestState(guest_VSR44);
   1256    case 45: return offsetofPPCGuestState(guest_VSR45);
   1257    case 46: return offsetofPPCGuestState(guest_VSR46);
   1258    case 47: return offsetofPPCGuestState(guest_VSR47);
   1259    case 48: return offsetofPPCGuestState(guest_VSR48);
   1260    case 49: return offsetofPPCGuestState(guest_VSR49);
   1261    case 50: return offsetofPPCGuestState(guest_VSR50);
   1262    case 51: return offsetofPPCGuestState(guest_VSR51);
   1263    case 52: return offsetofPPCGuestState(guest_VSR52);
   1264    case 53: return offsetofPPCGuestState(guest_VSR53);
   1265    case 54: return offsetofPPCGuestState(guest_VSR54);
   1266    case 55: return offsetofPPCGuestState(guest_VSR55);
   1267    case 56: return offsetofPPCGuestState(guest_VSR56);
   1268    case 57: return offsetofPPCGuestState(guest_VSR57);
   1269    case 58: return offsetofPPCGuestState(guest_VSR58);
   1270    case 59: return offsetofPPCGuestState(guest_VSR59);
   1271    case 60: return offsetofPPCGuestState(guest_VSR60);
   1272    case 61: return offsetofPPCGuestState(guest_VSR61);
   1273    case 62: return offsetofPPCGuestState(guest_VSR62);
   1274    case 63: return offsetofPPCGuestState(guest_VSR63);
   1275    default: break;
   1276    }
   1277    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
   1278 }
   1279 
   1280 /* Vector registers are mapped to VSX registers[32..63]. */
   1281 static Int vectorGuestRegOffset ( UInt archreg )
   1282 {
   1283    vassert(archreg < 32);
   1284 
   1285    switch (archreg) {
   1286    case  0: return offsetofPPCGuestState(guest_VSR32);
   1287    case  1: return offsetofPPCGuestState(guest_VSR33);
   1288    case  2: return offsetofPPCGuestState(guest_VSR34);
   1289    case  3: return offsetofPPCGuestState(guest_VSR35);
   1290    case  4: return offsetofPPCGuestState(guest_VSR36);
   1291    case  5: return offsetofPPCGuestState(guest_VSR37);
   1292    case  6: return offsetofPPCGuestState(guest_VSR38);
   1293    case  7: return offsetofPPCGuestState(guest_VSR39);
   1294    case  8: return offsetofPPCGuestState(guest_VSR40);
   1295    case  9: return offsetofPPCGuestState(guest_VSR41);
   1296    case 10: return offsetofPPCGuestState(guest_VSR42);
   1297    case 11: return offsetofPPCGuestState(guest_VSR43);
   1298    case 12: return offsetofPPCGuestState(guest_VSR44);
   1299    case 13: return offsetofPPCGuestState(guest_VSR45);
   1300    case 14: return offsetofPPCGuestState(guest_VSR46);
   1301    case 15: return offsetofPPCGuestState(guest_VSR47);
   1302    case 16: return offsetofPPCGuestState(guest_VSR48);
   1303    case 17: return offsetofPPCGuestState(guest_VSR49);
   1304    case 18: return offsetofPPCGuestState(guest_VSR50);
   1305    case 19: return offsetofPPCGuestState(guest_VSR51);
   1306    case 20: return offsetofPPCGuestState(guest_VSR52);
   1307    case 21: return offsetofPPCGuestState(guest_VSR53);
   1308    case 22: return offsetofPPCGuestState(guest_VSR54);
   1309    case 23: return offsetofPPCGuestState(guest_VSR55);
   1310    case 24: return offsetofPPCGuestState(guest_VSR56);
   1311    case 25: return offsetofPPCGuestState(guest_VSR57);
   1312    case 26: return offsetofPPCGuestState(guest_VSR58);
   1313    case 27: return offsetofPPCGuestState(guest_VSR59);
   1314    case 28: return offsetofPPCGuestState(guest_VSR60);
   1315    case 29: return offsetofPPCGuestState(guest_VSR61);
   1316    case 30: return offsetofPPCGuestState(guest_VSR62);
   1317    case 31: return offsetofPPCGuestState(guest_VSR63);
   1318    default: break;
   1319    }
   1320    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1321 }
   1322 
   1323 static IRExpr* getVReg ( UInt archreg )
   1324 {
   1325    vassert(archreg < 32);
   1326    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1327 }
   1328 
   1329 /* Ditto, but write to a reg instead. */
   1330 static void putVReg ( UInt archreg, IRExpr* e )
   1331 {
   1332    vassert(archreg < 32);
   1333    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1334    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1335 }
   1336 
   1337 /* Get contents of VSX guest register */
   1338 static IRExpr* getVSReg ( UInt archreg )
   1339 {
   1340    vassert(archreg < 64);
   1341    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
   1342 }
   1343 
   1344 /* Ditto, but write to a VSX reg instead. */
   1345 static void putVSReg ( UInt archreg, IRExpr* e )
   1346 {
   1347    vassert(archreg < 64);
   1348    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1349    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
   1350 }
   1351 
   1352 
   1353 static Int guestCR321offset ( UInt cr )
   1354 {
   1355    switch (cr) {
   1356    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1357    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1358    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1359    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1360    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1361    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1362    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1363    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1364    default: vpanic("guestCR321offset(ppc)");
   1365    }
   1366 }
   1367 
   1368 static Int guestCR0offset ( UInt cr )
   1369 {
   1370    switch (cr) {
   1371    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1372    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1373    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1374    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1375    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1376    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1377    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1378    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1379    default: vpanic("guestCR3offset(ppc)");
   1380    }
   1381 }
   1382 
   1383 typedef enum {
   1384    _placeholder0,
   1385    _placeholder1,
   1386    _placeholder2,
   1387    BYTE,
   1388    HWORD,
   1389    WORD,
   1390    DWORD
   1391 } _popcount_data_type;
   1392 
   1393 /* Generate an IR sequence to do a popcount operation on the supplied
   1394    IRTemp, and return a new IRTemp holding the result.  'ty' may be
   1395    Ity_I32 or Ity_I64 only. */
   1396 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
   1397 {
   1398   /* Do count across 2^data_type bits,
   1399      byte:        data_type = 3
   1400      half word:   data_type = 4
   1401      word:        data_type = 5
   1402      double word: data_type = 6  (not supported for 32-bit type)
   1403     */
   1404    Int shift[6];
   1405    _popcount_data_type idx, i;
   1406    IRTemp mask[6];
   1407    IRTemp old = IRTemp_INVALID;
   1408    IRTemp nyu = IRTemp_INVALID;
   1409 
   1410    vassert(ty == Ity_I64 || ty == Ity_I32);
   1411 
   1412    if (ty == Ity_I32) {
   1413 
   1414       for (idx = 0; idx < WORD; idx++) {
   1415          mask[idx]  = newTemp(ty);
   1416          shift[idx] = 1 << idx;
   1417       }
   1418       assign(mask[0], mkU32(0x55555555));
   1419       assign(mask[1], mkU32(0x33333333));
   1420       assign(mask[2], mkU32(0x0F0F0F0F));
   1421       assign(mask[3], mkU32(0x00FF00FF));
   1422       assign(mask[4], mkU32(0x0000FFFF));
   1423       old = src;
   1424       for (i = 0; i < data_type; i++) {
   1425          nyu = newTemp(ty);
   1426          assign(nyu,
   1427                 binop(Iop_Add32,
   1428                       binop(Iop_And32,
   1429                             mkexpr(old),
   1430                             mkexpr(mask[i])),
   1431                       binop(Iop_And32,
   1432                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1433                             mkexpr(mask[i]))));
   1434          old = nyu;
   1435       }
   1436       return nyu;
   1437    }
   1438 
   1439 // else, ty == Ity_I64
   1440    vassert(mode64);
   1441 
   1442    for (i = 0; i < DWORD; i++) {
   1443       mask[i] = newTemp( Ity_I64 );
   1444       shift[i] = 1 << i;
   1445    }
   1446    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
   1447    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
   1448    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
   1449    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
   1450    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
   1451    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
   1452    old = src;
   1453    for (i = 0; i < data_type; i++) {
   1454       nyu = newTemp( Ity_I64 );
   1455       assign( nyu,
   1456               binop( Iop_Add64,
   1457                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
   1458                      binop( Iop_And64,
   1459                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
   1460                             mkexpr( mask[i] ) ) ) );
   1461       old = nyu;
   1462    }
   1463    return nyu;
   1464 }
   1465 
   1466 /* Special purpose population count function for
   1467  * vpopcntd in 32-bit mode.
   1468  */
   1469 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
   1470 {
   1471    Int i, shift[6];
   1472    IRTemp mask[6];
   1473    IRTemp old = IRTemp_INVALID;
   1474    IRTemp nyu1 = IRTemp_INVALID;
   1475    IRTemp nyu2 = IRTemp_INVALID;
   1476    IRTemp retval = newTemp(Ity_I64);
   1477 
   1478    vassert(!mode64);
   1479 
   1480    for (i = 0; i < WORD; i++) {
   1481       mask[i]  = newTemp(Ity_I32);
   1482       shift[i] = 1 << i;
   1483    }
   1484    assign(mask[0], mkU32(0x55555555));
   1485    assign(mask[1], mkU32(0x33333333));
   1486    assign(mask[2], mkU32(0x0F0F0F0F));
   1487    assign(mask[3], mkU32(0x00FF00FF));
   1488    assign(mask[4], mkU32(0x0000FFFF));
   1489    old = src1;
   1490    for (i = 0; i < WORD; i++) {
   1491       nyu1 = newTemp(Ity_I32);
   1492       assign(nyu1,
   1493              binop(Iop_Add32,
   1494                    binop(Iop_And32,
   1495                          mkexpr(old),
   1496                          mkexpr(mask[i])),
   1497                    binop(Iop_And32,
   1498                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1499                          mkexpr(mask[i]))));
   1500       old = nyu1;
   1501    }
   1502 
   1503    old = src2;
   1504    for (i = 0; i < WORD; i++) {
   1505       nyu2 = newTemp(Ity_I32);
   1506       assign(nyu2,
   1507              binop(Iop_Add32,
   1508                    binop(Iop_And32,
   1509                          mkexpr(old),
   1510                          mkexpr(mask[i])),
   1511                    binop(Iop_And32,
   1512                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1513                          mkexpr(mask[i]))));
   1514       old = nyu2;
   1515    }
   1516    assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
   1517    return retval;
   1518 }
   1519 
   1520 
   1521 // ROTL(src32/64, rot_amt5/6)
   1522 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1523                                           IRExpr* rot_amt )
   1524 {
   1525    IRExpr *mask, *rot;
   1526    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1527 
   1528    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1529       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1530       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1531       rot  = binop(Iop_Or64,
   1532                 binop(Iop_Shl64, src, mask),
   1533                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1534    } else {
   1535       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1536       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1537       rot  = binop(Iop_Or32,
   1538                 binop(Iop_Shl32, src, mask),
   1539                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1540    }
   1541    /* Note: the ITE not merely an optimisation; it's needed
   1542       because otherwise the Shr is a shift by the word size when
   1543       mask denotes zero.  For rotates by immediates, a lot of
   1544       this junk gets folded out. */
   1545    return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
   1546                       /* non-zero rotate */ rot,
   1547                       /*     zero rotate */ src);
   1548 }
   1549 
   1550 /* Standard effective address calc: (rA + rB) */
   1551 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1552 {
   1553    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1554    vassert(rA < 32);
   1555    vassert(rB < 32);
   1556    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1557 }
   1558 
   1559 /* Standard effective address calc: (rA + simm) */
   1560 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1561 {
   1562    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1563    vassert(rA < 32);
   1564    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1565                 mkSzExtendS16(ty, simm16));
   1566 }
   1567 
   1568 /* Standard effective address calc: (rA|0) */
   1569 static IRExpr* ea_rAor0 ( UInt rA )
   1570 {
   1571    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1572    vassert(rA < 32);
   1573    if (rA == 0) {
   1574       return mkSzImm(ty, 0);
   1575    } else {
   1576       return getIReg(rA);
   1577    }
   1578 }
   1579 
   1580 /* Standard effective address calc: (rA|0) + rB */
   1581 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1582 {
   1583    vassert(rA < 32);
   1584    vassert(rB < 32);
   1585    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1586 }
   1587 
   1588 /* Standard effective address calc: (rA|0) + simm16 */
   1589 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1590 {
   1591    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1592    vassert(rA < 32);
   1593    if (rA == 0) {
   1594       return mkSzExtendS16(ty, simm16);
   1595    } else {
   1596       return ea_rA_simm( rA, simm16 );
   1597    }
   1598 }
   1599 
   1600 
   1601 /* Align effective address */
   1602 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1603 {
   1604    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1605    Long mask;
   1606    switch (align) {
   1607    case 1:  return addr;                    // byte aligned
   1608    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
   1609    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
   1610    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
   1611    default:
   1612       vex_printf("addr_align: align = %u\n", align);
   1613       vpanic("addr_align(ppc)");
   1614    }
   1615 
   1616    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1617    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1618 }
   1619 
   1620 
   1621 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1622    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1623    restart of the current insn. */
   1624 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1625 {
   1626    vassert(align == 4 || align == 8 || align == 16);
   1627    if (mode64) {
   1628       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1629       stmt(
   1630          IRStmt_Exit(
   1631             binop(Iop_CmpNE64,
   1632                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1633                   mkU64(0)),
   1634             Ijk_SigBUS,
   1635             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
   1636          )
   1637       );
   1638    } else {
   1639       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1640       stmt(
   1641          IRStmt_Exit(
   1642             binop(Iop_CmpNE32,
   1643                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1644                   mkU32(0)),
   1645             Ijk_SigBUS,
   1646             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
   1647          )
   1648       );
   1649    }
   1650 }
   1651 
   1652 
   1653 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1654    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1655    N) becomes undefined.  That is at function calls and returns.  ELF
   1656    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1657    the address of the next instruction to be executed.
   1658 */
   1659 static void make_redzone_AbiHint ( VexAbiInfo* vbi,
   1660                                    IRTemp nia, const HChar* who )
   1661 {
   1662    Int szB = vbi->guest_stack_redzone_size;
   1663    if (0) vex_printf("AbiHint: %s\n", who);
   1664    vassert(szB >= 0);
   1665    if (szB > 0) {
   1666       if (mode64) {
   1667          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1668          stmt( IRStmt_AbiHint(
   1669                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1670                   szB,
   1671                   mkexpr(nia)
   1672          ));
   1673       } else {
   1674          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1675          stmt( IRStmt_AbiHint(
   1676                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1677                   szB,
   1678                   mkexpr(nia)
   1679          ));
   1680       }
   1681    }
   1682 }
   1683 
   1684 
   1685 /*------------------------------------------------------------*/
   1686 /*--- Helpers for condition codes.                         ---*/
   1687 /*------------------------------------------------------------*/
   1688 
   1689 /* Condition register layout.
   1690 
   1691    In the hardware, CR is laid out like this.  The leftmost end is the
   1692    most significant bit in the register; however the IBM documentation
   1693    numbers the bits backwards for some reason.
   1694 
   1695    CR0      CR1    ..........   CR6       CR7
   1696    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1697    31  28                             3    0     (normal bit numbering)
   1698 
   1699    Each CR field is 4 bits:  [<,>,==,SO]
   1700 
   1701    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1702 
   1703    Indexing from BI to guest state:
   1704 
   1705      let    n = BI / 4
   1706           off = BI % 4
   1707      this references CR n:
   1708 
   1709         off==0   ->  guest_CRn_321 >> 3
   1710         off==1   ->  guest_CRn_321 >> 2
   1711         off==2   ->  guest_CRn_321 >> 1
   1712         off==3   ->  guest_CRn_SO
   1713 
   1714    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1715    (normal notation) and in guest_CRn_321 the significant bits are
   1716    3, 2 and 1 (normal notation).
   1717 */
   1718 
   1719 static void putCR321 ( UInt cr, IRExpr* e )
   1720 {
   1721    vassert(cr < 8);
   1722    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1723    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1724 }
   1725 
   1726 static void putCR0 ( UInt cr, IRExpr* e )
   1727 {
   1728    vassert(cr < 8);
   1729    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1730    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1731 }
   1732 
   1733 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1734 {
   1735    vassert(cr < 8);
   1736    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1737 }
   1738 
   1739 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1740 {
   1741    vassert(cr < 8);
   1742    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1743 }
   1744 
   1745 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1746    return it at the bottom of an I32; the top 31 bits are guaranteed
   1747    to be zero. */
   1748 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1749 {
   1750    UInt n   = bi / 4;
   1751    UInt off = bi % 4;
   1752    vassert(bi < 32);
   1753    if (off == 3) {
   1754       /* Fetch the SO bit for this CR field */
   1755       /* Note: And32 is redundant paranoia iff guest state only has 0
   1756          or 1 in that slot. */
   1757       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1758    } else {
   1759       /* Fetch the <, > or == bit for this CR field */
   1760       return binop( Iop_And32,
   1761                     binop( Iop_Shr32,
   1762                            unop(Iop_8Uto32, getCR321(n)),
   1763                            mkU8(toUChar(3-off)) ),
   1764                     mkU32(1) );
   1765    }
   1766 }
   1767 
   1768 /* Dually, write the least significant bit of BIT to the specified CR
   1769    bit.  Indexing as per getCRbit. */
   1770 static void putCRbit ( UInt bi, IRExpr* bit )
   1771 {
   1772    UInt    n, off;
   1773    IRExpr* safe;
   1774    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1775    safe = binop(Iop_And32, bit, mkU32(1));
   1776    n   = bi / 4;
   1777    off = bi % 4;
   1778    vassert(bi < 32);
   1779    if (off == 3) {
   1780       /* This is the SO bit for this CR field */
   1781       putCR0(n, unop(Iop_32to8, safe));
   1782    } else {
   1783       off = 3 - off;
   1784       vassert(off == 1 || off == 2 || off == 3);
   1785       putCR321(
   1786          n,
   1787          unop( Iop_32to8,
   1788                binop( Iop_Or32,
   1789                       /* old value with field masked out */
   1790                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1791                                        mkU32(~(1 << off))),
   1792                       /* new value in the right place */
   1793                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1794                )
   1795          )
   1796       );
   1797    }
   1798 }
   1799 
   1800 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1801    return it somewhere in an I32; it does not matter where, but
   1802    whichever bit it is, all other bits are guaranteed to be zero.  In
   1803    other words, the I32-typed expression will be zero if the bit is
   1804    zero and nonzero if the bit is 1.  Write into *where the index
   1805    of where the bit will be. */
   1806 
   1807 static
   1808 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   1809 {
   1810    UInt n   = bi / 4;
   1811    UInt off = bi % 4;
   1812    vassert(bi < 32);
   1813    if (off == 3) {
   1814       /* Fetch the SO bit for this CR field */
   1815       /* Note: And32 is redundant paranoia iff guest state only has 0
   1816          or 1 in that slot. */
   1817       *where = 0;
   1818       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1819    } else {
   1820       /* Fetch the <, > or == bit for this CR field */
   1821       *where = 3-off;
   1822       return binop( Iop_And32,
   1823                     unop(Iop_8Uto32, getCR321(n)),
   1824                     mkU32(1 << (3-off)) );
   1825    }
   1826 }
   1827 
   1828 /* Set the CR0 flags following an arithmetic operation.
   1829    (Condition Register CR0 Field Definition, PPC32 p60)
   1830 */
   1831 static IRExpr* getXER_SO ( void );
   1832 static void set_CR0 ( IRExpr* result )
   1833 {
   1834    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1835            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1836    if (mode64) {
   1837       putCR321( 0, unop(Iop_64to8,
   1838                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1839    } else {
   1840       putCR321( 0, unop(Iop_32to8,
   1841                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1842    }
   1843    putCR0( 0, getXER_SO() );
   1844 }
   1845 
   1846 
   1847 /* Set the CR6 flags following an AltiVec compare operation.
   1848  * NOTE: This also works for VSX single-precision compares.
   1849  * */
   1850 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1851 {
   1852    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1853       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1854       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1855    */
   1856    IRTemp v0 = newTemp(Ity_V128);
   1857    IRTemp v1 = newTemp(Ity_V128);
   1858    IRTemp v2 = newTemp(Ity_V128);
   1859    IRTemp v3 = newTemp(Ity_V128);
   1860    IRTemp rOnes  = newTemp(Ity_I8);
   1861    IRTemp rZeros = newTemp(Ity_I8);
   1862 
   1863    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1864 
   1865    assign( v0, result );
   1866    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1867    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1868    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1869 
   1870    assign( rZeros, unop(Iop_1Uto8,
   1871        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1872              unop(Iop_Not32,
   1873                   unop(Iop_V128to32,
   1874                        binop(Iop_OrV128,
   1875                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1876                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1877                   ))) );
   1878 
   1879    if (test_all_ones) {
   1880       assign( rOnes, unop(Iop_1Uto8,
   1881          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1882                unop(Iop_V128to32,
   1883                     binop(Iop_AndV128,
   1884                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   1885                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   1886                     ))) );
   1887       putCR321( 6, binop(Iop_Or8,
   1888                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   1889                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   1890    } else {
   1891       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   1892    }
   1893    putCR0( 6, mkU8(0) );
   1894 }
   1895 
   1896 
   1897 
   1898 /*------------------------------------------------------------*/
   1899 /*--- Helpers for XER flags.                               ---*/
   1900 /*------------------------------------------------------------*/
   1901 
   1902 static void putXER_SO ( IRExpr* e )
   1903 {
   1904    IRExpr* so;
   1905    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1906    so = binop(Iop_And8, e, mkU8(1));
   1907    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   1908 }
   1909 
   1910 static void putXER_OV ( IRExpr* e )
   1911 {
   1912    IRExpr* ov;
   1913    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1914    ov = binop(Iop_And8, e, mkU8(1));
   1915    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   1916 }
   1917 
   1918 static void putXER_CA ( IRExpr* e )
   1919 {
   1920    IRExpr* ca;
   1921    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1922    ca = binop(Iop_And8, e, mkU8(1));
   1923    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   1924 }
   1925 
   1926 static void putXER_BC ( IRExpr* e )
   1927 {
   1928    IRExpr* bc;
   1929    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1930    bc = binop(Iop_And8, e, mkU8(0x7F));
   1931    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   1932 }
   1933 
   1934 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   1935 {
   1936    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   1937 }
   1938 
   1939 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   1940 {
   1941    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   1942 }
   1943 
   1944 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   1945 {
   1946    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   1947 }
   1948 
   1949 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   1950 {
   1951    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   1952 }
   1953 
   1954 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   1955 {
   1956    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   1957    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   1958 }
   1959 
   1960 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   1961 {
   1962    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1963 }
   1964 
   1965 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   1966 {
   1967    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1968    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   1969 }
   1970 
   1971 
   1972 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   1973    %XER.SO accordingly. */
   1974 
   1975 static void set_XER_OV_32( UInt op, IRExpr* res,
   1976                            IRExpr* argL, IRExpr* argR )
   1977 {
   1978    IRTemp  t64;
   1979    IRExpr* xer_ov;
   1980    vassert(op < PPCG_FLAG_OP_NUMBER);
   1981    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   1982    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   1983    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   1984 
   1985 #  define INT32_MIN 0x80000000
   1986 
   1987 #  define XOR2(_aa,_bb) \
   1988       binop(Iop_Xor32,(_aa),(_bb))
   1989 
   1990 #  define XOR3(_cc,_dd,_ee) \
   1991       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   1992 
   1993 #  define AND3(_ff,_gg,_hh) \
   1994       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   1995 
   1996 #define NOT(_jj) \
   1997       unop(Iop_Not32, (_jj))
   1998 
   1999    switch (op) {
   2000    case /* 0  */ PPCG_FLAG_OP_ADD:
   2001    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2002       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   2003       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2004       xer_ov
   2005          = AND3( XOR3(argL,argR,mkU32(-1)),
   2006                  XOR2(argL,res),
   2007                  mkU32(INT32_MIN) );
   2008       /* xer_ov can only be 0 or 1<<31 */
   2009       xer_ov
   2010          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2011       break;
   2012 
   2013    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2014       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   2015       xer_ov
   2016          = mkOR1(
   2017               mkAND1(
   2018                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   2019                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   2020               ),
   2021               binop(Iop_CmpEQ32, argR, mkU32(0) )
   2022            );
   2023       xer_ov
   2024          = unop(Iop_1Uto32, xer_ov);
   2025       break;
   2026 
   2027    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2028       /* argR == 0 */
   2029       xer_ov
   2030          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   2031       break;
   2032 
   2033    case /* 4  */ PPCG_FLAG_OP_MULLW:
   2034       /* OV true if result can't be represented in 32 bits
   2035          i.e sHi != sign extension of sLo */
   2036       t64 = newTemp(Ity_I64);
   2037       assign( t64, binop(Iop_MullS32, argL, argR) );
   2038       xer_ov
   2039          = binop( Iop_CmpNE32,
   2040                   unop(Iop_64HIto32, mkexpr(t64)),
   2041                   binop( Iop_Sar32,
   2042                          unop(Iop_64to32, mkexpr(t64)),
   2043                          mkU8(31))
   2044                   );
   2045       xer_ov
   2046          = unop(Iop_1Uto32, xer_ov);
   2047       break;
   2048 
   2049    case /* 5  */ PPCG_FLAG_OP_NEG:
   2050       /* argL == INT32_MIN */
   2051       xer_ov
   2052          = unop( Iop_1Uto32,
   2053                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   2054       break;
   2055 
   2056    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2057    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2058    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2059       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   2060       xer_ov
   2061          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   2062                  XOR2(NOT(argL),res),
   2063                  mkU32(INT32_MIN) );
   2064       /* xer_ov can only be 0 or 1<<31 */
   2065       xer_ov
   2066          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2067       break;
   2068 
   2069    case PPCG_FLAG_OP_DIVWEU:
   2070       xer_ov
   2071                = binop( Iop_Or32,
   2072                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2073                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
   2074       break;
   2075 
   2076    case PPCG_FLAG_OP_DIVWE:
   2077 
   2078       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
   2079        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
   2080        * an overflow is implied.
   2081        */
   2082       xer_ov = binop( Iop_Or32,
   2083                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2084                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
   2085                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
   2086                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
   2087       break;
   2088 
   2089 
   2090 
   2091    default:
   2092       vex_printf("set_XER_OV: op = %u\n", op);
   2093       vpanic("set_XER_OV(ppc)");
   2094    }
   2095 
   2096    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2097    putXER_OV( unop(Iop_32to8, xer_ov) );
   2098 
   2099    /* Update the summary overflow */
   2100    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2101 
   2102 #  undef INT32_MIN
   2103 #  undef AND3
   2104 #  undef XOR3
   2105 #  undef XOR2
   2106 #  undef NOT
   2107 }
   2108 
   2109 static void set_XER_OV_64( UInt op, IRExpr* res,
   2110                            IRExpr* argL, IRExpr* argR )
   2111 {
   2112    IRExpr* xer_ov;
   2113    vassert(op < PPCG_FLAG_OP_NUMBER);
   2114    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   2115    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   2116    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   2117 
   2118 #  define INT64_MIN 0x8000000000000000ULL
   2119 
   2120 #  define XOR2(_aa,_bb) \
   2121       binop(Iop_Xor64,(_aa),(_bb))
   2122 
   2123 #  define XOR3(_cc,_dd,_ee) \
   2124       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   2125 
   2126 #  define AND3(_ff,_gg,_hh) \
   2127       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   2128 
   2129 #define NOT(_jj) \
   2130       unop(Iop_Not64, (_jj))
   2131 
   2132    switch (op) {
   2133    case /* 0  */ PPCG_FLAG_OP_ADD:
   2134    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2135       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   2136       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2137       xer_ov
   2138          = AND3( XOR3(argL,argR,mkU64(-1)),
   2139                  XOR2(argL,res),
   2140                  mkU64(INT64_MIN) );
   2141       /* xer_ov can only be 0 or 1<<63 */
   2142       xer_ov
   2143          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2144       break;
   2145 
   2146    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2147       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   2148       xer_ov
   2149          = mkOR1(
   2150               mkAND1(
   2151                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   2152                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   2153               ),
   2154               binop(Iop_CmpEQ64, argR, mkU64(0) )
   2155            );
   2156       break;
   2157 
   2158    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2159       /* argR == 0 */
   2160       xer_ov
   2161          = binop(Iop_CmpEQ64, argR, mkU64(0));
   2162       break;
   2163 
   2164    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   2165       /* OV true if result can't be represented in 64 bits
   2166          i.e sHi != sign extension of sLo */
   2167       xer_ov
   2168          = binop( Iop_CmpNE32,
   2169                   unop(Iop_64HIto32, res),
   2170                   binop( Iop_Sar32,
   2171                          unop(Iop_64to32, res),
   2172                          mkU8(31))
   2173                   );
   2174       break;
   2175    }
   2176 
   2177    case /* 5  */ PPCG_FLAG_OP_NEG:
   2178       /* argL == INT64_MIN */
   2179       xer_ov
   2180          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   2181       break;
   2182 
   2183    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2184    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2185    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2186       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   2187       xer_ov
   2188          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   2189                  XOR2(NOT(argL),res),
   2190                  mkU64(INT64_MIN) );
   2191       /* xer_ov can only be 0 or 1<<63 */
   2192       xer_ov
   2193          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2194       break;
   2195 
   2196    case PPCG_FLAG_OP_DIVDE:
   2197 
   2198       /* If argR == 0, we must set the OV bit.  But there's another condition
   2199        * where we can get overflow set for divde . . . when the
   2200        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
   2201        * both dividend and divisor are non-zero, it implies an overflow.
   2202        */
   2203       xer_ov
   2204                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2205                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
   2206                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
   2207                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
   2208       break;
   2209 
   2210    case PPCG_FLAG_OP_DIVDEU:
   2211      /* If argR == 0 or if argL >= argR, set OV. */
   2212      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2213                          binop( Iop_CmpLE64U, argR, argL ) );
   2214      break;
   2215 
   2216    case /* 18 */ PPCG_FLAG_OP_MULLD: {
   2217       IRTemp  t128;
   2218       /* OV true if result can't be represented in 64 bits
   2219          i.e sHi != sign extension of sLo */
   2220       t128 = newTemp(Ity_I128);
   2221       assign( t128, binop(Iop_MullS64, argL, argR) );
   2222       xer_ov
   2223          = binop( Iop_CmpNE64,
   2224                   unop(Iop_128HIto64, mkexpr(t128)),
   2225                   binop( Iop_Sar64,
   2226                          unop(Iop_128to64, mkexpr(t128)),
   2227                          mkU8(63))
   2228                   );
   2229       break;
   2230    }
   2231 
   2232    default:
   2233       vex_printf("set_XER_OV: op = %u\n", op);
   2234       vpanic("set_XER_OV(ppc64)");
   2235    }
   2236 
   2237    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2238    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   2239 
   2240    /* Update the summary overflow */
   2241    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2242 
   2243 #  undef INT64_MIN
   2244 #  undef AND3
   2245 #  undef XOR3
   2246 #  undef XOR2
   2247 #  undef NOT
   2248 }
   2249 
   2250 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   2251                          IRExpr* argL, IRExpr* argR )
   2252 {
   2253    if (ty == Ity_I32)
   2254       set_XER_OV_32( op, res, argL, argR );
   2255    else
   2256       set_XER_OV_64( op, res, argL, argR );
   2257 }
   2258 
   2259 
   2260 
   2261 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   2262    value being OLDCA.  Set %XER.CA accordingly. */
   2263 
   2264 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   2265                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2266 {
   2267    IRExpr* xer_ca;
   2268    vassert(op < PPCG_FLAG_OP_NUMBER);
   2269    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   2270    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   2271    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   2272    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   2273 
   2274    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2275       seems reasonable given that it's always generated by
   2276       getXER_CA32(), which masks it accordingly.  In any case it being
   2277       0 or 1 is an invariant of the ppc guest state representation;
   2278       if it has any other value, that invariant has been violated. */
   2279 
   2280    switch (op) {
   2281    case /* 0 */ PPCG_FLAG_OP_ADD:
   2282       /* res <u argL */
   2283       xer_ca
   2284          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   2285       break;
   2286 
   2287    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2288       /* res <u argL || (old_ca==1 && res==argL) */
   2289       xer_ca
   2290          = mkOR1(
   2291               binop(Iop_CmpLT32U, res, argL),
   2292               mkAND1(
   2293                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2294                  binop(Iop_CmpEQ32, res, argL)
   2295               )
   2296            );
   2297       xer_ca
   2298          = unop(Iop_1Uto32, xer_ca);
   2299       break;
   2300 
   2301    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2302       /* res <u argR || (old_ca==1 && res==argR) */
   2303       xer_ca
   2304          = mkOR1(
   2305               binop(Iop_CmpLT32U, res, argR),
   2306               mkAND1(
   2307                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2308                  binop(Iop_CmpEQ32, res, argR)
   2309               )
   2310            );
   2311       xer_ca
   2312          = unop(Iop_1Uto32, xer_ca);
   2313       break;
   2314 
   2315    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2316    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2317       /* res <=u argR */
   2318       xer_ca
   2319          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   2320       break;
   2321 
   2322    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2323       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2324          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2325          bit of argL. */
   2326       /* This term valid for shift amount < 32 only */
   2327       xer_ca
   2328          = binop(
   2329               Iop_And32,
   2330               binop(Iop_Sar32, argL, mkU8(31)),
   2331               binop( Iop_And32,
   2332                      argL,
   2333                      binop( Iop_Sub32,
   2334                             binop(Iop_Shl32, mkU32(1),
   2335                                              unop(Iop_32to8,argR)),
   2336                             mkU32(1) )
   2337                      )
   2338               );
   2339       xer_ca
   2340          = IRExpr_ITE(
   2341               /* shift amt > 31 ? */
   2342               binop(Iop_CmpLT32U, mkU32(31), argR),
   2343               /* yes -- get sign bit of argL */
   2344               binop(Iop_Shr32, argL, mkU8(31)),
   2345               /* no -- be like srawi */
   2346               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
   2347            );
   2348       break;
   2349 
   2350    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2351       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   2352          0.  Since the shift amount is known to be in the range
   2353          0 .. 31 inclusive the following seems viable:
   2354          xer.ca == 1 iff the following is nonzero:
   2355          (argL >>s 31)           -- either all 0s or all 1s
   2356          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2357       xer_ca
   2358          = binop(
   2359               Iop_And32,
   2360               binop(Iop_Sar32, argL, mkU8(31)),
   2361               binop( Iop_And32,
   2362                      argL,
   2363                      binop( Iop_Sub32,
   2364                             binop(Iop_Shl32, mkU32(1),
   2365                                              unop(Iop_32to8,argR)),
   2366                             mkU32(1) )
   2367                      )
   2368               );
   2369       xer_ca
   2370          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   2371       break;
   2372 
   2373    default:
   2374       vex_printf("set_XER_CA: op = %u\n", op);
   2375       vpanic("set_XER_CA(ppc)");
   2376    }
   2377 
   2378    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2379    putXER_CA( unop(Iop_32to8, xer_ca) );
   2380 }
   2381 
   2382 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   2383                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2384 {
   2385    IRExpr* xer_ca;
   2386    vassert(op < PPCG_FLAG_OP_NUMBER);
   2387    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   2388    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   2389    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   2390    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   2391 
   2392    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2393       seems reasonable given that it's always generated by
   2394       getXER_CA32(), which masks it accordingly.  In any case it being
   2395       0 or 1 is an invariant of the ppc guest state representation;
   2396       if it has any other value, that invariant has been violated. */
   2397 
   2398    switch (op) {
   2399    case /* 0 */ PPCG_FLAG_OP_ADD:
   2400       /* res <u argL */
   2401       xer_ca
   2402          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   2403       break;
   2404 
   2405    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2406       /* res <u argL || (old_ca==1 && res==argL) */
   2407       xer_ca
   2408          = mkOR1(
   2409               binop(Iop_CmpLT64U, res, argL),
   2410               mkAND1(
   2411                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2412                  binop(Iop_CmpEQ64, res, argL)
   2413                  )
   2414               );
   2415       xer_ca
   2416          = unop(Iop_1Uto32, xer_ca);
   2417       break;
   2418 
   2419    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2420       /* res <u argR || (old_ca==1 && res==argR) */
   2421       xer_ca
   2422          = mkOR1(
   2423               binop(Iop_CmpLT64U, res, argR),
   2424               mkAND1(
   2425                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2426                  binop(Iop_CmpEQ64, res, argR)
   2427               )
   2428            );
   2429       xer_ca
   2430          = unop(Iop_1Uto32, xer_ca);
   2431       break;
   2432 
   2433    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2434    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2435       /* res <=u argR */
   2436       xer_ca
   2437          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   2438       break;
   2439 
   2440 
   2441    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2442       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   2443          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2444          bit of argL. */
   2445          /* This term valid for shift amount < 31 only */
   2446 
   2447       xer_ca
   2448          = binop(
   2449               Iop_And64,
   2450               binop(Iop_Sar64, argL, mkU8(31)),
   2451               binop( Iop_And64,
   2452                      argL,
   2453                      binop( Iop_Sub64,
   2454                             binop(Iop_Shl64, mkU64(1),
   2455                                              unop(Iop_64to8,argR)),
   2456                             mkU64(1) )
   2457               )
   2458            );
   2459       xer_ca
   2460          = IRExpr_ITE(
   2461               /* shift amt > 31 ? */
   2462               binop(Iop_CmpLT64U, mkU64(31), argR),
   2463               /* yes -- get sign bit of argL */
   2464               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2465               /* no -- be like srawi */
   2466               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2467           );
   2468       break;
   2469 
   2470    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2471       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2472          Since the shift amount is known to be in the range 0 .. 31
   2473          inclusive the following seems viable:
   2474          xer.ca == 1 iff the following is nonzero:
   2475          (argL >>s 31)           -- either all 0s or all 1s
   2476          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2477 
   2478       xer_ca
   2479          = binop(
   2480               Iop_And64,
   2481               binop(Iop_Sar64, argL, mkU8(31)),
   2482               binop( Iop_And64,
   2483                      argL,
   2484                      binop( Iop_Sub64,
   2485                             binop(Iop_Shl64, mkU64(1),
   2486                                              unop(Iop_64to8,argR)),
   2487                             mkU64(1) )
   2488               )
   2489            );
   2490       xer_ca
   2491          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2492       break;
   2493 
   2494 
   2495    case /* 12 */ PPCG_FLAG_OP_SRAD:
   2496       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2497          If it is <= 63, behave like SRADI; else XER.CA is the sign
   2498          bit of argL. */
   2499          /* This term valid for shift amount < 63 only */
   2500 
   2501       xer_ca
   2502          = binop(
   2503               Iop_And64,
   2504               binop(Iop_Sar64, argL, mkU8(63)),
   2505               binop( Iop_And64,
   2506                      argL,
   2507                      binop( Iop_Sub64,
   2508                             binop(Iop_Shl64, mkU64(1),
   2509                                              unop(Iop_64to8,argR)),
   2510                             mkU64(1) )
   2511               )
   2512            );
   2513       xer_ca
   2514          = IRExpr_ITE(
   2515               /* shift amt > 63 ? */
   2516               binop(Iop_CmpLT64U, mkU64(63), argR),
   2517               /* yes -- get sign bit of argL */
   2518               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2519               /* no -- be like sradi */
   2520               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2521            );
   2522       break;
   2523 
   2524 
   2525    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2526       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2527          Since the shift amount is known to be in the range 0 .. 63
   2528          inclusive, the following seems viable:
   2529          xer.ca == 1 iff the following is nonzero:
   2530          (argL >>s 63)           -- either all 0s or all 1s
   2531          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2532 
   2533       xer_ca
   2534          = binop(
   2535               Iop_And64,
   2536               binop(Iop_Sar64, argL, mkU8(63)),
   2537               binop( Iop_And64,
   2538                      argL,
   2539                      binop( Iop_Sub64,
   2540                             binop(Iop_Shl64, mkU64(1),
   2541                                              unop(Iop_64to8,argR)),
   2542                             mkU64(1) )
   2543               )
   2544            );
   2545       xer_ca
   2546          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2547       break;
   2548 
   2549    default:
   2550       vex_printf("set_XER_CA: op = %u\n", op);
   2551       vpanic("set_XER_CA(ppc64)");
   2552    }
   2553 
   2554    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2555    putXER_CA( unop(Iop_32to8, xer_ca) );
   2556 }
   2557 
   2558 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2559                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2560 {
   2561    if (ty == Ity_I32)
   2562       set_XER_CA_32( op, res, argL, argR, oldca );
   2563    else
   2564       set_XER_CA_64( op, res, argL, argR, oldca );
   2565 }
   2566 
   2567 
   2568 
   2569 /*------------------------------------------------------------*/
   2570 /*--- Read/write to guest-state                           --- */
   2571 /*------------------------------------------------------------*/
   2572 
   2573 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2574 {
   2575    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2576    switch (reg) {
   2577    case PPC_GST_SPRG3_RO:
   2578       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2579 
   2580    case PPC_GST_CIA:
   2581       return IRExpr_Get( OFFB_CIA, ty );
   2582 
   2583    case PPC_GST_LR:
   2584       return IRExpr_Get( OFFB_LR, ty );
   2585 
   2586    case PPC_GST_CTR:
   2587       return IRExpr_Get( OFFB_CTR, ty );
   2588 
   2589    case PPC_GST_VRSAVE:
   2590       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2591 
   2592    case PPC_GST_VSCR:
   2593       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2594                               mkU32(MASK_VSCR_VALID));
   2595 
   2596    case PPC_GST_CR: {
   2597       /* Synthesise the entire CR into a single word.  Expensive. */
   2598 #     define FIELD(_n)                                               \
   2599          binop(Iop_Shl32,                                            \
   2600                unop(Iop_8Uto32,                                      \
   2601                     binop(Iop_Or8,                                   \
   2602                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2603                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2604                     )                                                \
   2605                ),                                                    \
   2606                mkU8(4 * (7-(_n)))                                    \
   2607          )
   2608       return binop(Iop_Or32,
   2609                    binop(Iop_Or32,
   2610                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2611                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2612                          ),
   2613                    binop(Iop_Or32,
   2614                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2615                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2616                          )
   2617                    );
   2618 #     undef FIELD
   2619    }
   2620 
   2621    case PPC_GST_XER:
   2622       return binop(Iop_Or32,
   2623                    binop(Iop_Or32,
   2624                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2625                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2626                    binop(Iop_Or32,
   2627                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2628                          getXER_BC32()));
   2629 
   2630    case PPC_GST_TFHAR:
   2631       return IRExpr_Get( OFFB_TFHAR, ty );
   2632 
   2633    case PPC_GST_TEXASR:
   2634       return IRExpr_Get( OFFB_TEXASR, ty );
   2635 
   2636    case PPC_GST_TFIAR:
   2637       return IRExpr_Get( OFFB_TFIAR, ty );
   2638 
   2639    default:
   2640       vex_printf("getGST(ppc): reg = %u", reg);
   2641       vpanic("getGST(ppc)");
   2642    }
   2643 }
   2644 
   2645 /* Get a masked word from the given reg */
   2646 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2647 {
   2648    IRTemp val = newTemp(Ity_I32);
   2649    vassert( reg < PPC_GST_MAX );
   2650 
   2651    switch (reg) {
   2652 
   2653    case PPC_GST_FPSCR: {
   2654       /* Vex-generated code expects the FPSCR to be set as follows:
   2655          all exceptions masked, round-to-nearest.
   2656          This corresponds to a FPSCR value of 0x0. */
   2657 
   2658       /* In the lower 32 bits of FPSCR, we're only keeping track of
   2659        * the binary floating point rounding mode, so if the mask isn't
   2660        * asking for this, just return 0x0.
   2661        */
   2662       if (mask & MASK_FPSCR_RN) {
   2663          assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
   2664       } else {
   2665          assign( val, mkU32(0x0) );
   2666       }
   2667       break;
   2668    }
   2669 
   2670    default:
   2671       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2672       vpanic("getGST_masked(ppc)");
   2673    }
   2674 
   2675    if (mask != 0xFFFFFFFF) {
   2676       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2677    } else {
   2678       return mkexpr(val);
   2679    }
   2680 }
   2681 
   2682 /* Get a masked word from the given reg */
   2683 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
   2684    IRExpr * val;
   2685    vassert( reg < PPC_GST_MAX );
   2686 
   2687    switch (reg) {
   2688 
   2689    case PPC_GST_FPSCR: {
   2690       /* In the upper 32 bits of FPSCR, we're only keeping track
   2691        * of the decimal floating point rounding mode, so if the mask
   2692        * isn't asking for this, just return 0x0.
   2693        */
   2694       if (mask & MASK_FPSCR_DRN) {
   2695          val = binop( Iop_And32,
   2696                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
   2697                       unop( Iop_64HIto32, mkU64( mask ) ) );
   2698       } else {
   2699          val = mkU32( 0x0ULL );
   2700       }
   2701       break;
   2702    }
   2703 
   2704    default:
   2705       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
   2706       vpanic( "getGST_masked_upper(ppc)" );
   2707    }
   2708    return val;
   2709 }
   2710 
   2711 
   2712 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2713    and return it at the bottom of an I32; the top 27 bits are
   2714    guaranteed to be zero. */
   2715 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2716 {
   2717    UInt shft, mask;
   2718 
   2719    vassert( fld < 8 );
   2720    vassert( reg < PPC_GST_MAX );
   2721 
   2722    shft = 4*(7-fld);
   2723    mask = 0xF<<shft;
   2724 
   2725    switch (reg) {
   2726    case PPC_GST_XER:
   2727       vassert(fld ==7);
   2728       return binop(Iop_Or32,
   2729                    binop(Iop_Or32,
   2730                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2731                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2732                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2733       break;
   2734 
   2735    default:
   2736       if (shft == 0)
   2737          return getGST_masked( reg, mask );
   2738       else
   2739          return binop(Iop_Shr32,
   2740                       getGST_masked( reg, mask ),
   2741                       mkU8(toUChar( shft )));
   2742    }
   2743 }
   2744 
   2745 static void putGST ( PPC_GST reg, IRExpr* src )
   2746 {
   2747    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2748    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2749    vassert( reg < PPC_GST_MAX );
   2750    switch (reg) {
   2751    case PPC_GST_IP_AT_SYSCALL:
   2752       vassert( ty_src == ty );
   2753       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2754       break;
   2755    case PPC_GST_CIA:
   2756       vassert( ty_src == ty );
   2757       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2758       break;
   2759    case PPC_GST_LR:
   2760       vassert( ty_src == ty );
   2761       stmt( IRStmt_Put( OFFB_LR, src ) );
   2762       break;
   2763    case PPC_GST_CTR:
   2764       vassert( ty_src == ty );
   2765       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2766       break;
   2767    case PPC_GST_VRSAVE:
   2768       vassert( ty_src == Ity_I32 );
   2769       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2770       break;
   2771    case PPC_GST_VSCR:
   2772       vassert( ty_src == Ity_I32 );
   2773       stmt( IRStmt_Put( OFFB_VSCR,
   2774                         binop(Iop_And32, src,
   2775                               mkU32(MASK_VSCR_VALID)) ) );
   2776       break;
   2777    case PPC_GST_XER:
   2778       vassert( ty_src == Ity_I32 );
   2779       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2780       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2781       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2782       putXER_BC( unop(Iop_32to8, src) );
   2783       break;
   2784 
   2785    case PPC_GST_EMWARN:
   2786       vassert( ty_src == Ity_I32 );
   2787       stmt( IRStmt_Put( OFFB_EMNOTE,src) );
   2788       break;
   2789 
   2790    case PPC_GST_CMSTART:
   2791       vassert( ty_src == ty );
   2792       stmt( IRStmt_Put( OFFB_CMSTART, src) );
   2793       break;
   2794 
   2795    case PPC_GST_CMLEN:
   2796       vassert( ty_src == ty );
   2797       stmt( IRStmt_Put( OFFB_CMLEN, src) );
   2798       break;
   2799 
   2800    case PPC_GST_TEXASR:
   2801       vassert( ty_src == Ity_I64 );
   2802       stmt( IRStmt_Put( OFFB_TEXASR, src ) );
   2803       break;
   2804    case PPC_GST_TFIAR:
   2805       vassert( ty_src == Ity_I64 );
   2806       stmt( IRStmt_Put( OFFB_TFIAR, src ) );
   2807       break;
   2808    case PPC_GST_TFHAR:
   2809       vassert( ty_src == Ity_I64 );
   2810       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
   2811       break;
   2812    default:
   2813       vex_printf("putGST(ppc): reg = %u", reg);
   2814       vpanic("putGST(ppc)");
   2815    }
   2816 }
   2817 
   2818 /* Write masked src to the given reg */
   2819 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
   2820 {
   2821    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2822    vassert( reg < PPC_GST_MAX );
   2823    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
   2824 
   2825    switch (reg) {
   2826    case PPC_GST_FPSCR: {
   2827       /* Allow writes to either binary or decimal floating point
   2828        * Rounding Mode
   2829        */
   2830       if (mask & MASK_FPSCR_RN) {
   2831          stmt( IRStmt_Put( OFFB_FPROUND,
   2832                            unop( Iop_32to8,
   2833                                  binop( Iop_And32,
   2834                                         unop( Iop_64to32, src ),
   2835                                         mkU32( MASK_FPSCR_RN & mask ) ) ) ) );
   2836       } else if (mask & MASK_FPSCR_DRN) {
   2837          stmt( IRStmt_Put( OFFB_DFPROUND,
   2838                            unop( Iop_32to8,
   2839                                  binop( Iop_And32,
   2840                                         unop( Iop_64HIto32, src ),
   2841                                         mkU32( ( MASK_FPSCR_DRN & mask )
   2842                                                  >> 32 ) ) ) ) );
   2843       }
   2844 
   2845       /* Give EmNote for attempted writes to:
   2846          - Exception Controls
   2847          - Non-IEEE Mode
   2848       */
   2849       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   2850          VexEmNote ew = EmWarn_PPCexns;
   2851 
   2852          /* If any of the src::exception_control bits are actually set,
   2853             side-exit to the next insn, reporting the warning,
   2854             so that Valgrind's dispatcher sees the warning. */
   2855          putGST( PPC_GST_EMWARN, mkU32(ew) );
   2856          stmt(
   2857             IRStmt_Exit(
   2858                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
   2859                Ijk_EmWarn,
   2860                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   2861       }
   2862 
   2863       /* Ignore all other writes */
   2864       break;
   2865    }
   2866 
   2867    default:
   2868       vex_printf("putGST_masked(ppc): reg = %u", reg);
   2869       vpanic("putGST_masked(ppc)");
   2870    }
   2871 }
   2872 
   2873 /* Write the least significant nibble of src to the specified
   2874    REG[FLD] (as per IBM/hardware notation). */
   2875 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   2876 {
   2877    UInt shft;
   2878    ULong mask;
   2879 
   2880    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2881    vassert( fld < 16 );
   2882    vassert( reg < PPC_GST_MAX );
   2883 
   2884    if (fld < 8)
   2885       shft = 4*(7-fld);
   2886    else
   2887       shft = 4*(15-fld);
   2888    mask = 0xF;
   2889    mask = mask << shft;
   2890 
   2891    switch (reg) {
   2892    case PPC_GST_CR:
   2893       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   2894       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   2895       break;
   2896 
   2897    default:
   2898       {
   2899          IRExpr * src64 = unop( Iop_32Uto64, src );
   2900 
   2901          if (shft == 0) {
   2902             putGST_masked( reg, src64, mask );
   2903          } else {
   2904             putGST_masked( reg,
   2905                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
   2906                            mask );
   2907          }
   2908       }
   2909    }
   2910 }
   2911 
   2912 /*------------------------------------------------------------*/
   2913 /* Helpers for VSX instructions that do floating point
   2914  * operations and need to determine if a src contains a
   2915  * special FP value.
   2916  *
   2917  *------------------------------------------------------------*/
   2918 
   2919 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
   2920 #define FP_FRAC_PART(x) binop( Iop_And64, \
   2921                                mkexpr( x ), \
   2922                                mkU64( NONZERO_FRAC_MASK ) )
   2923 
   2924 // Returns exponent part of a single precision floating point as I32
   2925 static IRExpr * fp_exp_part_sp(IRTemp src)
   2926 {
   2927    return binop( Iop_And32,
   2928                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   2929                  mkU32( 0xff ) );
   2930 }
   2931 
   2932 // Returns exponent part of floating point as I32
   2933 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
   2934 {
   2935    IRExpr * exp;
   2936    if (sp)
   2937       return fp_exp_part_sp(src);
   2938 
   2939    if (!mode64)
   2940       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
   2941                                                       mkexpr( src ) ),
   2942                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
   2943    else
   2944       exp = unop( Iop_64to32,
   2945                   binop( Iop_And64,
   2946                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
   2947                          mkU64( 0x7ff ) ) );
   2948    return exp;
   2949 }
   2950 
   2951 static IRExpr * is_Inf_sp(IRTemp src)
   2952 {
   2953    IRTemp frac_part = newTemp(Ity_I32);
   2954    IRExpr * Inf_exp;
   2955 
   2956    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
   2957    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
   2958    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
   2959 }
   2960 
   2961 
   2962 // Infinity: exp = 7ff and fraction is zero; s = 0/1
   2963 static IRExpr * is_Inf(IRTemp src, Bool sp)
   2964 {
   2965    IRExpr * Inf_exp, * hi32, * low32;
   2966    IRTemp frac_part;
   2967 
   2968    if (sp)
   2969       return is_Inf_sp(src);
   2970 
   2971    frac_part = newTemp(Ity_I64);
   2972    assign( frac_part, FP_FRAC_PART(src) );
   2973    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
   2974    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   2975    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   2976    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   2977                                   mkU32( 0 ) ) );
   2978 }
   2979 
   2980 static IRExpr * is_Zero_sp(IRTemp src)
   2981 {
   2982    IRTemp sign_less_part = newTemp(Ity_I32);
   2983    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
   2984    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
   2985 }
   2986 
   2987 // Zero: exp is zero and fraction is zero; s = 0/1
   2988 static IRExpr * is_Zero(IRTemp src, Bool sp)
   2989 {
   2990    IRExpr * hi32, * low32;
   2991    IRTemp sign_less_part;
   2992    if (sp)
   2993       return is_Zero_sp(src);
   2994 
   2995    sign_less_part = newTemp(Ity_I64);
   2996 
   2997    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
   2998    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
   2999    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
   3000    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   3001                               mkU32( 0 ) );
   3002 }
   3003 
   3004 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
   3005  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
   3006  *  This function returns an IRExpr value of '1' for any type of NaN.
   3007  */
   3008 static IRExpr * is_NaN(IRTemp src)
   3009 {
   3010    IRExpr * NaN_exp, * hi32, * low32;
   3011    IRTemp frac_part = newTemp(Ity_I64);
   3012 
   3013    assign( frac_part, FP_FRAC_PART(src) );
   3014    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   3015    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   3016    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
   3017                     mkU32( 0x7ff ) );
   3018 
   3019    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   3020                                                mkU32( 0 ) ) );
   3021 }
   3022 
   3023 /* This function returns an IRExpr value of '1' for any type of NaN.
   3024  * The passed 'src' argument is assumed to be Ity_I32.
   3025  */
   3026 static IRExpr * is_NaN_32(IRTemp src)
   3027 {
   3028 #define NONZERO_FRAC_MASK32 0x007fffffULL
   3029 #define FP_FRAC_PART32(x) binop( Iop_And32, \
   3030                                  mkexpr( x ), \
   3031                                  mkU32( NONZERO_FRAC_MASK32 ) )
   3032 
   3033    IRExpr * frac_part = FP_FRAC_PART32(src);
   3034    IRExpr * exp_part = binop( Iop_And32,
   3035                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   3036                               mkU32( 0x0ff ) );
   3037    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
   3038 
   3039    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
   3040 }
   3041 
   3042 /* This function takes an Ity_I32 input argument interpreted
   3043  * as a single-precision floating point value. If src is a
   3044  * SNaN, it is changed to a QNaN and returned; otherwise,
   3045  * the original value is returned.
   3046  */
   3047 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
   3048 {
   3049 #define SNAN_MASK32 0x00400000
   3050    IRTemp tmp = newTemp(Ity_I32);
   3051    IRTemp mask = newTemp(Ity_I32);
   3052    IRTemp is_SNAN = newTemp(Ity_I1);
   3053 
   3054    vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
   3055    assign(tmp, src);
   3056 
   3057    /* check if input is SNaN, if it is convert to QNaN */
   3058    assign( is_SNAN,
   3059            mkAND1( is_NaN_32( tmp ),
   3060                    binop( Iop_CmpEQ32,
   3061                           binop( Iop_And32, mkexpr( tmp ),
   3062                                  mkU32( SNAN_MASK32 ) ),
   3063                           mkU32( 0 ) ) ) );
   3064    /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
   3065    assign ( mask, binop( Iop_And32,
   3066                          unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
   3067                          mkU32( SNAN_MASK32 ) ) );
   3068    return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
   3069 }
   3070 
   3071 
   3072 /* This helper function performs the negation part of operations of the form:
   3073  *    "Negate Multiply-<op>"
   3074  *  where "<op>" is either "Add" or "Sub".
   3075  *
   3076  * This function takes one argument -- the floating point intermediate result (converted to
   3077  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
   3078  * the operation described above.
   3079  */
   3080 static IRTemp getNegatedResult(IRTemp intermediateResult)
   3081 {
   3082    ULong signbit_mask = 0x8000000000000000ULL;
   3083    IRTemp signbit_32 = newTemp(Ity_I32);
   3084    IRTemp resultantSignbit = newTemp(Ity_I1);
   3085    IRTemp negatedResult = newTemp(Ity_I64);
   3086    assign( signbit_32, binop( Iop_Shr32,
   3087                           unop( Iop_64HIto32,
   3088                                  binop( Iop_And64, mkexpr( intermediateResult ),
   3089                                         mkU64( signbit_mask ) ) ),
   3090                                  mkU8( 31 ) ) );
   3091    /* We negate the signbit if and only if the intermediate result from the
   3092     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3093     */
   3094    assign( resultantSignbit,
   3095         unop( Iop_Not1,
   3096               binop( Iop_CmpEQ32,
   3097                      binop( Iop_Xor32,
   3098                             mkexpr( signbit_32 ),
   3099                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
   3100                      mkU32( 1 ) ) ) );
   3101 
   3102    assign( negatedResult,
   3103         binop( Iop_Or64,
   3104                binop( Iop_And64,
   3105                       mkexpr( intermediateResult ),
   3106                       mkU64( ~signbit_mask ) ),
   3107                binop( Iop_32HLto64,
   3108                       binop( Iop_Shl32,
   3109                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3110                              mkU8( 31 ) ),
   3111                       mkU32( 0 ) ) ) );
   3112 
   3113    return negatedResult;
   3114 }
   3115 
   3116 /* This helper function performs the negation part of operations of the form:
   3117  *    "Negate Multiply-<op>"
   3118  *  where "<op>" is either "Add" or "Sub".
   3119  *
   3120  * This function takes one argument -- the floating point intermediate result (converted to
   3121  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
   3122  * the operation described above.
   3123  */
   3124 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
   3125 {
   3126    UInt signbit_mask = 0x80000000;
   3127    IRTemp signbit_32 = newTemp(Ity_I32);
   3128    IRTemp resultantSignbit = newTemp(Ity_I1);
   3129    IRTemp negatedResult = newTemp(Ity_I32);
   3130    assign( signbit_32, binop( Iop_Shr32,
   3131                                  binop( Iop_And32, mkexpr( intermediateResult ),
   3132                                         mkU32( signbit_mask ) ),
   3133                                  mkU8( 31 ) ) );
   3134    /* We negate the signbit if and only if the intermediate result from the
   3135     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3136     */
   3137    assign( resultantSignbit,
   3138         unop( Iop_Not1,
   3139               binop( Iop_CmpEQ32,
   3140                      binop( Iop_Xor32,
   3141                             mkexpr( signbit_32 ),
   3142                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
   3143                      mkU32( 1 ) ) ) );
   3144 
   3145    assign( negatedResult,
   3146            binop( Iop_Or32,
   3147                   binop( Iop_And32,
   3148                          mkexpr( intermediateResult ),
   3149                          mkU32( ~signbit_mask ) ),
   3150                   binop( Iop_Shl32,
   3151                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3152                          mkU8( 31 ) ) ) );
   3153 
   3154    return negatedResult;
   3155 }
   3156 
   3157 /*------------------------------------------------------------*/
   3158 /* Transactional memory helpers
   3159  *
   3160  *------------------------------------------------------------*/
   3161 
   3162 static ULong generate_TMreason( UInt failure_code,
   3163                                              UInt persistant,
   3164                                              UInt nest_overflow,
   3165                                              UInt tm_exact )
   3166 {
   3167    ULong tm_err_code =
   3168      ( (ULong) 0) << (63-6)   /* Failure code */
   3169      | ( (ULong) persistant) << (63-7)     /* Failure persistant */
   3170      | ( (ULong) 0) << (63-8)   /* Disallowed */
   3171      | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
   3172      | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
   3173      | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
   3174      | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
   3175      | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
   3176      | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
   3177      | ( (ULong) 0) << (63-15)  /* Implementation-specific */
   3178      | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
   3179      | ( (ULong) 0) << (63-30)  /* Reserved */
   3180      | ( (ULong) 0) << (63-31)  /* Abort */
   3181      | ( (ULong) 0) << (63-32)  /* Suspend */
   3182      | ( (ULong) 0) << (63-33)  /* Reserved */
   3183      | ( (ULong) 0) << (63-35)  /* Privilege */
   3184      | ( (ULong) 0) << (63-36)  /* Failure Summary */
   3185      | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
   3186      | ( (ULong) 0) << (63-38)  /* ROT */
   3187      | ( (ULong) 0) << (63-51)  /* Reserved */
   3188      | ( (ULong) 0) << (63-63);  /* Transaction Level */
   3189 
   3190      return tm_err_code;
   3191 }
   3192 
   3193 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
   3194                             Addr64 handler_address )
   3195 {
   3196    putGST( PPC_GST_TFIAR,  mkU64( err_address ) );
   3197    putGST( PPC_GST_TEXASR, mkU64( tm_reason ) );
   3198    putGST( PPC_GST_TFHAR,  mkU64( handler_address ) );
   3199 }
   3200 
   3201 /*------------------------------------------------------------*/
   3202 /*--- Integer Instruction Translation                     --- */
   3203 /*------------------------------------------------------------*/
   3204 
   3205 /*
   3206   Integer Arithmetic Instructions
   3207 */
   3208 static Bool dis_int_arith ( UInt theInstr )
   3209 {
   3210    /* D-Form, XO-Form */
   3211    UChar opc1    = ifieldOPC(theInstr);
   3212    UChar rD_addr = ifieldRegDS(theInstr);
   3213    UChar rA_addr = ifieldRegA(theInstr);
   3214    UInt  uimm16  = ifieldUIMM16(theInstr);
   3215    UChar rB_addr = ifieldRegB(theInstr);
   3216    UChar flag_OE = ifieldBIT10(theInstr);
   3217    UInt  opc2    = ifieldOPClo9(theInstr);
   3218    UChar flag_rC = ifieldBIT0(theInstr);
   3219 
   3220    Long   simm16 = extend_s_16to64(uimm16);
   3221    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3222    IRTemp rA     = newTemp(ty);
   3223    IRTemp rB     = newTemp(ty);
   3224    IRTemp rD     = newTemp(ty);
   3225 
   3226    Bool do_rc = False;
   3227 
   3228    assign( rA, getIReg(rA_addr) );
   3229    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   3230 
   3231    switch (opc1) {
   3232    /* D-Form */
   3233    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   3234       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3235       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3236                          mkSzExtendS16(ty, uimm16) ) );
   3237       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3238                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3239                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3240       break;
   3241 
   3242    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   3243       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3244       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3245                          mkSzExtendS16(ty, uimm16) ) );
   3246       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3247                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3248                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3249       do_rc = True;  // Always record to CR
   3250       flag_rC = 1;
   3251       break;
   3252 
   3253    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   3254       // li rD,val   == addi rD,0,val
   3255       // la disp(rA) == addi rD,rA,disp
   3256       if ( rA_addr == 0 ) {
   3257          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   3258          assign( rD, mkSzExtendS16(ty, uimm16) );
   3259       } else {
   3260          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3261          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3262                             mkSzExtendS16(ty, uimm16) ) );
   3263       }
   3264       break;
   3265 
   3266    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   3267       // lis rD,val == addis rD,0,val
   3268       if ( rA_addr == 0 ) {
   3269          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   3270          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   3271       } else {
   3272          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
   3273          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3274                             mkSzExtendS32(ty, uimm16 << 16) ) );
   3275       }
   3276       break;
   3277 
   3278    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   3279       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3280       if (mode64)
   3281          assign( rD, unop(Iop_128to64,
   3282                           binop(Iop_MullS64, mkexpr(rA),
   3283                                 mkSzExtendS16(ty, uimm16))) );
   3284       else
   3285          assign( rD, unop(Iop_64to32,
   3286                           binop(Iop_MullS32, mkexpr(rA),
   3287                                 mkSzExtendS16(ty, uimm16))) );
   3288       break;
   3289 
   3290    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   3291       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3292       // rD = simm16 - rA
   3293       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3294                          mkSzExtendS16(ty, uimm16),
   3295                          mkexpr(rA)) );
   3296       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   3297                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3298                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3299       break;
   3300 
   3301    /* XO-Form */
   3302    case 0x1F:
   3303       do_rc = True;    // All below record to CR
   3304 
   3305       switch (opc2) {
   3306       case 0x10A: // add  (Add, PPC32 p347)
   3307          DIP("add%s%s r%u,r%u,r%u\n",
   3308              flag_OE ? "o" : "", flag_rC ? ".":"",
   3309              rD_addr, rA_addr, rB_addr);
   3310          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3311                             mkexpr(rA), mkexpr(rB) ) );
   3312          if (flag_OE) {
   3313             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3314                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3315          }
   3316          break;
   3317 
   3318       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   3319          DIP("addc%s%s r%u,r%u,r%u\n",
   3320              flag_OE ? "o" : "", flag_rC ? ".":"",
   3321              rD_addr, rA_addr, rB_addr);
   3322          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3323                             mkexpr(rA), mkexpr(rB)) );
   3324          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3325                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3326                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3327          if (flag_OE) {
   3328             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3329                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3330          }
   3331          break;
   3332 
   3333       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   3334          IRTemp old_xer_ca = newTemp(ty);
   3335          DIP("adde%s%s r%u,r%u,r%u\n",
   3336              flag_OE ? "o" : "", flag_rC ? ".":"",
   3337              rD_addr, rA_addr, rB_addr);
   3338          // rD = rA + rB + XER[CA]
   3339          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3340          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3341                             binop( mkSzOp(ty, Iop_Add8),
   3342                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3343          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3344                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3345                      mkexpr(old_xer_ca) );
   3346          if (flag_OE) {
   3347             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3348                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3349          }
   3350          break;
   3351       }
   3352 
   3353       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   3354          IRTemp old_xer_ca = newTemp(ty);
   3355          IRExpr *min_one;
   3356          if (rB_addr != 0) {
   3357             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   3358             return False;
   3359          }
   3360          DIP("addme%s%s r%u,r%u,r%u\n",
   3361              flag_OE ? "o" : "", flag_rC ? ".":"",
   3362              rD_addr, rA_addr, rB_addr);
   3363          // rD = rA + (-1) + XER[CA]
   3364          // => Just another form of adde
   3365          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3366          min_one = mkSzImm(ty, (Long)-1);
   3367          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3368                             binop( mkSzOp(ty, Iop_Add8),
   3369                                    min_one, mkexpr(old_xer_ca)) ));
   3370          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3371                      mkexpr(rD), mkexpr(rA), min_one,
   3372                      mkexpr(old_xer_ca) );
   3373          if (flag_OE) {
   3374             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3375                         mkexpr(rD), mkexpr(rA), min_one );
   3376          }
   3377          break;
   3378       }
   3379 
   3380       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   3381          IRTemp old_xer_ca = newTemp(ty);
   3382          if (rB_addr != 0) {
   3383             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   3384             return False;
   3385          }
   3386          DIP("addze%s%s r%u,r%u,r%u\n",
   3387              flag_OE ? "o" : "", flag_rC ? ".":"",
   3388              rD_addr, rA_addr, rB_addr);
   3389          // rD = rA + (0) + XER[CA]
   3390          // => Just another form of adde
   3391          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3392          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3393                             mkexpr(rA), mkexpr(old_xer_ca)) );
   3394          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3395                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3396                      mkexpr(old_xer_ca) );
   3397          if (flag_OE) {
   3398             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3399                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3400          }
   3401          break;
   3402       }
   3403 
   3404       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   3405          DIP("divw%s%s r%u,r%u,r%u\n",
   3406              flag_OE ? "o" : "", flag_rC ? ".":"",
   3407              rD_addr, rA_addr, rB_addr);
   3408          if (mode64) {
   3409             /* Note:
   3410                XER settings are mode independent, and reflect the
   3411                overflow of the low-order 32bit result
   3412                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3413             */
   3414             /* rD[hi32] are undefined: setting them to sign of lo32
   3415                 - makes set_CR0 happy */
   3416             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   3417             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   3418             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   3419                                                          divisor) ) );
   3420             if (flag_OE) {
   3421                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3422                            mkexpr(rD), dividend, divisor );
   3423             }
   3424          } else {
   3425             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   3426             if (flag_OE) {
   3427                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3428                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3429             }
   3430          }
   3431          /* Note:
   3432             if (0x8000_0000 / -1) or (x / 0)
   3433             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3434             => But _no_ exception raised. */
   3435          break;
   3436 
   3437       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   3438          DIP("divwu%s%s r%u,r%u,r%u\n",
   3439              flag_OE ? "o" : "", flag_rC ? ".":"",
   3440              rD_addr, rA_addr, rB_addr);
   3441          if (mode64) {
   3442             /* Note:
   3443                XER settings are mode independent, and reflect the
   3444                overflow of the low-order 32bit result
   3445                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3446             */
   3447             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   3448             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   3449             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   3450                                                          divisor) ) );
   3451             if (flag_OE) {
   3452                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3453                            mkexpr(rD), dividend, divisor );
   3454             }
   3455          } else {
   3456             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   3457             if (flag_OE) {
   3458                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3459                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3460             }
   3461          }
   3462          /* Note: ditto comment divw, for (x / 0) */
   3463          break;
   3464 
   3465       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   3466          if (flag_OE != 0) {
   3467             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   3468             return False;
   3469          }
   3470          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3471              rD_addr, rA_addr, rB_addr);
   3472          if (mode64) {
   3473             /* rD[hi32] are undefined: setting them to sign of lo32
   3474                 - makes set_CR0 happy */
   3475             assign( rD, binop(Iop_Sar64,
   3476                            binop(Iop_Mul64,
   3477                                  mk64lo32Sto64( mkexpr(rA) ),
   3478                                  mk64lo32Sto64( mkexpr(rB) )),
   3479                               mkU8(32)) );
   3480          } else {
   3481             assign( rD, unop(Iop_64HIto32,
   3482                              binop(Iop_MullS32,
   3483                                    mkexpr(rA), mkexpr(rB))) );
   3484          }
   3485          break;
   3486 
   3487       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   3488          if (flag_OE != 0) {
   3489             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   3490             return False;
   3491          }
   3492          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3493              rD_addr, rA_addr, rB_addr);
   3494          if (mode64) {
   3495             /* rD[hi32] are undefined: setting them to sign of lo32
   3496                 - makes set_CR0 happy */
   3497             assign( rD, binop(Iop_Sar64,
   3498                            binop(Iop_Mul64,
   3499                                  mk64lo32Uto64( mkexpr(rA) ),
   3500                                  mk64lo32Uto64( mkexpr(rB) ) ),
   3501                               mkU8(32)) );
   3502          } else {
   3503             assign( rD, unop(Iop_64HIto32,
   3504                              binop(Iop_MullU32,
   3505                                    mkexpr(rA), mkexpr(rB))) );
   3506          }
   3507          break;
   3508 
   3509       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   3510          DIP("mullw%s%s r%u,r%u,r%u\n",
   3511              flag_OE ? "o" : "", flag_rC ? ".":"",
   3512              rD_addr, rA_addr, rB_addr);
   3513          if (mode64) {
   3514             /* rD[hi32] are undefined: setting them to sign of lo32
   3515                 - set_XER_OV() and set_CR0() depend on this */
   3516             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   3517             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   3518             assign( rD, binop(Iop_MullS32, a, b) );
   3519             if (flag_OE) {
   3520                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3521                            mkexpr(rD),
   3522                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   3523             }
   3524          } else {
   3525             assign( rD, unop(Iop_64to32,
   3526                              binop(Iop_MullU32,
   3527                                    mkexpr(rA), mkexpr(rB))) );
   3528             if (flag_OE) {
   3529                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3530                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3531             }
   3532          }
   3533          break;
   3534 
   3535       case 0x068: // neg        (Negate, PPC32 p493)
   3536          if (rB_addr != 0) {
   3537             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   3538             return False;
   3539          }
   3540          DIP("neg%s%s r%u,r%u\n",
   3541              flag_OE ? "o" : "", flag_rC ? ".":"",
   3542              rD_addr, rA_addr);
   3543          // rD = (~rA) + 1
   3544          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3545                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   3546                             mkSzImm(ty, 1)) );
   3547          if (flag_OE) {
   3548             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   3549                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3550          }
   3551          break;
   3552 
   3553       case 0x028: // subf       (Subtract From, PPC32 p537)
   3554          DIP("subf%s%s r%u,r%u,r%u\n",
   3555              flag_OE ? "o" : "", flag_rC ? ".":"",
   3556              rD_addr, rA_addr, rB_addr);
   3557          // rD = rB - rA
   3558          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3559                             mkexpr(rB), mkexpr(rA)) );
   3560          if (flag_OE) {
   3561             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   3562                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3563          }
   3564          break;
   3565 
   3566       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   3567          DIP("subfc%s%s r%u,r%u,r%u\n",
   3568              flag_OE ? "o" : "", flag_rC ? ".":"",
   3569              rD_addr, rA_addr, rB_addr);
   3570          // rD = rB - rA
   3571          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3572                             mkexpr(rB), mkexpr(rA)) );
   3573          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   3574                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3575                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3576          if (flag_OE) {
   3577             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   3578                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3579          }
   3580          break;
   3581 
   3582       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   3583          IRTemp old_xer_ca = newTemp(ty);
   3584          DIP("subfe%s%s r%u,r%u,r%u\n",
   3585              flag_OE ? "o" : "", flag_rC ? ".":"",
   3586              rD_addr, rA_addr, rB_addr);
   3587          // rD = (log not)rA + rB + XER[CA]
   3588          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3589          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3590                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3591                             binop( mkSzOp(ty, Iop_Add8),
   3592                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3593          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3594                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3595                      mkexpr(old_xer_ca) );
   3596          if (flag_OE) {
   3597             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3598                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3599          }
   3600          break;
   3601       }
   3602 
   3603       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   3604          IRTemp old_xer_ca = newTemp(ty);
   3605          IRExpr *min_one;
   3606          if (rB_addr != 0) {
   3607             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   3608             return False;
   3609          }
   3610          DIP("subfme%s%s r%u,r%u\n",
   3611              flag_OE ? "o" : "", flag_rC ? ".":"",
   3612              rD_addr, rA_addr);
   3613          // rD = (log not)rA + (-1) + XER[CA]
   3614          // => Just another form of subfe
   3615          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3616          min_one = mkSzImm(ty, (Long)-1);
   3617          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3618                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3619                             binop( mkSzOp(ty, Iop_Add8),
   3620                                    min_one, mkexpr(old_xer_ca))) );
   3621          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3622                      mkexpr(rD), mkexpr(rA), min_one,
   3623                      mkexpr(old_xer_ca) );
   3624          if (flag_OE) {
   3625             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3626                         mkexpr(rD), mkexpr(rA), min_one );
   3627          }
   3628          break;
   3629       }
   3630 
   3631       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   3632          IRTemp old_xer_ca = newTemp(ty);
   3633          if (rB_addr != 0) {
   3634             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   3635             return False;
   3636          }
   3637          DIP("subfze%s%s r%u,r%u\n",
   3638              flag_OE ? "o" : "", flag_rC ? ".":"",
   3639              rD_addr, rA_addr);
   3640          // rD = (log not)rA + (0) + XER[CA]
   3641          // => Just another form of subfe
   3642          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3643          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3644                            unop( mkSzOp(ty, Iop_Not8),
   3645                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   3646          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3647                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3648                      mkexpr(old_xer_ca) );
   3649          if (flag_OE) {
   3650             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3651                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3652          }
   3653          break;
   3654       }
   3655 
   3656 
   3657       /* 64bit Arithmetic */
   3658       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   3659          if (flag_OE != 0) {
   3660             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   3661             return False;
   3662          }
   3663          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3664              rD_addr, rA_addr, rB_addr);
   3665          assign( rD, unop(Iop_128HIto64,
   3666                           binop(Iop_MullS64,
   3667                                 mkexpr(rA), mkexpr(rB))) );
   3668 
   3669          break;
   3670 
   3671       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   3672          if (flag_OE != 0) {
   3673             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   3674             return False;
   3675          }
   3676          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3677              rD_addr, rA_addr, rB_addr);
   3678          assign( rD, unop(Iop_128HIto64,
   3679                           binop(Iop_MullU64,
   3680                                 mkexpr(rA), mkexpr(rB))) );
   3681          break;
   3682 
   3683       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   3684          DIP("mulld%s%s r%u,r%u,r%u\n",
   3685              flag_OE ? "o" : "", flag_rC ? ".":"",
   3686              rD_addr, rA_addr, rB_addr);
   3687          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   3688          if (flag_OE) {
   3689             set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
   3690                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3691          }
   3692          break;
   3693 
   3694       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   3695          DIP("divd%s%s r%u,r%u,r%u\n",
   3696              flag_OE ? "o" : "", flag_rC ? ".":"",
   3697              rD_addr, rA_addr, rB_addr);
   3698          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   3699          if (flag_OE) {
   3700             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3701                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3702          }
   3703          break;
   3704          /* Note:
   3705             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   3706             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3707             => But _no_ exception raised. */
   3708 
   3709       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   3710          DIP("divdu%s%s r%u,r%u,r%u\n",
   3711              flag_OE ? "o" : "", flag_rC ? ".":"",
   3712              rD_addr, rA_addr, rB_addr);
   3713          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   3714          if (flag_OE) {
   3715             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3716                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3717          }
   3718          break;
   3719          /* Note: ditto comment divd, for (x / 0) */
   3720 
   3721       case 0x18B: // divweu (Divide Word Extended Unsigned)
   3722       {
   3723         /*
   3724          *  If (RA) >= (RB), or if an attempt is made to perform the division
   3725          *         <anything> / 0
   3726          * then the contents of register RD are undefined as are (if Rc=1) the contents of
   3727          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
   3728          * to 1.
   3729          */
   3730          IRTemp res = newTemp(Ity_I32);
   3731          IRExpr * dividend, * divisor;
   3732          DIP("divweu%s%s r%u,r%u,r%u\n",
   3733              flag_OE ? "o" : "", flag_rC ? ".":"",
   3734                                          rD_addr, rA_addr, rB_addr);
   3735          if (mode64) {
   3736             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3737             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3738             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3739             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3740          } else {
   3741             dividend = mkexpr( rA );
   3742             divisor =  mkexpr( rB );
   3743             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3744             assign( rD, mkexpr( res) );
   3745          }
   3746 
   3747          if (flag_OE) {
   3748             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
   3749                            mkexpr(res), dividend, divisor );
   3750          }
   3751          break;
   3752       }
   3753 
   3754       case 0x1AB: // divwe (Divide Word Extended)
   3755       {
   3756          /*
   3757           * If the quotient cannot be represented in 32 bits, or if an
   3758           * attempt is made to perform the division
   3759           *      <anything> / 0
   3760           * then the contents of register RD are undefined as are (if
   3761           * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3762           * Field 0. In these cases, if OE=1 then OV is set to 1.
   3763           */
   3764 
   3765          IRTemp res = newTemp(Ity_I32);
   3766          IRExpr * dividend, * divisor;
   3767          DIP("divwe%s%s r%u,r%u,r%u\n",
   3768              flag_OE ? "o" : "", flag_rC ? ".":"",
   3769                                          rD_addr, rA_addr, rB_addr);
   3770          if (mode64) {
   3771             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3772             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3773             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3774             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3775          } else {
   3776             dividend = mkexpr( rA );
   3777             divisor =  mkexpr( rB );
   3778             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3779             assign( rD, mkexpr( res) );
   3780          }
   3781 
   3782          if (flag_OE) {
   3783             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
   3784                            mkexpr(res), dividend, divisor );
   3785          }
   3786          break;
   3787       }
   3788 
   3789 
   3790       case 0x1A9: // divde (Divide Doubleword Extended)
   3791         /*
   3792          * If the quotient cannot be represented in 64 bits, or if an
   3793          * attempt is made to perform the division
   3794          *      <anything> / 0
   3795          * then the contents of register RD are undefined as are (if
   3796          * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3797          * Field 0. In these cases, if OE=1 then OV is set to 1.
   3798          */
   3799          DIP("divde%s%s r%u,r%u,r%u\n",
   3800              flag_OE ? "o" : "", flag_rC ? ".":"",
   3801              rD_addr, rA_addr, rB_addr);
   3802          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
   3803          if (flag_OE) {
   3804             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
   3805                            mkexpr( rA ), mkexpr( rB ) );
   3806          }
   3807          break;
   3808 
   3809       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
   3810         // Same CR and OV rules as given for divweu above
   3811         DIP("divdeu%s%s r%u,r%u,r%u\n",
   3812             flag_OE ? "o" : "", flag_rC ? ".":"",
   3813             rD_addr, rA_addr, rB_addr);
   3814         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
   3815         if (flag_OE) {
   3816            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
   3817                           mkexpr( rA ), mkexpr( rB ) );
   3818         }
   3819         break;
   3820 
   3821       default:
   3822          vex_printf("dis_int_arith(ppc)(opc2)\n");
   3823          return False;
   3824       }
   3825       break;
   3826 
   3827    default:
   3828       vex_printf("dis_int_arith(ppc)(opc1)\n");
   3829       return False;
   3830    }
   3831 
   3832    putIReg( rD_addr, mkexpr(rD) );
   3833 
   3834    if (do_rc && flag_rC) {
   3835       set_CR0( mkexpr(rD) );
   3836    }
   3837    return True;
   3838 }
   3839 
   3840 
   3841 
   3842 /*
   3843   Integer Compare Instructions
   3844 */
   3845 static Bool dis_int_cmp ( UInt theInstr )
   3846 {
   3847    /* D-Form, X-Form */
   3848    UChar opc1    = ifieldOPC(theInstr);
   3849    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   3850    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   3851    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   3852    UChar rA_addr = ifieldRegA(theInstr);
   3853    UInt  uimm16  = ifieldUIMM16(theInstr);
   3854    UChar rB_addr = ifieldRegB(theInstr);
   3855    UInt  opc2    = ifieldOPClo10(theInstr);
   3856    UChar b0      = ifieldBIT0(theInstr);
   3857 
   3858    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   3859    IRExpr *a = getIReg(rA_addr);
   3860    IRExpr *b;
   3861 
   3862    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   3863       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   3864       return False;
   3865    }
   3866 
   3867    if (b22 != 0) {
   3868       vex_printf("dis_int_cmp(ppc)(b22)\n");
   3869       return False;
   3870    }
   3871 
   3872    switch (opc1) {
   3873    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   3874       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   3875           (Int)extend_s_16to32(uimm16));
   3876       b = mkSzExtendS16( ty, uimm16 );
   3877       if (flag_L == 1) {
   3878          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3879       } else {
   3880          a = mkNarrowTo32( ty, a );
   3881          b = mkNarrowTo32( ty, b );
   3882          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   3883       }
   3884       putCR0( crfD, getXER_SO() );
   3885       break;
   3886 
   3887    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   3888       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   3889       b = mkSzImm( ty, uimm16 );
   3890       if (flag_L == 1) {
   3891          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3892       } else {
   3893          a = mkNarrowTo32( ty, a );
   3894          b = mkNarrowTo32( ty, b );
   3895          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3896       }
   3897       putCR0( crfD, getXER_SO() );
   3898       break;
   3899 
   3900    /* X Form */
   3901    case 0x1F:
   3902       if (b0 != 0) {
   3903          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   3904          return False;
   3905       }
   3906       b = getIReg(rB_addr);
   3907 
   3908       switch (opc2) {
   3909       case 0x000: // cmp (Compare, PPC32 p367)
   3910          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3911          /* Comparing a reg with itself produces a result which
   3912             doesn't depend on the contents of the reg.  Therefore
   3913             remove the false dependency, which has been known to cause
   3914             memcheck to produce false errors. */
   3915          if (rA_addr == rB_addr)
   3916             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3917                     ? mkU64(0)  : mkU32(0);
   3918          if (flag_L == 1) {
   3919             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3920          } else {
   3921             a = mkNarrowTo32( ty, a );
   3922             b = mkNarrowTo32( ty, b );
   3923             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   3924          }
   3925          putCR0( crfD, getXER_SO() );
   3926          break;
   3927 
   3928       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   3929          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3930          /* Comparing a reg with itself produces a result which
   3931             doesn't depend on the contents of the reg.  Therefore
   3932             remove the false dependency, which has been known to cause
   3933             memcheck to produce false errors. */
   3934          if (rA_addr == rB_addr)
   3935             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3936                     ? mkU64(0)  : mkU32(0);
   3937          if (flag_L == 1) {
   3938             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3939          } else {
   3940             a = mkNarrowTo32( ty, a );
   3941             b = mkNarrowTo32( ty, b );
   3942             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3943          }
   3944          putCR0( crfD, getXER_SO() );
   3945          break;
   3946 
   3947       default:
   3948          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   3949          return False;
   3950       }
   3951       break;
   3952 
   3953    default:
   3954       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   3955       return False;
   3956    }
   3957 
   3958    return True;
   3959 }
   3960 
   3961 
   3962 /*
   3963   Integer Logical Instructions
   3964 */
   3965 static Bool dis_int_logic ( UInt theInstr )
   3966 {
   3967    /* D-Form, X-Form */
   3968    UChar opc1    = ifieldOPC(theInstr);
   3969    UChar rS_addr = ifieldRegDS(theInstr);
   3970    UChar rA_addr = ifieldRegA(theInstr);
   3971    UInt  uimm16  = ifieldUIMM16(theInstr);
   3972    UChar rB_addr = ifieldRegB(theInstr);
   3973    UInt  opc2    = ifieldOPClo10(theInstr);
   3974    UChar flag_rC = ifieldBIT0(theInstr);
   3975 
   3976    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3977    IRTemp rS     = newTemp(ty);
   3978    IRTemp rA     = newTemp(ty);
   3979    IRTemp rB     = newTemp(ty);
   3980    IRExpr* irx;
   3981    Bool do_rc    = False;
   3982 
   3983    assign( rS, getIReg(rS_addr) );
   3984    assign( rB, getIReg(rB_addr) );
   3985 
   3986    switch (opc1) {
   3987    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   3988       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3989       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3990                          mkSzImm(ty, uimm16)) );
   3991       do_rc = True;  // Always record to CR
   3992       flag_rC = 1;
   3993       break;
   3994 
   3995    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   3996       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3997       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3998                          mkSzImm(ty, uimm16 << 16)) );
   3999       do_rc = True;  // Always record to CR
   4000       flag_rC = 1;
   4001       break;
   4002 
   4003    case 0x18: // ori (OR Immediate, PPC32 p497)
   4004       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4005       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4006                          mkSzImm(ty, uimm16)) );
   4007       break;
   4008 
   4009    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   4010       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4011       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4012                          mkSzImm(ty, uimm16 << 16)) );
   4013       break;
   4014 
   4015    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   4016       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4017       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4018                          mkSzImm(ty, uimm16)) );
   4019       break;
   4020 
   4021    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   4022       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4023       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4024                          mkSzImm(ty, uimm16 << 16)) );
   4025       break;
   4026 
   4027    /* X Form */
   4028    case 0x1F:
   4029       do_rc = True; // All below record to CR, except for where we return at case end.
   4030 
   4031       switch (opc2) {
   4032       case 0x01C: // and (AND, PPC32 p356)
   4033          DIP("and%s r%u,r%u,r%u\n",
   4034              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4035          assign(rA, binop( mkSzOp(ty, Iop_And8),
   4036                            mkexpr(rS), mkexpr(rB)));
   4037          break;
   4038 
   4039       case 0x03C: // andc (AND with Complement, PPC32 p357)
   4040          DIP("andc%s r%u,r%u,r%u\n",
   4041              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4042          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4043                            unop( mkSzOp(ty, Iop_Not8),
   4044                                  mkexpr(rB))));
   4045          break;
   4046 
   4047       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   4048          IRExpr* lo32;
   4049          if (rB_addr!=0) {
   4050             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   4051             return False;
   4052          }
   4053          DIP("cntlzw%s r%u,r%u\n",
   4054              flag_rC ? ".":"", rA_addr, rS_addr);
   4055 
   4056          // mode64: count in low word only
   4057          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   4058 
   4059          // Iop_Clz32 undefined for arg==0, so deal with that case:
   4060          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   4061          assign(rA, mkWidenFrom32(ty,
   4062                          IRExpr_ITE( irx,
   4063                                      unop(Iop_Clz32, lo32),
   4064                                      mkU32(32)),
   4065                          False));
   4066 
   4067          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   4068          break;
   4069       }
   4070 
   4071       case 0x11C: // eqv (Equivalent, PPC32 p396)
   4072          DIP("eqv%s r%u,r%u,r%u\n",
   4073              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4074          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4075                            binop( mkSzOp(ty, Iop_Xor8),
   4076                                   mkexpr(rS), mkexpr(rB))) );
   4077          break;
   4078 
   4079       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   4080          if (rB_addr!=0) {
   4081             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   4082             return False;
   4083          }
   4084          DIP("extsb%s r%u,r%u\n",
   4085              flag_rC ? ".":"", rA_addr, rS_addr);
   4086          if (mode64)
   4087             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   4088          else
   4089             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   4090          break;
   4091 
   4092       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   4093          if (rB_addr!=0) {
   4094             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   4095             return False;
   4096          }
   4097          DIP("extsh%s r%u,r%u\n",
   4098              flag_rC ? ".":"", rA_addr, rS_addr);
   4099          if (mode64)
   4100             assign( rA, unop(Iop_16Sto64,
   4101                              unop(Iop_64to16, mkexpr(rS))) );
   4102          else
   4103             assign( rA, unop(Iop_16Sto32,
   4104                              unop(Iop_32to16, mkexpr(rS))) );
   4105          break;
   4106 
   4107       case 0x1DC: // nand (NAND, PPC32 p492)
   4108          DIP("nand%s r%u,r%u,r%u\n",
   4109              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4110          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4111                            binop( mkSzOp(ty, Iop_And8),
   4112                                   mkexpr(rS), mkexpr(rB))) );
   4113          break;
   4114 
   4115       case 0x07C: // nor (NOR, PPC32 p494)
   4116          DIP("nor%s r%u,r%u,r%u\n",
   4117              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4118          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4119                            binop( mkSzOp(ty, Iop_Or8),
   4120                                   mkexpr(rS), mkexpr(rB))) );
   4121          break;
   4122 
   4123       case 0x1BC: // or (OR, PPC32 p495)
   4124          if ((!flag_rC) && rS_addr == rB_addr) {
   4125             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   4126             assign( rA, mkexpr(rS) );
   4127          } else {
   4128             DIP("or%s r%u,r%u,r%u\n",
   4129                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4130             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   4131                                mkexpr(rS), mkexpr(rB)) );
   4132          }
   4133          break;
   4134 
   4135       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   4136          DIP("orc%s r%u,r%u,r%u\n",
   4137              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4138          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4139                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   4140          break;
   4141 
   4142       case 0x13C: // xor (XOR, PPC32 p549)
   4143          DIP("xor%s r%u,r%u,r%u\n",
   4144              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4145          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   4146                             mkexpr(rS), mkexpr(rB)) );
   4147          break;
   4148 
   4149 
   4150       /* 64bit Integer Logical Instructions */
   4151       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   4152          if (rB_addr!=0) {
   4153             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   4154             return False;
   4155          }
   4156          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   4157          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   4158          break;
   4159 
   4160       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   4161          if (rB_addr!=0) {
   4162             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   4163             return False;
   4164          }
   4165          DIP("cntlzd%s r%u,r%u\n",
   4166              flag_rC ? ".":"", rA_addr, rS_addr);
   4167          // Iop_Clz64 undefined for arg==0, so deal with that case:
   4168          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   4169          assign(rA, IRExpr_ITE( irx,
   4170                                 unop(Iop_Clz64, mkexpr(rS)),
   4171                                 mkU64(64) ));
   4172          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   4173          break;
   4174 
   4175       case 0x1FC: // cmpb (Power6: compare bytes)
   4176          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4177 
   4178          if (mode64)
   4179             assign( rA, unop( Iop_V128to64,
   4180                               binop( Iop_CmpEQ8x16,
   4181                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   4182                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   4183                                      )) );
   4184          else
   4185             assign( rA, unop( Iop_V128to32,
   4186                               binop( Iop_CmpEQ8x16,
   4187                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   4188                                      unop( Iop_32UtoV128, mkexpr(rB) )
   4189                                      )) );
   4190          break;
   4191 
   4192       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   4193          IRTemp frB = newTemp(Ity_F64);
   4194          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   4195 
   4196          assign( frB, getFReg(rB_addr));  // always F64
   4197          if (mode64)
   4198             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   4199          else
   4200             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   4201 
   4202          putIReg( rS_addr, mkexpr(rA));
   4203          return True;
   4204       }
   4205 
   4206       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   4207          IRTemp frA = newTemp(Ity_F64);
   4208          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   4209 
   4210          if (mode64)
   4211             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   4212          else
   4213             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   4214 
   4215          putFReg( rS_addr, mkexpr(frA));
   4216          return True;
   4217       }
   4218       case 0x1FA: // popcntd (population count doubleword
   4219       {
   4220     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
   4221     	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
   4222     	  putIReg( rA_addr, mkexpr(result) );
   4223     	  return True;
   4224       }
   4225       case 0x17A: // popcntw (Population Count Words)
   4226       {
   4227          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
   4228          if (mode64) {
   4229             IRTemp resultHi, resultLo;
   4230             IRTemp argLo = newTemp(Ity_I32);
   4231             IRTemp argHi = newTemp(Ity_I32);
   4232             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4233             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4234             resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
   4235             resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
   4236             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
   4237          } else {
   4238             IRTemp result = gen_POPCOUNT(ty, rS, WORD);
   4239             putIReg( rA_addr, mkexpr(result) );
   4240          }
   4241          return True;
   4242       }
   4243       case 0x7A: // popcntb (Population Count Byte)
   4244       {
   4245          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
   4246 
   4247          if (mode64) {
   4248             IRTemp resultHi, resultLo;
   4249             IRTemp argLo = newTemp(Ity_I32);
   4250             IRTemp argHi = newTemp(Ity_I32);
   4251             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4252             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4253             resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
   4254             resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
   4255             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
   4256                                     mkexpr(resultLo)));
   4257          } else {
   4258             IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
   4259             putIReg( rA_addr, mkexpr(result) );
   4260          }
   4261          return True;
   4262       }
   4263        case 0x0FC: // bpermd (Bit Permute Doubleword)
   4264        {
   4265           /* This is a lot of rigmarole to emulate bpermd like this, as it
   4266            * could be done much faster by implementing a call to the native
   4267            * instruction.  However, where possible I want to avoid using new
   4268            * native instructions so that we can use valgrind to emulate those
   4269            * instructions on older PPC64 hardware.
   4270            */
   4271  #define BPERMD_IDX_MASK 0x00000000000000FFULL
   4272  #define BPERMD_BIT_MASK 0x8000000000000000ULL
   4273           int i;
   4274           IRExpr * rS_expr = mkexpr(rS);
   4275           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
   4276           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4277           for (i = 0; i < 8; i++) {
   4278              IRTemp idx_tmp = newTemp( Ity_I64 );
   4279              IRTemp perm_bit = newTemp( Ity_I64 );
   4280              IRTemp idx = newTemp( Ity_I8 );
   4281              IRTemp idx_LT64 = newTemp( Ity_I1 );
   4282              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
   4283 
   4284              assign( idx_tmp,
   4285                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
   4286              assign( idx_LT64,
   4287                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
   4288              assign( idx,
   4289                            binop( Iop_And8,
   4290                                   unop( Iop_1Sto8,
   4291                                         mkexpr(idx_LT64) ),
   4292                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
   4293              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
   4294               * to determine which bit of rB to use for the perm bit, and then we shift
   4295               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
   4296               * to set the final perm bit.
   4297               */
   4298              assign( idx_LT64_ity64,
   4299                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
   4300              assign( perm_bit,
   4301                            binop( Iop_And64,
   4302                                   mkexpr( idx_LT64_ity64 ),
   4303                                   binop( Iop_Shr64,
   4304                                          binop( Iop_And64,
   4305                                                 mkU64( BPERMD_BIT_MASK ),
   4306                                                 binop( Iop_Shl64,
   4307                                                        mkexpr( rB ),
   4308                                                        mkexpr( idx ) ) ),
   4309                                          mkU8( 63 ) ) ) );
   4310              res = binop( Iop_Or64,
   4311                                 res,
   4312                                 binop( Iop_Shl64,
   4313                                        mkexpr( perm_bit ),
   4314                                        mkU8( i ) ) );
   4315              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
   4316           }
   4317           putIReg(rA_addr, res);
   4318           return True;
   4319        }
   4320 
   4321       default:
   4322          vex_printf("dis_int_logic(ppc)(opc2)\n");
   4323          return False;
   4324       }
   4325       break;
   4326 
   4327    default:
   4328       vex_printf("dis_int_logic(ppc)(opc1)\n");
   4329       return False;
   4330    }
   4331 
   4332    putIReg( rA_addr, mkexpr(rA) );
   4333 
   4334    if (do_rc && flag_rC) {
   4335       set_CR0( mkexpr(rA) );
   4336    }
   4337    return True;
   4338 }
   4339 
   4340 /*
   4341   Integer Parity Instructions
   4342 */
   4343 static Bool dis_int_parity ( UInt theInstr )
   4344 {
   4345    /* X-Form */
   4346    UChar opc1    = ifieldOPC(theInstr);
   4347    UChar rS_addr = ifieldRegDS(theInstr);
   4348    UChar rA_addr = ifieldRegA(theInstr);
   4349    UChar rB_addr = ifieldRegB(theInstr);
   4350    UInt  opc2    = ifieldOPClo10(theInstr);
   4351    UChar b0      = ifieldBIT0(theInstr);
   4352    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4353 
   4354    IRTemp rS     = newTemp(ty);
   4355    IRTemp rA     = newTemp(ty);
   4356    IRTemp iTot1  = newTemp(Ity_I32);
   4357    IRTemp iTot2  = newTemp(Ity_I32);
   4358    IRTemp iTot3  = newTemp(Ity_I32);
   4359    IRTemp iTot4  = newTemp(Ity_I32);
   4360    IRTemp iTot5  = newTemp(Ity_I32);
   4361    IRTemp iTot6  = newTemp(Ity_I32);
   4362    IRTemp iTot7  = newTemp(Ity_I32);
   4363    IRTemp iTot8  = newTemp(Ity_I32);
   4364    IRTemp rS1    = newTemp(ty);
   4365    IRTemp rS2    = newTemp(ty);
   4366    IRTemp rS3    = newTemp(ty);
   4367    IRTemp rS4    = newTemp(ty);
   4368    IRTemp rS5    = newTemp(ty);
   4369    IRTemp rS6    = newTemp(ty);
   4370    IRTemp rS7    = newTemp(ty);
   4371    IRTemp iHi    = newTemp(Ity_I32);
   4372    IRTemp iLo    = newTemp(Ity_I32);
   4373    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   4374    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   4375 
   4376    if (opc1 != 0x1f || rB_addr || b0) {
   4377       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   4378       return False;
   4379    }
   4380 
   4381    assign( rS, getIReg(rS_addr) );
   4382 
   4383    switch (opc2) {
   4384    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   4385       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   4386       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4387       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4388       assign( iTot2, binop(Iop_Add32,
   4389                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4390                            mkexpr(iTot1)) );
   4391       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4392       assign( iTot3, binop(Iop_Add32,
   4393                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4394                            mkexpr(iTot2)) );
   4395       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4396       assign( iTot4, binop(Iop_Add32,
   4397                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4398                            mkexpr(iTot3)) );
   4399       if (mode64) {
   4400          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4401          assign( iTot5, binop(Iop_Add32,
   4402                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   4403                               mkexpr(iTot4)) );
   4404          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4405          assign( iTot6, binop(Iop_Add32,
   4406                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4407                               mkexpr(iTot5)) );
   4408          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4409          assign( iTot7, binop(Iop_Add32,
   4410                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4411                               mkexpr(iTot6)) );
   4412          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   4413          assign( iTot8, binop(Iop_Add32,
   4414                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4415                               mkexpr(iTot7)) );
   4416          assign( rA, unop(Iop_32Uto64,
   4417                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   4418       } else
   4419          assign( rA, mkexpr(iTot4) );
   4420 
   4421       break;
   4422    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   4423       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4424       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4425       assign( iTot2, binop(Iop_Add32,
   4426                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4427                            mkexpr(iTot1)) );
   4428       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4429       assign( iTot3, binop(Iop_Add32,
   4430                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4431                            mkexpr(iTot2)) );
   4432       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4433       assign( iTot4, binop(Iop_Add32,
   4434                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4435                            mkexpr(iTot3)) );
   4436       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   4437 
   4438       if (mode64) {
   4439          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4440          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   4441          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4442          assign( iTot6, binop(Iop_Add32,
   4443                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4444                               mkexpr(iTot5)) );
   4445          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4446          assign( iTot7, binop(Iop_Add32,
   4447                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4448                               mkexpr(iTot6)) );
   4449          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   4450          assign( iTot8, binop(Iop_Add32,
   4451                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4452                               mkexpr(iTot7)) );
   4453          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   4454             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   4455       } else
   4456          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   4457       break;
   4458    default:
   4459       vex_printf("dis_int_parity(ppc)(opc2)\n");
   4460       return False;
   4461    }
   4462 
   4463    putIReg( rA_addr, mkexpr(rA) );
   4464 
   4465    return True;
   4466 }
   4467 
   4468 
   4469 /*
   4470   Integer Rotate Instructions
   4471 */
   4472 static Bool dis_int_rot ( UInt theInstr )
   4473 {
   4474    /* M-Form, MDS-Form */
   4475    UChar opc1    = ifieldOPC(theInstr);
   4476    UChar rS_addr = ifieldRegDS(theInstr);
   4477    UChar rA_addr = ifieldRegA(theInstr);
   4478    UChar rB_addr = ifieldRegB(theInstr);
   4479    UChar sh_imm  = rB_addr;
   4480    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   4481    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   4482    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   4483    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   4484    UChar b1      = ifieldBIT1(theInstr);
   4485    UChar flag_rC = ifieldBIT0(theInstr);
   4486 
   4487    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4488    IRTemp rS     = newTemp(ty);
   4489    IRTemp rA     = newTemp(ty);
   4490    IRTemp rB     = newTemp(ty);
   4491    IRTemp rot    = newTemp(ty);
   4492    IRExpr *r;
   4493    UInt   mask32;
   4494    ULong  mask64;
   4495 
   4496    assign( rS, getIReg(rS_addr) );
   4497    assign( rB, getIReg(rB_addr) );
   4498 
   4499    switch (opc1) {
   4500    case 0x14: {
   4501       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   4502       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4503           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4504       if (mode64) {
   4505          // tmp32 = (ROTL(rS_Lo32, Imm)
   4506          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   4507          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4508          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4509          r = unop(Iop_32Uto64, r);
   4510          assign( rot, binop(Iop_Or64, r,
   4511                             binop(Iop_Shl64, r, mkU8(32))) );
   4512          assign( rA,
   4513             binop(Iop_Or64,
   4514                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   4515                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   4516       }
   4517       else {
   4518          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   4519          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4520          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4521          assign( rA,
   4522             binop(Iop_Or32,
   4523                   binop(Iop_And32, mkU32(mask32), r),
   4524                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   4525       }
   4526       break;
   4527    }
   4528 
   4529    case 0x15: {
   4530       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   4531       vassert(MaskBeg < 32);
   4532       vassert(MaskEnd < 32);
   4533       vassert(sh_imm  < 32);
   4534 
   4535       if (mode64) {
   4536          IRTemp rTmp = newTemp(Ity_I64);
   4537          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4538          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4539              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4540          // tmp32 = (ROTL(rS_Lo32, Imm)
   4541          // rA = ((tmp32 || tmp32) & mask64)
   4542          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4543          r = unop(Iop_32Uto64, r);
   4544          assign( rTmp, r );
   4545          r = NULL;
   4546          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   4547                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   4548          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4549       }
   4550       else {
   4551          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   4552             /* Special-case the ,n,0,31-n form as that is just n-bit
   4553                shift left, PPC32 p501 */
   4554             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4555                 rA_addr, rS_addr, sh_imm);
   4556             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   4557          }
   4558          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   4559             /* Special-case the ,32-n,n,31 form as that is just n-bit
   4560                unsigned shift right, PPC32 p501 */
   4561             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4562                 rA_addr, rS_addr, MaskBeg);
   4563             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   4564          }
   4565          else {
   4566             /* General case. */
   4567             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4568             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4569                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4570             // rA = ROTL(rS, Imm) & mask
   4571             assign( rA, binop(Iop_And32,
   4572                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   4573                               mkU32(mask32)) );
   4574          }
   4575       }
   4576       break;
   4577    }
   4578 
   4579    case 0x17: {
   4580       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   4581       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   4582           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   4583       if (mode64) {
   4584          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4585          /* weird insn alert!
   4586             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   4587             rA = ((tmp32 || tmp32) & mask64)
   4588          */
   4589          // note, ROTL does the masking, so we don't do it here
   4590          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   4591                    unop(Iop_64to8, mkexpr(rB)) );
   4592          r = unop(Iop_32Uto64, r);
   4593          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   4594          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4595       } else {
   4596          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4597          // rA = ROTL(rS, rB[0-4]) & mask
   4598          // note, ROTL does the masking, so we don't do it here
   4599          assign( rA, binop(Iop_And32,
   4600                            ROTL(mkexpr(rS),
   4601                                 unop(Iop_32to8, mkexpr(rB))),
   4602                            mkU32(mask32)) );
   4603       }
   4604       break;
   4605    }
   4606 
   4607    /* 64bit Integer Rotates */
   4608    case 0x1E: {
   4609       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   4610       sh_imm |= b1 << 5;
   4611 
   4612       vassert( msk_imm < 64 );
   4613       vassert( sh_imm < 64 );
   4614 
   4615       switch (opc2) {
   4616       case 0x4: {
   4617          /* r = ROTL64( rS, rB_lo6) */
   4618          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   4619 
   4620          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   4621             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4622                 rA_addr, rS_addr, rB_addr, msk_imm);
   4623             // note, ROTL does the masking, so we don't do it here
   4624             mask64 = MASK64(0, 63-msk_imm);
   4625             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4626             break;
   4627          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   4628             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4629                 rA_addr, rS_addr, rB_addr, msk_imm);
   4630             mask64 = MASK64(63-msk_imm, 63);
   4631             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4632             break;
   4633          }
   4634          break;
   4635       }
   4636       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   4637          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4638              rA_addr, rS_addr, sh_imm, msk_imm);
   4639          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4640          mask64 = MASK64(sh_imm, 63-msk_imm);
   4641          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4642          break;
   4643          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   4644          /*
   4645            Hmm... looks like this'll do the job more simply:
   4646            r = SHL(rS, sh_imm)
   4647            m = ~(1 << (63-msk_imm))
   4648            assign(rA, r & m);
   4649          */
   4650 
   4651       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   4652          if (mode64
   4653              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   4654             /* special-case the ,64-n,n form as that is just
   4655                unsigned shift-right by n */
   4656             DIP("srdi%s r%u,r%u,%u\n",
   4657                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   4658             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   4659          } else {
   4660             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4661                 rA_addr, rS_addr, sh_imm, msk_imm);
   4662             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4663             mask64 = MASK64(0, 63-msk_imm);
   4664             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4665          }
   4666          break;
   4667 
   4668       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   4669          if (mode64
   4670              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   4671             /* special-case the ,n,63-n form as that is just
   4672                shift-left by n */
   4673             DIP("sldi%s r%u,r%u,%u\n",
   4674                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   4675             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   4676          } else {
   4677             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4678                 rA_addr, rS_addr, sh_imm, msk_imm);
   4679             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4680             mask64 = MASK64(63-msk_imm, 63);
   4681             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4682          }
   4683          break;
   4684 
   4685       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   4686          IRTemp rA_orig = newTemp(ty);
   4687          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4688              rA_addr, rS_addr, sh_imm, msk_imm);
   4689          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4690          mask64 = MASK64(sh_imm, 63-msk_imm);
   4691          assign( rA_orig, getIReg(rA_addr) );
   4692          assign( rA, binop(Iop_Or64,
   4693                            binop(Iop_And64, mkU64(mask64),  r),
   4694                            binop(Iop_And64, mkU64(~mask64),
   4695                                             mkexpr(rA_orig))) );
   4696          break;
   4697       }
   4698       default:
   4699          vex_printf("dis_int_rot(ppc)(opc2)\n");
   4700          return False;
   4701       }
   4702       break;
   4703    }
   4704 
   4705    default:
   4706       vex_printf("dis_int_rot(ppc)(opc1)\n");
   4707       return False;
   4708    }
   4709 
   4710    putIReg( rA_addr, mkexpr(rA) );
   4711 
   4712    if (flag_rC) {
   4713       set_CR0( mkexpr(rA) );
   4714    }
   4715    return True;
   4716 }
   4717 
   4718 
   4719 /*
   4720   Integer Load Instructions
   4721 */
   4722 static Bool dis_int_load ( UInt theInstr )
   4723 {
   4724    /* D-Form, X-Form, DS-Form */
   4725    UChar opc1     = ifieldOPC(theInstr);
   4726    UChar rD_addr  = ifieldRegDS(theInstr);
   4727    UChar rA_addr  = ifieldRegA(theInstr);
   4728    UInt  uimm16   = ifieldUIMM16(theInstr);
   4729    UChar rB_addr  = ifieldRegB(theInstr);
   4730    UInt  opc2     = ifieldOPClo10(theInstr);
   4731    UChar b1       = ifieldBIT1(theInstr);
   4732    UChar b0       = ifieldBIT0(theInstr);
   4733 
   4734    Int     simm16 = extend_s_16to32(uimm16);
   4735    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4736    IRTemp  EA     = newTemp(ty);
   4737    IRExpr* val;
   4738 
   4739    switch (opc1) {
   4740    case 0x1F: // register offset
   4741       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4742       break;
   4743    case 0x38: // immediate offset: 64bit: lq: maskoff
   4744               // lowest 4 bits of immediate before forming EA
   4745       simm16 = simm16 & 0xFFFFFFF0;
   4746       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4747       break;
   4748    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   4749               // lowest 2 bits of immediate before forming EA
   4750       simm16 = simm16 & 0xFFFFFFFC;
   4751       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4752       break;
   4753    default:   // immediate offset
   4754       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4755       break;
   4756    }
   4757 
   4758    switch (opc1) {
   4759    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   4760       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4761       val = loadBE(Ity_I8, mkexpr(EA));
   4762       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4763       break;
   4764 
   4765    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   4766       if (rA_addr == 0 || rA_addr == rD_addr) {
   4767          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   4768          return False;
   4769       }
   4770       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4771       val = loadBE(Ity_I8, mkexpr(EA));
   4772       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4773       putIReg( rA_addr, mkexpr(EA) );
   4774       break;
   4775 
   4776    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   4777       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4778       val = loadBE(Ity_I16, mkexpr(EA));
   4779       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4780       break;
   4781 
   4782    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   4783       if (rA_addr == 0 || rA_addr == rD_addr) {
   4784          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   4785          return False;
   4786       }
   4787       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4788       val = loadBE(Ity_I16, mkexpr(EA));
   4789       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4790       putIReg( rA_addr, mkexpr(EA) );
   4791       break;
   4792 
   4793    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   4794       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4795       val = loadBE(Ity_I16, mkexpr(EA));
   4796       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4797       break;
   4798 
   4799    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   4800       if (rA_addr == 0 || rA_addr == rD_addr) {
   4801          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   4802          return False;
   4803       }
   4804       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4805       val = loadBE(Ity_I16, mkexpr(EA));
   4806       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4807       putIReg( rA_addr, mkexpr(EA) );
   4808       break;
   4809 
   4810    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   4811       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4812       val = loadBE(Ity_I32, mkexpr(EA));
   4813       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4814       break;
   4815 
   4816    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   4817       if (rA_addr == 0 || rA_addr == rD_addr) {
   4818          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   4819          return False;
   4820       }
   4821       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4822       val = loadBE(Ity_I32, mkexpr(EA));
   4823       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4824       putIReg( rA_addr, mkexpr(EA) );
   4825       break;
   4826 
   4827    /* X Form */
   4828    case 0x1F:
   4829       if (b0 != 0) {
   4830          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   4831          return False;
   4832       }
   4833 
   4834       switch (opc2) {
   4835       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   4836          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4837          if (rA_addr == 0 || rA_addr == rD_addr) {
   4838             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4839             return False;
   4840          }
   4841          val = loadBE(Ity_I8, mkexpr(EA));
   4842          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4843          putIReg( rA_addr, mkexpr(EA) );
   4844          break;
   4845 
   4846       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   4847          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4848          val = loadBE(Ity_I8, mkexpr(EA));
   4849          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4850          break;
   4851 
   4852       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   4853          if (rA_addr == 0 || rA_addr == rD_addr) {
   4854             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   4855             return False;
   4856          }
   4857          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4858          val = loadBE(Ity_I16, mkexpr(EA));
   4859          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4860          putIReg( rA_addr, mkexpr(EA) );
   4861          break;
   4862 
   4863       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   4864          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4865          val = loadBE(Ity_I16, mkexpr(EA));
   4866          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4867          break;
   4868 
   4869       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   4870          if (rA_addr == 0 || rA_addr == rD_addr) {
   4871             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   4872             return False;
   4873          }
   4874          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4875          val = loadBE(Ity_I16, mkexpr(EA));
   4876          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4877          putIReg( rA_addr, mkexpr(EA) );
   4878          break;
   4879 
   4880       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   4881          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4882          val = loadBE(Ity_I16, mkexpr(EA));
   4883          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4884          break;
   4885 
   4886       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   4887          if (rA_addr == 0 || rA_addr == rD_addr) {
   4888             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4889             return False;
   4890          }
   4891          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4892          val = loadBE(Ity_I32, mkexpr(EA));
   4893          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4894          putIReg( rA_addr, mkexpr(EA) );
   4895          break;
   4896 
   4897       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   4898          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4899          val = loadBE(Ity_I32, mkexpr(EA));
   4900          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4901          break;
   4902 
   4903 
   4904       /* 64bit Loads */
   4905       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   4906          if (rA_addr == 0 || rA_addr == rD_addr) {
   4907             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   4908             return False;
   4909          }
   4910          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4911          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4912          putIReg( rA_addr, mkexpr(EA) );
   4913          break;
   4914 
   4915       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   4916          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4917          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4918          break;
   4919 
   4920       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   4921          if (rA_addr == 0 || rA_addr == rD_addr) {
   4922             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   4923             return False;
   4924          }
   4925          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4926          putIReg( rD_addr,
   4927                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4928          putIReg( rA_addr, mkexpr(EA) );
   4929          break;
   4930 
   4931       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   4932          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4933          putIReg( rD_addr,
   4934                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4935          break;
   4936 
   4937       default:
   4938          vex_printf("dis_int_load(ppc)(opc2)\n");
   4939          return False;
   4940       }
   4941       break;
   4942 
   4943    /* DS Form - 64bit Loads.  In each case EA will have been formed
   4944       with the lowest 2 bits masked off the immediate offset. */
   4945    case 0x3A:
   4946       switch ((b1<<1) | b0) {
   4947       case 0x0: // ld (Load DWord, PPC64 p472)
   4948          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4949          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4950          break;
   4951 
   4952       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   4953          if (rA_addr == 0 || rA_addr == rD_addr) {
   4954             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   4955             return False;
   4956          }
   4957          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4958          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4959          putIReg( rA_addr, mkexpr(EA) );
   4960          break;
   4961 
   4962       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   4963          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4964          putIReg( rD_addr,
   4965                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4966          break;
   4967 
   4968       default:
   4969          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4970          return False;
   4971       }
   4972       break;
   4973 
   4974    case 0x38: {
   4975       IRTemp  high = newTemp(ty);
   4976       IRTemp  low  = newTemp(ty);
   4977       /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
   4978       DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4979       /* NOTE: there are some changes to XER[41:42] that have not been
   4980        * implemented.
   4981        */
   4982       // trap if EA misaligned on 16 byte address
   4983       if (mode64) {
   4984          assign(high, loadBE(ty, mkexpr( EA ) ) );
   4985          assign(low, loadBE(ty, binop( Iop_Add64,
   4986                                        mkexpr( EA ),
   4987                                        mkU64( 8 ) ) ) );
   4988       } else {
   4989          assign(high, loadBE(ty, binop( Iop_Add32,
   4990                                         mkexpr( EA ),
   4991                                         mkU32( 4 ) ) ) );
   4992          assign(low, loadBE(ty, binop( Iop_Add32,
   4993                                         mkexpr( EA ),
   4994                                         mkU32( 12 ) ) ) );
   4995       }
   4996       gen_SIGBUS_if_misaligned( EA, 16 );
   4997       putIReg( rD_addr,  mkexpr( high) );
   4998       putIReg( rD_addr+1,  mkexpr( low) );
   4999       break;
   5000    }
   5001    default:
   5002       vex_printf("dis_int_load(ppc)(opc1)\n");
   5003       return False;
   5004    }
   5005    return True;
   5006 }
   5007 
   5008 
   5009 
   5010 /*
   5011   Integer Store Instructions
   5012 */
   5013 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
   5014 {
   5015    /* D-Form, X-Form, DS-Form */
   5016    UChar opc1    = ifieldOPC(theInstr);
   5017    UInt  rS_addr = ifieldRegDS(theInstr);
   5018    UInt  rA_addr = ifieldRegA(theInstr);
   5019    UInt  uimm16  = ifieldUIMM16(theInstr);
   5020    UInt  rB_addr = ifieldRegB(theInstr);
   5021    UInt  opc2    = ifieldOPClo10(theInstr);
   5022    UChar b1      = ifieldBIT1(theInstr);
   5023    UChar b0      = ifieldBIT0(theInstr);
   5024 
   5025    Int    simm16 = extend_s_16to32(uimm16);
   5026    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5027    IRTemp rS     = newTemp(ty);
   5028    IRTemp rB     = newTemp(ty);
   5029    IRTemp EA     = newTemp(ty);
   5030 
   5031    assign( rB, getIReg(rB_addr) );
   5032    assign( rS, getIReg(rS_addr) );
   5033 
   5034    switch (opc1) {
   5035    case 0x1F: // register offset
   5036       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5037       break;
   5038    case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
   5039               // lowest 2 bits of immediate before forming EA
   5040       simm16 = simm16 & 0xFFFFFFFC;
   5041    default:   // immediate offset
   5042       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5043       break;
   5044    }
   5045 
   5046    switch (opc1) {
   5047    case 0x26: // stb (Store B, PPC32 p509)
   5048       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5049       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5050       break;
   5051 
   5052    case 0x27: // stbu (Store B, Update, PPC32 p510)
   5053       if (rA_addr == 0 ) {
   5054          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   5055          return False;
   5056       }
   5057       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5058       putIReg( rA_addr, mkexpr(EA) );
   5059       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5060       break;
   5061 
   5062    case 0x2C: // sth (Store HW, PPC32 p522)
   5063       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5064       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5065       break;
   5066 
   5067    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   5068       if (rA_addr == 0) {
   5069          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   5070          return False;
   5071       }
   5072       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5073       putIReg( rA_addr, mkexpr(EA) );
   5074       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5075       break;
   5076 
   5077    case 0x24: // stw (Store W, PPC32 p530)
   5078       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5079       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5080       break;
   5081 
   5082    case 0x25: // stwu (Store W, Update, PPC32 p534)
   5083       if (rA_addr == 0) {
   5084          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   5085          return False;
   5086       }
   5087       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5088       putIReg( rA_addr, mkexpr(EA) );
   5089       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5090       break;
   5091 
   5092    /* X Form : all these use EA_indexed */
   5093    case 0x1F:
   5094       if (b0 != 0) {
   5095          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   5096          return False;
   5097       }
   5098 
   5099       switch (opc2) {
   5100       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   5101          if (rA_addr == 0) {
   5102             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   5103             return False;
   5104          }
   5105          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5106          putIReg( rA_addr, mkexpr(EA) );
   5107          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5108          break;
   5109 
   5110       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   5111          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5112          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5113          break;
   5114 
   5115       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   5116          if (rA_addr == 0) {
   5117             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   5118             return False;
   5119          }
   5120          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5121          putIReg( rA_addr, mkexpr(EA) );
   5122          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5123          break;
   5124 
   5125       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   5126          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5127          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5128          break;
   5129 
   5130       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   5131          if (rA_addr == 0) {
   5132             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   5133             return False;
   5134          }
   5135          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5136          putIReg( rA_addr, mkexpr(EA) );
   5137          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5138          break;
   5139 
   5140       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   5141          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5142          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5143          break;
   5144 
   5145 
   5146       /* 64bit Stores */
   5147       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   5148          if (rA_addr == 0) {
   5149             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   5150             return False;
   5151          }
   5152          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5153          putIReg( rA_addr, mkexpr(EA) );
   5154          storeBE( mkexpr(EA), mkexpr(rS) );
   5155          break;
   5156 
   5157       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   5158          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5159          storeBE( mkexpr(EA), mkexpr(rS) );
   5160          break;
   5161 
   5162       default:
   5163          vex_printf("dis_int_store(ppc)(opc2)\n");
   5164          return False;
   5165       }
   5166       break;
   5167 
   5168    /* DS Form - 64bit Stores.  In each case EA will have been formed
   5169       with the lowest 2 bits masked off the immediate offset. */
   5170    case 0x3E:
   5171       switch ((b1<<1) | b0) {
   5172       case 0x0: // std (Store DWord, PPC64 p580)
   5173          if (!mode64)
   5174             return False;
   5175 
   5176          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5177          storeBE( mkexpr(EA), mkexpr(rS) );
   5178          break;
   5179 
   5180       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   5181          if (!mode64)
   5182             return False;
   5183 
   5184          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5185          putIReg( rA_addr, mkexpr(EA) );
   5186          storeBE( mkexpr(EA), mkexpr(rS) );
   5187          break;
   5188 
   5189       case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
   5190          IRTemp EA_hi = newTemp(ty);
   5191          IRTemp EA_lo = newTemp(ty);
   5192          DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5193 
   5194          if (mode64) {
   5195             /* upper 64-bits */
   5196             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
   5197 
   5198             /* lower 64-bits */
   5199             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
   5200          } else {
   5201             /* upper half of upper 64-bits */
   5202             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
   5203 
   5204             /* lower half of upper 64-bits */
   5205             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
   5206          }
   5207          putIReg( rA_addr, mkexpr(EA_hi) );
   5208          storeBE( mkexpr(EA_hi), mkexpr(rS) );
   5209          putIReg( rA_addr, mkexpr( EA_lo) );
   5210          storeBE( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
   5211          break;
   5212       }
   5213       default:
   5214          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   5215          return False;
   5216       }
   5217       break;
   5218 
   5219    default:
   5220       vex_printf("dis_int_store(ppc)(opc1)\n");
   5221       return False;
   5222    }
   5223    return True;
   5224 }
   5225 
   5226 
   5227 
   5228 /*
   5229   Integer Load/Store Multiple Instructions
   5230 */
   5231 static Bool dis_int_ldst_mult ( UInt theInstr )
   5232 {
   5233    /* D-Form */
   5234    UChar opc1     = ifieldOPC(theInstr);
   5235    UChar rD_addr  = ifieldRegDS(theInstr);
   5236    UChar rS_addr  = rD_addr;
   5237    UChar rA_addr  = ifieldRegA(theInstr);
   5238    UInt  uimm16   = ifieldUIMM16(theInstr);
   5239 
   5240    Int     simm16 = extend_s_16to32(uimm16);
   5241    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   5242    IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
   5243    IRTemp  EA     = newTemp(ty);
   5244    UInt    r      = 0;
   5245    UInt    ea_off = 0;
   5246    IRExpr* irx_addr;
   5247 
   5248    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   5249 
   5250    switch (opc1) {
   5251    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   5252       if (rA_addr >= rD_addr) {
   5253          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   5254          return False;
   5255       }
   5256       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5257       for (r = rD_addr; r <= 31; r++) {
   5258          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5259          putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
   5260                                        False) );
   5261          ea_off += 4;
   5262       }
   5263       break;
   5264 
   5265    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   5266       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5267       for (r = rS_addr; r <= 31; r++) {
   5268          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5269          storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   5270          ea_off += 4;
   5271       }
   5272       break;
   5273 
   5274    default:
   5275       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   5276       return False;
   5277    }
   5278    return True;
   5279 }
   5280 
   5281 
   5282 
   5283 /*
   5284   Integer Load/Store String Instructions
   5285 */
   5286 static
   5287 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5288                              IRTemp EA,        // EA
   5289                              Int    rD,        // first dst register
   5290                              Int    maxBytes ) // 32 or 128
   5291 {
   5292    Int     i, shift = 24;
   5293    IRExpr* e_nbytes = mkexpr(tNBytes);
   5294    IRExpr* e_EA     = mkexpr(EA);
   5295    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5296 
   5297    vassert(rD >= 0 && rD < 32);
   5298    rD--; if (rD < 0) rD = 31;
   5299 
   5300    for (i = 0; i < maxBytes; i++) {
   5301       /* if (nBytes < (i+1)) goto NIA; */
   5302       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5303                          Ijk_Boring,
   5304                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   5305       /* when crossing into a new dest register, set it to zero. */
   5306       if ((i % 4) == 0) {
   5307          rD++; if (rD == 32) rD = 0;
   5308          putIReg(rD, mkSzImm(ty, 0));
   5309          shift = 24;
   5310       }
   5311       /* rD |=  (8Uto32(*(EA+i))) << shift */
   5312       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5313       putIReg(
   5314          rD,
   5315          mkWidenFrom32(
   5316             ty,
   5317             binop(
   5318                Iop_Or32,
   5319                mkNarrowTo32(ty, getIReg(rD)),
   5320                binop(
   5321                   Iop_Shl32,
   5322                   unop(
   5323                      Iop_8Uto32,
   5324                      loadBE(Ity_I8,
   5325                             binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
   5326                   ),
   5327                   mkU8(toUChar(shift))
   5328                )
   5329             ),
   5330             /*Signed*/False
   5331 	 )
   5332       );
   5333       shift -= 8;
   5334    }
   5335 }
   5336 
   5337 static
   5338 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5339                               IRTemp EA,        // EA
   5340                               Int    rS,        // first src register
   5341                               Int    maxBytes ) // 32 or 128
   5342 {
   5343    Int     i, shift = 24;
   5344    IRExpr* e_nbytes = mkexpr(tNBytes);
   5345    IRExpr* e_EA     = mkexpr(EA);
   5346    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5347 
   5348    vassert(rS >= 0 && rS < 32);
   5349    rS--; if (rS < 0) rS = 31;
   5350 
   5351    for (i = 0; i < maxBytes; i++) {
   5352       /* if (nBytes < (i+1)) goto NIA; */
   5353       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5354                          Ijk_Boring,
   5355                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
   5356       /* check for crossing into a new src register. */
   5357       if ((i % 4) == 0) {
   5358          rS++; if (rS == 32) rS = 0;
   5359          shift = 24;
   5360       }
   5361       /* *(EA+i) = 32to8(rS >> shift) */
   5362       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5363       storeBE(
   5364          binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   5365          unop(Iop_32to8,
   5366               binop(Iop_Shr32,
   5367                     mkNarrowTo32(ty, getIReg(rS)),
   5368                     mkU8(toUChar(shift))))
   5369       );
   5370       shift -= 8;
   5371    }
   5372 }
   5373 
   5374 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   5375 {
   5376    /* X-Form */
   5377    UChar opc1     = ifieldOPC(theInstr);
   5378    UChar rD_addr  = ifieldRegDS(theInstr);
   5379    UChar rS_addr  = rD_addr;
   5380    UChar rA_addr  = ifieldRegA(theInstr);
   5381    UChar rB_addr  = ifieldRegB(theInstr);
   5382    UChar NumBytes = rB_addr;
   5383    UInt  opc2     = ifieldOPClo10(theInstr);
   5384    UChar b0       = ifieldBIT0(theInstr);
   5385 
   5386    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5387    IRTemp t_EA    = newTemp(ty);
   5388    IRTemp t_nbytes = IRTemp_INVALID;
   5389 
   5390    *stopHere = False;
   5391 
   5392    if (opc1 != 0x1F || b0 != 0) {
   5393       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   5394       return False;
   5395    }
   5396 
   5397    switch (opc2) {
   5398    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   5399       /* NB: does not reject the case where RA is in the range of
   5400          registers to be loaded.  It should. */
   5401       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   5402       assign( t_EA, ea_rAor0(rA_addr) );
   5403       if (NumBytes == 8 && !mode64) {
   5404          /* Special case hack */
   5405          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   5406          putIReg( rD_addr,
   5407                   loadBE(Ity_I32, mkexpr(t_EA)) );
   5408          putIReg( (rD_addr+1) % 32,
   5409                   loadBE(Ity_I32,
   5410                          binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   5411       } else {
   5412          t_nbytes = newTemp(Ity_I32);
   5413          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5414          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5415          *stopHere = True;
   5416       }
   5417       return True;
   5418 
   5419    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   5420       /* NB: does not reject the case where RA is in the range of
   5421          registers to be loaded.  It should.  Although considering
   5422          that that can only be detected at run time, it's not easy to
   5423          do so. */
   5424       if (rD_addr == rA_addr || rD_addr == rB_addr)
   5425          return False;
   5426       if (rD_addr == 0 && rA_addr == 0)
   5427          return False;
   5428       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5429       t_nbytes = newTemp(Ity_I32);
   5430       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5431       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5432       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   5433       *stopHere = True;
   5434       return True;
   5435 
   5436    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   5437       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   5438       assign( t_EA, ea_rAor0(rA_addr) );
   5439       if (NumBytes == 8 && !mode64) {
   5440          /* Special case hack */
   5441          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   5442          storeBE( mkexpr(t_EA),
   5443                   getIReg(rD_addr) );
   5444          storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   5445                   getIReg((rD_addr+1) % 32) );
   5446       } else {
   5447          t_nbytes = newTemp(Ity_I32);
   5448          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5449          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5450          *stopHere = True;
   5451       }
   5452       return True;
   5453 
   5454    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   5455       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5456       t_nbytes = newTemp(Ity_I32);
   5457       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5458       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5459       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   5460       *stopHere = True;
   5461       return True;
   5462 
   5463    default:
   5464       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   5465       return False;
   5466    }
   5467    return True;
   5468 }
   5469 
   5470 
   5471 /* ------------------------------------------------------------------
   5472    Integer Branch Instructions
   5473    ------------------------------------------------------------------ */
   5474 
   5475 /*
   5476   Branch helper function
   5477   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   5478   Returns an I32 which is 0x00000000 if the ctr condition failed
   5479   and 0xFFFFFFFF otherwise.
   5480 */
   5481 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   5482 {
   5483    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5484    IRTemp ok = newTemp(Ity_I32);
   5485 
   5486    if ((BO >> 2) & 1) {     // independent of ctr
   5487       assign( ok, mkU32(0xFFFFFFFF) );
   5488    } else {
   5489       if ((BO >> 1) & 1) {  // ctr == 0 ?
   5490          assign( ok, unop( Iop_1Sto32,
   5491                            binop( mkSzOp(ty, Iop_CmpEQ8),
   5492                                   getGST( PPC_GST_CTR ),
   5493                                   mkSzImm(ty,0))) );
   5494       } else {              // ctr != 0 ?
   5495          assign( ok, unop( Iop_1Sto32,
   5496                            binop( mkSzOp(ty, Iop_CmpNE8),
   5497                                   getGST( PPC_GST_CTR ),
   5498                                   mkSzImm(ty,0))) );
   5499       }
   5500    }
   5501    return mkexpr(ok);
   5502 }
   5503 
   5504 
   5505 /*
   5506   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   5507   Returns an I32 which is either 0 if the condition failed or
   5508   some arbitrary nonzero value otherwise. */
   5509 
   5510 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   5511 {
   5512    Int where;
   5513    IRTemp res   = newTemp(Ity_I32);
   5514    IRTemp cr_bi = newTemp(Ity_I32);
   5515 
   5516    if ((BO >> 4) & 1) {
   5517       assign( res, mkU32(1) );
   5518    } else {
   5519       // ok = (CR[BI] == BO[3]) Note, the following relies on
   5520       // getCRbit_anywhere returning a value which
   5521       // is either zero or has exactly 1 bit set.
   5522       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   5523 
   5524       if ((BO >> 3) & 1) {
   5525          /* We can use cr_bi as-is. */
   5526          assign( res, mkexpr(cr_bi) );
   5527       } else {
   5528          /* We have to invert the sense of the information held in
   5529             cr_bi.  For that we need to know which bit
   5530             getCRbit_anywhere regards as significant. */
   5531          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   5532                                        mkU32(1<<where)) );
   5533       }
   5534    }
   5535    return mkexpr(res);
   5536 }
   5537 
   5538 
   5539 /*
   5540   Integer Branch Instructions
   5541 */
   5542 static Bool dis_branch ( UInt theInstr,
   5543                          VexAbiInfo* vbi,
   5544                          /*OUT*/DisResult* dres,
   5545                          Bool (*resteerOkFn)(void*,Addr64),
   5546                          void* callback_opaque )
   5547 {
   5548    UChar opc1    = ifieldOPC(theInstr);
   5549    UChar BO      = ifieldRegDS(theInstr);
   5550    UChar BI      = ifieldRegA(theInstr);
   5551    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   5552    UChar b11to15 = ifieldRegB(theInstr);
   5553    UInt  opc2    = ifieldOPClo10(theInstr);
   5554    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   5555    UChar flag_AA = ifieldBIT1(theInstr);
   5556    UChar flag_LK = ifieldBIT0(theInstr);
   5557 
   5558    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   5559    Addr64   tgt       = 0;
   5560    Int      BD        = extend_s_16to32(BD_u16);
   5561    IRTemp   do_branch = newTemp(Ity_I32);
   5562    IRTemp   ctr_ok    = newTemp(Ity_I32);
   5563    IRTemp   cond_ok   = newTemp(Ity_I32);
   5564    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   5565    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   5566    IRTemp   lr_old    = newTemp(ty);
   5567 
   5568    /* Hack to pass through code that just wants to read the PC */
   5569    if (theInstr == 0x429F0005) {
   5570       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   5571       putGST( PPC_GST_LR, e_nia );
   5572       return True;
   5573    }
   5574 
   5575    /* The default what-next.  Individual cases can override it. */
   5576    dres->whatNext = Dis_StopHere;
   5577    vassert(dres->jk_StopHere == Ijk_INVALID);
   5578 
   5579    switch (opc1) {
   5580    case 0x12: // b     (Branch, PPC32 p360)
   5581       if (flag_AA) {
   5582          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   5583       } else {
   5584          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   5585                              (Long)extend_s_26to64(LI_u26) );
   5586       }
   5587       if (mode64) {
   5588          DIP("b%s%s 0x%llx\n",
   5589              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   5590       } else {
   5591          DIP("b%s%s 0x%x\n",
   5592              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   5593       }
   5594 
   5595       if (flag_LK) {
   5596          putGST( PPC_GST_LR, e_nia );
   5597          if (vbi->guest_ppc_zap_RZ_at_bl
   5598              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   5599             IRTemp t_tgt = newTemp(ty);
   5600             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   5601             make_redzone_AbiHint( vbi, t_tgt,
   5602                                   "branch-and-link (unconditional call)" );
   5603          }
   5604       }
   5605 
   5606       if (resteerOkFn( callback_opaque, tgt )) {
   5607          dres->whatNext   = Dis_ResteerU;
   5608          dres->continueAt = tgt;
   5609       } else {
   5610          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
   5611          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
   5612       }
   5613       break;
   5614 
   5615    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   5616       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   5617           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   5618 
   5619       if (!(BO & 0x4)) {
   5620          putGST( PPC_GST_CTR,
   5621                  binop(mkSzOp(ty, Iop_Sub8),
   5622                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5623       }
   5624 
   5625       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   5626          cond_ok is either zero or nonzero, since that's the cheapest
   5627          way to compute it.  Anding them together gives a value which
   5628          is either zero or non zero and so that's what we must test
   5629          for in the IRStmt_Exit. */
   5630       assign( ctr_ok,  branch_ctr_ok( BO ) );
   5631       assign( cond_ok, branch_cond_ok( BO, BI ) );
   5632       assign( do_branch,
   5633               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5634 
   5635       if (flag_AA) {
   5636          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   5637       } else {
   5638          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   5639                             (Long)extend_s_16to64(BD_u16));
   5640       }
   5641       if (flag_LK)
   5642          putGST( PPC_GST_LR, e_nia );
   5643 
   5644       stmt( IRStmt_Exit(
   5645                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   5646                flag_LK ? Ijk_Call : Ijk_Boring,
   5647                mkSzConst(ty, tgt), OFFB_CIA ) );
   5648 
   5649       dres->jk_StopHere = Ijk_Boring;
   5650       putGST( PPC_GST_CIA, e_nia );
   5651       break;
   5652 
   5653    case 0x13:
   5654       /* For bclr and bcctr, it appears that the lowest two bits of
   5655          b11to15 are a branch hint, and so we only need to ensure it's
   5656          of the form 000XX. */
   5657       if ((b11to15 & ~3) != 0) {
   5658          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
   5659          return False;
   5660       }
   5661 
   5662       switch (opc2) {
   5663       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   5664          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   5665             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   5666             return False;
   5667          }
   5668          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5669 
   5670          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5671 
   5672          /* FIXME: this is confusing.  lr_old holds the old value
   5673             of ctr, not lr :-) */
   5674          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   5675 
   5676          if (flag_LK)
   5677             putGST( PPC_GST_LR, e_nia );
   5678 
   5679          stmt( IRStmt_Exit(
   5680                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   5681                   Ijk_Boring,
   5682                   c_nia, OFFB_CIA ));
   5683 
   5684          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   5685             make_redzone_AbiHint( vbi, lr_old,
   5686                                   "b-ctr-l (indirect call)" );
   5687 	 }
   5688 
   5689          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
   5690          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5691          break;
   5692 
   5693       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   5694          Bool vanilla_return = False;
   5695          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   5696             DIP("blr\n");
   5697             vanilla_return = True;
   5698          } else {
   5699             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5700          }
   5701 
   5702          if (!(BO & 0x4)) {
   5703             putGST( PPC_GST_CTR,
   5704                     binop(mkSzOp(ty, Iop_Sub8),
   5705                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5706          }
   5707 
   5708          /* See comments above for 'bc' about this */
   5709          assign( ctr_ok,  branch_ctr_ok( BO ) );
   5710          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5711          assign( do_branch,
   5712                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5713 
   5714          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   5715 
   5716          if (flag_LK)
   5717             putGST( PPC_GST_LR,  e_nia );
   5718 
   5719          stmt( IRStmt_Exit(
   5720                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   5721                   Ijk_Boring,
   5722                   c_nia, OFFB_CIA ));
   5723 
   5724          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   5725             make_redzone_AbiHint( vbi, lr_old,
   5726                                   "branch-to-lr (unconditional return)" );
   5727          }
   5728 
   5729          /* blrl is pretty strange; it's like a return that sets the
   5730             return address of its caller to the insn following this
   5731             one.  Mark it as a return. */
   5732          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   5733          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5734          break;
   5735       }
   5736       default:
   5737          vex_printf("dis_int_branch(ppc)(opc2)\n");
   5738          return False;
   5739       }
   5740       break;
   5741 
   5742    default:
   5743       vex_printf("dis_int_branch(ppc)(opc1)\n");
   5744       return False;
   5745    }
   5746 
   5747    return True;
   5748 }
   5749 
   5750 
   5751 
   5752 /*
   5753   Condition Register Logical Instructions
   5754 */
   5755 static Bool dis_cond_logic ( UInt theInstr )
   5756 {
   5757    /* XL-Form */
   5758    UChar opc1      = ifieldOPC(theInstr);
   5759    UChar crbD_addr = ifieldRegDS(theInstr);
   5760    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   5761    UChar crbA_addr = ifieldRegA(theInstr);
   5762    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   5763    UChar crbB_addr = ifieldRegB(theInstr);
   5764    UInt  opc2      = ifieldOPClo10(theInstr);
   5765    UChar b0        = ifieldBIT0(theInstr);
   5766 
   5767    IRTemp crbD     = newTemp(Ity_I32);
   5768    IRTemp crbA     = newTemp(Ity_I32);
   5769    IRTemp crbB     = newTemp(Ity_I32);
   5770 
   5771    if (opc1 != 19 || b0 != 0) {
   5772       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   5773       return False;
   5774    }
   5775 
   5776    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   5777       if (((crbD_addr & 0x3) != 0) ||
   5778           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   5779          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   5780          return False;
   5781       }
   5782       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   5783       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   5784       putCR321( crfD_addr, getCR321(crfS_addr) );
   5785    } else {
   5786       assign( crbA, getCRbit(crbA_addr) );
   5787       if (crbA_addr == crbB_addr)
   5788          crbB = crbA;
   5789       else
   5790          assign( crbB, getCRbit(crbB_addr) );
   5791 
   5792       switch (opc2) {
   5793       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   5794          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5795          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   5796          break;
   5797       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   5798          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5799          assign( crbD, binop(Iop_And32,
   5800                              mkexpr(crbA),
   5801                              unop(Iop_Not32, mkexpr(crbB))) );
   5802          break;
   5803       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   5804          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5805          assign( crbD, unop(Iop_Not32,
   5806                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   5807          break;
   5808       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   5809          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5810          assign( crbD, unop(Iop_Not32,
   5811                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   5812          break;
   5813       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   5814          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5815          assign( crbD, unop(Iop_Not32,
   5816                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   5817          break;
   5818       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   5819          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5820          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   5821          break;
   5822       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   5823          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5824          assign( crbD, binop(Iop_Or32,
   5825                              mkexpr(crbA),
   5826                              unop(Iop_Not32, mkexpr(crbB))) );
   5827          break;
   5828       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   5829          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5830          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   5831          break;
   5832       default:
   5833          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   5834          return False;
   5835       }
   5836 
   5837       putCRbit( crbD_addr, mkexpr(crbD) );
   5838    }
   5839    return True;
   5840 }
   5841 
   5842 
   5843 /*
   5844   Trap instructions
   5845 */
   5846 
   5847 /* Do the code generation for a trap.  Returned Bool is true iff
   5848    this is an unconditional trap.  If the two arg IRExpr*s are
   5849    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   5850    then they are 64-bit, and we must be disassembling 64-bit
   5851    instructions. */
   5852 static Bool do_trap ( UChar TO,
   5853                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   5854 {
   5855    IRTemp argL, argR;
   5856    IRExpr *argLe, *argRe, *cond, *tmp;
   5857 
   5858    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   5859 
   5860    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   5861    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   5862    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   5863    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   5864    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   5865    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   5866    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   5867    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   5868    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   5869    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   5870 
   5871    const UChar b11100 = 0x1C;
   5872    const UChar b00111 = 0x07;
   5873 
   5874    if (is32bit) {
   5875       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   5876       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   5877    } else {
   5878       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   5879       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   5880       vassert( mode64 );
   5881    }
   5882 
   5883    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   5884       /* Unconditional trap.  Just do the exit without
   5885          testing the arguments. */
   5886       stmt( IRStmt_Exit(
   5887                binop(opCMPEQ, const0, const0),
   5888                Ijk_SigTRAP,
   5889                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   5890                OFFB_CIA
   5891       ));
   5892       return True; /* unconditional trap */
   5893    }
   5894 
   5895    if (is32bit) {
   5896       argL = newTemp(Ity_I32);
   5897       argR = newTemp(Ity_I32);
   5898    } else {
   5899       argL = newTemp(Ity_I64);
   5900       argR = newTemp(Ity_I64);
   5901    }
   5902 
   5903    assign( argL, argL0 );
   5904    assign( argR, argR0 );
   5905 
   5906    argLe = mkexpr(argL);
   5907    argRe = mkexpr(argR);
   5908 
   5909    cond = const0;
   5910    if (TO & 16) { // L <s R
   5911       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   5912       cond = binop(opOR, tmp, cond);
   5913    }
   5914    if (TO & 8) { // L >s R
   5915       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   5916       cond = binop(opOR, tmp, cond);
   5917    }
   5918    if (TO & 4) { // L == R
   5919       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   5920       cond = binop(opOR, tmp, cond);
   5921    }
   5922    if (TO & 2) { // L <u R
   5923       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   5924       cond = binop(opOR, tmp, cond);
   5925    }
   5926    if (TO & 1) { // L >u R
   5927       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   5928       cond = binop(opOR, tmp, cond);
   5929    }
   5930    stmt( IRStmt_Exit(
   5931             binop(opCMPNE, cond, const0),
   5932             Ijk_SigTRAP,
   5933             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   5934             OFFB_CIA
   5935    ));
   5936    return False; /* not an unconditional trap */
   5937 }
   5938 
   5939 static Bool dis_trapi ( UInt theInstr,
   5940                         /*OUT*/DisResult* dres )
   5941 {
   5942    /* D-Form */
   5943    UChar  opc1    = ifieldOPC(theInstr);
   5944    UChar  TO      = ifieldRegDS(theInstr);
   5945    UChar  rA_addr = ifieldRegA(theInstr);
   5946    UInt   uimm16  = ifieldUIMM16(theInstr);
   5947    ULong  simm16  = extend_s_16to64(uimm16);
   5948    Addr64 cia     = guest_CIA_curr_instr;
   5949    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5950    Bool   uncond  = False;
   5951 
   5952    switch (opc1) {
   5953    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   5954       uncond = do_trap( TO,
   5955                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   5956                                : getIReg(rA_addr),
   5957                         mkU32( (UInt)simm16 ),
   5958                         cia );
   5959       if (TO == 4) {
   5960          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5961       } else {
   5962          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5963       }
   5964       break;
   5965    case 0x02: // tdi
   5966       if (!mode64)
   5967          return False;
   5968       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   5969       if (TO == 4) {
   5970          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5971       } else {
   5972          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5973       }
   5974       break;
   5975    default:
   5976       return False;
   5977    }
   5978 
   5979    if (uncond) {
   5980       /* If the trap shows signs of being unconditional, don't
   5981          continue decoding past it. */
   5982       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   5983       dres->jk_StopHere = Ijk_Boring;
   5984       dres->whatNext    = Dis_StopHere;
   5985    }
   5986 
   5987    return True;
   5988 }
   5989 
   5990 static Bool dis_trap ( UInt theInstr,
   5991                         /*OUT*/DisResult* dres )
   5992 {
   5993    /* X-Form */
   5994    UInt   opc2    = ifieldOPClo10(theInstr);
   5995    UChar  TO      = ifieldRegDS(theInstr);
   5996    UChar  rA_addr = ifieldRegA(theInstr);
   5997    UChar  rB_addr = ifieldRegB(theInstr);
   5998    Addr64 cia     = guest_CIA_curr_instr;
   5999    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   6000    Bool   uncond  = False;
   6001 
   6002    if (ifieldBIT0(theInstr) != 0)
   6003       return False;
   6004 
   6005    switch (opc2) {
   6006    case 0x004: // tw  (Trap Word, PPC64 p540)
   6007       uncond = do_trap( TO,
   6008                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   6009                                : getIReg(rA_addr),
   6010                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   6011                                : getIReg(rB_addr),
   6012                         cia );
   6013       if (TO == 4) {
   6014          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   6015       } else {
   6016          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   6017       }
   6018       break;
   6019    case 0x044: // td (Trap Doubleword, PPC64 p534)
   6020       if (!mode64)
   6021          return False;
   6022       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   6023       if (TO == 4) {
   6024          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   6025       } else {
   6026          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   6027       }
   6028       break;
   6029    default:
   6030       return False;
   6031    }
   6032 
   6033    if (uncond) {
   6034       /* If the trap shows signs of being unconditional, don't
   6035          continue decoding past it. */
   6036       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6037       dres->jk_StopHere = Ijk_Boring;
   6038       dres->whatNext    = Dis_StopHere;
   6039    }
   6040 
   6041    return True;
   6042 }
   6043 
   6044 
   6045 /*
   6046   System Linkage Instructions
   6047 */
   6048 static Bool dis_syslink ( UInt theInstr,
   6049                           VexAbiInfo* abiinfo, DisResult* dres )
   6050 {
   6051    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6052 
   6053    if (theInstr != 0x44000002) {
   6054       vex_printf("dis_syslink(ppc)(theInstr)\n");
   6055       return False;
   6056    }
   6057 
   6058    // sc  (System Call, PPC32 p504)
   6059    DIP("sc\n");
   6060 
   6061    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
   6062       Valgrind can back the guest up to this instruction if it needs
   6063       to restart the syscall. */
   6064    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   6065 
   6066    /* It's important that all ArchRegs carry their up-to-date value
   6067       at this point.  So we declare an end-of-block here, which
   6068       forces any TempRegs caching ArchRegs to be flushed. */
   6069    putGST( PPC_GST_CIA, abiinfo->guest_ppc_sc_continues_at_LR
   6070                         ? getGST( PPC_GST_LR )
   6071                         : mkSzImm( ty, nextInsnAddr() ));
   6072 
   6073    dres->whatNext    = Dis_StopHere;
   6074    dres->jk_StopHere = Ijk_Sys_syscall;
   6075    return True;
   6076 }
   6077 
   6078 
   6079 /*
   6080   Memory Synchronization Instructions
   6081 
   6082   Note on Reservations:
   6083   We rely on the assumption that V will in fact only allow one thread at
   6084   once to run.  In effect, a thread can make a reservation, but we don't
   6085   check any stores it does.  Instead, the reservation is cancelled when
   6086   the scheduler switches to another thread (run_thread_for_a_while()).
   6087 */
   6088 static Bool dis_memsync ( UInt theInstr )
   6089 {
   6090    /* X-Form, XL-Form */
   6091    UChar opc1    = ifieldOPC(theInstr);
   6092    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   6093    UChar flag_L  = ifieldRegDS(theInstr);
   6094    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   6095    UChar rD_addr = ifieldRegDS(theInstr);
   6096    UChar rS_addr = rD_addr;
   6097    UChar rA_addr = ifieldRegA(theInstr);
   6098    UChar rB_addr = ifieldRegB(theInstr);
   6099    UInt  opc2    = ifieldOPClo10(theInstr);
   6100    UChar b0      = ifieldBIT0(theInstr);
   6101 
   6102    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6103    IRTemp EA     = newTemp(ty);
   6104 
   6105    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6106 
   6107    switch (opc1) {
   6108    /* XL-Form */
   6109    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   6110       if (opc2 != 0x096) {
   6111          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   6112          return False;
   6113       }
   6114       if (b11to25 != 0 || b0 != 0) {
   6115          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   6116          return False;
   6117       }
   6118       DIP("isync\n");
   6119       stmt( IRStmt_MBE(Imbe_Fence) );
   6120       break;
   6121 
   6122    /* X-Form */
   6123    case 0x1F:
   6124       switch (opc2) {
   6125       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
   6126          if (b11to25 != 0 || b0 != 0) {
   6127             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
   6128             return False;
   6129          }
   6130          DIP("eieio\n");
   6131          /* Insert a memory fence, just to be on the safe side. */
   6132          stmt( IRStmt_MBE(Imbe_Fence) );
   6133          break;
   6134 
   6135       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   6136          IRTemp res;
   6137          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6138             in the documentation) is merely a hint bit to the
   6139             hardware, I think as to whether or not contention is
   6140             likely.  So we can just ignore it. */
   6141          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6142 
   6143          // trap if misaligned
   6144          gen_SIGBUS_if_misaligned( EA, 4 );
   6145 
   6146          // and actually do the load
   6147          res = newTemp(Ity_I32);
   6148          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   6149 
   6150          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   6151          break;
   6152       }
   6153 
   6154       case 0x096: {
   6155          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   6156          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   6157          // so isn't quite as straightforward as it might otherwise be.
   6158          IRTemp rS = newTemp(Ity_I32);
   6159          IRTemp resSC;
   6160          if (b0 != 1) {
   6161             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   6162             return False;
   6163          }
   6164          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6165 
   6166          // trap if misaligned
   6167          gen_SIGBUS_if_misaligned( EA, 4 );
   6168 
   6169          // Get the data to be stored, and narrow to 32 bits if necessary
   6170          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6171 
   6172          // Do the store, and get success/failure bit into resSC
   6173          resSC = newTemp(Ity_I1);
   6174          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   6175 
   6176          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6177          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6178          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6179          putCR0(0, getXER_SO());
   6180 
   6181          /* Note:
   6182             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6183             whether rS is stored is dependent on that value. */
   6184          /* So I guess we can just ignore this case? */
   6185          break;
   6186       }
   6187 
   6188       case 0x256: // sync (Synchronize, PPC32 p543),
   6189                   // also lwsync (L==1), ptesync (L==2)
   6190          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   6191 
   6192             The PowerPC architecture used in IBM chips has expanded
   6193             the sync instruction into two variants: lightweight sync
   6194             and heavyweight sync.  The original sync instruction is
   6195             the new heavyweight sync and lightweight sync is a strict
   6196             subset of the heavyweight sync functionality. This allows
   6197             the programmer to specify a less expensive operation on
   6198             high-end systems when the full sync functionality is not
   6199             necessary.
   6200 
   6201             The basic "sync" mnemonic now utilizes an operand. "sync"
   6202             without an operand now becomes a extended mnemonic for
   6203             heavyweight sync.  Processors without the lwsync
   6204             instruction will not decode the L field and will perform a
   6205             heavyweight sync.  Everything is backward compatible.
   6206 
   6207             sync    =       sync 0
   6208             lwsync  =       sync 1
   6209             ptesync =       sync 2    *** TODO - not implemented ***
   6210          */
   6211          if (b11to20 != 0 || b0 != 0) {
   6212             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   6213             return False;
   6214          }
   6215          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   6216             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   6217             return False;
   6218          }
   6219          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   6220          /* Insert a memory fence.  It's sometimes important that these
   6221             are carried through to the generated code. */
   6222          stmt( IRStmt_MBE(Imbe_Fence) );
   6223          break;
   6224 
   6225       /* 64bit Memsync */
   6226       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   6227          IRTemp res;
   6228          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6229             in the documentation) is merely a hint bit to the
   6230             hardware, I think as to whether or not contention is
   6231             likely.  So we can just ignore it. */
   6232          if (!mode64)
   6233             return False;
   6234          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6235 
   6236          // trap if misaligned
   6237          gen_SIGBUS_if_misaligned( EA, 8 );
   6238 
   6239          // and actually do the load
   6240          res = newTemp(Ity_I64);
   6241          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   6242 
   6243          putIReg( rD_addr, mkexpr(res) );
   6244          break;
   6245       }
   6246 
   6247       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   6248          // A marginally simplified version of the stwcx. case
   6249          IRTemp rS = newTemp(Ity_I64);
   6250          IRTemp resSC;
   6251          if (b0 != 1) {
   6252             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   6253             return False;
   6254          }
   6255          if (!mode64)
   6256             return False;
   6257          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6258 
   6259          // trap if misaligned
   6260          gen_SIGBUS_if_misaligned( EA, 8 );
   6261 
   6262          // Get the data to be stored
   6263          assign( rS, getIReg(rS_addr) );
   6264 
   6265          // Do the store, and get success/failure bit into resSC
   6266          resSC = newTemp(Ity_I1);
   6267          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   6268 
   6269          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6270          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6271          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6272          putCR0(0, getXER_SO());
   6273 
   6274          /* Note:
   6275             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6276             whether rS is stored is dependent on that value. */
   6277          /* So I guess we can just ignore this case? */
   6278          break;
   6279       }
   6280 
   6281       /* 128bit Memsync */
   6282       case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
   6283          IRTemp res_hi = newTemp(ty);
   6284          IRTemp res_lo = newTemp(ty);
   6285 
   6286          /* According to the PowerPC ISA version 2.07, b0 (called EH
   6287             in the documentation) is merely a hint bit to the
   6288             hardware, I think as to whether or not contention is
   6289             likely.  So we can just ignore it. */
   6290          DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   6291 
   6292          // trap if misaligned
   6293          gen_SIGBUS_if_misaligned( EA, 16 );
   6294 
   6295          // and actually do the load
   6296          if (mode64) {
   6297             stmt( IRStmt_LLSC( Iend_BE, res_hi,
   6298                                mkexpr(EA), NULL/*this is a load*/) );
   6299             stmt( IRStmt_LLSC( Iend_BE, res_lo,
   6300                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
   6301                                NULL/*this is a load*/) );
   6302          } else {
   6303             stmt( IRStmt_LLSC( Iend_BE, res_hi,
   6304                                binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
   6305                                NULL/*this is a load*/) );
   6306             stmt( IRStmt_LLSC( Iend_BE, res_lo,
   6307                                binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
   6308                                NULL/*this is a load*/) );
   6309          }
   6310          putIReg( rD_addr,   mkexpr(res_hi) );
   6311          putIReg( rD_addr+1, mkexpr(res_lo) );
   6312          break;
   6313       }
   6314 
   6315       case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
   6316          // A marginally simplified version of the stwcx. case
   6317          IRTemp rS_hi = newTemp(ty);
   6318          IRTemp rS_lo = newTemp(ty);
   6319          IRTemp resSC;
   6320          if (b0 != 1) {
   6321             vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
   6322             return False;
   6323          }
   6324 
   6325          DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6326 
   6327          // trap if misaligned
   6328          gen_SIGBUS_if_misaligned( EA, 16 );
   6329          // Get the data to be stored
   6330          assign( rS_hi, getIReg(rS_addr) );
   6331          assign( rS_lo, getIReg(rS_addr+1) );
   6332 
   6333          // Do the store, and get success/failure bit into resSC
   6334          resSC = newTemp(Ity_I1);
   6335 
   6336          if (mode64) {
   6337             stmt( IRStmt_LLSC( Iend_BE, resSC, mkexpr(EA), mkexpr(rS_hi) ) );
   6338             storeBE(binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) );
   6339          } else {
   6340             stmt( IRStmt_LLSC( Iend_BE, resSC, binop( Iop_Add32,
   6341                                                       mkexpr(EA),
   6342                                                       mkU32(4) ),
   6343                                                       mkexpr(rS_hi) ) );
   6344             storeBE(binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
   6345          }
   6346 
   6347          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6348          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6349          putCR321(0, binop( Iop_Shl8,
   6350                             unop(Iop_1Uto8, mkexpr(resSC) ),
   6351                             mkU8(1)));
   6352          putCR0(0, getXER_SO());
   6353          break;
   6354       }
   6355 
   6356       default:
   6357          vex_printf("dis_memsync(ppc)(opc2)\n");
   6358          return False;
   6359       }
   6360       break;
   6361 
   6362    default:
   6363       vex_printf("dis_memsync(ppc)(opc1)\n");
   6364       return False;
   6365    }
   6366    return True;
   6367 }
   6368 
   6369 
   6370 
   6371 /*
   6372   Integer Shift Instructions
   6373 */
   6374 static Bool dis_int_shift ( UInt theInstr )
   6375 {
   6376    /* X-Form, XS-Form */
   6377    UChar opc1    = ifieldOPC(theInstr);
   6378    UChar rS_addr = ifieldRegDS(theInstr);
   6379    UChar rA_addr = ifieldRegA(theInstr);
   6380    UChar rB_addr = ifieldRegB(theInstr);
   6381    UChar sh_imm  = rB_addr;
   6382    UInt  opc2    = ifieldOPClo10(theInstr);
   6383    UChar b1      = ifieldBIT1(theInstr);
   6384    UChar flag_rC = ifieldBIT0(theInstr);
   6385 
   6386    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   6387    IRTemp  rA         = newTemp(ty);
   6388    IRTemp  rS         = newTemp(ty);
   6389    IRTemp  rB         = newTemp(ty);
   6390    IRTemp  outofrange = newTemp(Ity_I1);
   6391    IRTemp  rS_lo32    = newTemp(Ity_I32);
   6392    IRTemp  rB_lo32    = newTemp(Ity_I32);
   6393    IRExpr* e_tmp;
   6394 
   6395    assign( rS, getIReg(rS_addr) );
   6396    assign( rB, getIReg(rB_addr) );
   6397    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   6398    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   6399 
   6400    if (opc1 == 0x1F) {
   6401       switch (opc2) {
   6402       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   6403          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6404              rA_addr, rS_addr, rB_addr);
   6405          /* rA = rS << rB */
   6406          /* ppc32 semantics are:
   6407             slw(x,y) = (x << (y & 31))         -- primary result
   6408                        & ~((y << 26) >>s 31)   -- make result 0
   6409                                                   for y in 32 .. 63
   6410          */
   6411          e_tmp =
   6412             binop( Iop_And32,
   6413                binop( Iop_Shl32,
   6414                       mkexpr(rS_lo32),
   6415                       unop( Iop_32to8,
   6416                             binop(Iop_And32,
   6417                                   mkexpr(rB_lo32), mkU32(31)))),
   6418                unop( Iop_Not32,
   6419                      binop( Iop_Sar32,
   6420                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   6421                             mkU8(31))) );
   6422          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6423          break;
   6424       }
   6425 
   6426       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   6427          IRTemp sh_amt = newTemp(Ity_I32);
   6428          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6429              rA_addr, rS_addr, rB_addr);
   6430          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   6431             amt = rB & 63
   6432             rA = Sar32( rS, amt > 31 ? 31 : amt )
   6433             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   6434          */
   6435          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   6436                                           mkexpr(rB_lo32)) );
   6437          assign( outofrange,
   6438                  binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
   6439          e_tmp = binop( Iop_Sar32,
   6440                         mkexpr(rS_lo32),
   6441                         unop( Iop_32to8,
   6442                               IRExpr_ITE( mkexpr(outofrange),
   6443                                           mkU32(31),
   6444                                           mkexpr(sh_amt)) ) );
   6445          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   6446 
   6447          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   6448                      mkexpr(rA),
   6449                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   6450                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   6451                      mkWidenFrom32(ty, getXER_CA32(), True) );
   6452          break;
   6453       }
   6454 
   6455       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   6456          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   6457              rA_addr, rS_addr, sh_imm);
   6458          vassert(sh_imm < 32);
   6459          if (mode64) {
   6460             assign( rA, binop(Iop_Sar64,
   6461                               binop(Iop_Shl64, getIReg(rS_addr),
   6462                                                mkU8(32)),
   6463                               mkU8(32 + sh_imm)) );
   6464          } else {
   6465             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   6466                                          mkU8(sh_imm)) );
   6467          }
   6468 
   6469          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   6470                      mkexpr(rA),
   6471                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   6472                      mkSzImm(ty, sh_imm),
   6473                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6474          break;
   6475 
   6476       case 0x218: // srw (Shift Right Word, PPC32 p508)
   6477          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6478              rA_addr, rS_addr, rB_addr);
   6479          /* rA = rS >>u rB */
   6480          /* ppc32 semantics are:
   6481             srw(x,y) = (x >>u (y & 31))        -- primary result
   6482                        & ~((y << 26) >>s 31)   -- make result 0
   6483                                                   for y in 32 .. 63
   6484          */
   6485          e_tmp =
   6486             binop(
   6487                Iop_And32,
   6488                binop( Iop_Shr32,
   6489                       mkexpr(rS_lo32),
   6490                       unop( Iop_32to8,
   6491                             binop(Iop_And32, mkexpr(rB_lo32),
   6492                                              mkU32(31)))),
   6493                unop( Iop_Not32,
   6494                      binop( Iop_Sar32,
   6495                             binop(Iop_Shl32, mkexpr(rB_lo32),
   6496                                              mkU8(26)),
   6497                             mkU8(31))));
   6498          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6499          break;
   6500 
   6501 
   6502       /* 64bit Shifts */
   6503       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   6504          DIP("sld%s r%u,r%u,r%u\n",
   6505              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6506          /* rA = rS << rB */
   6507          /* ppc64 semantics are:
   6508             slw(x,y) = (x << (y & 63))         -- primary result
   6509                        & ~((y << 57) >>s 63)   -- make result 0
   6510                                                   for y in 64 ..
   6511          */
   6512          assign( rA,
   6513             binop(
   6514                Iop_And64,
   6515                binop( Iop_Shl64,
   6516                       mkexpr(rS),
   6517                       unop( Iop_64to8,
   6518                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6519                unop( Iop_Not64,
   6520                      binop( Iop_Sar64,
   6521                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6522                             mkU8(63)))) );
   6523          break;
   6524 
   6525       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   6526          IRTemp sh_amt = newTemp(Ity_I64);
   6527          DIP("srad%s r%u,r%u,r%u\n",
   6528              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6529          /* amt = rB & 127
   6530             rA = Sar64( rS, amt > 63 ? 63 : amt )
   6531             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   6532          */
   6533          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   6534          assign( outofrange,
   6535                  binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
   6536          assign( rA,
   6537                  binop( Iop_Sar64,
   6538                         mkexpr(rS),
   6539                         unop( Iop_64to8,
   6540                               IRExpr_ITE( mkexpr(outofrange),
   6541                                           mkU64(63),
   6542                                           mkexpr(sh_amt)) ))
   6543                );
   6544          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   6545                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   6546                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6547          break;
   6548       }
   6549 
   6550       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   6551          sh_imm |= b1<<5;
   6552          vassert(sh_imm < 64);
   6553          DIP("sradi%s r%u,r%u,%u\n",
   6554              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   6555          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   6556 
   6557          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   6558                      mkexpr(rA),
   6559                      getIReg(rS_addr),
   6560                      mkU64(sh_imm),
   6561                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6562          break;
   6563 
   6564       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   6565          DIP("srd%s r%u,r%u,r%u\n",
   6566              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6567          /* rA = rS >>u rB */
   6568          /* ppc semantics are:
   6569             srw(x,y) = (x >>u (y & 63))        -- primary result
   6570                        & ~((y << 57) >>s 63)   -- make result 0
   6571                                                   for y in 64 .. 127
   6572          */
   6573          assign( rA,
   6574             binop(
   6575                Iop_And64,
   6576                binop( Iop_Shr64,
   6577                       mkexpr(rS),
   6578                       unop( Iop_64to8,
   6579                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6580                unop( Iop_Not64,
   6581                      binop( Iop_Sar64,
   6582                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6583                             mkU8(63)))) );
   6584          break;
   6585 
   6586       default:
   6587          vex_printf("dis_int_shift(ppc)(opc2)\n");
   6588          return False;
   6589       }
   6590    } else {
   6591       vex_printf("dis_int_shift(ppc)(opc1)\n");
   6592       return False;
   6593    }
   6594 
   6595    putIReg( rA_addr, mkexpr(rA) );
   6596 
   6597    if (flag_rC) {
   6598       set_CR0( mkexpr(rA) );
   6599    }
   6600    return True;
   6601 }
   6602 
   6603 
   6604 
   6605 /*
   6606   Integer Load/Store Reverse Instructions
   6607 */
   6608 /* Generates code to swap the byte order in an Ity_I32. */
   6609 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   6610 {
   6611    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6612    return
   6613       binop(Iop_Or32,
   6614          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   6615       binop(Iop_Or32,
   6616          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6617                           mkU32(0x00FF0000)),
   6618       binop(Iop_Or32,
   6619          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6620                           mkU32(0x0000FF00)),
   6621          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   6622                           mkU32(0x000000FF) )
   6623       )));
   6624 }
   6625 
   6626 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   6627    and zeroes the upper half. */
   6628 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   6629 {
   6630    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6631    return
   6632       binop(Iop_Or32,
   6633          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6634                           mkU32(0x0000FF00)),
   6635          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6636                           mkU32(0x000000FF))
   6637       );
   6638 }
   6639 
   6640 static Bool dis_int_ldst_rev ( UInt theInstr )
   6641 {
   6642    /* X-Form */
   6643    UChar opc1    = ifieldOPC(theInstr);
   6644    UChar rD_addr = ifieldRegDS(theInstr);
   6645    UChar rS_addr = rD_addr;
   6646    UChar rA_addr = ifieldRegA(theInstr);
   6647    UChar rB_addr = ifieldRegB(theInstr);
   6648    UInt  opc2    = ifieldOPClo10(theInstr);
   6649    UChar b0      = ifieldBIT0(theInstr);
   6650 
   6651    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6652    IRTemp EA = newTemp(ty);
   6653    IRTemp w1 = newTemp(Ity_I32);
   6654    IRTemp w2 = newTemp(Ity_I32);
   6655 
   6656    if (opc1 != 0x1F || b0 != 0) {
   6657       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   6658       return False;
   6659    }
   6660 
   6661    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6662 
   6663    switch (opc2) {
   6664 
   6665       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   6666          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6667          assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
   6668          assign( w2, gen_byterev16(w1) );
   6669          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6670                                          /* Signed */False) );
   6671          break;
   6672 
   6673       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   6674          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6675          assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
   6676          assign( w2, gen_byterev32(w1) );
   6677          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6678                                          /* Signed */False) );
   6679          break;
   6680 
   6681       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
   6682       {
   6683          IRExpr * nextAddr;
   6684          IRTemp w3 = newTemp( Ity_I32 );
   6685          IRTemp w4 = newTemp( Ity_I32 );
   6686          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6687          assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
   6688          assign( w2, gen_byterev32( w1 ) );
   6689          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   6690                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
   6691          assign( w3, loadBE( Ity_I32, nextAddr ) );
   6692          assign( w4, gen_byterev32( w3 ) );
   6693          putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
   6694          break;
   6695       }
   6696 
   6697       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   6698          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6699          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6700          storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   6701          break;
   6702 
   6703       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   6704          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6705          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6706          storeBE( mkexpr(EA), gen_byterev32(w1) );
   6707          break;
   6708 
   6709       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
   6710       {
   6711          IRTemp lo = newTemp(Ity_I32);
   6712          IRTemp hi = newTemp(Ity_I32);
   6713          IRTemp rS = newTemp(Ity_I64);
   6714          assign( rS, getIReg( rS_addr ) );
   6715          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6716          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
   6717          assign(hi, unop(Iop_64to32, mkexpr(rS)));
   6718          storeBE( mkexpr( EA ),
   6719                   binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
   6720          break;
   6721       }
   6722 
   6723       default:
   6724          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   6725          return False;
   6726    }
   6727    return True;
   6728 }
   6729 
   6730 
   6731 
   6732 /*
   6733   Processor Control Instructions
   6734 */
   6735 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
   6736 {
   6737    UChar opc1     = ifieldOPC(theInstr);
   6738 
   6739    /* X-Form */
   6740    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   6741    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   6742    UChar rD_addr  = ifieldRegDS(theInstr);
   6743    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   6744 
   6745    /* XFX-Form */
   6746    UChar rS_addr  = rD_addr;
   6747    UInt  SPR      = b11to20;
   6748    UInt  TBR      = b11to20;
   6749    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   6750    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   6751    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   6752 
   6753    UInt  opc2     = ifieldOPClo10(theInstr);
   6754    UChar b0       = ifieldBIT0(theInstr);
   6755 
   6756    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6757    IRTemp rS = newTemp(ty);
   6758    assign( rS, getIReg(rS_addr) );
   6759 
   6760    /* Reorder SPR field as per PPC32 p470 */
   6761    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   6762    /* Reorder TBR field as per PPC32 p475 */
   6763    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   6764 
   6765    /* b0 = 0, inst is treated as floating point inst for reservation purposes
   6766     * b0 = 1, inst is treated as vector inst for reservation purposes
   6767     */
   6768    if (opc1 != 0x1F) {
   6769       vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
   6770       return False;
   6771    }
   6772 
   6773    switch (opc2) {
   6774    /* X-Form */
   6775    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   6776       if (b21to22 != 0 || b11to20 != 0) {
   6777          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   6778          return False;
   6779       }
   6780       DIP("mcrxr crf%d\n", crfD);
   6781       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   6782       putGST_field( PPC_GST_CR,
   6783                     getGST_field( PPC_GST_XER, 7 ),
   6784                     crfD );
   6785 
   6786       // Clear XER[0-3]
   6787       putXER_SO( mkU8(0) );
   6788       putXER_OV( mkU8(0) );
   6789       putXER_CA( mkU8(0) );
   6790       break;
   6791    }
   6792 
   6793    case 0x013:
   6794       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   6795       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   6796       // However it seems that the 'mfcr' behaviour is an acceptable
   6797       // implementation of mfocr (from the 2.02 arch spec)
   6798       if (b11to20 == 0) {
   6799          DIP("mfcr r%u\n", rD_addr);
   6800          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6801                                          /* Signed */False) );
   6802          break;
   6803       }
   6804       if (b20 == 1 && b11 == 0) {
   6805          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   6806          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6807                                          /* Signed */False) );
   6808          break;
   6809       }
   6810       /* not decodable */
   6811       return False;
   6812 
   6813    /* XFX-Form */
   6814    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   6815 
   6816       switch (SPR) {  // Choose a register...
   6817       case 0x1:
   6818          DIP("mfxer r%u\n", rD_addr);
   6819          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   6820                                          /* Signed */False) );
   6821          break;
   6822       case 0x8:
   6823          DIP("mflr r%u\n", rD_addr);
   6824          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   6825          break;
   6826       case 0x9:
   6827          DIP("mfctr r%u\n", rD_addr);
   6828          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   6829          break;
   6830       case 0x80:  // 128
   6831          DIP("mfspr r%u (TFHAR)\n", rD_addr);
   6832          putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
   6833          break;
   6834       case 0x81:  // 129
   6835          DIP("mfspr r%u (TFIAR)\n", rD_addr);
   6836          putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
   6837          break;
   6838       case 0x82:  // 130
   6839          DIP("mfspr r%u (TEXASR)\n", rD_addr);
   6840          putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
   6841          break;
   6842       case 0x100:
   6843          DIP("mfvrsave r%u\n", rD_addr);
   6844          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   6845                                          /* Signed */False) );
   6846          break;
   6847 
   6848       case 0x103:
   6849          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   6850          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   6851          break;
   6852 
   6853       /* Even a lowly PPC7400 can run the associated helper, so no
   6854          obvious need for feature testing at this point. */
   6855       case 268 /* 0x10C */:
   6856       case 269 /* 0x10D */: {
   6857          UInt     arg  = SPR==268 ? 0 : 1;
   6858          IRTemp   val  = newTemp(Ity_I32);
   6859          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   6860          IRDirty* d    = unsafeIRDirty_1_N(
   6861                             val,
   6862                             0/*regparms*/,
   6863                             "ppc32g_dirtyhelper_MFSPR_268_269",
   6864                             fnptr_to_fnentry
   6865                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   6866                             args
   6867                          );
   6868          /* execute the dirty call, dumping the result in val. */
   6869          stmt( IRStmt_Dirty(d) );
   6870          putIReg( rD_addr,
   6871                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6872          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6873          break;
   6874       }
   6875 
   6876       /* Again, runs natively on PPC7400 (7447, really).  Not
   6877          bothering with a feature test. */
   6878       case 287: /* 0x11F */ {
   6879          IRTemp   val  = newTemp(Ity_I32);
   6880          IRExpr** args = mkIRExprVec_0();
   6881          IRDirty* d    = unsafeIRDirty_1_N(
   6882                             val,
   6883                             0/*regparms*/,
   6884                             "ppc32g_dirtyhelper_MFSPR_287",
   6885                             fnptr_to_fnentry
   6886                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   6887                             args
   6888                          );
   6889          /* execute the dirty call, dumping the result in val. */
   6890          stmt( IRStmt_Dirty(d) );
   6891          putIReg( rD_addr,
   6892                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6893          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6894          break;
   6895       }
   6896 
   6897       default:
   6898          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   6899          return False;
   6900       }
   6901       break;
   6902 
   6903    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   6904       IRTemp   val  = newTemp(Ity_I64);
   6905       IRExpr** args = mkIRExprVec_0();
   6906       IRDirty* d    = unsafeIRDirty_1_N(
   6907                               val,
   6908                               0/*regparms*/,
   6909                               "ppcg_dirtyhelper_MFTB",
   6910                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   6911                               args );
   6912       /* execute the dirty call, dumping the result in val. */
   6913       stmt( IRStmt_Dirty(d) );
   6914 
   6915       switch (TBR) {
   6916       case 269:
   6917          DIP("mftbu r%u", rD_addr);
   6918          putIReg( rD_addr,
   6919                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   6920                                 /* Signed */False) );
   6921          break;
   6922       case 268:
   6923          DIP("mftb r%u", rD_addr);
   6924          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   6925                                       unop(Iop_64to32, mkexpr(val)) );
   6926          break;
   6927       default:
   6928          return False; /* illegal instruction */
   6929       }
   6930       break;
   6931    }
   6932 
   6933    case 0x090: {
   6934       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   6935       // b20==1: mtocrf (Move to One Cond Reg Field)
   6936       Int   cr;
   6937       UChar shft;
   6938       if (b11 != 0)
   6939          return False;
   6940       if (b20 == 1) {
   6941          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   6942             1 field is written.  It seems more robust to decline to
   6943             decode the insn if so. */
   6944          switch (CRM) {
   6945             case 0x01: case 0x02: case 0x04: case 0x08:
   6946             case 0x10: case 0x20: case 0x40: case 0x80:
   6947                break;
   6948             default:
   6949                return False;
   6950          }
   6951       }
   6952       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   6953                            CRM, rS_addr);
   6954       /* Write to each field specified by CRM */
   6955       for (cr = 0; cr < 8; cr++) {
   6956          if ((CRM & (1 << (7-cr))) == 0)
   6957             continue;
   6958          shft = 4*(7-cr);
   6959          putGST_field( PPC_GST_CR,
   6960                        binop(Iop_Shr32,
   6961                              mkNarrowTo32(ty, mkexpr(rS)),
   6962                              mkU8(shft)), cr );
   6963       }
   6964       break;
   6965    }
   6966 
   6967    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   6968 
   6969       switch (SPR) {  // Choose a register...
   6970       case 0x1:
   6971          DIP("mtxer r%u\n", rS_addr);
   6972          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   6973          break;
   6974       case 0x8:
   6975          DIP("mtlr r%u\n", rS_addr);
   6976          putGST( PPC_GST_LR, mkexpr(rS) );
   6977          break;
   6978       case 0x9:
   6979          DIP("mtctr r%u\n", rS_addr);
   6980          putGST( PPC_GST_CTR, mkexpr(rS) );
   6981          break;
   6982       case 0x100:
   6983          DIP("mtvrsave r%u\n", rS_addr);
   6984          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   6985          break;
   6986       case 0x80:  // 128
   6987          DIP("mtspr r%u (TFHAR)\n", rS_addr);
   6988          putGST( PPC_GST_TFHAR, mkexpr(rS) );
   6989          break;
   6990       case 0x81:  // 129
   6991          DIP("mtspr r%u (TFIAR)\n", rS_addr);
   6992          putGST( PPC_GST_TFIAR, mkexpr(rS) );
   6993          break;
   6994       case 0x82:  // 130
   6995          DIP("mtspr r%u (TEXASR)\n", rS_addr);
   6996          putGST( PPC_GST_TEXASR, mkexpr(rS) );
   6997          break;
   6998       default:
   6999          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   7000          return False;
   7001       }
   7002       break;
   7003 
   7004    case 0x33:                // mfvsrd
   7005    {
   7006       UChar XS = ifieldRegXS( theInstr );
   7007       UChar rA_addr = ifieldRegA(theInstr);
   7008       IRExpr * high64;
   7009       IRTemp vS = newTemp( Ity_V128 );
   7010       DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS);
   7011 
   7012       /*  XS = SX || S
   7013        *  For SX=0, mfvsrd is treated as a Floating-Point
   7014        *            instruction in terms of resource availability.
   7015        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7016        *            terms of resource availability.
   7017        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7018        */
   7019       assign( vS, getVSReg( XS ) );
   7020       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7021       putIReg( rA_addr, (mode64) ? high64 :
   7022       unop( Iop_64to32, high64 ) );
   7023       break;
   7024    }
   7025 
   7026    case 0x73:                // mfvsrwz
   7027    {
   7028       UChar XS = ifieldRegXS( theInstr );
   7029       UChar rA_addr = ifieldRegA(theInstr);
   7030       IRExpr * high64;
   7031       IRTemp vS = newTemp( Ity_V128 );
   7032       DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS);
   7033       /*  XS = SX || S
   7034        *  For SX=0, mfvsrwz is treated as a Floating-Point
   7035        *            instruction in terms of resource availability.
   7036        *  For SX=1, mfvsrwz is treated as a Vector instruction in
   7037        *            terms of resource availability.
   7038        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7039        */
   7040 
   7041       assign( vS, getVSReg( XS ) );
   7042       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7043       /* move value to the destination setting the upper 32-bits to zero */
   7044       putIReg( rA_addr, (mode64) ?
   7045                                   binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
   7046                                   unop(  Iop_64to32,
   7047                                          binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
   7048       break;
   7049    }
   7050 
   7051    case 0xB3:                // mtvsrd
   7052    {
   7053       UChar XT = ifieldRegXT( theInstr );
   7054       UChar rA_addr = ifieldRegA(theInstr);
   7055       IRTemp rA = newTemp(ty);
   7056       DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr);
   7057       /*  XS = SX || S
   7058        *  For SX=0, mfvsrd is treated as a Floating-Point
   7059        *            instruction in terms of resource availability.
   7060        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7061        *            terms of resource availability.
   7062        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7063        */
   7064       assign( rA, getIReg(rA_addr) );
   7065 
   7066       if (mode64)
   7067          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
   7068       else
   7069          putVSReg( XT, binop( Iop_64HLtoV128,
   7070                               binop( Iop_32HLto64,
   7071                                      mkU32( 0 ),
   7072                                      mkexpr( rA ) ),
   7073                                      mkU64( 0 ) ) );
   7074       break;
   7075    }
   7076 
   7077    case 0xD3:                // mtvsrwa
   7078    {
   7079       UChar XT = ifieldRegXT( theInstr );
   7080       UChar rA_addr = ifieldRegA(theInstr);
   7081       IRTemp rA = newTemp( Ity_I32 );
   7082       DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr);
   7083       /*  XS = SX || S
   7084        *  For SX=0, mtvsrwa is treated as a Floating-Point
   7085        *            instruction in terms of resource availability.
   7086        *  For SX=1, mtvsrwa is treated as a Vector instruction in
   7087        *            terms of resource availability.
   7088        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7089        */
   7090       if (mode64)
   7091          assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7092       else
   7093          assign( rA, getIReg(rA_addr) );
   7094 
   7095       putVSReg( XT, binop( Iop_64HLtoV128,
   7096                            unop( Iop_32Sto64, mkexpr( rA ) ),
   7097                            mkU64( 0 ) ) );
   7098       break;
   7099    }
   7100 
   7101    case 0xF3:                // mtvsrwz
   7102       {
   7103          UChar XT = ifieldRegXT( theInstr );
   7104          UChar rA_addr = ifieldRegA(theInstr);
   7105          IRTemp rA = newTemp( Ity_I32 );
   7106          DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT);
   7107          /*  XS = SX || S
   7108           *  For SX=0, mtvsrwz is treated as a Floating-Point
   7109           *            instruction in terms of resource availability.
   7110           *  For SX=1, mtvsrwz is treated as a Vector instruction in
   7111           *            terms of resource availability.
   7112           * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7113           */
   7114          if (mode64)
   7115              assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7116          else
   7117              assign( rA, getIReg(rA_addr) );
   7118 
   7119          putVSReg( XT, binop( Iop_64HLtoV128,
   7120                               binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
   7121                               mkU64( 0 ) ) );
   7122          break;
   7123       }
   7124 
   7125    default:
   7126       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   7127       return False;
   7128    }
   7129    return True;
   7130 }
   7131 
   7132 
   7133 /*
   7134   Cache Management Instructions
   7135 */
   7136 static Bool dis_cache_manage ( UInt         theInstr,
   7137                                DisResult*   dres,
   7138                                VexArchInfo* guest_archinfo )
   7139 {
   7140    /* X-Form */
   7141    UChar opc1    = ifieldOPC(theInstr);
   7142    UChar b21to25 = ifieldRegDS(theInstr);
   7143    UChar rA_addr = ifieldRegA(theInstr);
   7144    UChar rB_addr = ifieldRegB(theInstr);
   7145    UInt  opc2    = ifieldOPClo10(theInstr);
   7146    UChar b0      = ifieldBIT0(theInstr);
   7147    UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
   7148    Bool  is_dcbzl = False;
   7149 
   7150    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7151 
   7152    // Check for valid hint values for dcbt and dcbtst as currently described in
   7153    // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
   7154    // means of modeling the hint anyway.
   7155    if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
   7156       if (b21to25 == 0x10 || b21to25 < 0x10)
   7157          b21to25 = 0;
   7158    }
   7159    if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
   7160       b21to25 = 0;
   7161 
   7162    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   7163       if (b21to25 == 1) {
   7164          is_dcbzl = True;
   7165          b21to25 = 0;
   7166          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   7167             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   7168             return False;
   7169          }
   7170       }
   7171    }
   7172 
   7173    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
   7174       if (0) vex_printf("dis_cache_manage %d %d %d\n",
   7175                         (Int)opc1, (Int)b21to25, (Int)b0);
   7176       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
   7177       return False;
   7178    }
   7179 
   7180    /* stay sane .. */
   7181    vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
   7182 
   7183    switch (opc2) {
   7184 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   7185 //zz       vassert(0); /* AWAITING TEST CASE */
   7186 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   7187 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   7188 //zz       break;
   7189 
   7190    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   7191       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   7192       /* nop as far as vex is concerned */
   7193       break;
   7194 
   7195    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   7196       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   7197       /* nop as far as vex is concerned */
   7198       break;
   7199 
   7200    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   7201       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   7202       /* nop as far as vex is concerned */
   7203       break;
   7204 
   7205    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   7206       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   7207       /* nop as far as vex is concerned */
   7208       break;
   7209 
   7210    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   7211                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   7212       /* Clear all bytes in cache block at (rA|0) + rB. */
   7213       IRTemp  EA   = newTemp(ty);
   7214       IRTemp  addr = newTemp(ty);
   7215       IRExpr* irx_addr;
   7216       UInt    i;
   7217       UInt clearszB;
   7218       if (is_dcbzl) {
   7219           clearszB = guest_archinfo->ppc_dcbzl_szB;
   7220           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   7221       }
   7222       else {
   7223           clearszB = guest_archinfo->ppc_dcbz_szB;
   7224           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   7225       }
   7226 
   7227       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7228 
   7229       if (mode64) {
   7230          /* Round EA down to the start of the containing block. */
   7231          assign( addr, binop( Iop_And64,
   7232                               mkexpr(EA),
   7233                               mkU64( ~((ULong)clearszB-1) )) );
   7234 
   7235          for (i = 0; i < clearszB / 8; i++) {
   7236             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   7237             storeBE( irx_addr, mkU64(0) );
   7238          }
   7239       } else {
   7240          /* Round EA down to the start of the containing block. */
   7241          assign( addr, binop( Iop_And32,
   7242                               mkexpr(EA),
   7243                               mkU32( ~(clearszB-1) )) );
   7244 
   7245          for (i = 0; i < clearszB / 4; i++) {
   7246             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   7247             storeBE( irx_addr, mkU32(0) );
   7248          }
   7249       }
   7250       break;
   7251    }
   7252 
   7253    case 0x3D6: {
   7254       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   7255       /* Invalidate all translations containing code from the cache
   7256          block at (rA|0) + rB. */
   7257       IRTemp EA   = newTemp(ty);
   7258       IRTemp addr = newTemp(ty);
   7259       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   7260       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7261 
   7262       /* Round EA down to the start of the containing block. */
   7263       assign( addr, binop( mkSzOp(ty, Iop_And8),
   7264                            mkexpr(EA),
   7265                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   7266       putGST( PPC_GST_CMSTART, mkexpr(addr) );
   7267       putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
   7268 
   7269       /* be paranoid ... */
   7270       stmt( IRStmt_MBE(Imbe_Fence) );
   7271 
   7272       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
   7273       dres->jk_StopHere = Ijk_InvalICache;
   7274       dres->whatNext    = Dis_StopHere;
   7275       break;
   7276    }
   7277 
   7278    default:
   7279       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   7280       return False;
   7281    }
   7282    return True;
   7283 }
   7284 
   7285 
   7286 /*------------------------------------------------------------*/
   7287 /*--- Floating Point Helpers                               ---*/
   7288 /*------------------------------------------------------------*/
   7289 
   7290 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   7291 /* Produces a value in 0 .. 3, which is encoded as per the type
   7292    IRRoundingMode.  PPCRoundingMode encoding is different to
   7293    IRRoundingMode, so need to map it.
   7294 */
   7295 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   7296 {
   7297 /*
   7298    rounding mode | PPC | IR
   7299    ------------------------
   7300    to nearest    | 00  | 00
   7301    to zero       | 01  | 11
   7302    to +infinity  | 10  | 10
   7303    to -infinity  | 11  | 01
   7304 */
   7305    IRTemp rm_PPC32 = newTemp(Ity_I32);
   7306    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   7307 
   7308    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7309    return binop( Iop_Xor32,
   7310                  mkexpr(rm_PPC32),
   7311                  binop( Iop_And32,
   7312                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   7313                         mkU32(2) ));
   7314 }
   7315 
   7316 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
   7317  * mapping would still work with the extended three bit DFP rounding
   7318  * mode designator.
   7319 
   7320  *  rounding mode                     | PPC  |  IR
   7321  *  -----------------------------------------------
   7322  *  to nearest, ties to even          | 000  | 000
   7323  *  to zero                           | 001  | 011
   7324  *  to +infinity                      | 010  | 010
   7325  *  to -infinity                      | 011  | 001
   7326  *  to nearest, ties away from 0      | 100  | 100
   7327  *  to nearest, ties toward 0         | 101  | 111
   7328  *  to away from 0                    | 110  | 110
   7329  *  to prepare for shorter precision  | 111  | 101
   7330  */
   7331 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
   7332 {
   7333    IRTemp rm_PPC32 = newTemp( Ity_I32 );
   7334    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
   7335 
   7336    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7337    return binop( Iop_Xor32,
   7338                  mkexpr( rm_PPC32 ),
   7339                  binop( Iop_And32,
   7340                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
   7341                         mkU32( 2 ) ) );
   7342 }
   7343 
   7344 #define NANmaskSingle   0x7F800000
   7345 #define NANmaskDouble   0x7FF00000
   7346 
   7347 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
   7348 {
   7349    IRTemp exp_zero  = newTemp(Ity_I8);
   7350    IRTemp frac_mask = newTemp(Ity_I32);
   7351    IRTemp frac_not_zero = newTemp(Ity_I8);
   7352 
   7353    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
   7354     * The input value is always 64-bits, for single precision values, the
   7355     * lower 32 bits must be zero.
   7356     *
   7357     * Single Pricision
   7358     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
   7359     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
   7360     *  [31:0]  unused for single precision representation
   7361     *
   7362     * Double Pricision
   7363     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
   7364     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
   7365     *
   7366     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
   7367     */
   7368    assign( frac_mask, unop( Iop_Not32,
   7369                             binop( Iop_Or32,
   7370                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
   7371 
   7372    assign( exp_zero,
   7373            unop( Iop_1Sto8,
   7374                  binop( Iop_CmpEQ32,
   7375                         binop( Iop_And32,
   7376                                unop( Iop_64HIto32,
   7377                                      unop( Iop_ReinterpF64asI64,
   7378                                            value ) ),
   7379                                Hi32Mask ),
   7380                         Hi32Mask ) ) );
   7381    assign( frac_not_zero,
   7382            binop( Iop_Or8,
   7383                   unop( Iop_1Sto8,
   7384                         binop( Iop_CmpNE32,
   7385                                binop( Iop_And32,
   7386                                       unop( Iop_64HIto32,
   7387                                             unop( Iop_ReinterpF64asI64,
   7388                                                   value ) ),
   7389                                       mkexpr( frac_mask ) ),
   7390                                mkU32( 0x0 ) ) ),
   7391                   unop( Iop_1Sto8,
   7392                         binop( Iop_CmpNE32,
   7393                                binop( Iop_And32,
   7394                                       unop( Iop_64to32,
   7395                                             unop( Iop_ReinterpF64asI64,
   7396                                                   value ) ),
   7397                                       mkU32( 0xFFFFFFFF ) ),
   7398                                mkU32( 0x0 ) ) ) ) );
   7399    return unop( Iop_8Sto32,
   7400                 binop( Iop_And8,
   7401                        mkexpr( exp_zero ),
   7402                        mkexpr( frac_not_zero ) ) );
   7403 }
   7404 
   7405 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
   7406 {
   7407    /* This function will only complement the 64-bit floating point value if it
   7408     * is not Nan.  NaN is not a signed value.  Need to do computations using
   7409     * 32-bit operands to ensure it will run in 32-bit mode.
   7410     */
   7411    return  binop( Iop_32HLto64,
   7412                   binop( Iop_Or32,
   7413                          binop( Iop_And32,
   7414                                 nan_mask,
   7415                                 unop( Iop_64HIto32,
   7416                                       unop( Iop_ReinterpF64asI64,
   7417                                             value ) ) ),
   7418                          binop( Iop_And32,
   7419                                 unop( Iop_Not32,
   7420                                       nan_mask ),
   7421                                 unop( Iop_64HIto32,
   7422                                       unop( Iop_ReinterpF64asI64,
   7423                                             unop( Iop_NegF64,
   7424                                                   value ) ) ) ) ),
   7425                   unop( Iop_64to32,
   7426                         unop( Iop_ReinterpF64asI64, value ) ) );
   7427 }
   7428 
   7429 /*------------------------------------------------------------*/
   7430 /*--- Floating Point Instruction Translation               ---*/
   7431 /*------------------------------------------------------------*/
   7432 
   7433 /*
   7434   Floating Point Load Instructions
   7435 */
   7436 static Bool dis_fp_load ( UInt theInstr )
   7437 {
   7438    /* X-Form, D-Form */
   7439    UChar opc1      = ifieldOPC(theInstr);
   7440    UChar frD_addr  = ifieldRegDS(theInstr);
   7441    UChar rA_addr   = ifieldRegA(theInstr);
   7442    UChar rB_addr   = ifieldRegB(theInstr);
   7443    UInt  opc2      = ifieldOPClo10(theInstr);
   7444    UChar b0        = ifieldBIT0(theInstr);
   7445    UInt  uimm16    = ifieldUIMM16(theInstr);
   7446 
   7447    Int    simm16 = extend_s_16to32(uimm16);
   7448    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7449    IRTemp EA     = newTemp(ty);
   7450    IRTemp rA     = newTemp(ty);
   7451    IRTemp rB     = newTemp(ty);
   7452    IRTemp iHi    = newTemp(Ity_I32);
   7453    IRTemp iLo    = newTemp(Ity_I32);
   7454 
   7455    assign( rA, getIReg(rA_addr) );
   7456    assign( rB, getIReg(rB_addr) );
   7457 
   7458    /* These are completely straightforward from a rounding and status
   7459       bits perspective: no rounding involved and no funny status or CR
   7460       bits affected. */
   7461 
   7462    switch (opc1) {
   7463    case 0x30: // lfs (Load Float Single, PPC32 p441)
   7464       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7465       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7466       putFReg( frD_addr,
   7467                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   7468       break;
   7469 
   7470    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   7471       if (rA_addr == 0)
   7472          return False;
   7473       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7474       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7475       putFReg( frD_addr,
   7476                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   7477       putIReg( rA_addr, mkexpr(EA) );
   7478       break;
   7479 
   7480    case 0x32: // lfd (Load Float Double, PPC32 p437)
   7481       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7482       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7483       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7484       break;
   7485 
   7486    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   7487       if (rA_addr == 0)
   7488          return False;
   7489       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7490       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7491       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7492       putIReg( rA_addr, mkexpr(EA) );
   7493       break;
   7494 
   7495    case 0x1F:
   7496       if (b0 != 0) {
   7497          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   7498          return False;
   7499       }
   7500 
   7501       switch(opc2) {
   7502       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   7503          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7504          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7505          putFReg( frD_addr, unop( Iop_F32toF64,
   7506                                   loadBE(Ity_F32, mkexpr(EA))) );
   7507          break;
   7508 
   7509       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   7510          if (rA_addr == 0)
   7511             return False;
   7512          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7513          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7514          putFReg( frD_addr,
   7515                   unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   7516          putIReg( rA_addr, mkexpr(EA) );
   7517          break;
   7518 
   7519       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   7520          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7521          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7522          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7523          break;
   7524 
   7525       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   7526          if (rA_addr == 0)
   7527             return False;
   7528          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7529          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7530          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7531          putIReg( rA_addr, mkexpr(EA) );
   7532          break;
   7533 
   7534       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   7535          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7536          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7537          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   7538          assign( iHi, binop(Iop_Sub32,
   7539                             mkU32(0),
   7540                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   7541          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   7542                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   7543          break;
   7544 
   7545       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
   7546       {
   7547          IRTemp dw = newTemp( Ity_I64 );
   7548          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7549          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7550          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   7551          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
   7552          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
   7553          break;
   7554       }
   7555 
   7556       default:
   7557          vex_printf("dis_fp_load(ppc)(opc2)\n");
   7558          return False;
   7559       }
   7560       break;
   7561 
   7562    default:
   7563       vex_printf("dis_fp_load(ppc)(opc1)\n");
   7564       return False;
   7565    }
   7566    return True;
   7567 }
   7568 
   7569 
   7570 
   7571 /*
   7572   Floating Point Store Instructions
   7573 */
   7574 static Bool dis_fp_store ( UInt theInstr )
   7575 {
   7576    /* X-Form, D-Form */
   7577    UChar opc1      = ifieldOPC(theInstr);
   7578    UChar frS_addr  = ifieldRegDS(theInstr);
   7579    UChar rA_addr   = ifieldRegA(theInstr);
   7580    UChar rB_addr   = ifieldRegB(theInstr);
   7581    UInt  opc2      = ifieldOPClo10(theInstr);
   7582    UChar b0        = ifieldBIT0(theInstr);
   7583    Int   uimm16    = ifieldUIMM16(theInstr);
   7584 
   7585    Int    simm16 = extend_s_16to32(uimm16);
   7586    IRTemp frS    = newTemp(Ity_F64);
   7587    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7588    IRTemp EA     = newTemp(ty);
   7589    IRTemp rA     = newTemp(ty);
   7590    IRTemp rB     = newTemp(ty);
   7591 
   7592    assign( frS, getFReg(frS_addr) );
   7593    assign( rA,  getIReg(rA_addr) );
   7594    assign( rB,  getIReg(rB_addr) );
   7595 
   7596    /* These are straightforward from a status bits perspective: no
   7597       funny status or CR bits affected.  For single precision stores,
   7598       the values are truncated and denormalised (not rounded) to turn
   7599       them into single precision values. */
   7600 
   7601    switch (opc1) {
   7602 
   7603    case 0x34: // stfs (Store Float Single, PPC32 p518)
   7604       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7605       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7606       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   7607          the value to be stored in the correct way, without any
   7608          rounding. */
   7609       storeBE( mkexpr(EA),
   7610                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7611       break;
   7612 
   7613    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   7614       if (rA_addr == 0)
   7615          return False;
   7616       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7617       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7618       /* See comment for stfs */
   7619       storeBE( mkexpr(EA),
   7620                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7621       putIReg( rA_addr, mkexpr(EA) );
   7622       break;
   7623 
   7624    case 0x36: // stfd (Store Float Double, PPC32 p513)
   7625       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7626       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7627       storeBE( mkexpr(EA), mkexpr(frS) );
   7628       break;
   7629 
   7630    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   7631       if (rA_addr == 0)
   7632          return False;
   7633       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7634       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7635       storeBE( mkexpr(EA), mkexpr(frS) );
   7636       putIReg( rA_addr, mkexpr(EA) );
   7637       break;
   7638 
   7639    case 0x1F:
   7640       if (b0 != 0) {
   7641          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   7642          return False;
   7643       }
   7644       switch(opc2) {
   7645       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   7646          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7647          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7648          /* See note for stfs */
   7649          storeBE( mkexpr(EA),
   7650                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7651          break;
   7652 
   7653       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   7654          if (rA_addr == 0)
   7655             return False;
   7656          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7657          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7658          /* See note for stfs */
   7659          storeBE( mkexpr(EA),
   7660                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7661          putIReg( rA_addr, mkexpr(EA) );
   7662          break;
   7663 
   7664       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   7665          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7666          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7667          storeBE( mkexpr(EA), mkexpr(frS) );
   7668          break;
   7669 
   7670       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   7671          if (rA_addr == 0)
   7672             return False;
   7673          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7674          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7675          storeBE( mkexpr(EA), mkexpr(frS) );
   7676          putIReg( rA_addr, mkexpr(EA) );
   7677          break;
   7678 
   7679       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   7680          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7681          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7682          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7683          storeBE( mkexpr(EA),
   7684                   unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   7685          break;
   7686 
   7687       default:
   7688          vex_printf("dis_fp_store(ppc)(opc2)\n");
   7689          return False;
   7690       }
   7691       break;
   7692 
   7693    default:
   7694       vex_printf("dis_fp_store(ppc)(opc1)\n");
   7695       return False;
   7696    }
   7697    return True;
   7698 }
   7699 
   7700 
   7701 
   7702 /*
   7703   Floating Point Arith Instructions
   7704 */
   7705 static Bool dis_fp_arith ( UInt theInstr )
   7706 {
   7707    /* A-Form */
   7708    UChar opc1     = ifieldOPC(theInstr);
   7709    UChar frD_addr = ifieldRegDS(theInstr);
   7710    UChar frA_addr = ifieldRegA(theInstr);
   7711    UChar frB_addr = ifieldRegB(theInstr);
   7712    UChar frC_addr = ifieldRegC(theInstr);
   7713    UChar opc2     = ifieldOPClo5(theInstr);
   7714    UChar flag_rC  = ifieldBIT0(theInstr);
   7715 
   7716    IRTemp  frD = newTemp(Ity_F64);
   7717    IRTemp  frA = newTemp(Ity_F64);
   7718    IRTemp  frB = newTemp(Ity_F64);
   7719    IRTemp  frC = newTemp(Ity_F64);
   7720    IRExpr* rm  = get_IR_roundingmode();
   7721 
   7722    /* By default, we will examine the results of the operation and set
   7723       fpscr[FPRF] accordingly. */
   7724    Bool set_FPRF = True;
   7725 
   7726    /* By default, if flag_RC is set, we will clear cr1 after the
   7727       operation.  In reality we should set cr1 to indicate the
   7728       exception status of the operation, but since we're not
   7729       simulating exceptions, the exception status will appear to be
   7730       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7731    Bool clear_CR1 = True;
   7732 
   7733    assign( frA, getFReg(frA_addr));
   7734    assign( frB, getFReg(frB_addr));
   7735    assign( frC, getFReg(frC_addr));
   7736 
   7737    switch (opc1) {
   7738    case 0x3B:
   7739       switch (opc2) {
   7740       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   7741          if (frC_addr != 0)
   7742             return False;
   7743          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7744              frD_addr, frA_addr, frB_addr);
   7745          assign( frD, triop( Iop_DivF64r32,
   7746                              rm, mkexpr(frA), mkexpr(frB) ));
   7747          break;
   7748 
   7749       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   7750          if (frC_addr != 0)
   7751             return False;
   7752          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7753              frD_addr, frA_addr, frB_addr);
   7754          assign( frD, triop( Iop_SubF64r32,
   7755                              rm, mkexpr(frA), mkexpr(frB) ));
   7756          break;
   7757 
   7758       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   7759          if (frC_addr != 0)
   7760             return False;
   7761          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7762              frD_addr, frA_addr, frB_addr);
   7763          assign( frD, triop( Iop_AddF64r32,
   7764                              rm, mkexpr(frA), mkexpr(frB) ));
   7765          break;
   7766 
   7767       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   7768          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7769          if (frA_addr != 0 || frC_addr != 0)
   7770             return False;
   7771          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   7772              frD_addr, frB_addr);
   7773          // however illogically, on ppc970 this insn behaves identically
   7774          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   7775          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   7776          break;
   7777 
   7778       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   7779          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7780          if (frA_addr != 0 || frC_addr != 0)
   7781             return False;
   7782          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   7783              frD_addr, frB_addr);
   7784          { IRExpr* ieee_one
   7785               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7786            assign( frD, triop( Iop_DivF64r32,
   7787                                rm,
   7788                                ieee_one, mkexpr(frB) ));
   7789          }
   7790          break;
   7791 
   7792       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   7793          if (frB_addr != 0)
   7794             return False;
   7795          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7796              frD_addr, frA_addr, frC_addr);
   7797          assign( frD, triop( Iop_MulF64r32,
   7798                              rm, mkexpr(frA), mkexpr(frC) ));
   7799          break;
   7800 
   7801       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   7802          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7803          // Undocumented instruction?
   7804          if (frA_addr != 0 || frC_addr != 0)
   7805             return False;
   7806          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   7807              frD_addr, frB_addr);
   7808          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7809          break;
   7810 
   7811       default:
   7812          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   7813          return False;
   7814       }
   7815       break;
   7816 
   7817    case 0x3F:
   7818       switch (opc2) {
   7819       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   7820          if (frC_addr != 0)
   7821             return False;
   7822          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7823              frD_addr, frA_addr, frB_addr);
   7824          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   7825          break;
   7826 
   7827       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   7828          if (frC_addr != 0)
   7829             return False;
   7830          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7831              frD_addr, frA_addr, frB_addr);
   7832          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   7833          break;
   7834 
   7835       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   7836          if (frC_addr != 0)
   7837             return False;
   7838          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7839              frD_addr, frA_addr, frB_addr);
   7840          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   7841          break;
   7842 
   7843       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   7844          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7845          if (frA_addr != 0 || frC_addr != 0)
   7846             return False;
   7847          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   7848              frD_addr, frB_addr);
   7849          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   7850          break;
   7851 
   7852       case 0x17: { // fsel (Floating Select, PPC32 p426)
   7853          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7854          IRTemp cc    = newTemp(Ity_I32);
   7855          IRTemp cc_b0 = newTemp(Ity_I32);
   7856 
   7857          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7858              frD_addr, frA_addr, frC_addr, frB_addr);
   7859 
   7860          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   7861          // => GT|EQ == (cc & 0x1 == 0)
   7862          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   7863                                        IRExpr_Const(IRConst_F64(0))) );
   7864          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   7865 
   7866          // frD = (frA >= 0.0) ? frC : frB
   7867          //     = (cc_b0 == 0) ? frC : frB
   7868          assign( frD,
   7869                  IRExpr_ITE(
   7870                     binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
   7871                     mkexpr(frC),
   7872                     mkexpr(frB) ));
   7873 
   7874          /* One of the rare ones which don't mess with FPRF */
   7875          set_FPRF = False;
   7876          break;
   7877       }
   7878 
   7879       case 0x18: // fre (Floating Reciprocal Estimate)
   7880          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7881          // Note: unclear whether this insn really exists or not
   7882          // ppc970 doesn't have it, but POWER5 does
   7883          if (frA_addr != 0 || frC_addr != 0)
   7884             return False;
   7885          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   7886              frD_addr, frB_addr);
   7887          { IRExpr* ieee_one
   7888               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7889            assign( frD, triop( Iop_DivF64,
   7890                                rm,
   7891                                ieee_one, mkexpr(frB) ));
   7892          }
   7893          break;
   7894 
   7895       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   7896          if (frB_addr != 0)
   7897             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   7898          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7899              frD_addr, frA_addr, frC_addr);
   7900          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   7901          break;
   7902 
   7903       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   7904          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7905          if (frA_addr != 0 || frC_addr != 0)
   7906             return False;
   7907          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   7908              frD_addr, frB_addr);
   7909          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7910          break;
   7911 
   7912       default:
   7913          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   7914          return False;
   7915       }
   7916       break;
   7917 
   7918    default:
   7919       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   7920       return False;
   7921    }
   7922 
   7923    putFReg( frD_addr, mkexpr(frD) );
   7924 
   7925    if (set_FPRF) {
   7926       // XXX XXX XXX FIXME
   7927       // set FPRF from frD
   7928    }
   7929 
   7930    if (flag_rC && clear_CR1) {
   7931       putCR321( 1, mkU8(0) );
   7932       putCR0( 1, mkU8(0) );
   7933    }
   7934 
   7935    return True;
   7936 }
   7937 
   7938 
   7939 
   7940 /*
   7941   Floating Point Mult-Add Instructions
   7942 */
   7943 static Bool dis_fp_multadd ( UInt theInstr )
   7944 {
   7945    /* A-Form */
   7946    UChar opc1     = ifieldOPC(theInstr);
   7947    UChar frD_addr = ifieldRegDS(theInstr);
   7948    UChar frA_addr = ifieldRegA(theInstr);
   7949    UChar frB_addr = ifieldRegB(theInstr);
   7950    UChar frC_addr = ifieldRegC(theInstr);
   7951    UChar opc2     = ifieldOPClo5(theInstr);
   7952    UChar flag_rC  = ifieldBIT0(theInstr);
   7953 
   7954    IRTemp  frD = newTemp(Ity_F64);
   7955    IRTemp  frA = newTemp(Ity_F64);
   7956    IRTemp  frB = newTemp(Ity_F64);
   7957    IRTemp  frC = newTemp(Ity_F64);
   7958    IRTemp  rmt = newTemp(Ity_I32);
   7959    IRTemp  tmp = newTemp(Ity_F64);
   7960    IRTemp  sign_tmp = newTemp(Ity_I64);
   7961    IRTemp  nan_mask = newTemp(Ity_I32);
   7962    IRExpr* rm;
   7963 
   7964    /* By default, we will examine the results of the operation and set
   7965       fpscr[FPRF] accordingly. */
   7966    Bool set_FPRF = True;
   7967 
   7968    /* By default, if flag_RC is set, we will clear cr1 after the
   7969       operation.  In reality we should set cr1 to indicate the
   7970       exception status of the operation, but since we're not
   7971       simulating exceptions, the exception status will appear to be
   7972       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7973    Bool clear_CR1 = True;
   7974 
   7975    /* Bind the rounding mode expression to a temp; there's no
   7976       point in creating gratuitous CSEs, as we know we'll need
   7977       to use it twice. */
   7978    assign( rmt, get_IR_roundingmode() );
   7979    rm = mkexpr(rmt);
   7980 
   7981    assign( frA, getFReg(frA_addr));
   7982    assign( frB, getFReg(frB_addr));
   7983    assign( frC, getFReg(frC_addr));
   7984 
   7985    /* The rounding in this is all a bit dodgy.  The idea is to only do
   7986       one rounding.  That clearly isn't achieveable without dedicated
   7987       four-input IR primops, although in the single precision case we
   7988       can sort-of simulate it by doing the inner multiply in double
   7989       precision.
   7990 
   7991       In the negated cases, the negation happens after rounding. */
   7992 
   7993    switch (opc1) {
   7994    case 0x3B:
   7995       switch (opc2) {
   7996       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   7997          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7998              frD_addr, frA_addr, frC_addr, frB_addr);
   7999          assign( frD, qop( Iop_MSubF64r32, rm,
   8000                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8001          break;
   8002 
   8003       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   8004          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8005              frD_addr, frA_addr, frC_addr, frB_addr);
   8006          assign( frD, qop( Iop_MAddF64r32, rm,
   8007                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8008          break;
   8009 
   8010       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   8011       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   8012 
   8013          if (opc2 == 0x1E) {
   8014             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8015                      frD_addr, frA_addr, frC_addr, frB_addr);
   8016             assign( tmp, qop( Iop_MSubF64r32, rm,
   8017                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8018          } else {
   8019             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8020                      frD_addr, frA_addr, frC_addr, frB_addr);
   8021             assign( tmp, qop( Iop_MAddF64r32, rm,
   8022                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8023          }
   8024 
   8025          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8026                                       mkU32( NANmaskSingle ) ) );
   8027          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8028                                                mkexpr( nan_mask ) ) );
   8029          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8030          break;
   8031 
   8032       default:
   8033          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   8034          return False;
   8035       }
   8036       break;
   8037 
   8038    case 0x3F:
   8039       switch (opc2) {
   8040       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   8041          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8042              frD_addr, frA_addr, frC_addr, frB_addr);
   8043          assign( frD, qop( Iop_MSubF64, rm,
   8044                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8045          break;
   8046 
   8047       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   8048          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8049              frD_addr, frA_addr, frC_addr, frB_addr);
   8050          assign( frD, qop( Iop_MAddF64, rm,
   8051                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8052          break;
   8053 
   8054       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   8055       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   8056 
   8057          if (opc2 == 0x1E) {
   8058             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8059                      frD_addr, frA_addr, frC_addr, frB_addr);
   8060             assign( tmp, qop( Iop_MSubF64, rm,
   8061                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8062          } else {
   8063             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8064                      frD_addr, frA_addr, frC_addr, frB_addr);
   8065             assign( tmp, qop( Iop_MAddF64, rm,
   8066                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8067          }
   8068 
   8069          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8070                                       mkU32( NANmaskDouble ) ) );
   8071          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8072                                                mkexpr( nan_mask ) ) );
   8073          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8074          break;
   8075 
   8076       default:
   8077          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   8078          return False;
   8079       }
   8080       break;
   8081 
   8082    default:
   8083       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   8084       return False;
   8085    }
   8086 
   8087    putFReg( frD_addr, mkexpr(frD) );
   8088 
   8089    if (set_FPRF) {
   8090       // XXX XXX XXX FIXME
   8091       // set FPRF from frD
   8092    }
   8093 
   8094    if (flag_rC && clear_CR1) {
   8095       putCR321( 1, mkU8(0) );
   8096       putCR0( 1, mkU8(0) );
   8097    }
   8098 
   8099    return True;
   8100 }
   8101 
   8102 /*
   8103  * fe_flag is set to 1 if any of the following conditions occurs:
   8104  *  - The floating-point operand in register FRB is a Zero, a
   8105  *    NaN, an Infinity, or a negative value.
   8106  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
   8107  *  Otherwise fe_flag is set to 0.
   8108  *
   8109  * fg_flag is set to 1 if either of the following conditions occurs.
   8110  *   - The floating-point operand in register FRB is a Zero, an
   8111  *     Infinity, or a denormalized value.
   8112  *  Otherwise fg_flag is set to 0.
   8113  *
   8114  */
   8115 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8116 {
   8117    // The following temps are for holding intermediate results
   8118    IRTemp e_b = newTemp(Ity_I32);
   8119    IRExpr * fe_flag,  * fg_flag;
   8120    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8121    UInt bias = sp? 127 : 1023;
   8122    IRExpr * frbNaN, * frbDenorm, * frBNeg;
   8123    IRExpr * eb_LTE;
   8124    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8125    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8126    *fe_flag_tmp = newTemp(Ity_I32);
   8127    *fg_flag_tmp = newTemp(Ity_I32);
   8128    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
   8129    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8130 
   8131    //////////////////  fe_flag tests BEGIN //////////////////////
   8132    /* We first do all tests that may result in setting fe_flag to '1'.
   8133     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
   8134     * for details.)
   8135     */
   8136    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
   8137    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
   8138    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
   8139    {
   8140       // Test_value = -970 for double precision
   8141       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
   8142       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
   8143    }
   8144    frBNeg = binop( Iop_CmpEQ32,
   8145                    binop( Iop_Shr32,
   8146                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
   8147                           mkU8( 31 ) ),
   8148                    mkU32( 1 ) );
   8149    //////////////////  fe_flag tests END //////////////////////
   8150 
   8151    //////////////////  fg_flag tests BEGIN //////////////////////
   8152    /*
   8153     * The following tests were already performed above in the fe_flag
   8154     * tests.  So these conditions will result in both fe_ and fg_ flags
   8155     * being set.
   8156     *   - Test if FRB is Zero
   8157     *   - Test if FRB is an Infinity
   8158     */
   8159 
   8160    /*
   8161     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8162     * the exp is 0 and the fraction is non-zero.
   8163     */
   8164    if (sp) {
   8165       IRTemp frac_part = newTemp(Ity_I32);
   8166       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
   8167       frbDenorm
   8168                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8169                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
   8170    } else {
   8171       IRExpr * hi32, * low32, * fraction_is_nonzero;
   8172       IRTemp frac_part = newTemp(Ity_I64);
   8173 
   8174       assign( frac_part, FP_FRAC_PART(frB_Int) );
   8175       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8176       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8177       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8178                                                 mkU32( 0 ) );
   8179       frbDenorm
   8180                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8181                          fraction_is_nonzero );
   8182    }
   8183    //////////////////  fg_flag tests END //////////////////////
   8184 
   8185    /////////////////////////
   8186    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
   8187                     mkOR1( frbNaN,
   8188                            mkOR1( mkexpr( frbInf_tmp ),
   8189                                   mkOR1( frBNeg, eb_LTE ) ) ) );
   8190 
   8191    fe_flag = unop(Iop_1Uto32, fe_flag);
   8192 
   8193    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
   8194                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
   8195    fg_flag = unop(Iop_1Uto32, fg_flag);
   8196    assign (*fg_flag_tmp, fg_flag);
   8197    assign (*fe_flag_tmp, fe_flag);
   8198 }
   8199 /*
   8200  * fe_flag is set to 1 if any of the following conditions occurs:
   8201  *  - The double-precision floating-point operand in register FRA is a NaN or an
   8202  *    Infinity.
   8203  *  - The double-precision floating-point operand in register FRB is a Zero, a
   8204  *    NaN, or an Infinity.
   8205  *  - e_b is less than or equal to -1022.
   8206  *  - e_b is greater than or equal to 1021.
   8207  *  - The double-precision floating-point operand in register FRA is not a zero
   8208  *    and the difference, e_a - e_b, is greater than or equal to 1023.
   8209  *  - The double-precision floating-point operand in register FRA is not a zero
   8210  *    and the difference, e_a - e_b, is less than or equal to -1021.
   8211  *  - The double-precision floating-point operand in register FRA is not a zero
   8212  *    and e_a is less than or equal to -970
   8213  *  Otherwise fe_flag is set to 0.
   8214  *
   8215  * fg_flag is set to 1 if either of the following conditions occurs.
   8216  *   - The double-precision floating-point operand in register FRA is an Infinity.
   8217  *   - The double-precision floating-point operand in register FRB is a Zero, an
   8218  *     Infinity, or a denormalized value.
   8219  *  Otherwise fg_flag is set to 0.
   8220  *
   8221  */
   8222 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8223 {
   8224    // The following temps are for holding intermediate results
   8225    IRTemp e_a = newTemp(Ity_I32);
   8226    IRTemp e_b = newTemp(Ity_I32);
   8227    IRTemp frA_exp_shR = newTemp(Ity_I32);
   8228    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8229 
   8230    UInt bias = sp? 127 : 1023;
   8231    *fe_flag_tmp = newTemp(Ity_I32);
   8232    *fg_flag_tmp = newTemp(Ity_I32);
   8233 
   8234    /* The following variables hold boolean results from tests
   8235     * that are OR'ed together for setting the fe_ and fg_ flags.
   8236     * For some cases, the booleans are used more than once, so
   8237     * I make those IRTemp's instead of IRExpr's.
   8238     */
   8239    IRExpr * fraNaN, * frbNaN, * frbDenorm;
   8240    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
   8241    IRTemp  fraInf_tmp = newTemp(Ity_I1);
   8242    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8243    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8244    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
   8245 
   8246 /* The following are the flags that are set by OR'ing the results of
   8247  * all the tests done for tdiv.  These flags are the input to the specified CR.
   8248  */
   8249    IRExpr * fe_flag, * fg_flag;
   8250 
   8251    // Create temps that will be used throughout the following tests.
   8252    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
   8253    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
   8254    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
   8255    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
   8256    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8257 
   8258 
   8259    //////////////////  fe_flag tests BEGIN //////////////////////
   8260    /* We first do all tests that may result in setting fe_flag to '1'. */
   8261 
   8262    /*
   8263     * Test if the double-precision floating-point operand in register FRA is
   8264     * a NaN:
   8265     */
   8266    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
   8267    /*
   8268     * Test if the double-precision floating-point operand in register FRA is
   8269     * an Infinity.
   8270     */
   8271    assign(fraInf_tmp, is_Inf(frA_int, sp));
   8272 
   8273    /*
   8274     * Test if the double-precision floating-point operand in register FRB is
   8275     * a NaN:
   8276     */
   8277    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
   8278    /*
   8279     * Test if the double-precision floating-point operand in register FRB is
   8280     * an Infinity.
   8281     */
   8282    assign( frbInf_tmp, is_Inf(frB_int, sp) );
   8283    /*
   8284     * Test if the double-precision floating-point operand in register FRB is
   8285     * a Zero.
   8286     */
   8287    assign( frbZero_tmp, is_Zero(frB_int, sp) );
   8288 
   8289    /*
   8290     * Test if e_b <= -1022 for double precision;
   8291     * or e_b <= -126 for single precision
   8292     */
   8293    {
   8294       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
   8295       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
   8296    }
   8297 
   8298    /*
   8299     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
   8300     * or e_b >= -125 (125 < e_b) for single precision
   8301     */
   8302    {
   8303       Int test_value = sp ? 125 : 1021;
   8304       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
   8305    }
   8306 
   8307    /*
   8308     * Test if FRA != Zero and (e_a - e_b) >= bias
   8309     */
   8310    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
   8311    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8312                        binop( Iop_CmpLT32S, mkU32( bias ),
   8313                               binop( Iop_Sub32, mkexpr( e_a ),
   8314                                      mkexpr( e_b ) ) ) );
   8315 
   8316    /*
   8317     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
   8318     */
   8319    {
   8320       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
   8321 
   8322       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8323                           binop( Iop_CmpLE32S,
   8324                                  binop( Iop_Sub32,
   8325                                         mkexpr( e_a ),
   8326                                         mkexpr( e_b ) ),
   8327                                         mkU32( test_value ) ) );
   8328    }
   8329 
   8330    /*
   8331     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
   8332     */
   8333    {
   8334       UInt test_value = 0xfffffc36;  //Int test_value = -970;
   8335 
   8336       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
   8337                                                         mkexpr( e_a ),
   8338                                                         mkU32( test_value ) ) );
   8339    }
   8340    //////////////////  fe_flag tests END //////////////////////
   8341 
   8342    //////////////////  fg_flag tests BEGIN //////////////////////
   8343    /*
   8344     * The following tests were already performed above in the fe_flag
   8345     * tests.  So these conditions will result in both fe_ and fg_ flags
   8346     * being set.
   8347     *   - Test if FRA is an Infinity
   8348     *   - Test if FRB ix Zero
   8349     *   - Test if FRB is an Infinity
   8350     */
   8351 
   8352    /*
   8353     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8354     * the exp is 0 and the fraction is non-zero.
   8355     */
   8356    {
   8357       IRExpr * fraction_is_nonzero;
   8358 
   8359       if (sp) {
   8360          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
   8361                                       mkU32( 0 ) );
   8362       } else {
   8363          IRExpr * hi32, * low32;
   8364          IRTemp frac_part = newTemp(Ity_I64);
   8365          assign( frac_part, FP_FRAC_PART(frB_int) );
   8366 
   8367          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8368          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8369          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8370                                       mkU32( 0 ) );
   8371       }
   8372       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
   8373                                  mkU32( 0x0 ) ), fraction_is_nonzero );
   8374 
   8375    }
   8376    //////////////////  fg_flag tests END //////////////////////
   8377 
   8378    fe_flag
   8379    = mkOR1(
   8380             fraNaN,
   8381             mkOR1(
   8382                    mkexpr( fraInf_tmp ),
   8383                    mkOR1(
   8384                           mkexpr( frbZero_tmp ),
   8385                           mkOR1(
   8386                                  frbNaN,
   8387                                  mkOR1(
   8388                                         mkexpr( frbInf_tmp ),
   8389                                         mkOR1( eb_LTE,
   8390                                                mkOR1( eb_GTE,
   8391                                                       mkOR1( ea_eb_GTE,
   8392                                                              mkOR1( ea_eb_LTE,
   8393                                                                     ea_LTE ) ) ) ) ) ) ) ) );
   8394 
   8395    fe_flag = unop(Iop_1Uto32, fe_flag);
   8396 
   8397    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
   8398                                                  mkOR1( mkexpr( frbInf_tmp ),
   8399                                                         frbDenorm ) ) );
   8400    fg_flag = unop(Iop_1Uto32, fg_flag);
   8401    assign(*fe_flag_tmp, fe_flag);
   8402    assign(*fg_flag_tmp, fg_flag);
   8403 }
   8404 
   8405 /* See description for _do_fp_tdiv() above. */
   8406 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
   8407 {
   8408    IRTemp  fe_flag, fg_flag;
   8409    /////////////////////////
   8410    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8411     * where fl_flag == 1 on ppc64.
   8412     */
   8413    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
   8414    fe_flag = fg_flag = IRTemp_INVALID;
   8415    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
   8416    return binop( Iop_Or32,
   8417                  binop( Iop_Or32,
   8418                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
   8419                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8420                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
   8421 }
   8422 
   8423 static Bool dis_fp_tests ( UInt theInstr )
   8424 {
   8425    UChar opc1     = ifieldOPC(theInstr);
   8426    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8427    UChar frB_addr = ifieldRegB(theInstr);
   8428    UChar b0       = ifieldBIT0(theInstr);
   8429    UInt  opc2     = ifieldOPClo10(theInstr);
   8430    IRTemp frB_I64     = newTemp(Ity_I64);
   8431 
   8432    if (opc1 != 0x3F || b0 != 0 ){
   8433       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8434       return False;
   8435    }
   8436    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
   8437 
   8438    switch (opc2) {
   8439       case 0x080: // ftdiv
   8440       {
   8441          UChar frA_addr = ifieldRegA(theInstr);
   8442          IRTemp frA_I64     = newTemp(Ity_I64);
   8443          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8444          if (b21to22 != 0 ) {
   8445             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8446             return False;
   8447          }
   8448 
   8449          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
   8450          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   8451 
   8452          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8453          break;
   8454       }
   8455       case 0x0A0: // ftsqrt
   8456       {
   8457          IRTemp flags = newTemp(Ity_I32);
   8458          IRTemp  fe_flag, fg_flag;
   8459          fe_flag = fg_flag = IRTemp_INVALID;
   8460          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
   8461          if ( b18to22 != 0) {
   8462             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
   8463             return False;
   8464          }
   8465          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
   8466          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
   8467          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8468           * where fl_flag == 1 on ppc64.
   8469           */
   8470          assign( flags,
   8471                  binop( Iop_Or32,
   8472                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   8473                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8474                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   8475          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   8476          break;
   8477       }
   8478 
   8479       default:
   8480          vex_printf("dis_fp_tests(ppc)(opc2)\n");
   8481          return False;
   8482 
   8483    }
   8484    return True;
   8485 }
   8486 
   8487 /*
   8488   Floating Point Compare Instructions
   8489 */
   8490 static Bool dis_fp_cmp ( UInt theInstr )
   8491 {
   8492    /* X-Form */
   8493    UChar opc1     = ifieldOPC(theInstr);
   8494    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8495    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8496    UChar frA_addr = ifieldRegA(theInstr);
   8497    UChar frB_addr = ifieldRegB(theInstr);
   8498    UInt  opc2     = ifieldOPClo10(theInstr);
   8499    UChar b0       = ifieldBIT0(theInstr);
   8500 
   8501    IRTemp ccIR    = newTemp(Ity_I32);
   8502    IRTemp ccPPC32 = newTemp(Ity_I32);
   8503 
   8504    IRTemp frA     = newTemp(Ity_F64);
   8505    IRTemp frB     = newTemp(Ity_F64);
   8506 
   8507    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   8508       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   8509       return False;
   8510    }
   8511 
   8512    assign( frA, getFReg(frA_addr));
   8513    assign( frB, getFReg(frB_addr));
   8514 
   8515    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   8516 
   8517    /* Map compare result from IR to PPC32 */
   8518    /*
   8519      FP cmp result | PPC | IR
   8520      --------------------------
   8521      UN            | 0x1 | 0x45
   8522      EQ            | 0x2 | 0x40
   8523      GT            | 0x4 | 0x00
   8524      LT            | 0x8 | 0x01
   8525    */
   8526 
   8527    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   8528    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   8529    assign(
   8530       ccPPC32,
   8531       binop(
   8532          Iop_Shl32,
   8533          mkU32(1),
   8534          unop(
   8535             Iop_32to8,
   8536             binop(
   8537                Iop_Or32,
   8538                binop(
   8539                   Iop_And32,
   8540                   unop(
   8541                      Iop_Not32,
   8542                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   8543                   ),
   8544                   mkU32(2)
   8545                ),
   8546                binop(
   8547                   Iop_And32,
   8548                   binop(
   8549                      Iop_Xor32,
   8550                      mkexpr(ccIR),
   8551                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   8552                   ),
   8553                   mkU32(1)
   8554                )
   8555             )
   8556          )
   8557       )
   8558    );
   8559 
   8560    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   8561 
   8562    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   8563       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   8564    */
   8565    // XXX XXX XXX FIXME
   8566    // Also write the result into FPRF (it's not entirely clear how)
   8567 
   8568    /* Note: Differences between fcmpu and fcmpo are only in exception
   8569       flag settings, which aren't supported anyway. */
   8570    switch (opc2) {
   8571    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   8572       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8573       break;
   8574    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   8575       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8576       break;
   8577    default:
   8578       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   8579       return False;
   8580    }
   8581    return True;
   8582 }
   8583 
   8584 
   8585 
   8586 /*
   8587   Floating Point Rounding/Conversion Instructions
   8588 */
   8589 static Bool dis_fp_round ( UInt theInstr )
   8590 {
   8591    /* X-Form */
   8592    UChar opc1     = ifieldOPC(theInstr);
   8593    UChar b16to20  = ifieldRegA(theInstr);
   8594    UChar frD_addr = ifieldRegDS(theInstr);
   8595    UChar frB_addr = ifieldRegB(theInstr);
   8596    UInt  opc2     = ifieldOPClo10(theInstr);
   8597    UChar flag_rC  = ifieldBIT0(theInstr);
   8598 
   8599    IRTemp  frD     = newTemp(Ity_F64);
   8600    IRTemp  frB     = newTemp(Ity_F64);
   8601    IRTemp  r_tmp32 = newTemp(Ity_I32);
   8602    IRTemp  r_tmp64 = newTemp(Ity_I64);
   8603    IRExpr* rm      = get_IR_roundingmode();
   8604 
   8605    /* By default, we will examine the results of the operation and set
   8606       fpscr[FPRF] accordingly. */
   8607    Bool set_FPRF = True;
   8608 
   8609    /* By default, if flag_RC is set, we will clear cr1 after the
   8610       operation.  In reality we should set cr1 to indicate the
   8611       exception status of the operation, but since we're not
   8612       simulating exceptions, the exception status will appear to be
   8613       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8614    Bool clear_CR1 = True;
   8615    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
   8616       vex_printf("dis_fp_round(ppc)(instr)\n");
   8617       return False;
   8618    }
   8619 
   8620    assign( frB, getFReg(frB_addr));
   8621    if (opc1 == 0x3B) {
   8622       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
   8623        * they're very similar to the other instructions handled here, but have
   8624        * a different primary opcode.
   8625        */
   8626       switch (opc2) {
   8627          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
   8628             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8629             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8630             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
   8631                                                               mkexpr( r_tmp64 ) ) ) );
   8632             goto putFR;
   8633 
   8634          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
   8635             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8636             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8637             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
   8638             goto putFR;
   8639       }
   8640    }
   8641 
   8642 
   8643    switch (opc2) {
   8644    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   8645       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8646       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   8647       break;
   8648 
   8649    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   8650       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8651       assign( r_tmp32,
   8652               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   8653       assign( frD, unop( Iop_ReinterpI64asF64,
   8654                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8655       /* FPRF is undefined after fctiw.  Leave unchanged. */
   8656       set_FPRF = False;
   8657       break;
   8658 
   8659    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   8660       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8661       assign( r_tmp32,
   8662               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   8663       assign( frD, unop( Iop_ReinterpI64asF64,
   8664                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8665       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8666       set_FPRF = False;
   8667       break;
   8668 
   8669    case 0x08F: case 0x08E: // fctiwu[z]
   8670       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
   8671                flag_rC ? ".":"", frD_addr, frB_addr);
   8672       assign( r_tmp32,
   8673               binop( Iop_F64toI32U,
   8674                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
   8675                      mkexpr( frB ) ) );
   8676       assign( frD, unop( Iop_ReinterpI64asF64,
   8677                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8678       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8679       set_FPRF = False;
   8680       break;
   8681 
   8682 
   8683    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   8684       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8685       assign( r_tmp64,
   8686               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   8687       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8688       /* FPRF is undefined after fctid.  Leave unchanged. */
   8689       set_FPRF = False;
   8690       break;
   8691 
   8692    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   8693       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8694       assign( r_tmp64,
   8695               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   8696       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8697       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8698       set_FPRF = False;
   8699       break;
   8700 
   8701    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
   8702    {
   8703       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
   8704                flag_rC ? ".":"", frD_addr, frB_addr);
   8705       assign( r_tmp64,
   8706               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
   8707       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8708       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8709       set_FPRF = False;
   8710       break;
   8711    }
   8712    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   8713       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8714       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8715       assign( frD,
   8716               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   8717       break;
   8718 
   8719    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
   8720       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8721       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8722       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
   8723       break;
   8724 
   8725    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   8726       switch(opc2) {
   8727       case 0x188: // frin (Floating Round to Integer Nearest)
   8728          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8729          assign( r_tmp64,
   8730                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   8731          break;
   8732       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   8733          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8734          assign( r_tmp64,
   8735                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   8736          break;
   8737       case 0x1C8: // frip (Floating Round to Integer Plus)
   8738          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8739          assign( r_tmp64,
   8740                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   8741          break;
   8742       case 0x1E8: // frim (Floating Round to Integer Minus)
   8743          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8744          assign( r_tmp64,
   8745                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   8746          break;
   8747       }
   8748 
   8749       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   8750       /* F64 has only log10(2**52) significant digits anyway */
   8751       /* need to preserve sign of zero */
   8752       /*   frD = (fabs(frB) > 9e18) ? frB :
   8753                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   8754       assign(frD, IRExpr_ITE(
   8755                      binop(Iop_CmpNE8,
   8756                            unop(Iop_32to8,
   8757                                 binop(Iop_CmpF64,
   8758                                       IRExpr_Const(IRConst_F64(9e18)),
   8759                                       unop(Iop_AbsF64, mkexpr(frB)))),
   8760                            mkU8(0)),
   8761                      mkexpr(frB),
   8762                      IRExpr_ITE(
   8763                         binop(Iop_CmpNE32,
   8764                               binop(Iop_Shr32,
   8765                                     unop(Iop_64HIto32,
   8766                                          unop(Iop_ReinterpF64asI64,
   8767                                               mkexpr(frB))),
   8768                                     mkU8(31)),
   8769                               mkU32(0)),
   8770                         unop(Iop_NegF64,
   8771                              unop( Iop_AbsF64,
   8772                                    binop(Iop_I64StoF64, mkU32(0),
   8773                                          mkexpr(r_tmp64)) )),
   8774                         binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
   8775                      )
   8776       ));
   8777       break;
   8778 
   8779    default:
   8780       vex_printf("dis_fp_round(ppc)(opc2)\n");
   8781       return False;
   8782    }
   8783 putFR:
   8784    putFReg( frD_addr, mkexpr(frD) );
   8785 
   8786    if (set_FPRF) {
   8787       // XXX XXX XXX FIXME
   8788       // set FPRF from frD
   8789    }
   8790 
   8791    if (flag_rC && clear_CR1) {
   8792       putCR321( 1, mkU8(0) );
   8793       putCR0( 1, mkU8(0) );
   8794    }
   8795 
   8796    return True;
   8797 }
   8798 
   8799 /*
   8800   Floating Point Pair Instructions
   8801 */
   8802 static Bool dis_fp_pair ( UInt theInstr )
   8803 {
   8804    /* X-Form/DS-Form */
   8805    UChar  opc1         = ifieldOPC(theInstr);
   8806    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   8807    UChar  frT_lo_addr  = frT_hi_addr + 1;
   8808    UChar  rA_addr      = ifieldRegA(theInstr);
   8809    UChar  rB_addr      = ifieldRegB(theInstr);
   8810    UInt  uimm16        = ifieldUIMM16(theInstr);
   8811    Int    simm16       = extend_s_16to32(uimm16);
   8812    UInt   opc2         = ifieldOPClo10(theInstr);
   8813    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   8814    IRTemp EA_hi        = newTemp(ty);
   8815    IRTemp EA_lo        = newTemp(ty);
   8816    IRTemp frT_hi       = newTemp(Ity_F64);
   8817    IRTemp frT_lo       = newTemp(Ity_F64);
   8818    UChar b0            = ifieldBIT0(theInstr);
   8819    Bool is_load        = 0;
   8820 
   8821    if ((frT_hi_addr %2) != 0) {
   8822       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   8823       return False;
   8824    }
   8825 
   8826    switch (opc1) {
   8827    case 0x1F: // register offset
   8828       switch(opc2) {
   8829       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   8830          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8831          is_load = 1;
   8832          break;
   8833       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   8834          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8835          break;
   8836       default:
   8837          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   8838          return False;
   8839       }
   8840 
   8841       if (b0 != 0) {
   8842          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   8843          return False;
   8844       }
   8845       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   8846       break;
   8847    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   8848       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8849       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8850       is_load = 1;
   8851       break;
   8852    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   8853       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8854       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8855       break;
   8856    default:   // immediate offset
   8857       vex_printf("dis_fp_pair(ppc)(instr)\n");
   8858       return False;
   8859    }
   8860 
   8861    if (mode64)
   8862       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   8863    else
   8864       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   8865 
   8866    assign( frT_hi, getFReg(frT_hi_addr) );
   8867    assign( frT_lo, getFReg(frT_lo_addr) );
   8868 
   8869    if (is_load) {
   8870       putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
   8871       putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
   8872    } else {
   8873       storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
   8874       storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
   8875    }
   8876 
   8877    return True;
   8878 }
   8879 
   8880 
   8881 /*
   8882   Floating Point Merge Instructions
   8883 */
   8884 static Bool dis_fp_merge ( UInt theInstr )
   8885 {
   8886    /* X-Form */
   8887    UInt  opc2     = ifieldOPClo10(theInstr);
   8888    UChar frD_addr = ifieldRegDS(theInstr);
   8889    UChar frA_addr = ifieldRegA(theInstr);
   8890    UChar frB_addr = ifieldRegB(theInstr);
   8891 
   8892    IRTemp frD = newTemp(Ity_F64);
   8893    IRTemp frA = newTemp(Ity_F64);
   8894    IRTemp frB = newTemp(Ity_F64);
   8895 
   8896    assign( frA, getFReg(frA_addr));
   8897    assign( frB, getFReg(frB_addr));
   8898 
   8899    switch (opc2) {
   8900    case 0x3c6: // fmrgew floating merge even word
   8901       DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   8902 
   8903       assign( frD, unop( Iop_ReinterpI64asF64,
   8904                          binop( Iop_32HLto64,
   8905                                 unop( Iop_64HIto32,
   8906                                       unop( Iop_ReinterpF64asI64,
   8907                                             mkexpr(frA) ) ),
   8908                                 unop( Iop_64HIto32,
   8909                                       unop( Iop_ReinterpF64asI64,
   8910                                             mkexpr(frB) ) ) ) ) );
   8911    break;
   8912 
   8913    case 0x346: // fmrgow floating merge odd word
   8914       DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   8915 
   8916       assign( frD, unop( Iop_ReinterpI64asF64,
   8917                          binop( Iop_32HLto64,
   8918                                 unop( Iop_64to32,
   8919                                       unop( Iop_ReinterpF64asI64,
   8920                                             mkexpr(frA) ) ),
   8921                                 unop( Iop_64to32,
   8922                                       unop( Iop_ReinterpF64asI64,
   8923                                             mkexpr(frB) ) ) ) ) );
   8924    break;
   8925 
   8926    default:
   8927       vex_printf("dis_fp_merge(ppc)(opc2)\n");
   8928       return False;
   8929    }
   8930 
   8931    putFReg( frD_addr, mkexpr(frD) );
   8932    return True;
   8933 }
   8934 
   8935 /*
   8936   Floating Point Move Instructions
   8937 */
   8938 static Bool dis_fp_move ( UInt theInstr )
   8939 {
   8940    /* X-Form */
   8941    UChar opc1     = ifieldOPC(theInstr);
   8942    UChar frD_addr = ifieldRegDS(theInstr);
   8943    UChar frA_addr = ifieldRegA(theInstr);
   8944    UChar frB_addr = ifieldRegB(theInstr);
   8945    UInt  opc2     = ifieldOPClo10(theInstr);
   8946    UChar flag_rC  = ifieldBIT0(theInstr);
   8947 
   8948    IRTemp frD = newTemp(Ity_F64);
   8949    IRTemp frB = newTemp(Ity_F64);
   8950    IRTemp itmpB = newTemp(Ity_F64);
   8951    IRTemp frA;
   8952    IRTemp signA;
   8953    IRTemp hiD;
   8954 
   8955    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   8956       vex_printf("dis_fp_move(ppc)(instr)\n");
   8957       return False;
   8958    }
   8959 
   8960    assign( frB, getFReg(frB_addr));
   8961 
   8962    switch (opc2) {
   8963    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   8964       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   8965           frB_addr);
   8966       signA = newTemp(Ity_I32);
   8967       hiD = newTemp(Ity_I32);
   8968       itmpB = newTemp(Ity_I64);
   8969       frA = newTemp(Ity_F64);
   8970       assign( frA, getFReg(frA_addr) );
   8971 
   8972       /* get A's sign bit */
   8973       assign(signA, binop(Iop_And32,
   8974                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   8975                                                   mkexpr(frA))),
   8976                           mkU32(0x80000000)) );
   8977 
   8978       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   8979 
   8980       /* mask off B's sign bit and or in A's sign bit */
   8981       assign(hiD, binop(Iop_Or32,
   8982                         binop(Iop_And32,
   8983                               unop(Iop_64HIto32,
   8984                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   8985                               mkU32(0x7fffffff)),
   8986                         mkexpr(signA)) );
   8987 
   8988       /* combine hiD/loB into frD */
   8989       assign( frD, unop(Iop_ReinterpI64asF64,
   8990                         binop(Iop_32HLto64,
   8991                               mkexpr(hiD),
   8992                               unop(Iop_64to32,
   8993                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   8994       break;
   8995 
   8996    case 0x028: // fneg (Floating Negate, PPC32 p416)
   8997       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8998       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   8999       break;
   9000 
   9001    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   9002       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9003       assign( frD, mkexpr(frB) );
   9004       break;
   9005 
   9006    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   9007       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9008       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   9009       break;
   9010 
   9011    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   9012       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9013       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   9014       break;
   9015 
   9016    default:
   9017       vex_printf("dis_fp_move(ppc)(opc2)\n");
   9018       return False;
   9019    }
   9020 
   9021    putFReg( frD_addr, mkexpr(frD) );
   9022 
   9023    /* None of these change FPRF.  cr1 is set in the usual way though,
   9024       if flag_rC is set. */
   9025 
   9026    if (flag_rC) {
   9027       putCR321( 1, mkU8(0) );
   9028       putCR0( 1, mkU8(0) );
   9029    }
   9030 
   9031    return True;
   9032 }
   9033 
   9034 
   9035 
   9036 /*
   9037   Floating Point Status/Control Register Instructions
   9038 */
   9039 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
   9040 {
   9041    /* Many forms - see each switch case */
   9042    UChar opc1    = ifieldOPC(theInstr);
   9043    UInt  opc2    = ifieldOPClo10(theInstr);
   9044    UChar flag_rC = ifieldBIT0(theInstr);
   9045 
   9046    if (opc1 != 0x3F) {
   9047       vex_printf("dis_fp_scr(ppc)(instr)\n");
   9048       return False;
   9049    }
   9050 
   9051    switch (opc2) {
   9052    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   9053       // Bit crbD of the FPSCR is set.
   9054       UChar crbD    = ifieldRegDS(theInstr);
   9055       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9056 
   9057       if (b11to20 != 0) {
   9058          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   9059          return False;
   9060       }
   9061       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   9062       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
   9063 		     1ULL << ( 31 - crbD ) );
   9064       break;
   9065    }
   9066 
   9067    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   9068       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   9069       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   9070       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   9071       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   9072       IRTemp  tmp     = newTemp(Ity_I32);
   9073       IRExpr* fpscr_all;
   9074       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   9075          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   9076          return False;
   9077       }
   9078       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   9079       vassert(crfD < 8);
   9080       vassert(crfS < 8);
   9081       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9082       assign( tmp, binop(Iop_And32,
   9083                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   9084                         mkU32(0xF)) );
   9085       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   9086       break;
   9087    }
   9088 
   9089    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   9090       // Bit crbD of the FPSCR is cleared.
   9091       UChar crbD    = ifieldRegDS(theInstr);
   9092       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9093 
   9094       if (b11to20 != 0) {
   9095          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   9096          return False;
   9097       }
   9098       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   9099       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
   9100       break;
   9101    }
   9102 
   9103    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   9104       UInt crfD     = IFIELD( theInstr, 23, 3 );
   9105       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   9106       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   9107       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   9108       UChar Wbit;
   9109 
   9110       if (b16to22 != 0 || b11 != 0) {
   9111          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   9112          return False;
   9113       }
   9114       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
   9115       if (GX_level) {
   9116          /* This implies that Decimal Floating Point is supported, and the
   9117           * FPSCR must be managed as a 64-bit register.
   9118           */
   9119          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9120       } else {
   9121          Wbit = 0;
   9122       }
   9123       crfD = crfD + (8 * (1 - Wbit) );
   9124       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
   9125       break;
   9126    }
   9127 
   9128    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   9129       UChar   frD_addr  = ifieldRegDS(theInstr);
   9130       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   9131       IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9132       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
   9133                                                  MASK_FPSCR_DRN );
   9134 
   9135       if (b11to20 != 0) {
   9136          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   9137          return False;
   9138       }
   9139       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   9140       putFReg( frD_addr,
   9141           unop( Iop_ReinterpI64asF64,
   9142                 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
   9143       break;
   9144    }
   9145 
   9146    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   9147       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   9148       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   9149       UChar frB_addr = ifieldRegB(theInstr);
   9150       IRTemp frB   = newTemp(Ity_F64);
   9151       IRTemp rB_64 = newTemp( Ity_I64 );
   9152       Int i;
   9153       ULong mask;
   9154       UChar Wbit;
   9155 #define BFP_MASK_SEED 0x3000000000000000ULL
   9156 #define DFP_MASK_SEED 0x7000000000000000ULL
   9157 
   9158       if (GX_level) {
   9159          /* This implies that Decimal Floating Point is supported, and the
   9160           * FPSCR must be managed as a 64-bit register.
   9161           */
   9162          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9163       } else {
   9164          Wbit = 0;
   9165       }
   9166 
   9167       if (b25 == 1) {
   9168          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   9169           * a one do a full 64 bit move.  Note, the FPSCR is not really
   9170           * properly modeled.  This instruciton only changes the value of
   9171           * the rounding mode.  The HW exception bits do not get set in
   9172           * the simulator.  1/12/09
   9173           */
   9174          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   9175          mask = 0xFF;
   9176 
   9177       } else {
   9178          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   9179          // Build 32bit mask from FM:
   9180          mask = 0;
   9181          for (i=0; i<8; i++) {
   9182             if ((FM & (1<<(7-i))) == 1) {
   9183                /* FPSCR field k is set to the contents of the corresponding
   9184                 * field of register FRB, where k = i+8x(1-W).  In the Power
   9185                 * ISA, register field numbering is from left to right, so field
   9186                 * 15 is the least significant field in a 64-bit register.  To
   9187                 * generate the mask, we set all the appropriate rounding mode
   9188                 * bits in the highest order nibble (field 0) and shift right
   9189                 * 'k x nibble length'.
   9190                 */
   9191                if (Wbit)
   9192                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9193                else
   9194                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9195             }
   9196          }
   9197       }
   9198       assign( frB, getFReg(frB_addr));
   9199       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   9200       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
   9201       break;
   9202    }
   9203 
   9204    default:
   9205       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   9206       return False;
   9207    }
   9208    return True;
   9209 }
   9210 
   9211 /*------------------------------------------------------------*/
   9212 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
   9213 /*------------------------------------------------------------*/
   9214 #define DFP_LONG  1
   9215 #define DFP_EXTND 2
   9216 #define DFP_LONG_BIAS   398
   9217 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
   9218 #define DFP_EXTND_BIAS  6176
   9219 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
   9220 #define DFP_LONG_EXP_MSK   0XFF
   9221 #define DFP_EXTND_EXP_MSK  0XFFF
   9222 
   9223 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
   9224 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
   9225 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
   9226 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
   9227 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
   9228 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
   9229 #define DFP_LONG_EXP_MAX          369      // biased max
   9230 #define DFP_LONG_EXP_MIN          0        // biased min
   9231 #define DFP_EXTND_EXP_MAX         6111     // biased max
   9232 #define DFP_EXTND_EXP_MIN         0        // biased min
   9233 #define DFP_LONG_MAX_SIG_DIGITS   16
   9234 #define DFP_EXTND_MAX_SIG_DIGITS  34
   9235 #define MAX_DIGITS_IN_STRING      8
   9236 
   9237 
   9238 #define  AND(x, y) binop( Iop_And32, x, y )
   9239 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
   9240 #define   OR(x, y) binop( Iop_Or32,  x, y )
   9241 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
   9242 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
   9243 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
   9244 
   9245 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
   9246 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
   9247 
   9248 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
   9249    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
   9250     ((_b1) << 1) | ((_b0) << 0))
   9251 
   9252 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
   9253 {
   9254    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9255    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
   9256    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
   9257    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
   9258    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
   9259    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
   9260    IRTemp lmd_07_val    = newTemp( Ity_I32 );
   9261    IRTemp lmd_8_val     = newTemp( Ity_I32 );
   9262    IRTemp lmd_9_val     = newTemp( Ity_I32 );
   9263 
   9264    /* The encodig is as follows:
   9265     * lmd - left most digit
   9266     * lme - left most 2-bits of the exponent
   9267     *
   9268     *    lmd
   9269     *   0 - 7    (lmexp << 3) | lmd
   9270     *     8      0b11000 (24 decimal) if lme=0b00;
   9271     *            0b11010 (26 decimal) if lme=0b01;
   9272     *            0b11100 (28 decimal) if lme=0b10;
   9273     *     9      0b11001 (25 decimal) if lme=0b00;
   9274     *            0b11011 (27 decimal) if lme=0b01;
   9275     *            0b11101 (29 decimal) if lme=0b10;
   9276     */
   9277 
   9278    /* Generate the masks for each condition */
   9279    assign( lmd_07_mask,
   9280            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
   9281    assign( lmd_8_mask,
   9282            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
   9283    assign( lmd_9_mask,
   9284            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
   9285    assign( lmexp_00_mask,
   9286            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
   9287    assign( lmexp_01_mask,
   9288            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
   9289    assign( lmexp_10_mask,
   9290            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
   9291 
   9292    /* Generate the values for each LMD condition, assuming the condition
   9293     * is TRUE.
   9294     */
   9295    assign( lmd_07_val,
   9296            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
   9297    assign( lmd_8_val,
   9298            binop( Iop_Or32,
   9299                   binop( Iop_Or32,
   9300                          binop( Iop_And32,
   9301                                 mkexpr( lmexp_00_mask ),
   9302                                 mkU32( 24 ) ),
   9303                          binop( Iop_And32,
   9304                                 mkexpr( lmexp_01_mask ),
   9305                                 mkU32( 26 ) ) ),
   9306                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
   9307    assign( lmd_9_val,
   9308            binop( Iop_Or32,
   9309                   binop( Iop_Or32,
   9310                          binop( Iop_And32,
   9311                                 mkexpr( lmexp_00_mask ),
   9312                                 mkU32( 25 ) ),
   9313                          binop( Iop_And32,
   9314                                 mkexpr( lmexp_01_mask ),
   9315                                 mkU32( 27 ) ) ),
   9316                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
   9317 
   9318    /* generate the result from the possible LMD values */
   9319    return binop( Iop_Or32,
   9320                  binop( Iop_Or32,
   9321                         binop( Iop_And32,
   9322                                mkexpr( lmd_07_mask ),
   9323                                mkexpr( lmd_07_val ) ),
   9324                         binop( Iop_And32,
   9325                                mkexpr( lmd_8_mask ),
   9326                                mkexpr( lmd_8_val ) ) ),
   9327                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
   9328 }
   9329 
   9330 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
   9331 {
   9332    /* Extract the exponent and the left most digit of the mantissa
   9333     * from the G field bits [0:4].
   9334     */
   9335    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9336    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
   9337    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
   9338    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
   9339    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
   9340    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
   9341    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
   9342 
   9343    IRTemp lmd_07_val = newTemp( Ity_I32 );
   9344    IRTemp lmd_8_val  = newTemp( Ity_I32 );
   9345    IRTemp lmd_9_val  = newTemp( Ity_I32 );
   9346 
   9347    /* The left most digit (LMD) encoding is as follows:
   9348     *    lmd
   9349     *   0 - 7    (lmexp << 3) | lmd
   9350     *     8      0b11000 (24 decimal) if lme=0b00;
   9351     *            0b11010 (26 decimal) if lme=0b01;
   9352     *            0b11100 (28 decimal) if lme=0b10
   9353     *     9      0b11001 (25 decimal) if lme=0b00;
   9354     *            0b11011 (27 decimal) if lme=0b01;
   9355     *            0b11101 (29 decimal) if lme=0b10;
   9356     */
   9357 
   9358    /* Generate the masks for each condition of LMD and exponent bits */
   9359    assign( lmd_07_mask,
   9360            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
   9361                                     gfield_0_4,
   9362                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
   9363    assign( lmd_8_00_mask,
   9364            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9365                                     gfield_0_4,
   9366                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
   9367    assign( lmd_8_01_mask,
   9368            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9369                                     gfield_0_4,
   9370                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
   9371    assign( lmd_8_10_mask,
   9372            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9373                                     gfield_0_4,
   9374                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
   9375    assign( lmd_9_00_mask,
   9376            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9377                                     gfield_0_4,
   9378                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
   9379    assign( lmd_9_01_mask,
   9380            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9381                                     gfield_0_4,
   9382                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
   9383    assign( lmd_9_10_mask,
   9384            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9385                                     gfield_0_4,
   9386                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
   9387 
   9388    /* Generate the values for each LMD condition, assuming the condition
   9389     * is TRUE.
   9390     */
   9391    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
   9392    assign( lmd_8_val, mkU32( 0x8 ) );
   9393    assign( lmd_9_val, mkU32( 0x9 ) );
   9394 
   9395    assign( *lmd,
   9396            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
   9397                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
   9398                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
   9399                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
   9400                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
   9401                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
   9402                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
   9403                      ) ) );
   9404 }
   9405 
   9406 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
   9407 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
   9408 #define DIGIT3_SHR 12
   9409 #define DIGIT4_SHR 16
   9410 #define DIGIT5_SHR 20
   9411 #define DIGIT6_SHR 24
   9412 #define DIGIT7_SHR 28
   9413 
   9414 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
   9415 {
   9416    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
   9417     * digit is a valid BCD number, i.e. less then 9.
   9418     */
   9419    IRTemp valid = newTemp( Ity_I32 );
   9420 
   9421    assign( valid,
   9422            AND4( AND4 ( unop( Iop_1Sto32,
   9423                               binop( Iop_CmpLE32U,
   9424                                      binop( Iop_And32,
   9425                                             bcd_l,
   9426                                             mkU32 ( 0xF ) ),
   9427                                       mkU32( 0x9 ) ) ),
   9428                         unop( Iop_1Sto32,
   9429                               binop( Iop_CmpLE32U,
   9430                                      binop( Iop_And32,
   9431                                             binop( Iop_Shr32,
   9432                                                    bcd_l,
   9433                                                    mkU8 ( DIGIT1_SHR ) ),
   9434                                              mkU32 ( 0xF ) ),
   9435                                       mkU32( 0x9 ) ) ),
   9436                         unop( Iop_1Sto32,
   9437                               binop( Iop_CmpLE32U,
   9438                                      binop( Iop_And32,
   9439                                             binop( Iop_Shr32,
   9440                                                    bcd_l,
   9441                                                    mkU8 ( DIGIT2_SHR ) ),
   9442                                             mkU32 ( 0xF ) ),
   9443                                       mkU32( 0x9 ) ) ),
   9444                         unop( Iop_1Sto32,
   9445                               binop( Iop_CmpLE32U,
   9446                                      binop( Iop_And32,
   9447                                             binop( Iop_Shr32,
   9448                                                    bcd_l,
   9449                                                    mkU8 ( DIGIT3_SHR ) ),
   9450                                              mkU32 ( 0xF ) ),
   9451                                       mkU32( 0x9 ) ) ) ),
   9452                  AND4 ( unop( Iop_1Sto32,
   9453                               binop( Iop_CmpLE32U,
   9454                                      binop( Iop_And32,
   9455                                             binop( Iop_Shr32,
   9456                                                    bcd_l,
   9457                                                    mkU8 ( DIGIT4_SHR ) ),
   9458                                             mkU32 ( 0xF ) ),
   9459                                      mkU32( 0x9 ) ) ),
   9460                         unop( Iop_1Sto32,
   9461                               binop( Iop_CmpLE32U,
   9462                                      binop( Iop_And32,
   9463                                             binop( Iop_Shr32,
   9464                                                    bcd_l,
   9465                                                    mkU8 ( DIGIT5_SHR ) ),
   9466                                             mkU32 ( 0xF ) ),
   9467                                      mkU32( 0x9 ) ) ),
   9468                         unop( Iop_1Sto32,
   9469                               binop( Iop_CmpLE32U,
   9470                                      binop( Iop_And32,
   9471                                             binop( Iop_Shr32,
   9472                                                    bcd_l,
   9473                                                    mkU8 ( DIGIT6_SHR ) ),
   9474                                             mkU32 ( 0xF ) ),
   9475                                      mkU32( 0x9 ) ) ),
   9476                         unop( Iop_1Sto32,
   9477                               binop( Iop_CmpLE32U,
   9478                                      binop( Iop_And32,
   9479                                             binop( Iop_Shr32,
   9480                                                    bcd_l,
   9481                                                    mkU8 ( DIGIT7_SHR ) ),
   9482                                             mkU32 ( 0xF ) ),
   9483                                      mkU32( 0x9 ) ) ) ),
   9484                  AND4( unop( Iop_1Sto32,
   9485                              binop( Iop_CmpLE32U,
   9486                                     binop( Iop_And32,
   9487                                            bcd_u,
   9488                                            mkU32 ( 0xF ) ),
   9489                                     mkU32( 0x9 ) ) ),
   9490                        unop( Iop_1Sto32,
   9491                              binop( Iop_CmpLE32U,
   9492                                     binop( Iop_And32,
   9493                                            binop( Iop_Shr32,
   9494                                                   bcd_u,
   9495                                                   mkU8 ( DIGIT1_SHR ) ),
   9496                                            mkU32 ( 0xF ) ),
   9497                                     mkU32( 0x9 ) ) ),
   9498                        unop( Iop_1Sto32,
   9499                              binop( Iop_CmpLE32U,
   9500                                     binop( Iop_And32,
   9501                                            binop( Iop_Shr32,
   9502                                                   bcd_u,
   9503                                                   mkU8 ( DIGIT2_SHR ) ),
   9504                                            mkU32 ( 0xF ) ),
   9505                                     mkU32( 0x9 ) ) ),
   9506                        unop( Iop_1Sto32,
   9507                              binop( Iop_CmpLE32U,
   9508                                     binop( Iop_And32,
   9509                                            binop( Iop_Shr32,
   9510                                                   bcd_u,
   9511                                                   mkU8 ( DIGIT3_SHR ) ),
   9512                                            mkU32 ( 0xF ) ),
   9513                                     mkU32( 0x9 ) ) ) ),
   9514                  AND4( unop( Iop_1Sto32,
   9515                              binop( Iop_CmpLE32U,
   9516                                     binop( Iop_And32,
   9517                                            binop( Iop_Shr32,
   9518                                                   bcd_u,
   9519                                                   mkU8 ( DIGIT4_SHR ) ),
   9520                                            mkU32 ( 0xF ) ),
   9521                                     mkU32( 0x9 ) ) ),
   9522                        unop( Iop_1Sto32,
   9523                              binop( Iop_CmpLE32U,
   9524                                     binop( Iop_And32,
   9525                                            binop( Iop_Shr32,
   9526                                                   bcd_u,
   9527                                                   mkU8 ( DIGIT5_SHR ) ),
   9528                                            mkU32 ( 0xF ) ),
   9529                                     mkU32( 0x9 ) ) ),
   9530                        unop( Iop_1Sto32,
   9531                              binop( Iop_CmpLE32U,
   9532                                     binop( Iop_And32,
   9533                                            binop( Iop_Shr32,
   9534                                                   bcd_u,
   9535                                                   mkU8 ( DIGIT6_SHR ) ),
   9536                                            mkU32 ( 0xF ) ),
   9537                                     mkU32( 0x9 ) ) ),
   9538                        unop( Iop_1Sto32,
   9539                              binop( Iop_CmpLE32U,
   9540                                     binop( Iop_And32,
   9541                                            binop( Iop_Shr32,
   9542                                                   bcd_u,
   9543                                                   mkU8 ( DIGIT7_SHR ) ),
   9544                                            mkU32 ( 0xF ) ),
   9545                                     mkU32( 0x9 ) ) ) ) ) );
   9546 
   9547    return unop( Iop_Not32, mkexpr( valid ) );
   9548 }
   9549 #undef DIGIT1_SHR
   9550 #undef DIGIT2_SHR
   9551 #undef DIGIT3_SHR
   9552 #undef DIGIT4_SHR
   9553 #undef DIGIT5_SHR
   9554 #undef DIGIT6_SHR
   9555 #undef DIGIT7_SHR
   9556 
   9557 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
   9558 {
   9559    return binop( Iop_Or32,
   9560                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
   9561                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
   9562                );
   9563 }
   9564 
   9565 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
   9566 {
   9567    return binop( Iop_Or32,
   9568                  binop( Iop_Or32,
   9569                         unop( Iop_1Sto32,
   9570                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
   9571                         unop( Iop_1Sto32,
   9572                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
   9573                  binop( Iop_Or32,
   9574                         unop( Iop_1Sto32,
   9575                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
   9576                         unop( Iop_1Sto32,
   9577                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
   9578 }
   9579 
   9580 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
   9581                                    IRExpr * neg_sign_mask )
   9582 {
   9583    return binop( Iop_Or32,
   9584                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
   9585                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
   9586 }
   9587 
   9588 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
   9589                                    IRExpr * pos_sign_mask,
   9590                                    IRExpr * neg_sign_mask )
   9591 /* first argument is all 1's if the BCD string had an invalid digit in it. */
   9592 {
   9593    return binop( Iop_Or32,
   9594                  invalid_bcd_mask,
   9595                  unop( Iop_1Sto32,
   9596                        binop( Iop_CmpEQ32,
   9597                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
   9598                               mkU32( 0x0 ) ) ) );
   9599 }
   9600 
   9601 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
   9602                                          IRTemp * top_12_l, IRTemp * mid_60_u,
   9603                                          IRTemp * mid_60_l, IRTemp * low_60_u,
   9604                                          IRTemp * low_60_l)
   9605 {
   9606    IRTemp tmplow60 = newTemp( Ity_I64 );
   9607    IRTemp tmpmid60 = newTemp( Ity_I64 );
   9608    IRTemp tmptop12 = newTemp( Ity_I64 );
   9609    IRTemp low_50   = newTemp( Ity_I64 );
   9610    IRTemp mid_50   = newTemp( Ity_I64 );
   9611    IRTemp top_10   = newTemp( Ity_I64 );
   9612    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
   9613 
   9614    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
   9615 
   9616    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
   9617    assign( low_50,
   9618            binop( Iop_32HLto64,
   9619                   binop( Iop_And32,
   9620                          unop( Iop_64HIto32, frBI64_lo ),
   9621                          mkU32( 0x3FFFF ) ),
   9622                          unop( Iop_64to32, frBI64_lo ) ) );
   9623 
   9624    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9625     * BCD string.
   9626     */
   9627    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
   9628    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
   9629    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
   9630 
   9631    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
   9632     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
   9633     */
   9634    assign( mid_50,
   9635            binop( Iop_32HLto64,
   9636                   binop( Iop_Or32,
   9637                          binop( Iop_Shl32,
   9638                                 binop( Iop_And32,
   9639                                        unop( Iop_64HIto32, frBI64_hi ),
   9640                                        mkU32( 0xF ) ),
   9641                                 mkU8( 14 ) ),
   9642                          binop( Iop_Shr32,
   9643                                 unop( Iop_64to32, frBI64_hi ),
   9644                                 mkU8( 18 ) ) ),
   9645                   binop( Iop_Or32,
   9646                          binop( Iop_Shl32,
   9647                                 unop( Iop_64to32, frBI64_hi ),
   9648                                 mkU8( 14 ) ),
   9649                          binop( Iop_Shr32,
   9650                                 unop( Iop_64HIto32, frBI64_lo ),
   9651                                 mkU8( 18 ) ) ) ) );
   9652 
   9653    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9654     * BCD string.
   9655     */
   9656    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
   9657    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
   9658    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
   9659 
   9660    /* top_10[49:0] = frBI64_hi[45:36]) |  */
   9661    assign( top_10,
   9662            binop( Iop_32HLto64,
   9663                   mkU32( 0 ),
   9664                   binop( Iop_And32,
   9665                          binop( Iop_Shr32,
   9666                                 unop( Iop_64HIto32, frBI64_hi ),
   9667                                 mkU8( 4 ) ),
   9668                          mkU32( 0x3FF ) ) ) );
   9669 
   9670    /* Convert the 10 bit densely packed BCD string to a 12 bit
   9671     * BCD string.
   9672     */
   9673    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
   9674    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
   9675    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
   9676 }
   9677 
   9678 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
   9679                          IRTemp * final_cnt, IRTemp * final_flag,
   9680                          IRExpr * string )
   9681 {
   9682    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
   9683    int digits = MAX_DIGITS_IN_STRING;
   9684    int i;
   9685 
   9686    cnt[start-1] = newTemp( Ity_I8 );
   9687    flag[start-1] = newTemp( Ity_I8 );
   9688    assign( cnt[start-1], init_cnt);
   9689    assign( flag[start-1], init_flag);
   9690 
   9691    for ( i = start; i <= digits; i++) {
   9692       cnt[i] = newTemp( Ity_I8 );
   9693       flag[i] = newTemp( Ity_I8 );
   9694       assign( cnt[i],
   9695               binop( Iop_Add8,
   9696                      mkexpr( cnt[i-1] ),
   9697                      binop(Iop_And8,
   9698                            unop( Iop_1Uto8,
   9699                                  binop(Iop_CmpEQ32,
   9700                                        binop(Iop_And32,
   9701                                              string,
   9702                                              mkU32( 0xF <<
   9703                                                     ( ( digits - i ) * 4) ) ),
   9704                                        mkU32( 0 ) ) ),
   9705                            binop( Iop_Xor8, /* complement flag */
   9706                                   mkexpr( flag[i - 1] ),
   9707                                   mkU8( 0xFF ) ) ) ) );
   9708 
   9709       /* set flag to 1 if digit was not a zero */
   9710       assign( flag[i],
   9711               binop(Iop_Or8,
   9712                     unop( Iop_1Sto8,
   9713                           binop(Iop_CmpNE32,
   9714                                 binop(Iop_And32,
   9715                                       string,
   9716                                       mkU32( 0xF <<
   9717                                              ( (digits - i) * 4) ) ),
   9718                                 mkU32( 0 ) ) ),
   9719                     mkexpr( flag[i - 1] ) ) );
   9720    }
   9721 
   9722    *final_cnt = cnt[digits];
   9723    *final_flag = flag[digits];
   9724 }
   9725 
   9726 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
   9727                                         IRExpr * low_32 )
   9728 {
   9729    IRTemp num_lmd    = newTemp( Ity_I8 );
   9730    IRTemp num_upper  = newTemp( Ity_I8 );
   9731    IRTemp num_low    = newTemp( Ity_I8 );
   9732    IRTemp lmd_flag   = newTemp( Ity_I8 );
   9733    IRTemp upper_flag = newTemp( Ity_I8 );
   9734    IRTemp low_flag   = newTemp( Ity_I8 );
   9735 
   9736    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   9737    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   9738 
   9739    Count_zeros( 2,
   9740                 mkexpr( num_lmd ),
   9741                 mkexpr( lmd_flag ),
   9742                 &num_upper,
   9743                 &upper_flag,
   9744                 upper_28 );
   9745 
   9746    Count_zeros( 1,
   9747                 mkexpr( num_upper ),
   9748                 mkexpr( upper_flag ),
   9749                 &num_low,
   9750                 &low_flag,
   9751                 low_32 );
   9752 
   9753    return mkexpr( num_low );
   9754 }
   9755 
   9756 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
   9757                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
   9758                                          IRExpr * low_60_u, IRExpr * low_60_l)
   9759 {
   9760    IRTemp num_lmd   = newTemp( Ity_I8 );
   9761    IRTemp num_top   = newTemp( Ity_I8 );
   9762    IRTemp num_mid_u = newTemp( Ity_I8 );
   9763    IRTemp num_mid_l = newTemp( Ity_I8 );
   9764    IRTemp num_low_u = newTemp( Ity_I8 );
   9765    IRTemp num_low_l = newTemp( Ity_I8 );
   9766 
   9767    IRTemp lmd_flag   = newTemp( Ity_I8 );
   9768    IRTemp top_flag   = newTemp( Ity_I8 );
   9769    IRTemp mid_u_flag = newTemp( Ity_I8 );
   9770    IRTemp mid_l_flag = newTemp( Ity_I8 );
   9771    IRTemp low_u_flag = newTemp( Ity_I8 );
   9772    IRTemp low_l_flag = newTemp( Ity_I8 );
   9773 
   9774    /* Check the LMD, digit 16, to see if it is zero. */
   9775    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   9776 
   9777    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   9778 
   9779    Count_zeros( 6,
   9780                 mkexpr( num_lmd ),
   9781                 mkexpr( lmd_flag ),
   9782                 &num_top,
   9783                 &top_flag,
   9784                 top_12_l );
   9785 
   9786    Count_zeros( 1,
   9787                 mkexpr( num_top ),
   9788                 mkexpr( top_flag ),
   9789                 &num_mid_u,
   9790                 &mid_u_flag,
   9791                 binop( Iop_Or32,
   9792                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
   9793                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
   9794 
   9795    Count_zeros( 2,
   9796                 mkexpr( num_mid_u ),
   9797                 mkexpr( mid_u_flag ),
   9798                 &num_mid_l,
   9799                 &mid_l_flag,
   9800                 mid_60_l );
   9801 
   9802    Count_zeros( 1,
   9803                 mkexpr( num_mid_l ),
   9804                 mkexpr( mid_l_flag ),
   9805                 &num_low_u,
   9806                 &low_u_flag,
   9807                 binop( Iop_Or32,
   9808                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
   9809                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
   9810 
   9811    Count_zeros( 2,
   9812                 mkexpr( num_low_u ),
   9813                 mkexpr( low_u_flag ),
   9814                 &num_low_l,
   9815                 &low_l_flag,
   9816                 low_60_l );
   9817 
   9818    return mkexpr( num_low_l );
   9819 }
   9820 
   9821 static IRExpr * Check_unordered(IRExpr * val)
   9822 {
   9823    IRTemp gfield0to5 = newTemp( Ity_I32 );
   9824 
   9825    /* Extract G[0:4] */
   9826    assign( gfield0to5,
   9827            binop( Iop_And32,
   9828                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
   9829                   mkU32( 0x1F ) ) );
   9830 
   9831    /* Check for unordered, return all 1'x if true */
   9832    return binop( Iop_Or32, /* QNaN check */
   9833                  unop( Iop_1Sto32,
   9834                        binop( Iop_CmpEQ32,
   9835                               mkexpr( gfield0to5 ),
   9836                               mkU32( 0x1E ) ) ),
   9837                               unop( Iop_1Sto32, /* SNaN check */
   9838                                     binop( Iop_CmpEQ32,
   9839                                            mkexpr( gfield0to5 ),
   9840                                            mkU32( 0x1F ) ) ) );
   9841 }
   9842 
   9843 #undef AND
   9844 #undef AND4
   9845 #undef OR
   9846 #undef OR3
   9847 #undef OR4
   9848 #undef NOT
   9849 #undef SHR
   9850 #undef SHL
   9851 #undef BITS5
   9852 
   9853 /*------------------------------------------------------------*/
   9854 /*--- Decimal Floating Point (DFP) instruction translation ---*/
   9855 /*------------------------------------------------------------*/
   9856 
   9857 /* DFP Arithmetic instructions */
   9858 static Bool dis_dfp_arith(UInt theInstr)
   9859 {
   9860    UInt opc2 = ifieldOPClo10( theInstr );
   9861    UChar frS_addr = ifieldRegDS( theInstr );
   9862    UChar frA_addr = ifieldRegA( theInstr );
   9863    UChar frB_addr = ifieldRegB( theInstr );
   9864    UChar flag_rC = ifieldBIT0( theInstr );
   9865 
   9866    IRTemp frA = newTemp( Ity_D64 );
   9867    IRTemp frB = newTemp( Ity_D64 );
   9868    IRTemp frS = newTemp( Ity_D64 );
   9869    IRExpr* round = get_IR_roundingmode_DFP();
   9870 
   9871    /* By default, if flag_RC is set, we will clear cr1 after the
   9872     * operation.  In reality we should set cr1 to indicate the
   9873     * exception status of the operation, but since we're not
   9874     * simulating exceptions, the exception status will appear to be
   9875     * zero.  Hence cr1 should be cleared if this is a . form insn.
   9876     */
   9877    Bool clear_CR1 = True;
   9878 
   9879    assign( frA, getDReg( frA_addr ) );
   9880    assign( frB, getDReg( frB_addr ) );
   9881 
   9882    switch (opc2) {
   9883    case 0x2: // dadd
   9884       DIP( "dadd%s fr%u,fr%u,fr%u\n",
   9885            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9886       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9887       break;
   9888    case 0x202: // dsub
   9889       DIP( "dsub%s fr%u,fr%u,fr%u\n",
   9890            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9891       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9892       break;
   9893    case 0x22: // dmul
   9894       DIP( "dmul%s fr%u,fr%u,fr%u\n",
   9895            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9896       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9897       break;
   9898    case 0x222: // ddiv
   9899       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
   9900            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9901       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9902       break;
   9903    }
   9904 
   9905    putDReg( frS_addr, mkexpr( frS ) );
   9906 
   9907    if (flag_rC && clear_CR1) {
   9908       putCR321( 1, mkU8( 0 ) );
   9909       putCR0( 1, mkU8( 0 ) );
   9910    }
   9911 
   9912    return True;
   9913 }
   9914 
   9915 /* Quad DFP Arithmetic instructions */
   9916 static Bool dis_dfp_arithq(UInt theInstr)
   9917 {
   9918    UInt opc2 = ifieldOPClo10( theInstr );
   9919    UChar frS_addr = ifieldRegDS( theInstr );
   9920    UChar frA_addr = ifieldRegA( theInstr );
   9921    UChar frB_addr = ifieldRegB( theInstr );
   9922    UChar flag_rC = ifieldBIT0( theInstr );
   9923 
   9924    IRTemp frA = newTemp( Ity_D128 );
   9925    IRTemp frB = newTemp( Ity_D128 );
   9926    IRTemp frS = newTemp( Ity_D128 );
   9927    IRExpr* round = get_IR_roundingmode_DFP();
   9928 
   9929    /* By default, if flag_RC is set, we will clear cr1 after the
   9930     * operation.  In reality we should set cr1 to indicate the
   9931     * exception status of the operation, but since we're not
   9932     * simulating exceptions, the exception status will appear to be
   9933     * zero.  Hence cr1 should be cleared if this is a . form insn.
   9934     */
   9935    Bool clear_CR1 = True;
   9936 
   9937    assign( frA, getDReg_pair( frA_addr ) );
   9938    assign( frB, getDReg_pair( frB_addr ) );
   9939 
   9940    switch (opc2) {
   9941    case 0x2: // daddq
   9942       DIP( "daddq%s fr%u,fr%u,fr%u\n",
   9943            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9944       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9945       break;
   9946    case 0x202: // dsubq
   9947       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
   9948            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9949       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9950       break;
   9951    case 0x22: // dmulq
   9952       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
   9953            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9954       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9955       break;
   9956    case 0x222: // ddivq
   9957       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
   9958            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9959       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9960       break;
   9961    }
   9962 
   9963    putDReg_pair( frS_addr, mkexpr( frS ) );
   9964 
   9965    if (flag_rC && clear_CR1) {
   9966       putCR321( 1, mkU8( 0 ) );
   9967       putCR0( 1, mkU8( 0 ) );
   9968    }
   9969 
   9970    return True;
   9971 }
   9972 
   9973 /* DFP 64-bit logical shift instructions  */
   9974 static Bool dis_dfp_shift(UInt theInstr) {
   9975    UInt opc2       = ifieldOPClo9( theInstr );
   9976    UChar frS_addr  = ifieldRegDS( theInstr );
   9977    UChar frA_addr  = ifieldRegA( theInstr );
   9978    UChar shift_val = IFIELD(theInstr, 10, 6);
   9979    UChar flag_rC   = ifieldBIT0( theInstr );
   9980 
   9981    IRTemp frA = newTemp( Ity_D64 );
   9982    IRTemp frS = newTemp( Ity_D64 );
   9983    Bool clear_CR1 = True;
   9984 
   9985    assign( frA, getDReg( frA_addr ) );
   9986 
   9987    switch (opc2) {
   9988    case 0x42: // dscli
   9989       DIP( "dscli%s fr%u,fr%u,%u\n",
   9990            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9991       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
   9992       break;
   9993    case 0x62: // dscri
   9994       DIP( "dscri%s fr%u,fr%u,%u\n",
   9995            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9996       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
   9997       break;
   9998    }
   9999 
   10000    putDReg( frS_addr, mkexpr( frS ) );
   10001 
   10002    if (flag_rC && clear_CR1) {
   10003       putCR321( 1, mkU8( 0 ) );
   10004       putCR0( 1, mkU8( 0 ) );
   10005    }
   10006 
   10007    return True;
   10008 }
   10009 
   10010 /* Quad DFP  logical shift instructions  */
   10011 static Bool dis_dfp_shiftq(UInt theInstr) {
   10012    UInt opc2       = ifieldOPClo9( theInstr );
   10013    UChar frS_addr  = ifieldRegDS( theInstr );
   10014    UChar frA_addr  = ifieldRegA( theInstr );
   10015    UChar shift_val = IFIELD(theInstr, 10, 6);
   10016    UChar flag_rC   = ifieldBIT0( theInstr );
   10017 
   10018    IRTemp frA = newTemp( Ity_D128 );
   10019    IRTemp frS = newTemp( Ity_D128 );
   10020    Bool clear_CR1 = True;
   10021 
   10022    assign( frA, getDReg_pair( frA_addr ) );
   10023 
   10024    switch (opc2) {
   10025    case 0x42: // dscliq
   10026       DIP( "dscliq%s fr%u,fr%u,%u\n",
   10027            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10028       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10029       break;
   10030    case 0x62: // dscriq
   10031       DIP( "dscriq%s fr%u,fr%u,%u\n",
   10032            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10033       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10034       break;
   10035    }
   10036 
   10037    putDReg_pair( frS_addr, mkexpr( frS ) );
   10038 
   10039    if (flag_rC && clear_CR1) {
   10040       putCR321( 1, mkU8( 0 ) );
   10041       putCR0( 1, mkU8( 0 ) );
   10042    }
   10043 
   10044    return True;
   10045 }
   10046 
   10047 /* DFP 64-bit format conversion instructions */
   10048 static Bool dis_dfp_fmt_conv(UInt theInstr) {
   10049    UInt opc2      = ifieldOPClo10( theInstr );
   10050    UChar frS_addr = ifieldRegDS( theInstr );
   10051    UChar frB_addr = ifieldRegB( theInstr );
   10052    IRExpr* round  = get_IR_roundingmode_DFP();
   10053    UChar flag_rC  = ifieldBIT0( theInstr );
   10054    IRTemp frB;
   10055    IRTemp frS;
   10056    Bool clear_CR1 = True;
   10057 
   10058    switch (opc2) {
   10059    case 0x102: //dctdp
   10060       DIP( "dctdp%s fr%u,fr%u\n",
   10061            flag_rC ? ".":"", frS_addr, frB_addr );
   10062 
   10063       frB = newTemp( Ity_D32 );
   10064       frS = newTemp( Ity_D64 );
   10065       assign( frB, getDReg32( frB_addr ) );
   10066       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
   10067       putDReg( frS_addr, mkexpr( frS ) );
   10068       break;
   10069    case 0x302: // drsp
   10070       DIP( "drsp%s fr%u,fr%u\n",
   10071            flag_rC ? ".":"", frS_addr, frB_addr );
   10072       frB = newTemp( Ity_D64 );
   10073       frS = newTemp( Ity_D32 );
   10074       assign( frB, getDReg( frB_addr ) );
   10075       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
   10076       putDReg32( frS_addr, mkexpr( frS ) );
   10077       break;
   10078    case 0x122: // dctfix
   10079       {
   10080          IRTemp tmp = newTemp( Ity_I64 );
   10081 
   10082          DIP( "dctfix%s fr%u,fr%u\n",
   10083               flag_rC ? ".":"", frS_addr, frB_addr );
   10084          frB = newTemp( Ity_D64 );
   10085          frS = newTemp( Ity_D64 );
   10086          assign( frB, getDReg( frB_addr ) );
   10087          assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
   10088          assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10089          putDReg( frS_addr, mkexpr( frS ) );
   10090       }
   10091       break;
   10092    case 0x322: // dcffix
   10093       DIP( "dcffix%s fr%u,fr%u\n",
   10094            flag_rC ? ".":"", frS_addr, frB_addr );
   10095       frB = newTemp( Ity_D64 );
   10096       frS = newTemp( Ity_D64 );
   10097       assign( frB, getDReg( frB_addr ) );
   10098       assign( frS, binop( Iop_I64StoD64,
   10099                           round,
   10100                           unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
   10101       putDReg( frS_addr, mkexpr( frS ) );
   10102       break;
   10103    }
   10104 
   10105    if (flag_rC && clear_CR1) {
   10106       putCR321( 1, mkU8( 0 ) );
   10107       putCR0( 1, mkU8( 0 ) );
   10108    }
   10109 
   10110    return True;
   10111 }
   10112 
   10113 /* Quad DFP format conversion instructions */
   10114 static Bool dis_dfp_fmt_convq(UInt theInstr) {
   10115    UInt opc2      = ifieldOPClo10( theInstr );
   10116    UChar frS_addr = ifieldRegDS( theInstr );
   10117    UChar frB_addr = ifieldRegB( theInstr );
   10118    IRExpr* round  = get_IR_roundingmode_DFP();
   10119    IRTemp frB64   = newTemp( Ity_D64 );
   10120    IRTemp frB128  = newTemp( Ity_D128 );
   10121    IRTemp frS64   = newTemp( Ity_D64 );
   10122    IRTemp frS128  = newTemp( Ity_D128 );
   10123    UChar flag_rC  = ifieldBIT0( theInstr );
   10124    Bool clear_CR1 = True;
   10125 
   10126    switch (opc2) {
   10127    case 0x102: // dctqpq
   10128       DIP( "dctqpq%s fr%u,fr%u\n",
   10129            flag_rC ? ".":"", frS_addr, frB_addr );
   10130       assign( frB64, getDReg( frB_addr ) );
   10131       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
   10132       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10133       break;
   10134    case 0x122: // dctfixq
   10135       {
   10136          IRTemp tmp = newTemp( Ity_I64 );
   10137 
   10138          DIP( "dctfixq%s fr%u,fr%u\n",
   10139               flag_rC ? ".":"", frS_addr, frB_addr );
   10140          assign( frB128, getDReg_pair( frB_addr ) );
   10141          assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
   10142          assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10143          putDReg( frS_addr, mkexpr( frS64 ) );
   10144       }
   10145       break;
   10146    case 0x302: //drdpq
   10147       DIP( "drdpq%s fr%u,fr%u\n",
   10148            flag_rC ? ".":"", frS_addr, frB_addr );
   10149       assign( frB128, getDReg_pair( frB_addr ) );
   10150       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
   10151       putDReg( frS_addr, mkexpr( frS64 ) );
   10152       break;
   10153    case 0x322: // dcffixq
   10154      {
   10155       /* Have to introduce an IOP for this instruction so it will work
   10156        * on POWER 6 because emulating the instruction requires a POWER 7
   10157        * DFP instruction in the emulation code.
   10158        */
   10159       DIP( "dcffixq%s fr%u,fr%u\n",
   10160            flag_rC ? ".":"", frS_addr, frB_addr );
   10161       assign( frB64, getDReg( frB_addr ) );
   10162       assign( frS128, unop( Iop_I64StoD128,
   10163                             unop( Iop_ReinterpD64asI64,
   10164                                   mkexpr( frB64 ) ) ) );
   10165       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10166       break;
   10167      }
   10168    }
   10169 
   10170    if (flag_rC && clear_CR1) {
   10171       putCR321( 1, mkU8( 0 ) );
   10172       putCR0( 1, mkU8( 0 ) );
   10173    }
   10174 
   10175    return True;
   10176 }
   10177 
   10178 static Bool dis_dfp_round( UInt theInstr ) {
   10179    UChar frS_addr = ifieldRegDS(theInstr);
   10180    UChar R        = IFIELD(theInstr, 16, 1);
   10181    UChar RMC      = IFIELD(theInstr, 9, 2);
   10182    UChar frB_addr = ifieldRegB( theInstr );
   10183    UChar flag_rC  = ifieldBIT0( theInstr );
   10184    IRTemp frB     = newTemp( Ity_D64 );
   10185    IRTemp frS     = newTemp( Ity_D64 );
   10186    UInt opc2      = ifieldOPClo8( theInstr );
   10187    Bool clear_CR1 = True;
   10188 
   10189    switch (opc2) {
   10190    /* drintn, is the same as drintx.  The only difference is this
   10191     * instruction does not generate an exception for an inexact operation.
   10192     * Currently not supporting inexact exceptions.
   10193     */
   10194    case 0x63: // drintx
   10195    case 0xE3: // drintn
   10196       DIP( "drintx/drintn%s fr%u,fr%u\n",
   10197            flag_rC ? ".":"", frS_addr, frB_addr );
   10198 
   10199       /* NOTE, this instruction takes a DFP value and rounds to the
   10200        * neares floating point integer value, i.e. fractional part
   10201        * is zero.  The result is a floating point number.
   10202        */
   10203       /* pass the value of R and RMC in the same field */
   10204       assign( frB, getDReg( frB_addr ) );
   10205       assign( frS, binop( Iop_RoundD64toInt,
   10206                           mkU32( ( R << 3 ) | RMC ),
   10207                           mkexpr( frB ) ) );
   10208       putDReg( frS_addr, mkexpr( frS ) );
   10209       break;
   10210    default:
   10211       vex_printf("dis_dfp_round(ppc)(opc2)\n");
   10212       return False;
   10213    }
   10214 
   10215    if (flag_rC && clear_CR1) {
   10216       putCR321( 1, mkU8( 0 ) );
   10217       putCR0( 1, mkU8( 0 ) );
   10218    }
   10219 
   10220    return True;
   10221 }
   10222 
   10223 static Bool dis_dfp_roundq(UInt theInstr) {
   10224    UChar frS_addr = ifieldRegDS( theInstr );
   10225    UChar frB_addr = ifieldRegB( theInstr );
   10226    UChar R = IFIELD(theInstr, 16, 1);
   10227    UChar RMC = IFIELD(theInstr, 9, 2);
   10228    UChar flag_rC = ifieldBIT0( theInstr );
   10229    IRTemp frB = newTemp( Ity_D128 );
   10230    IRTemp frS = newTemp( Ity_D128 );
   10231    Bool clear_CR1 = True;
   10232    UInt opc2 = ifieldOPClo8( theInstr );
   10233 
   10234    switch (opc2) {
   10235    /* drintnq, is the same as drintxq.  The only difference is this
   10236     * instruction does not generate an exception for an inexact operation.
   10237     * Currently not supporting inexact exceptions.
   10238     */
   10239    case 0x63: // drintxq
   10240    case 0xE3: // drintnq
   10241       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
   10242            flag_rC ? ".":"", frS_addr, frB_addr );
   10243 
   10244       /* pass the value of R and RMC in the same field */
   10245       assign( frB, getDReg_pair( frB_addr ) );
   10246       assign( frS, binop( Iop_RoundD128toInt,
   10247                           mkU32( ( R << 3 ) | RMC ),
   10248                           mkexpr( frB ) ) );
   10249       putDReg_pair( frS_addr, mkexpr( frS ) );
   10250       break;
   10251    default:
   10252       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
   10253       return False;
   10254    }
   10255 
   10256    if (flag_rC && clear_CR1) {
   10257       putCR321( 1, mkU8( 0 ) );
   10258       putCR0( 1, mkU8( 0 ) );
   10259    }
   10260 
   10261    return True;
   10262 }
   10263 
   10264 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
   10265    UInt opc2 = ifieldOPClo8( theInstr );
   10266    UChar frS_addr = ifieldRegDS( theInstr );
   10267    UChar frA_addr = ifieldRegA( theInstr );
   10268    UChar frB_addr = ifieldRegB( theInstr );
   10269    UChar flag_rC = ifieldBIT0( theInstr );
   10270    UInt TE_value = IFIELD(theInstr, 16, 4);
   10271    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10272    UInt RMC = IFIELD(theInstr, 9, 2);
   10273    IRTemp frA = newTemp( Ity_D64 );
   10274    IRTemp frB = newTemp( Ity_D64 );
   10275    IRTemp frS = newTemp( Ity_D64 );
   10276    Bool clear_CR1 = True;
   10277 
   10278    assign( frB, getDReg( frB_addr ) );
   10279 
   10280    switch (opc2) {
   10281    case 0x43: // dquai
   10282       DIP( "dquai%s fr%u,fr%u,fr%u\n",
   10283            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10284       IRTemp TE_I64 = newTemp( Ity_I64 );
   10285 
   10286       /* Generate a reference DFP value frA with the desired exponent
   10287        * given by TE using significand from frB.  Need to add the bias
   10288        * 398 to TE.  TE is stored as a 2's complement number.
   10289        */
   10290       if (TE_sign == 1) {
   10291          /* Take 2's complement of the 5-bit value and subtract from bias.
   10292           *  Bias is adjusted for the +1 required when taking 2's complement.
   10293           */
   10294          assign( TE_I64,
   10295                  unop( Iop_32Uto64,
   10296                        binop( Iop_Sub32, mkU32( 397 ),
   10297                               binop( Iop_And32, mkU32( 0xF ),
   10298                                      unop( Iop_Not32, mkU32( TE_value ) )
   10299                                      ) ) ) );
   10300 
   10301       } else {
   10302           assign( TE_I64,
   10303                   unop( Iop_32Uto64,
   10304                         binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
   10305                         ) );
   10306       }
   10307 
   10308       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
   10309                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
   10310 
   10311       assign( frS, triop( Iop_QuantizeD64,
   10312                           mkU32( RMC ),
   10313                           mkexpr( frA ),
   10314                           mkexpr( frB ) ) );
   10315       break;
   10316 
   10317    case 0x3: // dqua
   10318       DIP( "dqua%s fr%u,fr%u,fr%u\n",
   10319            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10320       assign( frA, getDReg( frA_addr ) );
   10321       assign( frS, triop( Iop_QuantizeD64,
   10322                           mkU32( RMC ),
   10323                           mkexpr( frA ),
   10324                           mkexpr( frB ) ) );
   10325       break;
   10326    case 0x23: // drrnd
   10327       {
   10328          IRTemp tmp = newTemp( Ity_I8 );
   10329 
   10330          DIP( "drrnd%s fr%u,fr%u,fr%u\n",
   10331               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10332          assign( frA, getDReg( frA_addr ) );
   10333          /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
   10334          assign( tmp, unop( Iop_32to8,
   10335                             unop( Iop_64to32,
   10336                                   unop( Iop_ReinterpD64asI64,
   10337                                         mkexpr( frA ) ) ) ) );
   10338          assign( frS, triop( Iop_SignificanceRoundD64,
   10339                              mkU32( RMC ),
   10340                              mkexpr( tmp ),
   10341                              mkexpr( frB ) ) );
   10342       }
   10343       break;
   10344    default:
   10345       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
   10346       return False;
   10347    }
   10348    putDReg( frS_addr, mkexpr( frS ) );
   10349 
   10350    if (flag_rC && clear_CR1) {
   10351       putCR321( 1, mkU8( 0 ) );
   10352       putCR0( 1, mkU8( 0 ) );
   10353    }
   10354 
   10355    return True;
   10356 }
   10357 
   10358 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
   10359    UInt opc2 = ifieldOPClo8( theInstr );
   10360    UChar frS_addr = ifieldRegDS( theInstr );
   10361    UChar frA_addr = ifieldRegA( theInstr );
   10362    UChar frB_addr = ifieldRegB( theInstr );
   10363    UChar flag_rC = ifieldBIT0( theInstr );
   10364    UInt TE_value = IFIELD(theInstr, 16, 4);
   10365    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10366    UInt RMC = IFIELD(theInstr, 9, 2);
   10367    IRTemp frA = newTemp( Ity_D128 );
   10368    IRTemp frB = newTemp( Ity_D128 );
   10369    IRTemp frS = newTemp( Ity_D128 );
   10370    Bool clear_CR1 = True;
   10371 
   10372    assign( frB, getDReg_pair( frB_addr ) );
   10373 
   10374    switch (opc2) {
   10375    case 0x43: // dquaiq
   10376       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10377            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10378       IRTemp TE_I64 = newTemp( Ity_I64 );
   10379 
   10380       /* Generate a reference DFP value frA with the desired exponent
   10381        * given by TE using significand of 1.  Need to add the bias
   10382        * 6176 to TE.
   10383        */
   10384       if (TE_sign == 1) {
   10385          /* Take 2's complement of the 5-bit value and subtract from bias.
   10386           *  Bias adjusted for the +1 required when taking 2's complement.
   10387           */
   10388          assign( TE_I64,
   10389                  unop( Iop_32Uto64,
   10390                        binop( Iop_Sub32, mkU32( 6175 ),
   10391                               binop( Iop_And32, mkU32( 0xF ),
   10392                                      unop( Iop_Not32, mkU32( TE_value ) )
   10393                                      ) ) ) );
   10394 
   10395       } else {
   10396          assign( TE_I64,
   10397                  unop( Iop_32Uto64,
   10398                        binop( Iop_Add32,
   10399                              mkU32( 6176 ),
   10400                              mkU32( TE_value ) ) ) );
   10401       }
   10402 
   10403       assign( frA,
   10404               binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
   10405                      unop( Iop_D64toD128,
   10406                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
   10407       assign( frS, triop( Iop_QuantizeD128,
   10408                           mkU32( RMC ),
   10409                           mkexpr( frA ),
   10410                           mkexpr( frB ) ) );
   10411       break;
   10412    case 0x3: // dquaq
   10413       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10414            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10415       assign( frA, getDReg_pair( frA_addr ) );
   10416       assign( frS, triop( Iop_QuantizeD128,
   10417                           mkU32( RMC ),
   10418                           mkexpr( frA ),
   10419                           mkexpr( frB ) ) );
   10420       break;
   10421    case 0x23: // drrndq
   10422       {
   10423          IRTemp tmp = newTemp( Ity_I8 );
   10424 
   10425          DIP( "drrndq%s fr%u,fr%u,fr%u\n",
   10426               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10427          assign( frA, getDReg_pair( frA_addr ) );
   10428          assign( tmp, unop( Iop_32to8,
   10429                             unop( Iop_64to32,
   10430                                   unop( Iop_ReinterpD64asI64,
   10431                                         unop( Iop_D128HItoD64,
   10432                                               mkexpr( frA ) ) ) ) ) );
   10433          assign( frS, triop( Iop_SignificanceRoundD128,
   10434                              mkU32( RMC ),
   10435                              mkexpr( tmp ),
   10436                              mkexpr( frB ) ) );
   10437       }
   10438       break;
   10439    default:
   10440       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
   10441       return False;
   10442    }
   10443    putDReg_pair( frS_addr, mkexpr( frS ) );
   10444 
   10445    if (flag_rC && clear_CR1) {
   10446       putCR321( 1, mkU8( 0 ) );
   10447       putCR0( 1, mkU8( 0 ) );
   10448    }
   10449 
   10450    return True;
   10451 }
   10452 
   10453 static Bool dis_dfp_extract_insert(UInt theInstr) {
   10454    UInt opc2 = ifieldOPClo10( theInstr );
   10455    UChar frS_addr = ifieldRegDS( theInstr );
   10456    UChar frA_addr = ifieldRegA( theInstr );
   10457    UChar frB_addr = ifieldRegB( theInstr );
   10458    UChar flag_rC = ifieldBIT0( theInstr );
   10459    Bool clear_CR1 = True;
   10460 
   10461    IRTemp frA = newTemp( Ity_D64 );
   10462    IRTemp frB = newTemp( Ity_D64 );
   10463    IRTemp frS = newTemp( Ity_D64 );
   10464    IRTemp tmp = newTemp( Ity_I64 );
   10465 
   10466    assign( frA, getDReg( frA_addr ) );
   10467    assign( frB, getDReg( frB_addr ) );
   10468 
   10469    switch (opc2) {
   10470    case 0x162: // dxex
   10471       DIP( "dxex%s fr%u,fr%u,fr%u\n",
   10472            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10473       assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
   10474       assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10475       break;
   10476    case 0x362: // diex
   10477       DIP( "diex%s fr%u,fr%u,fr%u\n",
   10478            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10479       assign( frS, binop( Iop_InsertExpD64,
   10480                           unop( Iop_ReinterpD64asI64,
   10481                                 mkexpr( frA ) ),
   10482                           mkexpr( frB ) ) );
   10483       break;
   10484    default:
   10485       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
   10486       return False;
   10487    }
   10488 
   10489    putDReg( frS_addr, mkexpr( frS ) );
   10490 
   10491    if (flag_rC && clear_CR1) {
   10492       putCR321( 1, mkU8( 0 ) );
   10493       putCR0( 1, mkU8( 0 ) );
   10494    }
   10495 
   10496    return True;
   10497 }
   10498 
   10499 static Bool dis_dfp_extract_insertq(UInt theInstr) {
   10500    UInt opc2 = ifieldOPClo10( theInstr );
   10501    UChar frS_addr = ifieldRegDS( theInstr );
   10502    UChar frA_addr = ifieldRegA( theInstr );
   10503    UChar frB_addr = ifieldRegB( theInstr );
   10504    UChar flag_rC = ifieldBIT0( theInstr );
   10505 
   10506    IRTemp frA   = newTemp( Ity_D64 );
   10507    IRTemp frB   = newTemp( Ity_D128 );
   10508    IRTemp frS64 = newTemp( Ity_D64 );
   10509    IRTemp frS   = newTemp( Ity_D128 );
   10510    IRTemp tmp   = newTemp( Ity_I64 );
   10511    Bool clear_CR1 = True;
   10512 
   10513    assign( frB, getDReg_pair( frB_addr ) );
   10514 
   10515    switch (opc2) {
   10516    case 0x162:  // dxexq
   10517       DIP( "dxexq%s fr%u,fr%u\n",
   10518            flag_rC ? ".":"", frS_addr,  frB_addr );
   10519       /* Instruction actually returns a 64-bit result.  So as to be
   10520        * consistent and not have to add a new struct, the emulation returns
   10521        * the 64-bit result in the upper and lower register.
   10522        */
   10523       assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
   10524       assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10525       putDReg( frS_addr, mkexpr( frS64 ) );
   10526       break;
   10527    case 0x362:  // diexq
   10528       DIP( "diexq%s fr%u,fr%u,fr%u\n",
   10529            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10530       assign( frA, getDReg( frA_addr ) );
   10531       assign( frS, binop( Iop_InsertExpD128,
   10532                           unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
   10533                           mkexpr( frB ) ) );
   10534       putDReg_pair( frS_addr, mkexpr( frS ) );
   10535       break;
   10536    default:
   10537       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
   10538       return False;
   10539    }
   10540 
   10541    if (flag_rC && clear_CR1) {
   10542       putCR321( 1, mkU8( 0 ) );
   10543       putCR0( 1, mkU8( 0 ) );
   10544    }
   10545 
   10546    return True;
   10547 }
   10548 
   10549 /* DFP 64-bit comparison instructions */
   10550 static Bool dis_dfp_compare(UInt theInstr) {
   10551    /* X-Form */
   10552    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   10553    UChar frA_addr = ifieldRegA( theInstr );
   10554    UChar frB_addr = ifieldRegB( theInstr );
   10555    UInt opc1 = ifieldOPC( theInstr );
   10556    IRTemp frA;
   10557    IRTemp frB;
   10558 
   10559    IRTemp ccIR = newTemp( Ity_I32 );
   10560    IRTemp ccPPC32 = newTemp( Ity_I32 );
   10561 
   10562 
   10563    /* Note: Differences between dcmpu and dcmpo are only in exception
   10564     flag settings, which aren't supported anyway. */
   10565    switch (opc1) {
   10566    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
   10567       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   10568       frA = newTemp( Ity_D64 );
   10569       frB = newTemp( Ity_D64 );
   10570 
   10571       assign( frA, getDReg( frA_addr ) );
   10572       assign( frB, getDReg( frB_addr ) );
   10573 
   10574       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
   10575       break;
   10576    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
   10577       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   10578       frA = newTemp( Ity_D128 );
   10579       frB = newTemp( Ity_D128 );
   10580 
   10581       assign( frA, getDReg_pair( frA_addr ) );
   10582       assign( frB, getDReg_pair( frB_addr ) );
   10583       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
   10584       break;
   10585    default:
   10586       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
   10587       return False;
   10588    }
   10589 
   10590    /* Map compare result from IR to PPC32 */
   10591    /*
   10592     FP cmp result | PPC | IR
   10593     --------------------------
   10594     UN            | 0x1 | 0x45
   10595     EQ            | 0x2 | 0x40
   10596     GT            | 0x4 | 0x00
   10597     LT            | 0x8 | 0x01
   10598     */
   10599 
   10600    assign( ccPPC32,
   10601            binop( Iop_Shl32,
   10602                   mkU32( 1 ),
   10603                   unop( Iop_32to8,
   10604                         binop( Iop_Or32,
   10605                                binop( Iop_And32,
   10606                                       unop( Iop_Not32,
   10607                                             binop( Iop_Shr32,
   10608                                                    mkexpr( ccIR ),
   10609                                                    mkU8( 5 ) ) ),
   10610                                       mkU32( 2 ) ),
   10611                                binop( Iop_And32,
   10612                                       binop( Iop_Xor32,
   10613                                              mkexpr( ccIR ),
   10614                                              binop( Iop_Shr32,
   10615                                                     mkexpr( ccIR ),
   10616                                                     mkU8( 6 ) ) ),
   10617                                       mkU32( 1 ) ) ) ) ) );
   10618 
   10619    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
   10620    return True;
   10621 }
   10622 
   10623 /* Test class/group/exponent/significance instructions. */
   10624 static Bool dis_dfp_exponent_test ( UInt theInstr )
   10625 {
   10626    UChar frA_addr   = ifieldRegA( theInstr );
   10627    UChar frB_addr   = ifieldRegB( theInstr );
   10628    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
   10629    IRTemp frA       = newTemp( Ity_D64 );
   10630    IRTemp frB       = newTemp( Ity_D64 );
   10631    IRTemp frA128    = newTemp( Ity_D128 );
   10632    IRTemp frB128    = newTemp( Ity_D128 );
   10633    UInt opc1        = ifieldOPC( theInstr );
   10634    IRTemp gfield_A  = newTemp( Ity_I32 );
   10635    IRTemp gfield_B  = newTemp( Ity_I32 );
   10636    IRTemp gfield_mask   = newTemp( Ity_I32 );
   10637    IRTemp exponent_A    = newTemp( Ity_I32 );
   10638    IRTemp exponent_B    = newTemp( Ity_I32 );
   10639    IRTemp A_NaN_true    = newTemp( Ity_I32 );
   10640    IRTemp B_NaN_true    = newTemp( Ity_I32 );
   10641    IRTemp A_inf_true    = newTemp( Ity_I32 );
   10642    IRTemp B_inf_true    = newTemp( Ity_I32 );
   10643    IRTemp A_equals_B    = newTemp( Ity_I32 );
   10644    IRTemp finite_number = newTemp( Ity_I32 );
   10645    IRTemp cc0 = newTemp( Ity_I32 );
   10646    IRTemp cc1 = newTemp( Ity_I32 );
   10647    IRTemp cc2 = newTemp( Ity_I32 );
   10648    IRTemp cc3 = newTemp( Ity_I32 );
   10649 
   10650    /* The dtstex and dtstexg instructions only differ in the size of the
   10651     * exponent field.  The following switch statement takes care of the size
   10652     * specific setup.  Once the value of the exponents, the G-field shift
   10653     * and mask is setup the remaining code is identical.
   10654     */
   10655    switch (opc1) {
   10656    case 0x3b: // dtstex       Extended instruction setup
   10657       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10658       assign( frA, getDReg( frA_addr ) );
   10659       assign( frB, getDReg( frB_addr ) );
   10660       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   10661       assign(exponent_A, unop( Iop_64to32,
   10662                                unop( Iop_ExtractExpD64,
   10663                                      mkexpr( frA ) ) ) );
   10664       assign(exponent_B, unop( Iop_64to32,
   10665                                unop( Iop_ExtractExpD64,
   10666                                      mkexpr( frB ) ) ) );
   10667       break;
   10668 
   10669    case 0x3F: //  dtstexq      Quad instruction setup
   10670       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10671       assign( frA128, getDReg_pair( frA_addr ) );
   10672       assign( frB128, getDReg_pair( frB_addr ) );
   10673       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
   10674       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
   10675       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   10676       assign( exponent_A, unop( Iop_64to32,
   10677                                 unop( Iop_ExtractExpD128,
   10678                                       mkexpr( frA128 ) ) ) );
   10679       assign( exponent_B, unop( Iop_64to32,
   10680                                 unop( Iop_ExtractExpD128,
   10681                                       mkexpr( frB128 ) ) ) );
   10682       break;
   10683    default:
   10684       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
   10685       return False;
   10686    }
   10687 
   10688    /* Extract the Gfield */
   10689    assign( gfield_A, binop( Iop_And32,
   10690                             mkexpr( gfield_mask ),
   10691                             unop( Iop_64HIto32,
   10692                                   unop( Iop_ReinterpD64asI64,
   10693                                         mkexpr(frA) ) ) ) );
   10694 
   10695    assign( gfield_B, binop( Iop_And32,
   10696                             mkexpr( gfield_mask ),
   10697                             unop( Iop_64HIto32,
   10698                                   unop( Iop_ReinterpD64asI64,
   10699                                         mkexpr(frB) ) ) ) );
   10700 
   10701    /* check for NAN */
   10702    assign( A_NaN_true, binop(Iop_Or32,
   10703                              unop( Iop_1Sto32,
   10704                                    binop( Iop_CmpEQ32,
   10705                                           mkexpr( gfield_A ),
   10706                                           mkU32( 0x7C000000 ) ) ),
   10707                              unop( Iop_1Sto32,
   10708                                    binop( Iop_CmpEQ32,
   10709                                           mkexpr( gfield_A ),
   10710                                           mkU32( 0x7E000000 ) )
   10711                                    ) ) );
   10712    assign( B_NaN_true, binop(Iop_Or32,
   10713                              unop( Iop_1Sto32,
   10714                                    binop( Iop_CmpEQ32,
   10715                                           mkexpr( gfield_B ),
   10716                                           mkU32( 0x7C000000 ) ) ),
   10717                              unop( Iop_1Sto32,
   10718                                    binop( Iop_CmpEQ32,
   10719                                           mkexpr( gfield_B ),
   10720                                           mkU32( 0x7E000000 ) )
   10721                              ) ) );
   10722 
   10723    /* check for infinity */
   10724    assign( A_inf_true,
   10725            unop( Iop_1Sto32,
   10726                  binop( Iop_CmpEQ32,
   10727                         mkexpr( gfield_A ),
   10728                         mkU32( 0x78000000 ) ) ) );
   10729 
   10730    assign( B_inf_true,
   10731            unop( Iop_1Sto32,
   10732                  binop( Iop_CmpEQ32,
   10733                         mkexpr( gfield_B ),
   10734                         mkU32( 0x78000000 ) ) ) );
   10735 
   10736    assign( finite_number,
   10737            unop( Iop_Not32,
   10738                  binop( Iop_Or32,
   10739                         binop( Iop_Or32,
   10740                                mkexpr( A_NaN_true ),
   10741                                mkexpr( B_NaN_true ) ),
   10742                         binop( Iop_Or32,
   10743                                mkexpr( A_inf_true ),
   10744                                mkexpr( B_inf_true ) ) ) ) );
   10745 
   10746    /* Calculate the condition code bits
   10747     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
   10748     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
   10749     * cc0, cc1 and cc0 reflect the results of the comparisons.
   10750     */
   10751    assign( A_equals_B,
   10752            binop( Iop_Or32,
   10753                   unop( Iop_1Uto32,
   10754                   binop( Iop_CmpEQ32,
   10755                          mkexpr( exponent_A ),
   10756                          mkexpr( exponent_B ) ) ),
   10757                   binop( Iop_Or32,
   10758                          binop( Iop_And32,
   10759                                 mkexpr( A_inf_true ),
   10760                                 mkexpr( B_inf_true ) ),
   10761                          binop( Iop_And32,
   10762                                 mkexpr( A_NaN_true ),
   10763                                 mkexpr( B_NaN_true ) ) ) ) );
   10764 
   10765    assign( cc0, binop( Iop_And32,
   10766                        mkexpr( finite_number ),
   10767                        binop( Iop_Shl32,
   10768                               unop( Iop_1Uto32,
   10769                                     binop( Iop_CmpLT32U,
   10770                                            mkexpr( exponent_A ),
   10771                                            mkexpr( exponent_B ) ) ),
   10772                                            mkU8( 3 ) ) ) );
   10773 
   10774    assign( cc1, binop( Iop_And32,
   10775                        mkexpr( finite_number ),
   10776                        binop( Iop_Shl32,
   10777                               unop( Iop_1Uto32,
   10778                                     binop( Iop_CmpLT32U,
   10779                                            mkexpr( exponent_B ),
   10780                                            mkexpr( exponent_A ) ) ),
   10781                                            mkU8( 2 ) ) ) );
   10782 
   10783    assign( cc2, binop( Iop_Shl32,
   10784                        binop( Iop_And32,
   10785                               mkexpr( A_equals_B ),
   10786                               mkU32( 1 ) ),
   10787                               mkU8( 1 ) ) );
   10788 
   10789    assign( cc3, binop( Iop_And32,
   10790                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
   10791                        binop( Iop_And32,
   10792                               mkU32( 0x1 ),
   10793                               binop( Iop_Or32,
   10794                                      binop( Iop_Or32,
   10795                                             mkexpr ( A_inf_true ),
   10796                                             mkexpr ( B_inf_true ) ),
   10797                                             binop( Iop_Or32,
   10798                                                    mkexpr ( A_NaN_true ),
   10799                                                    mkexpr ( B_NaN_true ) ) )
   10800                               ) ) );
   10801 
   10802    /* store the condition code */
   10803    putGST_field( PPC_GST_CR,
   10804                  binop( Iop_Or32,
   10805                         mkexpr( cc0 ),
   10806                         binop( Iop_Or32,
   10807                                mkexpr( cc1 ),
   10808                                binop( Iop_Or32,
   10809                                       mkexpr( cc2 ),
   10810                                       mkexpr( cc3 ) ) ) ),
   10811                  crfD );
   10812    return True;
   10813 }
   10814 
   10815 /* Test class/group/exponent/significance instructions. */
   10816 static Bool dis_dfp_class_test ( UInt theInstr )
   10817 {
   10818    UChar frA_addr   = ifieldRegA( theInstr );
   10819    IRTemp frA       = newTemp( Ity_D64 );
   10820    IRTemp abs_frA   = newTemp( Ity_D64 );
   10821    IRTemp frAI64_hi = newTemp( Ity_I64 );
   10822    IRTemp frAI64_lo = newTemp( Ity_I64 );
   10823    UInt opc1        = ifieldOPC( theInstr );
   10824    UInt opc2        = ifieldOPClo9( theInstr );
   10825    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
   10826    UInt DCM         = IFIELD( theInstr, 10, 6 );
   10827    IRTemp DCM_calc  = newTemp( Ity_I32 );
   10828    UInt max_exp     = 0;
   10829    UInt min_exp     = 0;
   10830    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
   10831    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
   10832    IRTemp significand64  = newTemp( Ity_D64 );
   10833    IRTemp significand128 = newTemp( Ity_D128 );
   10834    IRTemp exp_min_normal = newTemp( Ity_I64 );
   10835    IRTemp exponent       = newTemp( Ity_I32 );
   10836 
   10837    IRTemp infinity_true  = newTemp( Ity_I32 );
   10838    IRTemp SNaN_true      = newTemp( Ity_I32 );
   10839    IRTemp QNaN_true      = newTemp( Ity_I32 );
   10840    IRTemp subnormal_true = newTemp( Ity_I32 );
   10841    IRTemp normal_true    = newTemp( Ity_I32 );
   10842    IRTemp extreme_true   = newTemp( Ity_I32 );
   10843    IRTemp lmd            = newTemp( Ity_I32 );
   10844    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
   10845    IRTemp zero_true      = newTemp( Ity_I32 );
   10846    IRTemp sign           = newTemp( Ity_I32 );
   10847    IRTemp field          = newTemp( Ity_I32 );
   10848    IRTemp ccIR_zero      = newTemp( Ity_I32 );
   10849    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
   10850 
   10851    /* UInt size     = DFP_LONG;  JRS:unused */
   10852    IRTemp gfield = newTemp( Ity_I32 );
   10853    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
   10854    IRTemp gfield_mask       = newTemp( Ity_I32 );
   10855    IRTemp dcm0 = newTemp( Ity_I32 );
   10856    IRTemp dcm1 = newTemp( Ity_I32 );
   10857    IRTemp dcm2 = newTemp( Ity_I32 );
   10858    IRTemp dcm3 = newTemp( Ity_I32 );
   10859    IRTemp dcm4 = newTemp( Ity_I32 );
   10860    IRTemp dcm5 = newTemp( Ity_I32 );
   10861 
   10862    /* The only difference between the dtstdc and dtstdcq instructions is
   10863     * size of the T and G fields.  The calculation of the 4 bit field
   10864     * is the same.  Setup the parameters and values that are DFP size
   10865     * specific.  The rest of the code is independent of the DFP size.
   10866     *
   10867     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
   10868     * The interpretation of the ccIR values is as follows:
   10869     *
   10870     *    DFP cmp result | IR
   10871     * --------------------------
   10872     *	 UN             | 0x45
   10873     *	 EQ             | 0x40
   10874     *	 GT             | 0x00
   10875     *	 LT             | 0x01
   10876     */
   10877 
   10878    assign( frA, getDReg( frA_addr ) );
   10879    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
   10880 
   10881    assign( abs_frA, unop( Iop_ReinterpI64asD64,
   10882                           binop( Iop_And64,
   10883                                  unop( Iop_ReinterpD64asI64,
   10884                                        mkexpr( frA ) ),
   10885                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
   10886    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
   10887    switch (opc1) {
   10888    case 0x3b: // dtstdc, dtstdg
   10889       DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   10890                crfD, frA_addr, DCM);
   10891       /* setup the parameters for the long format of the two instructions */
   10892       assign( frAI64_lo, mkU64( 0 ) );
   10893       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   10894       max_exp = DFP_LONG_EXP_MAX;
   10895       min_exp = DFP_LONG_EXP_MIN;
   10896 
   10897       assign( exponent, unop( Iop_64to32,
   10898                               unop( Iop_ExtractExpD64,
   10899                                     mkexpr( frA ) ) ) );
   10900       assign( significand64,
   10901               unop( Iop_ReinterpI64asD64,
   10902                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
   10903       assign( exp_min_normal,mkU64( 398 - 383 ) );
   10904       assign( min_subnormalD64,
   10905               binop( Iop_InsertExpD64,
   10906                      mkexpr( exp_min_normal ),
   10907                      mkexpr( significand64 ) ) );
   10908 
   10909       assign( ccIR_subnormal,
   10910               binop( Iop_CmpD64,
   10911                      mkexpr( abs_frA ),
   10912                      mkexpr( min_subnormalD64 ) ) );
   10913 
   10914       /* compare absolute value of frA with zero */
   10915       assign( ccIR_zero,
   10916               binop( Iop_CmpD64,
   10917                      mkexpr( abs_frA ),
   10918                      unop( Iop_ReinterpI64asD64,
   10919                            mkU64( 0x2238000000000000ULL ) ) ) );
   10920 
   10921       /* size = DFP_LONG; JRS: unused */
   10922       break;
   10923 
   10924    case 0x3F:   // dtstdcq, dtstdgq
   10925       DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   10926                crfD, frA_addr, DCM);
   10927       /* setup the parameters for the extended format of the
   10928        * two instructions
   10929        */
   10930       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
   10931                                getDReg( frA_addr+1 ) ) );
   10932 
   10933       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   10934       max_exp = DFP_EXTND_EXP_MAX;
   10935       min_exp = DFP_EXTND_EXP_MIN;
   10936       assign( exponent, unop( Iop_64to32,
   10937                               unop( Iop_ExtractExpD128,
   10938                                     getDReg_pair( frA_addr) ) ) );
   10939 
   10940       /* create quand exponent for minimum normal number */
   10941       assign( exp_min_normal, mkU64( 6176 - 6143 ) );
   10942       assign( significand128,
   10943               unop( Iop_D64toD128,
   10944                     unop( Iop_ReinterpI64asD64,
   10945                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
   10946 
   10947       assign( min_subnormalD128,
   10948               binop( Iop_InsertExpD128,
   10949                      mkexpr( exp_min_normal ),
   10950                      mkexpr( significand128 ) ) );
   10951 
   10952       assign( ccIR_subnormal,
   10953               binop( Iop_CmpD128,
   10954                      binop( Iop_D64HLtoD128,
   10955                             unop( Iop_ReinterpI64asD64,
   10956                                   binop( Iop_And64,
   10957                                          unop( Iop_ReinterpD64asI64,
   10958                                                mkexpr( frA ) ),
   10959                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
   10960                             getDReg( frA_addr+1 ) ),
   10961                      mkexpr( min_subnormalD128 ) ) );
   10962       assign( ccIR_zero,
   10963               binop( Iop_CmpD128,
   10964                      binop( Iop_D64HLtoD128,
   10965                             mkexpr( abs_frA ),
   10966                             getDReg( frA_addr+1 ) ),
   10967                      unop( Iop_D64toD128,
   10968                            unop( Iop_ReinterpI64asD64,
   10969                                  mkU64( 0x0ULL ) ) ) ) );
   10970 
   10971       /* size = DFP_EXTND; JRS:unused */
   10972       break;
   10973    default:
   10974       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
   10975       return False;
   10976    }
   10977 
   10978    /* The G-field is in the upper 32-bits.  The I64 logical operations
   10979     * do not seem to be supported in 32-bit mode so keep things as 32-bit
   10980     * operations.
   10981     */
   10982    assign( gfield, binop( Iop_And32,
   10983                           mkexpr( gfield_mask ),
   10984                           unop( Iop_64HIto32,
   10985                                 mkexpr(frAI64_hi) ) ) );
   10986 
   10987    /* There is a lot of code that is the same to do the class and group
   10988     * instructions.  Later there is an if statement to handle the specific
   10989     * instruction.
   10990     *
   10991     * Will be using I32 values, compares, shifts and logical operations for
   10992     * this code as the 64-bit compare, shifts, logical operations are not
   10993     * supported in 32-bit mode.
   10994     */
   10995 
   10996    /* Check the bits for Infinity, QNaN or Signaling NaN */
   10997    assign( infinity_true,
   10998            unop( Iop_1Sto32,
   10999                  binop( Iop_CmpEQ32,
   11000                         binop( Iop_And32,
   11001                                mkU32( 0x7C000000 ),
   11002                                mkexpr( gfield ) ),
   11003                         mkU32( 0x78000000 ) ) ) );
   11004 
   11005    assign( SNaN_true,
   11006            unop( Iop_1Sto32,
   11007                  binop( Iop_CmpEQ32,
   11008                         binop( Iop_And32,
   11009                                mkU32( 0x7E000000 ),
   11010                                mkexpr( gfield ) ),
   11011                         mkU32( 0x7E000000 ) ) ) );
   11012 
   11013    assign( QNaN_true,
   11014            binop( Iop_And32,
   11015                   unop( Iop_1Sto32,
   11016                        binop( Iop_CmpEQ32,
   11017                               binop( Iop_And32,
   11018                                      mkU32( 0x7E000000 ),
   11019                                      mkexpr( gfield ) ),
   11020                               mkU32( 0x7C000000 ) ) ),
   11021                   unop( Iop_Not32,
   11022                         mkexpr( SNaN_true ) ) ) );
   11023 
   11024    assign( zero_true,
   11025            binop( Iop_And32,
   11026                   unop(Iop_1Sto32,
   11027                        binop( Iop_CmpEQ32,
   11028                               mkexpr( ccIR_zero ),
   11029                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
   11030                   unop( Iop_Not32,
   11031                         binop( Iop_Or32,
   11032                                mkexpr( infinity_true ),
   11033                                binop( Iop_Or32,
   11034                                       mkexpr( QNaN_true ),
   11035                                       mkexpr( SNaN_true ) ) ) ) ) );
   11036 
   11037    /* Do compare of frA the minimum normal value.  Comparison is size
   11038     * depenent and was done above to get the ccIR value.
   11039     */
   11040    assign( subnormal_true,
   11041            binop( Iop_And32,
   11042                   binop( Iop_Or32,
   11043                          unop( Iop_1Sto32,
   11044                                binop( Iop_CmpEQ32,
   11045                                       mkexpr( ccIR_subnormal ),
   11046                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
   11047                          unop( Iop_1Sto32,
   11048                                binop( Iop_CmpEQ32,
   11049                                       mkexpr( ccIR_subnormal ),
   11050                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
   11051            unop( Iop_Not32,
   11052                  binop( Iop_Or32,
   11053                         binop( Iop_Or32,
   11054                                mkexpr( infinity_true ),
   11055                                mkexpr( zero_true) ),
   11056                         binop( Iop_Or32,
   11057                                mkexpr( QNaN_true ),
   11058                                mkexpr( SNaN_true ) ) ) ) ) );
   11059 
   11060    /* Normal number is not subnormal, infinity, NaN or Zero */
   11061    assign( normal_true,
   11062            unop( Iop_Not32,
   11063                  binop( Iop_Or32,
   11064                         binop( Iop_Or32,
   11065                                mkexpr( infinity_true ),
   11066                                mkexpr( zero_true ) ),
   11067                         binop( Iop_Or32,
   11068                                mkexpr( subnormal_true ),
   11069                                binop( Iop_Or32,
   11070                                       mkexpr( QNaN_true ),
   11071                                       mkexpr( SNaN_true ) ) ) ) ) );
   11072 
   11073    /* Calculate the DCM bit field based on the tests for the specific
   11074     * instruction
   11075     */
   11076    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
   11077       /* DCM[0:5] Bit   Data Class definition
   11078        *   0   Zero
   11079        *   1   Subnormal
   11080        *   2   Normal
   11081        *   3   Infinity
   11082        *   4   Quiet NaN
   11083        *   5   Signaling NaN
   11084        */
   11085 
   11086       assign( dcm0, binop( Iop_Shl32,
   11087                            mkexpr( zero_true ),
   11088                            mkU8( 5 ) ) );
   11089       assign( dcm1, binop( Iop_Shl32,
   11090                            binop( Iop_And32,
   11091                                   mkexpr( subnormal_true ),
   11092                                   mkU32( 1 ) ),
   11093                            mkU8( 4 ) ) );
   11094       assign( dcm2, binop( Iop_Shl32,
   11095                            binop( Iop_And32,
   11096                                   mkexpr( normal_true ),
   11097                                   mkU32( 1 ) ),
   11098                            mkU8( 3 ) ) );
   11099       assign( dcm3, binop( Iop_Shl32,
   11100                            binop( Iop_And32,
   11101                                   mkexpr( infinity_true),
   11102                                   mkU32( 1 ) ),
   11103                            mkU8( 2 ) ) );
   11104       assign( dcm4, binop( Iop_Shl32,
   11105                            binop( Iop_And32,
   11106                                   mkexpr( QNaN_true ),
   11107                                   mkU32( 1 ) ),
   11108                            mkU8( 1 ) ) );
   11109       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
   11110 
   11111    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
   11112       /* check if the exponent is extreme */
   11113       assign( extreme_true, binop( Iop_Or32,
   11114                                    unop( Iop_1Sto32,
   11115                                          binop( Iop_CmpEQ32,
   11116                                                 mkexpr( exponent ),
   11117                                                 mkU32( max_exp ) ) ),
   11118                                    unop( Iop_1Sto32,
   11119                                          binop( Iop_CmpEQ32,
   11120                                                 mkexpr( exponent ),
   11121                                                 mkU32( min_exp ) ) ) ) );
   11122 
   11123       /* Check if LMD is zero */
   11124       Get_lmd( &lmd, binop( Iop_Shr32,
   11125                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
   11126 
   11127       assign( lmd_zero_true, unop( Iop_1Sto32,
   11128                                    binop( Iop_CmpEQ32,
   11129                                           mkexpr( lmd ),
   11130                                           mkU32( 0 ) ) ) );
   11131 
   11132       /* DCM[0:5] Bit   Data Class definition
   11133        *  0   Zero with non-extreme exponent
   11134        *  1   Zero with extreme exponent
   11135        *  2   Subnormal or (Normal with extreme exponent)
   11136        *  3   Normal with non-extreme exponent and
   11137        *      leftmost zero digit in significand
   11138        *  4   Normal with non-extreme exponent and
   11139        *      leftmost nonzero digit in significand
   11140        *  5   Special symbol (Infinity, QNaN, or SNaN)
   11141        */
   11142       assign( dcm0, binop( Iop_Shl32,
   11143                            binop( Iop_And32,
   11144                                   binop( Iop_And32,
   11145                                          unop( Iop_Not32,
   11146                                                mkexpr( extreme_true ) ),
   11147                                          mkexpr( zero_true ) ),
   11148                                   mkU32( 0x1 ) ),
   11149                            mkU8( 5 ) ) );
   11150 
   11151       assign( dcm1, binop( Iop_Shl32,
   11152                            binop( Iop_And32,
   11153                                   binop( Iop_And32,
   11154                                          mkexpr( extreme_true ),
   11155                                          mkexpr( zero_true ) ),
   11156                                   mkU32( 0x1 ) ),
   11157                            mkU8( 4 ) ) );
   11158 
   11159       assign( dcm2, binop( Iop_Shl32,
   11160                            binop( Iop_And32,
   11161                                   binop( Iop_Or32,
   11162                                          binop( Iop_And32,
   11163                                                 mkexpr( extreme_true ),
   11164                                                 mkexpr( normal_true ) ),
   11165                                          mkexpr( subnormal_true ) ),
   11166                                   mkU32( 0x1 ) ),
   11167                            mkU8( 3 ) ) );
   11168 
   11169       assign( dcm3, binop( Iop_Shl32,
   11170                            binop( Iop_And32,
   11171                                   binop( Iop_And32,
   11172                                          binop( Iop_And32,
   11173                                                 unop( Iop_Not32,
   11174                                                       mkexpr( extreme_true ) ),
   11175                                                       mkexpr( normal_true ) ),
   11176                                          unop( Iop_1Sto32,
   11177                                                binop( Iop_CmpEQ32,
   11178                                                       mkexpr( lmd ),
   11179                                                       mkU32( 0 ) ) ) ),
   11180                                   mkU32( 0x1 ) ),
   11181                            mkU8( 2 ) ) );
   11182 
   11183       assign( dcm4, binop( Iop_Shl32,
   11184                            binop( Iop_And32,
   11185                                   binop( Iop_And32,
   11186                                          binop( Iop_And32,
   11187                                                 unop( Iop_Not32,
   11188                                                       mkexpr( extreme_true ) ),
   11189                                                 mkexpr( normal_true ) ),
   11190                                           unop( Iop_1Sto32,
   11191                                                 binop( Iop_CmpNE32,
   11192                                                        mkexpr( lmd ),
   11193                                                        mkU32( 0 ) ) ) ),
   11194                                   mkU32( 0x1 ) ),
   11195                            mkU8( 1 ) ) );
   11196 
   11197       assign( dcm5, binop( Iop_And32,
   11198                            binop( Iop_Or32,
   11199                                   mkexpr( SNaN_true),
   11200                                   binop( Iop_Or32,
   11201                                          mkexpr( QNaN_true),
   11202                                          mkexpr( infinity_true) ) ),
   11203                            mkU32( 0x1 ) ) );
   11204    }
   11205 
   11206    /* create DCM field */
   11207    assign( DCM_calc,
   11208            binop( Iop_Or32,
   11209                   mkexpr( dcm0 ),
   11210                   binop( Iop_Or32,
   11211                          mkexpr( dcm1 ),
   11212                          binop( Iop_Or32,
   11213                                 mkexpr( dcm2 ),
   11214                                 binop( Iop_Or32,
   11215                                        mkexpr( dcm3 ),
   11216                                        binop( Iop_Or32,
   11217                                               mkexpr( dcm4 ),
   11218                                               mkexpr( dcm5 ) ) ) ) ) ) );
   11219 
   11220    /* Get the sign of the DFP number, ignore sign for QNaN */
   11221    assign( sign,
   11222            unop( Iop_1Uto32,
   11223                  binop( Iop_CmpEQ32,
   11224                         binop( Iop_Shr32,
   11225                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
   11226                                mkU8( 63 - 32 ) ),
   11227                         mkU32( 1 ) ) ) );
   11228 
   11229    /* This instruction generates a four bit field to be stored in the
   11230     * condition code register.  The condition code register consists of 7
   11231     * fields.  The field to be written to is specified by the BF (AKA crfD)
   11232     * field.
   11233     *
   11234     * The field layout is as follows:
   11235     *
   11236     *      Field          Meaning
   11237     *      0000           Operand positive with no match
   11238     *      0100           Operand positive with at least one match
   11239     *      0001           Operand negative with no match
   11240     *      0101           Operand negative with at least one match
   11241     */
   11242    assign( field, binop( Iop_Or32,
   11243                          binop( Iop_Shl32,
   11244                                 mkexpr( sign ),
   11245                                 mkU8( 3 ) ),
   11246                                 binop( Iop_Shl32,
   11247                                        unop( Iop_1Uto32,
   11248                                              binop( Iop_CmpNE32,
   11249                                                     binop( Iop_And32,
   11250                                                            mkU32( DCM ),
   11251                                                            mkexpr( DCM_calc ) ),
   11252                                                      mkU32( 0 ) ) ),
   11253                                        mkU8( 1 ) ) ) );
   11254 
   11255    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
   11256    return True;
   11257 }
   11258 
   11259 static Bool dis_dfp_bcd(UInt theInstr) {
   11260    UInt opc2        = ifieldOPClo10( theInstr );
   11261    ULong sp         = IFIELD(theInstr, 19, 2);
   11262    ULong s          = IFIELD(theInstr, 20, 1);
   11263    UChar frT_addr   = ifieldRegDS( theInstr );
   11264    UChar frB_addr   = ifieldRegB( theInstr );
   11265    IRTemp frB       = newTemp( Ity_D64 );
   11266    IRTemp frBI64    = newTemp( Ity_I64 );
   11267    IRTemp result    = newTemp( Ity_I64 );
   11268    IRTemp resultD64 = newTemp( Ity_D64 );
   11269    IRTemp bcd64     = newTemp( Ity_I64 );
   11270    IRTemp bcd_u     = newTemp( Ity_I32 );
   11271    IRTemp bcd_l     = newTemp( Ity_I32 );
   11272    IRTemp dbcd_u    = newTemp( Ity_I32 );
   11273    IRTemp dbcd_l    = newTemp( Ity_I32 );
   11274    IRTemp lmd       = newTemp( Ity_I32 );
   11275 
   11276    assign( frB, getDReg( frB_addr ) );
   11277    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   11278 
   11279    switch ( opc2 ) {
   11280    case 0x142: // ddedpd   DFP Decode DPD to BCD
   11281       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11282 
   11283          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   11284          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
   11285          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
   11286 
   11287       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11288          /* Unsigned BCD string */
   11289          Get_lmd( &lmd,
   11290                   binop( Iop_Shr32,
   11291                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11292                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11293 
   11294          assign( result,
   11295                  binop( Iop_32HLto64,
   11296                         binop( Iop_Or32,
   11297                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
   11298                                mkexpr( bcd_u ) ),
   11299                         mkexpr( bcd_l ) ) );
   11300 
   11301       } else {
   11302          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   11303           * the positive and negative values are encoded in the least
   11304           * significant bits.
   11305           */
   11306          IRTemp sign = newTemp( Ity_I32 );
   11307 
   11308          if (sp == 2) {
   11309             /* Positive sign = 0xC, negative sign = 0xD */
   11310 
   11311             assign( sign,
   11312                     binop( Iop_Or32,
   11313                            binop( Iop_Shr32,
   11314                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11315                                   mkU8( 31 ) ),
   11316                            mkU32( 0xC ) ) );
   11317 
   11318          } else if ( sp == 3 ) {
   11319             /* Positive sign = 0xF, negative sign = 0xD */
   11320             IRTemp tmp32 = newTemp( Ity_I32 );
   11321 
   11322             /* Complement sign bit then OR into bit position 1 */
   11323             assign( tmp32,
   11324                     binop( Iop_Xor32,
   11325                            binop( Iop_Shr32,
   11326                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11327                                   mkU8( 30 ) ),
   11328                            mkU32( 0x2 ) ) );
   11329 
   11330             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11331 
   11332          } else {
   11333             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11334          }
   11335 
   11336          /* Put sign in bottom 4 bits, move most significant 4-bits from
   11337           * bcd_l to bcd_u.
   11338           */
   11339          assign( result,
   11340                  binop( Iop_32HLto64,
   11341                         binop( Iop_Or32,
   11342                                binop( Iop_Shr32,
   11343                                       mkexpr( bcd_l ),
   11344                                       mkU8( 28 ) ),
   11345                                binop( Iop_Shl32,
   11346                                       mkexpr( bcd_u ),
   11347                                       mkU8( 4 ) ) ),
   11348                         binop( Iop_Or32,
   11349                                       mkexpr( sign ),
   11350                                binop( Iop_Shl32,
   11351                                       mkexpr( bcd_l ),
   11352                                       mkU8( 4 ) ) ) ) );
   11353       }
   11354 
   11355       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
   11356       break;
   11357 
   11358    case 0x342: // denbcd   DFP Encode BCD to DPD
   11359    {
   11360       IRTemp valid_mask   = newTemp( Ity_I32 );
   11361       IRTemp invalid_mask = newTemp( Ity_I32 );
   11362       IRTemp without_lmd  = newTemp( Ity_I64 );
   11363       IRTemp tmp64        = newTemp( Ity_I64 );
   11364       IRTemp dbcd64       = newTemp( Ity_I64 );
   11365       IRTemp left_exp     = newTemp( Ity_I32 );
   11366       IRTemp g0_4         = newTemp( Ity_I32 );
   11367 
   11368       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11369 
   11370       if ( s == 0 ) {
   11371          /* Unsigned BCD string */
   11372          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
   11373          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
   11374          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
   11375 
   11376          assign( lmd,
   11377                  binop( Iop_Shr32,
   11378                         binop( Iop_And32,
   11379                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11380                                mkU32( 0xF0000000 ) ),
   11381                         mkU8( 28 ) ) );
   11382 
   11383          assign( invalid_mask,
   11384                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11385                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
   11386          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11387 
   11388          assign( without_lmd,
   11389                  unop( Iop_ReinterpD64asI64,
   11390                        binop( Iop_InsertExpD64,
   11391                               mkU64( DFP_LONG_BIAS ),
   11392                               unop( Iop_ReinterpI64asD64,
   11393                                     binop( Iop_32HLto64,
   11394                                            mkexpr( dbcd_u ),
   11395                                            mkexpr( dbcd_l ) ) ) ) ) );
   11396          assign( left_exp,
   11397                  binop( Iop_Shr32,
   11398                         binop( Iop_And32,
   11399                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
   11400                                mkU32( 0x60000000 ) ),
   11401                         mkU8( 29 ) ) );
   11402 
   11403          assign( g0_4,
   11404                  binop( Iop_Shl32,
   11405                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
   11406                         mkU8( 26 ) ) );
   11407 
   11408          assign( tmp64,
   11409                  binop( Iop_32HLto64,
   11410                         binop( Iop_Or32,
   11411                                binop( Iop_And32,
   11412                                       unop( Iop_64HIto32,
   11413                                             mkexpr( without_lmd ) ),
   11414                                       mkU32( 0x83FFFFFF ) ),
   11415                                mkexpr( g0_4 ) ),
   11416                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
   11417 
   11418       } else if ( s == 1 ) {
   11419          IRTemp sign = newTemp( Ity_I32 );
   11420          IRTemp sign_bit = newTemp( Ity_I32 );
   11421          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   11422          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   11423          IRTemp tmp = newTemp( Ity_I64 );
   11424 
   11425          /* Signed BCD string, least significant 4 bits are sign bits
   11426           * positive sign = 0xC, negative sign = 0xD
   11427           */
   11428          assign( tmp, unop( Iop_BCDtoDPB,
   11429                             binop( Iop_32HLto64,
   11430                                    binop( Iop_Shr32,
   11431                                           unop( Iop_64HIto32,
   11432                                                 mkexpr( frBI64 ) ),
   11433                                                 mkU8( 4 ) ),
   11434                                    binop( Iop_Or32,
   11435                                           binop( Iop_Shr32,
   11436                                                  unop( Iop_64to32,
   11437                                                        mkexpr( frBI64 ) ),
   11438                                                   mkU8( 4 ) ),
   11439                                           binop( Iop_Shl32,
   11440                                                  unop( Iop_64HIto32,
   11441                                                        mkexpr( frBI64 ) ),
   11442                                                        mkU8( 28 ) ) ) ) ) );
   11443 
   11444          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
   11445          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
   11446 
   11447          /* Get the sign of the BCD string. */
   11448          assign( sign,
   11449                  binop( Iop_And32,
   11450                         unop( Iop_64to32, mkexpr( frBI64 ) ),
   11451                         mkU32( 0xF ) ) );
   11452 
   11453          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   11454          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   11455          assign( sign_bit,
   11456                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   11457                                     mkexpr( neg_sign_mask ) ) );
   11458 
   11459          /* Check for invalid sign and BCD digit.  Don't check the bottom
   11460           * four bits of bcd_l as that is the sign value.
   11461           */
   11462          assign( invalid_mask,
   11463                  Generate_inv_mask(
   11464                                    bcd_digit_inval( unop( Iop_64HIto32,
   11465                                                           mkexpr( frBI64 ) ),
   11466                                                     binop( Iop_Shr32,
   11467                                                            unop( Iop_64to32,
   11468                                                                  mkexpr( frBI64 ) ),
   11469                                                            mkU8( 4 ) ) ),
   11470                                    mkexpr( pos_sign_mask ),
   11471                                    mkexpr( neg_sign_mask ) ) );
   11472 
   11473          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11474 
   11475          /* Generate the result assuming the sign value was valid. */
   11476          assign( tmp64,
   11477                  unop( Iop_ReinterpD64asI64,
   11478                        binop( Iop_InsertExpD64,
   11479                               mkU64( DFP_LONG_BIAS ),
   11480                               unop( Iop_ReinterpI64asD64,
   11481                                     binop( Iop_32HLto64,
   11482                                            binop( Iop_Or32,
   11483                                                   mkexpr( dbcd_u ),
   11484                                                   mkexpr( sign_bit ) ),
   11485                                            mkexpr( dbcd_l ) ) ) ) ) );
   11486       }
   11487 
   11488       /* Generate the value to store depending on the validity of the
   11489        * sign value and the validity of the BCD digits.
   11490        */
   11491       assign( resultD64,
   11492               unop( Iop_ReinterpI64asD64,
   11493                     binop( Iop_32HLto64,
   11494                            binop( Iop_Or32,
   11495                                   binop( Iop_And32,
   11496                                          mkexpr( valid_mask ),
   11497                                          unop( Iop_64HIto32,
   11498                                                mkexpr( tmp64 ) ) ),
   11499                                   binop( Iop_And32,
   11500                                          mkU32( 0x7C000000 ),
   11501                                          mkexpr( invalid_mask ) ) ),
   11502                            binop( Iop_Or32,
   11503                                   binop( Iop_And32,
   11504                                          mkexpr( valid_mask ),
   11505                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
   11506                                   binop( Iop_And32,
   11507                                          mkU32( 0x0 ),
   11508                                          mkexpr( invalid_mask ) ) ) ) ) );
   11509       putDReg( frT_addr, mkexpr( resultD64 ) );
   11510    }
   11511    break;
   11512    default:
   11513       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
   11514       return False;
   11515    }
   11516    return True;
   11517 }
   11518 
   11519 static Bool dis_dfp_bcdq( UInt theInstr )
   11520 {
   11521    UInt opc2        = ifieldOPClo10( theInstr );
   11522    ULong sp         = IFIELD(theInstr, 19, 2);
   11523    ULong s          = IFIELD(theInstr, 20, 1);
   11524    IRTemp frB_hi    = newTemp( Ity_D64 );
   11525    IRTemp frB_lo    = newTemp( Ity_D64 );
   11526    IRTemp frBI64_hi = newTemp( Ity_I64 );
   11527    IRTemp frBI64_lo = newTemp( Ity_I64 );
   11528    UChar frT_addr   = ifieldRegDS( theInstr );
   11529    UChar frB_addr   = ifieldRegB( theInstr );
   11530 
   11531    IRTemp lmd       = newTemp( Ity_I32 );
   11532    IRTemp result_hi = newTemp( Ity_I64 );
   11533    IRTemp result_lo = newTemp( Ity_I64 );
   11534 
   11535    assign( frB_hi, getDReg( frB_addr ) );
   11536    assign( frB_lo, getDReg( frB_addr + 1 ) );
   11537    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   11538    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   11539 
   11540    switch ( opc2 ) {
   11541    case 0x142: // ddedpdq   DFP Decode DPD to BCD
   11542    {
   11543       IRTemp low_60_u = newTemp( Ity_I32 );
   11544       IRTemp low_60_l = newTemp( Ity_I32 );
   11545       IRTemp mid_60_u = newTemp( Ity_I32 );
   11546       IRTemp mid_60_l = newTemp( Ity_I32 );
   11547       IRTemp top_12_l = newTemp( Ity_I32 );
   11548 
   11549       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11550 
   11551       /* Note, instruction only stores the lower 32 BCD digits in
   11552        * the result
   11553        */
   11554       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   11555                                    mkexpr( frBI64_lo ),
   11556                                    &top_12_l,
   11557                                    &mid_60_u,
   11558                                    &mid_60_l,
   11559                                    &low_60_u,
   11560                                    &low_60_l );
   11561 
   11562       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11563          /* Unsigned BCD string */
   11564          assign( result_hi,
   11565                  binop( Iop_32HLto64,
   11566                         binop( Iop_Or32,
   11567                                binop( Iop_Shl32,
   11568                                       mkexpr( top_12_l ),
   11569                                       mkU8( 24 ) ),
   11570                                binop( Iop_Shr32,
   11571                                       mkexpr( mid_60_u ),
   11572                                       mkU8( 4 ) ) ),
   11573                         binop( Iop_Or32,
   11574                                binop( Iop_Shl32,
   11575                                       mkexpr( mid_60_u ),
   11576                                       mkU8( 28 ) ),
   11577                                binop( Iop_Shr32,
   11578                                       mkexpr( mid_60_l ),
   11579                                       mkU8( 4 ) ) ) ) );
   11580 
   11581          assign( result_lo,
   11582                  binop( Iop_32HLto64,
   11583                         binop( Iop_Or32,
   11584                                binop( Iop_Shl32,
   11585                                       mkexpr( mid_60_l ),
   11586                                       mkU8( 28 ) ),
   11587                                mkexpr( low_60_u ) ),
   11588                         mkexpr( low_60_l ) ) );
   11589 
   11590       } else {
   11591          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   11592           * the positive and negative values are encoded in the least
   11593           * significant bits.
   11594           */
   11595          IRTemp sign = newTemp( Ity_I32 );
   11596 
   11597          if ( sp == 2 ) {
   11598             /* Positive sign = 0xC, negative sign = 0xD */
   11599             assign( sign,
   11600                     binop( Iop_Or32,
   11601                            binop( Iop_Shr32,
   11602                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11603                                   mkU8( 31 ) ),
   11604                            mkU32( 0xC ) ) );
   11605 
   11606          } else if ( sp == 3 ) {
   11607             IRTemp tmp32 = newTemp( Ity_I32 );
   11608 
   11609             /* Positive sign = 0xF, negative sign = 0xD.
   11610              * Need to complement sign bit then OR into bit position 1.
   11611              */
   11612             assign( tmp32,
   11613                     binop( Iop_Xor32,
   11614                            binop( Iop_Shr32,
   11615                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11616                                   mkU8( 30 ) ),
   11617                            mkU32( 0x2 ) ) );
   11618 
   11619             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11620 
   11621          } else {
   11622             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11623          }
   11624 
   11625          assign( result_hi,
   11626                  binop( Iop_32HLto64,
   11627                         binop( Iop_Or32,
   11628                                binop( Iop_Shl32,
   11629                                       mkexpr( top_12_l ),
   11630                                       mkU8( 28 ) ),
   11631                                mkexpr( mid_60_u ) ),
   11632                         mkexpr( mid_60_l ) ) );
   11633 
   11634          assign( result_lo,
   11635                  binop( Iop_32HLto64,
   11636                         binop( Iop_Or32,
   11637                                binop( Iop_Shl32,
   11638                                       mkexpr( low_60_u ),
   11639                                       mkU8( 4 ) ),
   11640                                binop( Iop_Shr32,
   11641                                       mkexpr( low_60_l ),
   11642                                       mkU8( 28 ) ) ),
   11643                         binop( Iop_Or32,
   11644                                binop( Iop_Shl32,
   11645                                       mkexpr( low_60_l ),
   11646                                       mkU8( 4 ) ),
   11647                                mkexpr( sign ) ) ) );
   11648       }
   11649 
   11650       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   11651       putDReg( frT_addr + 1,
   11652                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   11653    }
   11654    break;
   11655    case 0x342: // denbcdq   DFP Encode BCD to DPD
   11656    {
   11657       IRTemp valid_mask      = newTemp( Ity_I32 );
   11658       IRTemp invalid_mask    = newTemp( Ity_I32 );
   11659       IRTemp result128       = newTemp( Ity_D128 );
   11660       IRTemp dfp_significand = newTemp( Ity_D128 );
   11661       IRTemp tmp_hi          = newTemp( Ity_I64 );
   11662       IRTemp tmp_lo          = newTemp( Ity_I64 );
   11663       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
   11664       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
   11665       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
   11666       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
   11667       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
   11668       IRTemp bcd_top_8       = newTemp( Ity_I64 );
   11669       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
   11670       IRTemp bcd_low_60      = newTemp( Ity_I64 );
   11671       IRTemp sign_bit        = newTemp( Ity_I32 );
   11672       IRTemp tmptop10        = newTemp( Ity_I64 );
   11673       IRTemp tmpmid50        = newTemp( Ity_I64 );
   11674       IRTemp tmplow50        = newTemp( Ity_I64 );
   11675       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
   11676 
   11677       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11678 
   11679       if ( s == 0 ) {
   11680          /* Unsigned BCD string */
   11681          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
   11682 
   11683          assign( bcd_top_8,
   11684                  binop( Iop_32HLto64,
   11685                         mkU32( 0 ),
   11686                         binop( Iop_And32,
   11687                                binop( Iop_Shr32,
   11688                                       unop( Iop_64HIto32,
   11689                                             mkexpr( frBI64_hi ) ),
   11690                                       mkU8( 24 ) ),
   11691                                mkU32( 0xFF ) ) ) );
   11692          assign( bcd_mid_60,
   11693                  binop( Iop_32HLto64,
   11694                         binop( Iop_Or32,
   11695                                binop( Iop_Shr32,
   11696                                       unop( Iop_64to32,
   11697                                             mkexpr( frBI64_hi ) ),
   11698                                       mkU8( 28 ) ),
   11699                                binop( Iop_Shl32,
   11700                                       unop( Iop_64HIto32,
   11701                                             mkexpr( frBI64_hi ) ),
   11702                                       mkU8( 4 ) ) ),
   11703                         binop( Iop_Or32,
   11704                                binop( Iop_Shl32,
   11705                                       unop( Iop_64to32,
   11706                                             mkexpr( frBI64_hi ) ),
   11707                                       mkU8( 4 ) ),
   11708                                binop( Iop_Shr32,
   11709                                       unop( Iop_64HIto32,
   11710                                             mkexpr( frBI64_lo ) ),
   11711                                       mkU8( 28 ) ) ) ) );
   11712 
   11713          /* Note, the various helper functions ignores top 4-bits */
   11714          assign( bcd_low_60, mkexpr( frBI64_lo ) );
   11715 
   11716          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
   11717          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   11718 
   11719          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
   11720          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   11721          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   11722 
   11723          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   11724          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   11725          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   11726 
   11727          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
   11728           * value is not part of the final result. Only the right most
   11729           * BCD digits are stored.
   11730           */
   11731          assign( lmd, mkU32( 0 ) );
   11732 
   11733          assign( invalid_mask,
   11734                  binop( Iop_Or32,
   11735                         bcd_digit_inval( mkU32( 0 ),
   11736                                          unop( Iop_64to32,
   11737                                                mkexpr( bcd_top_8 ) ) ),
   11738                         binop( Iop_Or32,
   11739                                bcd_digit_inval( unop( Iop_64HIto32,
   11740                                                       mkexpr( bcd_mid_60 ) ),
   11741                                                 unop( Iop_64to32,
   11742                                                       mkexpr( bcd_mid_60 ) ) ),
   11743                                bcd_digit_inval( unop( Iop_64HIto32,
   11744                                                       mkexpr( bcd_low_60 ) ),
   11745                                                 unop( Iop_64to32,
   11746                                                       mkexpr( bcd_low_60 ) )
   11747                                                 ) ) ) );
   11748 
   11749       } else if ( s == 1 ) {
   11750          IRTemp sign          = newTemp( Ity_I32 );
   11751          IRTemp zero          = newTemp( Ity_I32 );
   11752          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   11753          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   11754 
   11755          /* The sign of the BCD string is stored in lower 4 bits */
   11756          assign( sign,
   11757                  binop( Iop_And32,
   11758                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
   11759                         mkU32( 0xF ) ) );
   11760          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   11761          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   11762          assign( sign_bit,
   11763                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   11764                                     mkexpr( neg_sign_mask ) ) );
   11765 
   11766          /* Generate the value assuminig the sign and BCD digits are vaild */
   11767          assign( bcd_top_8,
   11768                  binop( Iop_32HLto64,
   11769                         mkU32( 0x0 ),
   11770                         binop( Iop_Shr32,
   11771                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11772                                mkU8( 28 ) ) ) );
   11773 
   11774          /* The various helper routines ignore the upper 4-bits */
   11775          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
   11776 
   11777          /* Remove bottom four sign bits */
   11778          assign( bcd_low_60,
   11779                  binop( Iop_32HLto64,
   11780                         binop( Iop_Shr32,
   11781                                unop( Iop_64HIto32,
   11782                                      mkexpr( frBI64_lo ) ),
   11783                                mkU8( 4 ) ),
   11784                                binop( Iop_Or32,
   11785                                       binop( Iop_Shl32,
   11786                                              unop( Iop_64HIto32,
   11787                                                    mkexpr( frBI64_lo ) ),
   11788                                              mkU8( 28 ) ),
   11789                                       binop( Iop_Shr32,
   11790                                              unop( Iop_64to32,
   11791                                                    mkexpr( frBI64_lo ) ),
   11792                                              mkU8( 4 ) ) ) ) );
   11793          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
   11794          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   11795 
   11796          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
   11797          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   11798          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   11799 
   11800          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   11801          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   11802          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   11803 
   11804          /* The entire BCD string fits in lower 110-bits.  The LMD value
   11805           * is not stored in the final result for the DFP Long instruction.
   11806           */
   11807          assign( lmd, mkU32( 0 ) );
   11808 
   11809          /* Check for invalid sign and invalid BCD digit.  Don't check the
   11810           *  bottom four bits of frBI64_lo as that is the sign value.
   11811           */
   11812          assign( zero, mkU32( 0 ) );
   11813          assign( inval_bcd_digit_mask,
   11814                  binop( Iop_Or32,
   11815                         bcd_digit_inval( mkexpr( zero ),
   11816                                          unop( Iop_64to32,
   11817                                                mkexpr( bcd_top_8 ) ) ),
   11818                         binop( Iop_Or32,
   11819                                bcd_digit_inval( unop( Iop_64HIto32,
   11820                                                      mkexpr( bcd_mid_60 ) ),
   11821                                                unop( Iop_64to32,
   11822                                                      mkexpr( bcd_mid_60 ) ) ),
   11823                                bcd_digit_inval( unop( Iop_64HIto32,
   11824                                                      mkexpr( frBI64_lo ) ),
   11825                                                binop( Iop_Shr32,
   11826                                                       unop( Iop_64to32,
   11827                                                             mkexpr( frBI64_lo ) ),
   11828                                                         mkU8( 4 ) ) ) ) ) );
   11829          assign( invalid_mask,
   11830                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
   11831                                     mkexpr( pos_sign_mask ),
   11832                                     mkexpr( neg_sign_mask ) ) );
   11833 
   11834       }
   11835 
   11836       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11837 
   11838       /* Calculate the value of the result assuming sign and BCD digits
   11839        * are all valid.
   11840        */
   11841       assign( dfp_significand,
   11842               binop( Iop_D64HLtoD128,
   11843                      unop( Iop_ReinterpI64asD64,
   11844                            binop( Iop_32HLto64,
   11845                                   binop( Iop_Or32,
   11846                                          mkexpr( sign_bit ),
   11847                                          mkexpr( dbcd_top_l ) ),
   11848                                   binop( Iop_Or32,
   11849                                          binop( Iop_Shl32,
   11850                                                 mkexpr( dbcd_mid_u ),
   11851                                                 mkU8( 18 ) ),
   11852                                          binop( Iop_Shr32,
   11853                                                 mkexpr( dbcd_mid_l ),
   11854                                                 mkU8( 14 ) ) ) ) ),
   11855                      unop( Iop_ReinterpI64asD64,
   11856                            binop( Iop_32HLto64,
   11857                                   binop( Iop_Or32,
   11858                                          mkexpr( dbcd_low_u ),
   11859                                          binop( Iop_Shl32,
   11860                                                 mkexpr( dbcd_mid_l ),
   11861                                                 mkU8( 18 ) ) ),
   11862                                   mkexpr( dbcd_low_l ) ) ) ) );
   11863 
   11864       /* Break the result back down to 32-bit chunks and replace chunks.
   11865        * If there was an invalid BCD digit or invalid sign value, replace
   11866        * the calculated result with the invalid bit string.
   11867        */
   11868       assign( result128,
   11869               binop( Iop_InsertExpD128,
   11870                      mkU64( DFP_EXTND_BIAS ),
   11871                      mkexpr( dfp_significand ) ) );
   11872 
   11873       assign( tmp_hi,
   11874               unop( Iop_ReinterpD64asI64,
   11875                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
   11876 
   11877       assign( tmp_lo,
   11878               unop( Iop_ReinterpD64asI64,
   11879                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
   11880 
   11881       assign( result_hi,
   11882               binop( Iop_32HLto64,
   11883                      binop( Iop_Or32,
   11884                             binop( Iop_And32,
   11885                                    mkexpr( valid_mask ),
   11886                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
   11887                             binop( Iop_And32,
   11888                                    mkU32( 0x7C000000 ),
   11889                                    mkexpr( invalid_mask ) ) ),
   11890                      binop( Iop_Or32,
   11891                             binop( Iop_And32,
   11892                                    mkexpr( valid_mask ),
   11893                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
   11894                             binop( Iop_And32,
   11895                                    mkU32( 0x0 ),
   11896                                    mkexpr( invalid_mask ) ) ) ) );
   11897 
   11898       assign( result_lo,
   11899               binop( Iop_32HLto64,
   11900                      binop( Iop_Or32,
   11901                             binop( Iop_And32,
   11902                                    mkexpr( valid_mask ),
   11903                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
   11904                             binop( Iop_And32,
   11905                                    mkU32( 0x0 ),
   11906                                    mkexpr( invalid_mask ) ) ),
   11907                      binop( Iop_Or32,
   11908                             binop( Iop_And32,
   11909                                    mkexpr( valid_mask ),
   11910                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
   11911                             binop( Iop_And32,
   11912                                    mkU32( 0x0 ),
   11913                                    mkexpr( invalid_mask ) ) ) ) );
   11914 
   11915       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   11916       putDReg( frT_addr + 1,
   11917                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   11918 
   11919    }
   11920    break;
   11921    default:
   11922       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
   11923       break;
   11924    }
   11925    return True;
   11926 }
   11927 
   11928 static Bool dis_dfp_significant_digits( UInt theInstr )
   11929 {
   11930    UChar frA_addr = ifieldRegA( theInstr );
   11931    UChar frB_addr = ifieldRegB( theInstr );
   11932    IRTemp frA     = newTemp( Ity_D64 );
   11933    UInt opc1      = ifieldOPC( theInstr );
   11934    IRTemp B_sig   = newTemp( Ity_I8 );
   11935    IRTemp K       = newTemp( Ity_I8 );
   11936    IRTemp lmd_B   = newTemp( Ity_I32 );
   11937    IRTemp field   = newTemp( Ity_I32 );
   11938    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   11939    IRTemp Unordered_true     = newTemp( Ity_I32 );
   11940    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
   11941    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
   11942    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
   11943    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
   11944    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
   11945 
   11946    /* Get the reference singificance stored in frA */
   11947    assign( frA, getDReg( frA_addr ) );
   11948 
   11949    /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
   11950     * supported in 32-bit mode.
   11951     */
   11952    assign( K, unop( Iop_32to8,
   11953                     binop( Iop_And32,
   11954                            unop( Iop_64to32,
   11955                                  unop( Iop_ReinterpD64asI64,
   11956                                        mkexpr( frA ) ) ),
   11957                            mkU32( 0x3F ) ) ) );
   11958 
   11959    switch ( opc1 ) {
   11960    case 0x3b: // dtstsf   DFP Test Significance
   11961    {
   11962       IRTemp frB     = newTemp( Ity_D64 );
   11963       IRTemp frBI64  = newTemp( Ity_I64 );
   11964       IRTemp B_bcd_u = newTemp( Ity_I32 );
   11965       IRTemp B_bcd_l = newTemp( Ity_I32 );
   11966       IRTemp tmp64   = newTemp( Ity_I64 );
   11967 
   11968       DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   11969 
   11970       assign( frB, getDReg( frB_addr ) );
   11971       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   11972 
   11973       /* Get the BCD string for the value stored in a series of I32 values.
   11974        * Count the number of leading zeros.  Subtract the number of leading
   11975        * zeros from 16 (maximum number of significant digits in DFP
   11976        * Long).
   11977        */
   11978       Get_lmd( &lmd_B,
   11979                binop( Iop_Shr32,
   11980                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11981                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11982 
   11983       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   11984       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
   11985       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
   11986 
   11987       assign( B_sig,
   11988               binop( Iop_Sub8,
   11989                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
   11990                      Count_leading_zeros_60( mkexpr( lmd_B ),
   11991                                              mkexpr( B_bcd_u ),
   11992                                              mkexpr( B_bcd_l ) ) ) );
   11993       assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
   11994    }
   11995    break;
   11996    case 0x3F: // dtstsfq     DFP Test Significance
   11997    {
   11998       IRTemp frB_hi     = newTemp( Ity_D64 );
   11999       IRTemp frB_lo     = newTemp( Ity_D64 );
   12000       IRTemp frBI64_hi  = newTemp( Ity_I64 );
   12001       IRTemp frBI64_lo  = newTemp( Ity_I64 );
   12002       IRTemp B_low_60_u = newTemp( Ity_I32 );
   12003       IRTemp B_low_60_l = newTemp( Ity_I32 );
   12004       IRTemp B_mid_60_u = newTemp( Ity_I32 );
   12005       IRTemp B_mid_60_l = newTemp( Ity_I32 );
   12006       IRTemp B_top_12_l = newTemp( Ity_I32 );
   12007 
   12008       DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   12009 
   12010       assign( frB_hi, getDReg( frB_addr ) );
   12011       assign( frB_lo, getDReg( frB_addr + 1 ) );
   12012 
   12013       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   12014       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   12015 
   12016       /* Get the BCD string for the value stored in a series of I32 values.
   12017        * Count the number of leading zeros.  Subtract the number of leading
   12018        * zeros from 32 (maximum number of significant digits in DFP
   12019        * extended).
   12020        */
   12021       Get_lmd( &lmd_B,
   12022                binop( Iop_Shr32,
   12023                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12024                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   12025 
   12026       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   12027                                    mkexpr( frBI64_lo ),
   12028                                    &B_top_12_l,
   12029                                    &B_mid_60_u,
   12030                                    &B_mid_60_l,
   12031                                    &B_low_60_u,
   12032                                    &B_low_60_l );
   12033 
   12034       assign( B_sig,
   12035               binop( Iop_Sub8,
   12036                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
   12037                      Count_leading_zeros_128( mkexpr( lmd_B ),
   12038                                               mkexpr( B_top_12_l ),
   12039                                               mkexpr( B_mid_60_u ),
   12040                                               mkexpr( B_mid_60_l ),
   12041                                               mkexpr( B_low_60_u ),
   12042                                               mkexpr( B_low_60_l ) ) ) );
   12043 
   12044       assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
   12045    }
   12046    break;
   12047    }
   12048 
   12049    /* Compare (16 - cnt[0]) against K and set the condition code field
   12050     * accordingly.
   12051     *
   12052     * The field layout is as follows:
   12053     *
   12054     * bit[3:0]    Description
   12055     *    3     K != 0 and K < Number of significant digits if FRB
   12056     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
   12057     *    1     K != 0 and K = Number of significant digits if FRB
   12058     *    0     K ? Number of significant digits if FRB
   12059     */
   12060    assign( Eq_true_mask,
   12061            unop( Iop_1Sto32,
   12062                  binop( Iop_CmpEQ32,
   12063                         unop( Iop_8Uto32, mkexpr( K ) ),
   12064                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12065    assign( Lt_true_mask,
   12066            unop( Iop_1Sto32,
   12067                  binop( Iop_CmpLT32U,
   12068                         unop( Iop_8Uto32, mkexpr( K ) ),
   12069                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12070    assign( Gt_true_mask,
   12071            unop( Iop_1Sto32,
   12072                  binop( Iop_CmpLT32U,
   12073                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
   12074                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
   12075 
   12076    assign( KisZero_true_mask,
   12077            unop( Iop_1Sto32,
   12078                  binop( Iop_CmpEQ32,
   12079                         unop( Iop_8Uto32, mkexpr( K ) ),
   12080                         mkU32( 0 ) ) ) );
   12081    assign( KisZero_false_mask,
   12082            unop( Iop_1Sto32,
   12083                  binop( Iop_CmpNE32,
   12084                         unop( Iop_8Uto32, mkexpr( K ) ),
   12085                         mkU32( 0 ) ) ) );
   12086 
   12087    assign( field,
   12088            binop( Iop_Or32,
   12089                   binop( Iop_And32,
   12090                          mkexpr( KisZero_false_mask ),
   12091                          binop( Iop_Or32,
   12092                                 binop( Iop_And32,
   12093                                        mkexpr( Lt_true_mask ),
   12094                                        mkU32( 0x8 ) ),
   12095                                 binop( Iop_Or32,
   12096                                        binop( Iop_And32,
   12097                                               mkexpr( Gt_true_mask ),
   12098                                               mkU32( 0x4 ) ),
   12099                                        binop( Iop_And32,
   12100                                               mkexpr( Eq_true_mask ),
   12101                                               mkU32( 0x2 ) ) ) ) ),
   12102                   binop( Iop_And32,
   12103                          mkexpr( KisZero_true_mask ),
   12104                          mkU32( 0x4 ) ) ) );
   12105 
   12106    putGST_field( PPC_GST_CR,
   12107                  binop( Iop_Or32,
   12108                         binop( Iop_And32,
   12109                                mkexpr( Unordered_true ),
   12110                                mkU32( 0x1 ) ),
   12111                         binop( Iop_And32,
   12112                                unop( Iop_Not32, mkexpr( Unordered_true ) ),
   12113                                mkexpr( field ) ) ),
   12114                  crfD );
   12115 
   12116    return True;
   12117 }
   12118 
   12119 /*------------------------------------------------------------*/
   12120 /*--- AltiVec Instruction Translation                      ---*/
   12121 /*------------------------------------------------------------*/
   12122 
   12123 /*
   12124   Altivec Cache Control Instructions (Data Streams)
   12125 */
   12126 static Bool dis_av_datastream ( UInt theInstr )
   12127 {
   12128    /* X-Form */
   12129    UChar opc1     = ifieldOPC(theInstr);
   12130    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   12131    UChar flag_A   = flag_T;
   12132    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   12133    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   12134    UChar rA_addr  = ifieldRegA(theInstr);
   12135    UChar rB_addr  = ifieldRegB(theInstr);
   12136    UInt  opc2     = ifieldOPClo10(theInstr);
   12137    UChar b0       = ifieldBIT0(theInstr);
   12138 
   12139    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   12140       vex_printf("dis_av_datastream(ppc)(instr)\n");
   12141       return False;
   12142    }
   12143 
   12144    switch (opc2) {
   12145    case 0x156: // dst (Data Stream Touch, AV p115)
   12146       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12147                                 rA_addr, rB_addr, STRM);
   12148       break;
   12149 
   12150    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   12151       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12152                                   rA_addr, rB_addr, STRM);
   12153       break;
   12154 
   12155    case 0x336: // dss (Data Stream Stop, AV p114)
   12156       if (rA_addr != 0 || rB_addr != 0) {
   12157          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   12158          return False;
   12159       }
   12160       if (flag_A == 0) {
   12161          DIP("dss %d\n", STRM);
   12162       } else {
   12163          DIP("dssall\n");
   12164       }
   12165       break;
   12166 
   12167    default:
   12168       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   12169       return False;
   12170    }
   12171    return True;
   12172 }
   12173 
   12174 /*
   12175   AltiVec Processor Control Instructions
   12176 */
   12177 static Bool dis_av_procctl ( UInt theInstr )
   12178 {
   12179    /* VX-Form */
   12180    UChar opc1    = ifieldOPC(theInstr);
   12181    UChar vD_addr = ifieldRegDS(theInstr);
   12182    UChar vA_addr = ifieldRegA(theInstr);
   12183    UChar vB_addr = ifieldRegB(theInstr);
   12184    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   12185 
   12186    if (opc1 != 0x4) {
   12187       vex_printf("dis_av_procctl(ppc)(instr)\n");
   12188       return False;
   12189    }
   12190 
   12191    switch (opc2) {
   12192    case 0x604: // mfvscr (Move from VSCR, AV p129)
   12193       if (vA_addr != 0 || vB_addr != 0) {
   12194          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12195          return False;
   12196       }
   12197       DIP("mfvscr v%d\n", vD_addr);
   12198       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   12199       break;
   12200 
   12201    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   12202       IRTemp vB = newTemp(Ity_V128);
   12203       if (vD_addr != 0 || vA_addr != 0) {
   12204          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12205          return False;
   12206       }
   12207       DIP("mtvscr v%d\n", vB_addr);
   12208       assign( vB, getVReg(vB_addr));
   12209       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   12210       break;
   12211    }
   12212    default:
   12213       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   12214       return False;
   12215    }
   12216    return True;
   12217 }
   12218 
   12219 /*
   12220  * VSX scalar and vector convert instructions
   12221  */
   12222 static Bool
   12223 dis_vx_conv ( UInt theInstr, UInt opc2 )
   12224 {
   12225    /* XX2-Form */
   12226    UChar opc1 = ifieldOPC( theInstr );
   12227    UChar XT = ifieldRegXT( theInstr );
   12228    UChar XB = ifieldRegXB( theInstr );
   12229    IRTemp xB, xB2;
   12230    IRTemp b3, b2, b1, b0;
   12231    xB = xB2 = IRTemp_INVALID;
   12232 
   12233    if (opc1 != 0x3C) {
   12234       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   12235       return False;
   12236    }
   12237 
   12238    /* Create and assign temps only as needed for the given instruction. */
   12239    switch (opc2) {
   12240       // scalar double-precision floating point argument
   12241       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
   12242          xB = newTemp(Ity_F64);
   12243          assign( xB,
   12244                  unop( Iop_ReinterpI64asF64,
   12245                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12246          break;
   12247       // vector double-precision floating point arguments
   12248       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   12249 
   12250          xB = newTemp(Ity_F64);
   12251          xB2 = newTemp(Ity_F64);
   12252          assign( xB,
   12253                  unop( Iop_ReinterpI64asF64,
   12254                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12255          assign( xB2,
   12256                  unop( Iop_ReinterpI64asF64,
   12257                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   12258          break;
   12259       // vector single precision or [un]signed integer word arguments
   12260       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   12261       case 0x1f0: case 0x1d0:
   12262          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12263          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   12264          break;
   12265          // vector [un]signed integer doubleword argument
   12266       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   12267          xB = newTemp(Ity_I64);
   12268          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12269          xB2 = newTemp(Ity_I64);
   12270          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   12271          break;
   12272       // scalar [un]signed integer doubleword argument
   12273       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
   12274          xB = newTemp(Ity_I64);
   12275          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12276          break;
   12277       // scalar single precision argument
   12278       case 0x292: // xscvspdp
   12279          xB  = newTemp(Ity_I32);
   12280 
   12281          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
   12282                                                   unop( Iop_V128HIto64,
   12283                                                         getVSReg( XB ) ) ) ) );
   12284          break;
   12285       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
   12286          xB = newTemp(Ity_I32);
   12287          assign( xB,
   12288                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12289          break;
   12290 
   12291       /* Certain instructions have their complete implementation in the main switch statement
   12292        * that follows this one; thus we have a "do nothing" case for those instructions here.
   12293        */
   12294       case 0x170: case 0x150:
   12295          break; // do nothing
   12296 
   12297       default:
   12298          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   12299          return False;
   12300    }
   12301 
   12302 
   12303    switch (opc2) {
   12304       case 0x2B0:
   12305          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   12306          //             to Signed Integer Doubleword format with Saturate)
   12307          DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12308          putVSReg( XT,
   12309                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   12310                                                  mkU32( Irrm_ZERO ),
   12311                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   12312          break;
   12313       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   12314                   //             Convert to Signed Integer Word format with Saturate)
   12315          DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12316          putVSReg( XT,
   12317                    binop( Iop_64HLtoV128,
   12318                           unop( Iop_32Sto64,
   12319                                 binop( Iop_F64toI32S,
   12320                                        mkU32( Irrm_ZERO ),
   12321                                        mkexpr( xB ) ) ),
   12322                                        mkU64( 0ULL ) ) );
   12323          break;
   12324       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   12325                   //             to Unsigned Integer Doubleword format with Saturate)
   12326          DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12327          putVSReg( XT,
   12328                    binop( Iop_64HLtoV128,
   12329                           binop( Iop_F64toI64U,
   12330                                  mkU32( Irrm_ZERO ),
   12331                                  mkexpr( xB ) ),
   12332                                  mkU64( 0ULL ) ) );
   12333          break;
   12334       case 0x270:
   12335          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
   12336          //             to Single-Precision format)
   12337          DIP("xscvsxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12338          putVSReg( XT,
   12339                    binop( Iop_64HLtoV128,
   12340                           unop( Iop_ReinterpF64asI64,
   12341                                 binop( Iop_RoundF64toF32,
   12342                                        get_IR_roundingmode(),
   12343                                        binop( Iop_I64StoF64,
   12344                                               get_IR_roundingmode(),
   12345                                               mkexpr( xB ) ) ) ),
   12346                           mkU64( 0 ) ) );
   12347          break;
   12348       case 0x2F0:
   12349          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   12350          //            Double-Precision format)
   12351          DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12352          putVSReg( XT,
   12353                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12354                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12355                                                        mkexpr( xB ) ) ),
   12356                                                        mkU64( 0 ) ) );
   12357          break;
   12358       case 0x250:
   12359          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
   12360          //            Doubleword to Singel-Precision format)
   12361          DIP("xscvuxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12362          putVSReg( XT,
   12363                    binop( Iop_64HLtoV128,
   12364                           unop( Iop_ReinterpF64asI64,
   12365                                 binop( Iop_RoundF64toF32,
   12366                                        get_IR_roundingmode(),
   12367                                        binop( Iop_I64UtoF64,
   12368                                               get_IR_roundingmode(),
   12369                                               mkexpr( xB ) ) ) ),
   12370                           mkU64( 0 ) ) );
   12371          break;
   12372       case 0x2D0:
   12373          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   12374          //            Double-Precision format)
   12375          DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12376          putVSReg( XT,
   12377                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12378                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12379                                                        mkexpr( xB ) ) ),
   12380                                                        mkU64( 0 ) ) );
   12381          break;
   12382       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   12383                   //             to Signed Integer Word format with Saturate)
   12384       {
   12385          IRTemp hiResult_32 = newTemp(Ity_I32);
   12386          IRTemp loResult_32 = newTemp(Ity_I32);
   12387          IRExpr* rmZero = mkU32(Irrm_ZERO);
   12388 
   12389          DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12390          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   12391          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   12392          putVSReg( XT,
   12393                    binop( Iop_64HLtoV128,
   12394                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   12395                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   12396          break;
   12397       }
   12398       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   12399          //  (VSX Vector truncate Single-Precision to integer and
   12400          //   Convert to [Un]signed Integer Word format with Saturate)
   12401       {
   12402          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   12403          IRTemp tempResult = newTemp(Ity_V128);
   12404          IRTemp res0 = newTemp(Ity_I32);
   12405          IRTemp res1 = newTemp(Ity_I32);
   12406          IRTemp res2 = newTemp(Ity_I32);
   12407          IRTemp res3 = newTemp(Ity_I32);
   12408          IRTemp hi64 = newTemp(Ity_I64);
   12409          IRTemp lo64 = newTemp(Ity_I64);
   12410          Bool un_signed = (opc2 == 0x110);
   12411          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   12412 
   12413          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
   12414          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   12415           * then result is set to 0x80000000.  */
   12416          assign(tempResult, unop(op, getVSReg(XB)));
   12417          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   12418          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   12419          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   12420          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   12421          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   12422          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   12423 
   12424          b3_result = IRExpr_ITE(is_NaN_32(b3),
   12425                                 // then: result is 0x{8|0}80000000
   12426                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12427                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12428                                 mkexpr(res3));
   12429          b2_result = IRExpr_ITE(is_NaN_32(b2),
   12430                                 // then: result is 0x{8|0}80000000
   12431                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12432                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12433                                 mkexpr(res2));
   12434          b1_result = IRExpr_ITE(is_NaN_32(b1),
   12435                                 // then: result is 0x{8|0}80000000
   12436                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12437                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12438                                 mkexpr(res1));
   12439          b0_result = IRExpr_ITE(is_NaN_32(b0),
   12440                                 // then: result is 0x{8|0}80000000
   12441                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12442                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12443                                 mkexpr(res0));
   12444 
   12445          putVSReg( XT,
   12446                    binop( Iop_64HLtoV128,
   12447                           binop( Iop_32HLto64, b3_result, b2_result ),
   12448                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   12449          break;
   12450       }
   12451       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   12452                   //           Convert to Single-Precision format
   12453          DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12454          putVSReg( XT,
   12455                    binop( Iop_64HLtoV128,
   12456                           binop( Iop_32HLto64,
   12457                                  unop( Iop_ReinterpF32asI32,
   12458                                        unop( Iop_TruncF64asF32,
   12459                                              binop( Iop_RoundF64toF32,
   12460                                                     get_IR_roundingmode(),
   12461                                                     mkexpr( xB ) ) ) ),
   12462                                  mkU32( 0 ) ),
   12463                           mkU64( 0ULL ) ) );
   12464          break;
   12465       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
   12466                               vector Single-Precision non-signalling */
   12467          DIP("xscvdpspn v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12468          putVSReg( XT,
   12469                    binop( Iop_64HLtoV128,
   12470                           binop( Iop_32HLto64,
   12471                                  unop( Iop_ReinterpF32asI32,
   12472                                        unop( Iop_TruncF64asF32,
   12473                                              mkexpr( xB ) ) ),
   12474                                  mkU32( 0 ) ),
   12475                           mkU64( 0ULL ) ) );
   12476          break;
   12477       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   12478                   //             and Convert to Unsigned Integer Word format with Saturate)
   12479          DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12480          putVSReg( XT,
   12481                    binop( Iop_64HLtoV128,
   12482                           binop( Iop_32HLto64,
   12483                                  mkU32( 0 ),
   12484                                  binop( Iop_F64toI32U,
   12485                                         mkU32( Irrm_ZERO ),
   12486                                         mkexpr( xB ) ) ),
   12487                           mkU64( 0ULL ) ) );
   12488          break;
   12489       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
   12490          DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12491          putVSReg( XT,
   12492                    binop( Iop_64HLtoV128,
   12493                           unop( Iop_ReinterpF64asI64,
   12494                                 unop( Iop_F32toF64,
   12495                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12496                           mkU64( 0ULL ) ) );
   12497          break;
   12498       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
   12499          DIP("xscvspdpn v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12500          putVSReg( XT,
   12501                    binop( Iop_64HLtoV128,
   12502                           unop( Iop_ReinterpF64asI64,
   12503                                 unop( Iop_F32toF64,
   12504                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12505                                       mkU64( 0ULL ) ) );
   12506          break;
   12507       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   12508                   //           and Convert to Single-Precision format)
   12509          DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12510          putVSReg( XT,
   12511                    binop( Iop_64HLtoV128,
   12512                           binop( Iop_32HLto64,
   12513                                  unop( Iop_ReinterpF32asI32,
   12514                                        unop( Iop_TruncF64asF32,
   12515                                              binop( Iop_RoundF64toF32,
   12516                                                     get_IR_roundingmode(),
   12517                                                     mkexpr( xB ) ) ) ),
   12518                                  mkU32( 0 ) ),
   12519                           binop( Iop_32HLto64,
   12520                                  unop( Iop_ReinterpF32asI32,
   12521                                        unop( Iop_TruncF64asF32,
   12522                                              binop( Iop_RoundF64toF32,
   12523                                                     get_IR_roundingmode(),
   12524                                                     mkexpr( xB2 ) ) ) ),
   12525                                  mkU32( 0 ) ) ) );
   12526          break;
   12527       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   12528                   //             and Convert to Unsigned Integer Doubleword format
   12529                   //             with Saturate)
   12530          DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12531          putVSReg( XT,
   12532                    binop( Iop_64HLtoV128,
   12533                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   12534                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   12535          break;
   12536       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   12537                   //             Convert to Unsigned Integer Word format with Saturate)
   12538          DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12539          putVSReg( XT,
   12540                    binop( Iop_64HLtoV128,
   12541                           binop( Iop_32HLto64,
   12542                                  binop( Iop_F64toI32U,
   12543                                         mkU32( Irrm_ZERO ),
   12544                                         mkexpr( xB ) ),
   12545                                  mkU32( 0 ) ),
   12546                           binop( Iop_32HLto64,
   12547                                  binop( Iop_F64toI32U,
   12548                                         mkU32( Irrm_ZERO ),
   12549                                         mkexpr( xB2 ) ),
   12550                                  mkU32( 0 ) ) ) );
   12551          break;
   12552       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   12553          DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12554          putVSReg( XT,
   12555                    binop( Iop_64HLtoV128,
   12556                           unop( Iop_ReinterpF64asI64,
   12557                                 unop( Iop_F32toF64,
   12558                                       unop( Iop_ReinterpI32asF32,
   12559                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
   12560                           unop( Iop_ReinterpF64asI64,
   12561                                 unop( Iop_F32toF64,
   12562                                       unop( Iop_ReinterpI32asF32,
   12563                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
   12564          break;
   12565       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   12566                   //           Convert to Signed Integer Doubleword format with Saturate)
   12567          DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12568          putVSReg( XT,
   12569                    binop( Iop_64HLtoV128,
   12570                           binop( Iop_F64toI64S,
   12571                                  mkU32( Irrm_ZERO ),
   12572                                  unop( Iop_F32toF64,
   12573                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   12574                           binop( Iop_F64toI64S,
   12575                                  mkU32( Irrm_ZERO ),
   12576                                  unop( Iop_F32toF64,
   12577                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   12578          break;
   12579       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   12580                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   12581          DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12582          putVSReg( XT,
   12583                    binop( Iop_64HLtoV128,
   12584                           binop( Iop_F64toI64U,
   12585                                  mkU32( Irrm_ZERO ),
   12586                                  unop( Iop_F32toF64,
   12587                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   12588                           binop( Iop_F64toI64U,
   12589                                  mkU32( Irrm_ZERO ),
   12590                                  unop( Iop_F32toF64,
   12591                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   12592          break;
   12593       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   12594                   //             Convert to Signed Integer Doubleword format with Saturate)
   12595          DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12596          putVSReg( XT,
   12597                    binop( Iop_64HLtoV128,
   12598                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   12599                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   12600          break;
   12601       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   12602                   //            to Double-Precision format)
   12603          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12604          putVSReg( XT,
   12605                    binop( Iop_64HLtoV128,
   12606                           unop( Iop_ReinterpF64asI64,
   12607                                 binop( Iop_I64StoF64,
   12608                                        get_IR_roundingmode(),
   12609                                        mkexpr( xB ) ) ),
   12610                           unop( Iop_ReinterpF64asI64,
   12611                                 binop( Iop_I64StoF64,
   12612                                        get_IR_roundingmode(),
   12613                                        mkexpr( xB2 ) ) ) ) );
   12614          break;
   12615       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   12616                   //            to Double-Precision format)
   12617          DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12618          putVSReg( XT,
   12619                    binop( Iop_64HLtoV128,
   12620                           unop( Iop_ReinterpF64asI64,
   12621                                 binop( Iop_I64UtoF64,
   12622                                        get_IR_roundingmode(),
   12623                                        mkexpr( xB ) ) ),
   12624                           unop( Iop_ReinterpF64asI64,
   12625                                 binop( Iop_I64UtoF64,
   12626                                        get_IR_roundingmode(),
   12627                                        mkexpr( xB2 ) ) ) ) );
   12628 
   12629          break;
   12630       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   12631                   //            to Single-Precision format)
   12632          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12633          putVSReg( XT,
   12634                    binop( Iop_64HLtoV128,
   12635                           binop( Iop_32HLto64,
   12636                                  unop( Iop_ReinterpF32asI32,
   12637                                        unop( Iop_TruncF64asF32,
   12638                                              binop( Iop_RoundF64toF32,
   12639                                                     get_IR_roundingmode(),
   12640                                                     binop( Iop_I64StoF64,
   12641                                                            get_IR_roundingmode(),
   12642                                                            mkexpr( xB ) ) ) ) ),
   12643                                  mkU32( 0 ) ),
   12644                           binop( Iop_32HLto64,
   12645                                  unop( Iop_ReinterpF32asI32,
   12646                                        unop( Iop_TruncF64asF32,
   12647                                              binop( Iop_RoundF64toF32,
   12648                                                     get_IR_roundingmode(),
   12649                                                     binop( Iop_I64StoF64,
   12650                                                            get_IR_roundingmode(),
   12651                                                            mkexpr( xB2 ) ) ) ) ),
   12652                                  mkU32( 0 ) ) ) );
   12653          break;
   12654       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   12655                   //            to Single-Precision format)
   12656          DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
   12657          putVSReg( XT,
   12658                    binop( Iop_64HLtoV128,
   12659                           binop( Iop_32HLto64,
   12660                                  unop( Iop_ReinterpF32asI32,
   12661                                        unop( Iop_TruncF64asF32,
   12662                                              binop( Iop_RoundF64toF32,
   12663                                                     get_IR_roundingmode(),
   12664                                                     binop( Iop_I64UtoF64,
   12665                                                            get_IR_roundingmode(),
   12666                                                            mkexpr( xB ) ) ) ) ),
   12667                                  mkU32( 0 ) ),
   12668                           binop( Iop_32HLto64,
   12669                                  unop( Iop_ReinterpF32asI32,
   12670                                        unop( Iop_TruncF64asF32,
   12671                                              binop( Iop_RoundF64toF32,
   12672                                                     get_IR_roundingmode(),
   12673                                                     binop( Iop_I64UtoF64,
   12674                                                            get_IR_roundingmode(),
   12675                                                            mkexpr( xB2 ) ) ) ) ),
   12676                                  mkU32( 0 ) ) ) );
   12677          break;
   12678 
   12679       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   12680          DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12681          putVSReg( XT,
   12682                    binop( Iop_64HLtoV128,
   12683                           unop( Iop_ReinterpF64asI64,
   12684                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12685                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   12686                           unop( Iop_ReinterpF64asI64,
   12687                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12688                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   12689          break;
   12690       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   12691          DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12692          putVSReg( XT,
   12693                    binop( Iop_64HLtoV128,
   12694                           unop( Iop_ReinterpF64asI64,
   12695                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12696                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   12697                           unop( Iop_ReinterpF64asI64,
   12698                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12699                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   12700          break;
   12701       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   12702          DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12703          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   12704          break;
   12705       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   12706          DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12707          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   12708          break;
   12709 
   12710       default:
   12711          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   12712          return False;
   12713    }
   12714    return True;
   12715 }
   12716 
   12717 /*
   12718  * VSX vector Double Precision Floating Point Arithmetic Instructions
   12719  */
   12720 static Bool
   12721 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   12722 {
   12723    /* XX3-Form */
   12724    UChar opc1 = ifieldOPC( theInstr );
   12725    UChar XT = ifieldRegXT( theInstr );
   12726    UChar XA = ifieldRegXA( theInstr );
   12727    UChar XB = ifieldRegXB( theInstr );
   12728    IRExpr* rm = get_IR_roundingmode();
   12729    IRTemp frA = newTemp(Ity_F64);
   12730    IRTemp frB = newTemp(Ity_F64);
   12731    IRTemp frA2 = newTemp(Ity_F64);
   12732    IRTemp frB2 = newTemp(Ity_F64);
   12733 
   12734    if (opc1 != 0x3C) {
   12735       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   12736       return False;
   12737    }
   12738 
   12739    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   12740    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   12741    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   12742    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   12743 
   12744    switch (opc2) {
   12745       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   12746       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   12747       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   12748       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   12749       {
   12750          IROp mOp;
   12751          const HChar * oper_name;
   12752          switch (opc2) {
   12753             case 0x1E0:
   12754                mOp = Iop_DivF64;
   12755                oper_name = "div";
   12756                break;
   12757             case 0x1C0:
   12758                mOp = Iop_MulF64;
   12759                oper_name = "mul";
   12760                break;
   12761             case 0x180:
   12762                mOp = Iop_AddF64;
   12763                oper_name = "add";
   12764                break;
   12765             case 0x1A0:
   12766                mOp = Iop_SubF64;
   12767                oper_name = "sub";
   12768                break;
   12769 
   12770             default:
   12771                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   12772          }
   12773          IRTemp hiResult = newTemp(Ity_I64);
   12774          IRTemp loResult = newTemp(Ity_I64);
   12775          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
   12776 
   12777          assign( hiResult,
   12778                  unop( Iop_ReinterpF64asI64,
   12779                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   12780          assign( loResult,
   12781                  unop( Iop_ReinterpF64asI64,
   12782                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   12783          putVSReg( XT,
   12784                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   12785          break;
   12786       }
   12787       case 0x196: // xvsqrtdp
   12788       {
   12789          IRTemp hiResult = newTemp(Ity_I64);
   12790          IRTemp loResult = newTemp(Ity_I64);
   12791          DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   12792 
   12793          assign( hiResult,
   12794                  unop( Iop_ReinterpF64asI64,
   12795                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   12796          assign( loResult,
   12797                  unop( Iop_ReinterpF64asI64,
   12798                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   12799          putVSReg( XT,
   12800                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   12801          break;
   12802       }
   12803       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   12804       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   12805       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   12806       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   12807       {
   12808          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   12809           *    XT == FRC
   12810           *    XA == FRA
   12811           *    XB == FRB
   12812           *
   12813           * and for xvm{add|sub}adp . . .
   12814           *    XT == FRB
   12815           *    XA == FRA
   12816           *    XB == FRC
   12817           */
   12818          Bool negate;
   12819          IROp mOp = Iop_INVALID;
   12820          const HChar * oper_name = NULL;
   12821          Bool mdp = False;
   12822 
   12823          switch (opc2) {
   12824             case 0x184: case 0x1A4:
   12825             case 0x384: case 0x3A4:
   12826                mOp = Iop_MAddF64;
   12827                oper_name = "add";
   12828                mdp = (opc2 & 0x0FF) == 0x0A4;
   12829                break;
   12830 
   12831             case 0x1C4: case 0x1E4:
   12832             case 0x3C4: case 0x3E4:
   12833                mOp = Iop_MSubF64;
   12834                oper_name = "sub";
   12835                mdp = (opc2 & 0x0FF) == 0x0E4;
   12836                break;
   12837 
   12838             default:
   12839                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   12840          }
   12841 
   12842          switch (opc2) {
   12843             case 0x384: case 0x3A4:
   12844             case 0x3C4: case 0x3E4:
   12845                negate = True;
   12846                break;
   12847             default:
   12848                negate = False;
   12849          }
   12850          IRTemp hiResult = newTemp(Ity_I64);
   12851          IRTemp loResult = newTemp(Ity_I64);
   12852          IRTemp frT = newTemp(Ity_F64);
   12853          IRTemp frT2 = newTemp(Ity_F64);
   12854          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   12855              (UInt)XT, (UInt)XA, (UInt)XB);
   12856          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   12857          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   12858 
   12859          assign( hiResult,
   12860                  unop( Iop_ReinterpF64asI64,
   12861                        qop( mOp,
   12862                             rm,
   12863                             mkexpr( frA ),
   12864                             mkexpr( mdp ? frT : frB ),
   12865                             mkexpr( mdp ? frB : frT ) ) ) );
   12866          assign( loResult,
   12867                  unop( Iop_ReinterpF64asI64,
   12868                        qop( mOp,
   12869                             rm,
   12870                             mkexpr( frA2 ),
   12871                             mkexpr( mdp ? frT2 : frB2 ),
   12872                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   12873          putVSReg( XT,
   12874                    binop( Iop_64HLtoV128,
   12875                           mkexpr( negate ? getNegatedResult( hiResult )
   12876                                          : hiResult ),
   12877                           mkexpr( negate ? getNegatedResult( loResult )
   12878                                          : loResult ) ) );
   12879          break;
   12880       }
   12881       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   12882       {
   12883          IRTemp frBHi_I64 = newTemp(Ity_I64);
   12884          IRTemp frBLo_I64 = newTemp(Ity_I64);
   12885          IRTemp flagsHi = newTemp(Ity_I32);
   12886          IRTemp flagsLo = newTemp(Ity_I32);
   12887          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12888          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   12889          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   12890 
   12891          DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   12892          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   12893          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   12894          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   12895          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   12896          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12897           * where fl_flag == 1 on ppc64.
   12898           */
   12899          assign( flagsHi,
   12900                  binop( Iop_Or32,
   12901                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12902                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   12903                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   12904          assign( flagsLo,
   12905                  binop( Iop_Or32,
   12906                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12907                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   12908                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   12909          putGST_field( PPC_GST_CR,
   12910                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   12911                        crfD );
   12912          break;
   12913       }
   12914       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   12915       {
   12916          IRTemp frBHi_I64 = newTemp(Ity_I64);
   12917          IRTemp frBLo_I64 = newTemp(Ity_I64);
   12918          IRTemp frAHi_I64 = newTemp(Ity_I64);
   12919          IRTemp frALo_I64 = newTemp(Ity_I64);
   12920          IRTemp flagsHi = newTemp(Ity_I32);
   12921          IRTemp flagsLo = newTemp(Ity_I32);
   12922          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12923          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   12924          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   12925 
   12926          DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   12927          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   12928          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   12929          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   12930          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   12931 
   12932          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   12933          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   12934          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12935           * where fl_flag == 1 on ppc64.
   12936           */
   12937          assign( flagsHi,
   12938                  binop( Iop_Or32,
   12939                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12940                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   12941                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   12942          assign( flagsLo,
   12943                  binop( Iop_Or32,
   12944                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12945                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   12946                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   12947          putGST_field( PPC_GST_CR,
   12948                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   12949                        crfD );
   12950          break;
   12951       }
   12952 
   12953       default:
   12954          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   12955          return False;
   12956    }
   12957    return True;
   12958 }
   12959 
   12960 /*
   12961  * VSX vector Single Precision Floating Point Arithmetic Instructions
   12962  */
   12963 static Bool
   12964 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   12965 {
   12966    /* XX3-Form */
   12967    UChar opc1 = ifieldOPC( theInstr );
   12968    UChar XT = ifieldRegXT( theInstr );
   12969    UChar XA = ifieldRegXA( theInstr );
   12970    UChar XB = ifieldRegXB( theInstr );
   12971    IRExpr* rm = get_IR_roundingmode();
   12972    IRTemp a3, a2, a1, a0;
   12973    IRTemp b3, b2, b1, b0;
   12974    IRTemp res0 = newTemp(Ity_I32);
   12975    IRTemp res1 = newTemp(Ity_I32);
   12976    IRTemp res2 = newTemp(Ity_I32);
   12977    IRTemp res3 = newTemp(Ity_I32);
   12978 
   12979    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   12980    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12981 
   12982    if (opc1 != 0x3C) {
   12983       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   12984       return False;
   12985    }
   12986 
   12987    switch (opc2) {
   12988       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   12989          DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12990          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
   12991          putVSReg( XT, triop(Iop_Add32Fx4, rm,
   12992                              getVSReg( XA ), getVSReg( XB )) );
   12993          break;
   12994 
   12995       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   12996          DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12997          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
   12998          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
   12999                              getVSReg( XA ), getVSReg( XB )) );
   13000          break;
   13001 
   13002       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   13003          DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13004          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
   13005          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
   13006                              getVSReg( XA ), getVSReg( XB )) );
   13007          break;
   13008 
   13009       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   13010       {
   13011          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   13012           * So there are two choices:
   13013           *   1. Implement the xvdivsp with a native insn; or
   13014           *   2. Extract the 4 single precision floats from each vector
   13015           *      register inputs and perform fdivs on each pair
   13016           * I will do the latter, due to the general philosophy of
   13017           * reusing existing implementations when practical.
   13018           */
   13019          DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13020          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13021          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13022 
   13023          assign( res0,
   13024               unop( Iop_ReinterpF32asI32,
   13025                     unop( Iop_TruncF64asF32,
   13026                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   13027          assign( res1,
   13028                  unop( Iop_ReinterpF32asI32,
   13029                        unop( Iop_TruncF64asF32,
   13030                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   13031          assign( res2,
   13032                  unop( Iop_ReinterpF32asI32,
   13033                        unop( Iop_TruncF64asF32,
   13034                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   13035          assign( res3,
   13036                  unop( Iop_ReinterpF32asI32,
   13037                        unop( Iop_TruncF64asF32,
   13038                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   13039 
   13040          putVSReg( XT,
   13041                    binop( Iop_64HLtoV128,
   13042                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13043                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13044          break;
   13045       }
   13046       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   13047       {
   13048          DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13049          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13050          /* Note: The native xvsqrtsp insruction does not always give the same precision
   13051           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   13052           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   13053           * to the actual instruction.
   13054           */
   13055 
   13056          assign( res0,
   13057                  unop( Iop_ReinterpF32asI32,
   13058                        unop( Iop_TruncF64asF32,
   13059                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   13060          assign( res1,
   13061                  unop( Iop_ReinterpF32asI32,
   13062                        unop( Iop_TruncF64asF32,
   13063                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   13064          assign( res2,
   13065                  unop( Iop_ReinterpF32asI32,
   13066                        unop( Iop_TruncF64asF32,
   13067                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   13068          assign( res3,
   13069                  unop( Iop_ReinterpF32asI32,
   13070                        unop( Iop_TruncF64asF32,
   13071                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   13072 
   13073          putVSReg( XT,
   13074                    binop( Iop_64HLtoV128,
   13075                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13076                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13077          break;
   13078       }
   13079 
   13080       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   13081       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   13082       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   13083       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   13084       {
   13085          IRTemp t3, t2, t1, t0;
   13086          Bool msp = False;
   13087          Bool negate;
   13088          const HChar * oper_name = NULL;
   13089          IROp mOp = Iop_INVALID;
   13090          switch (opc2) {
   13091             case 0x104: case 0x124:
   13092             case 0x304: case 0x324:
   13093                msp = (opc2 & 0x0FF) == 0x024;
   13094                mOp = Iop_MAddF64r32;
   13095                oper_name = "madd";
   13096                break;
   13097 
   13098             case 0x144: case 0x164:
   13099             case 0x344: case 0x364:
   13100                msp = (opc2 & 0x0FF) == 0x064;
   13101                mOp = Iop_MSubF64r32;
   13102                oper_name = "sub";
   13103                break;
   13104 
   13105             default:
   13106                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   13107          }
   13108 
   13109          switch (opc2) {
   13110             case 0x304: case 0x324:
   13111             case 0x344: case 0x364:
   13112                negate = True;
   13113                break;
   13114 
   13115             default:
   13116                negate = False;
   13117          }
   13118 
   13119          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
   13120              (UInt)XT, (UInt)XA, (UInt)XB);
   13121 
   13122          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   13123          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13124          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13125          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   13126 
   13127          assign( res0,
   13128                  unop( Iop_ReinterpF32asI32,
   13129                        unop( Iop_TruncF64asF32,
   13130                              qop( mOp,
   13131                                   rm,
   13132                                   mkexpr( a0 ),
   13133                                   mkexpr( msp ? t0 : b0 ),
   13134                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   13135          assign( res1,
   13136                  unop( Iop_ReinterpF32asI32,
   13137                        unop( Iop_TruncF64asF32,
   13138                              qop( mOp,
   13139                                   rm,
   13140                                   mkexpr( a1 ),
   13141                                   mkexpr( msp ? t1 : b1 ),
   13142                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   13143          assign( res2,
   13144                  unop( Iop_ReinterpF32asI32,
   13145                        unop( Iop_TruncF64asF32,
   13146                              qop( mOp,
   13147                                   rm,
   13148                                   mkexpr( a2 ),
   13149                                   mkexpr( msp ? t2 : b2 ),
   13150                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   13151          assign( res3,
   13152                  unop( Iop_ReinterpF32asI32,
   13153                        unop( Iop_TruncF64asF32,
   13154                              qop( mOp,
   13155                                   rm,
   13156                                   mkexpr( a3 ),
   13157                                   mkexpr( msp ? t3 : b3 ),
   13158                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   13159 
   13160          putVSReg( XT,
   13161                    binop( Iop_64HLtoV128,
   13162                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   13163                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   13164                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   13165                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   13166 
   13167          break;
   13168       }
   13169       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   13170       {
   13171          IRTemp flags0 = newTemp(Ity_I32);
   13172          IRTemp flags1 = newTemp(Ity_I32);
   13173          IRTemp flags2 = newTemp(Ity_I32);
   13174          IRTemp flags3 = newTemp(Ity_I32);
   13175          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13176          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13177          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13178          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13179          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13180          DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   13181 
   13182          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13183          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13184          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13185          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13186          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13187 
   13188          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13189           * where fl_flag == 1 on ppc64.
   13190           */
   13191          assign( flags0,
   13192                  binop( Iop_Or32,
   13193                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13194                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13195                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13196          assign( flags1,
   13197                  binop( Iop_Or32,
   13198                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13199                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13200                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13201          assign( flags2,
   13202                  binop( Iop_Or32,
   13203                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13204                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13205                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13206          assign( flags3,
   13207                  binop( Iop_Or32,
   13208                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13209                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13210                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13211          putGST_field( PPC_GST_CR,
   13212                        binop( Iop_Or32,
   13213                               mkexpr( flags0 ),
   13214                               binop( Iop_Or32,
   13215                                      mkexpr( flags1 ),
   13216                                      binop( Iop_Or32,
   13217                                             mkexpr( flags2 ),
   13218                                             mkexpr( flags3 ) ) ) ),
   13219                        crfD );
   13220 
   13221          break;
   13222       }
   13223       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   13224       {
   13225          IRTemp flags0 = newTemp(Ity_I32);
   13226          IRTemp flags1 = newTemp(Ity_I32);
   13227          IRTemp flags2 = newTemp(Ity_I32);
   13228          IRTemp flags3 = newTemp(Ity_I32);
   13229          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13230          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13231          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13232          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13233          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13234          DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   13235 
   13236          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13237          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13238          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13239          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13240          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13241          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13242 
   13243          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13244           * where fl_flag == 1 on ppc64.
   13245           */
   13246          assign( flags0,
   13247                  binop( Iop_Or32,
   13248                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13249                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13250                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13251          assign( flags1,
   13252                  binop( Iop_Or32,
   13253                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13254                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13255                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13256          assign( flags2,
   13257                  binop( Iop_Or32,
   13258                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13259                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13260                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13261          assign( flags3,
   13262                  binop( Iop_Or32,
   13263                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13264                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13265                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13266          putGST_field( PPC_GST_CR,
   13267                        binop( Iop_Or32,
   13268                               mkexpr( flags0 ),
   13269                               binop( Iop_Or32,
   13270                                      mkexpr( flags1 ),
   13271                                      binop( Iop_Or32,
   13272                                             mkexpr( flags2 ),
   13273                                             mkexpr( flags3 ) ) ) ),
   13274                        crfD );
   13275 
   13276          break;
   13277       }
   13278 
   13279       default:
   13280          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   13281          return False;
   13282    }
   13283    return True;
   13284 }
   13285 
   13286 /*
   13287  * Vector Population Count/bit matrix transpose
   13288  */
   13289 static Bool
   13290 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
   13291 {
   13292    UChar vRB_addr = ifieldRegB(theInstr);
   13293    UChar vRT_addr = ifieldRegDS(theInstr);
   13294    UChar opc1 = ifieldOPC( theInstr );
   13295    IRTemp vB = newTemp(Ity_V128);
   13296    assign( vB, getVReg(vRB_addr));
   13297 
   13298    if (opc1 != 0x4) {
   13299       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
   13300       return False;
   13301    }
   13302 
   13303    switch (opc2) {
   13304       case 0x702:    // vclzb
   13305          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
   13306          putVReg( vRT_addr, unop(Iop_Clz8Sx16, mkexpr( vB ) ) );
   13307          break;
   13308 
   13309       case 0x742:    // vclzh
   13310          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
   13311          putVReg( vRT_addr, unop(Iop_Clz16Sx8, mkexpr( vB ) ) );
   13312          break;
   13313 
   13314       case 0x782:    // vclzw
   13315          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
   13316          putVReg( vRT_addr, unop(Iop_Clz32Sx4, mkexpr( vB ) ) );
   13317          break;
   13318 
   13319       case 0x7C2:    // vclzd
   13320          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
   13321          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
   13322          break;
   13323 
   13324       case 0x703:    // vpopcntb
   13325       {
   13326          /* Break vector into 32-bit words and do the population count
   13327           * on byte in the words
   13328           */
   13329          IRType ty = Ity_I32;
   13330          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13331          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13332          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13333          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13334 
   13335          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
   13336          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13337          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
   13338          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
   13339          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
   13340          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
   13341 
   13342          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13343                                          cnt_bits32_63, cnt_bits0_31) );
   13344          break;
   13345       }
   13346 
   13347       case 0x743:    // vpopcnth
   13348       {
   13349          /* Break vector into 32-bit words and do the population count
   13350           * for each half word
   13351           */
   13352          IRType ty = Ity_I32;
   13353          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13354          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13355          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13356          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13357 
   13358          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
   13359          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13360 
   13361          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
   13362          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
   13363          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
   13364          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
   13365 
   13366          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13367                                          cnt_bits32_63, cnt_bits0_31) );
   13368          break;
   13369       }
   13370 
   13371       case 0x783:    // vpopcntw
   13372       {
   13373          /* Break vector into 32-bit words and do the population count
   13374           * on each word.
   13375           */
   13376          IRType ty = Ity_I32;
   13377          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13378          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13379          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13380          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13381 
   13382          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
   13383          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13384 
   13385          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
   13386          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
   13387          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
   13388          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
   13389 
   13390          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13391                                          cnt_bits32_63, cnt_bits0_31) );
   13392          break;
   13393       }
   13394 
   13395       case 0x7C3:    // vpopcntd
   13396       {
   13397          if (mode64) {
   13398             /* Break vector into 64-bit double words and do the population count
   13399              * on each double word.
   13400              */
   13401             IRType ty = Ity_I64;
   13402             IRTemp bits0_63   = newTemp(Ity_I64);
   13403             IRTemp bits64_127 = newTemp(Ity_I64);
   13404             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13405             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
   13406 
   13407             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13408 
   13409             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
   13410             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   13411             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
   13412             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
   13413 
   13414             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13415                                       mkexpr( cnt_bits64_127 ),
   13416                                       mkexpr( cnt_bits0_63 ) ) );
   13417          } else {
   13418             /* Break vector into 32-bit words and do the population count
   13419              * on each doubleword.
   13420              */
   13421             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13422             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13423             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13424             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
   13425 
   13426             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13427             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13428 
   13429             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
   13430             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
   13431 
   13432             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13433                                       mkexpr( cnt_bits64_127 ),
   13434                                       mkexpr( cnt_bits0_63 ) ) );
   13435          }
   13436          break;
   13437       }
   13438 
   13439       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
   13440          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
   13441          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
   13442          break;
   13443 
   13444       default:
   13445          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
   13446          return False;
   13447       break;
   13448    }
   13449    return True;
   13450 }
   13451 
   13452 typedef enum {
   13453    PPC_CMP_EQ = 2,
   13454    PPC_CMP_GT = 4,
   13455    PPC_CMP_GE = 6,
   13456    PPC_CMP_LT = 8
   13457 } ppc_cmp_t;
   13458 
   13459 
   13460 /*
   13461   This helper function takes as input the IRExpr returned
   13462   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   13463   in IR form.  This helper function converts it to PPC form.
   13464 
   13465   Map compare result from IR to PPC
   13466 
   13467   FP cmp result | PPC | IR
   13468   --------------------------
   13469   UN            | 0x1 | 0x45
   13470   EQ            | 0x2 | 0x40
   13471   GT            | 0x4 | 0x00
   13472   LT            | 0x8 | 0x01
   13473 
   13474  condcode = Shl(1, (~(ccIR>>5) & 2)
   13475                     | ((ccIR ^ (ccIR>>6)) & 1)
   13476 */
   13477 static IRTemp
   13478 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   13479 {
   13480    IRTemp condcode = newTemp( Ity_I32 );
   13481    IRTemp ccIR = newTemp( Ity_I32 );
   13482 
   13483    assign(ccIR, ccIR_expr);
   13484    assign( condcode,
   13485            binop( Iop_Shl32,
   13486                   mkU32( 1 ),
   13487                   unop( Iop_32to8,
   13488                         binop( Iop_Or32,
   13489                                binop( Iop_And32,
   13490                                       unop( Iop_Not32,
   13491                                             binop( Iop_Shr32,
   13492                                                    mkexpr( ccIR ),
   13493                                                    mkU8( 5 ) ) ),
   13494                                       mkU32( 2 ) ),
   13495                                binop( Iop_And32,
   13496                                       binop( Iop_Xor32,
   13497                                              mkexpr( ccIR ),
   13498                                              binop( Iop_Shr32,
   13499                                                     mkexpr( ccIR ),
   13500                                                     mkU8( 6 ) ) ),
   13501                                       mkU32( 1 ) ) ) ) ) );
   13502    return condcode;
   13503 }
   13504 
   13505 /*
   13506  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   13507  * following these special rules:
   13508  *   - The max/min of a QNaN and any value is that value
   13509  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   13510  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   13511  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   13512  */
   13513 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   13514 {
   13515    IRTemp frA_isNaN = newTemp(Ity_I1);
   13516    IRTemp frB_isNaN = newTemp(Ity_I1);
   13517    IRTemp frA_isSNaN = newTemp(Ity_I1);
   13518    IRTemp frB_isSNaN = newTemp(Ity_I1);
   13519    IRTemp frA_isQNaN = newTemp(Ity_I1);
   13520    IRTemp frB_isQNaN = newTemp(Ity_I1);
   13521 
   13522    assign( frA_isNaN, is_NaN( frA_I64 ) );
   13523    assign( frB_isNaN, is_NaN( frB_I64 ) );
   13524    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   13525    assign( frA_isSNaN,
   13526            mkAND1( mkexpr(frA_isNaN),
   13527                    binop( Iop_CmpEQ32,
   13528                           binop( Iop_And32,
   13529                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   13530                                  mkU32( 0x00080000 ) ),
   13531                           mkU32( 0 ) ) ) );
   13532    assign( frB_isSNaN,
   13533            mkAND1( mkexpr(frB_isNaN),
   13534                    binop( Iop_CmpEQ32,
   13535                           binop( Iop_And32,
   13536                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   13537                                  mkU32( 0x00080000 ) ),
   13538                           mkU32( 0 ) ) ) );
   13539    assign( frA_isQNaN,
   13540            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   13541    assign( frB_isQNaN,
   13542            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   13543 
   13544    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   13545     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13546     *   if frA is a SNaN
   13547     *     result = frA converted to QNaN
   13548     *   else if frB is a SNaN
   13549     *     result = frB converted to QNaN
   13550     *   else if frB is a QNaN
   13551     *     result = frA
   13552     *   // One of frA or frB was a NaN in order for this function to be called, so
   13553     *   // if we get to this point, we KNOW that frA must be a QNaN.
   13554     *   else // frA is a QNaN
   13555     *     result = frB
   13556     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13557     */
   13558 
   13559 #define SNAN_MASK 0x0008000000000000ULL
   13560    return
   13561    IRExpr_ITE(mkexpr(frA_isSNaN),
   13562               /* then: result = frA converted to QNaN */
   13563               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
   13564               /* else:  if frB is a SNaN */
   13565               IRExpr_ITE(mkexpr(frB_isSNaN),
   13566                          /* then: result = frB converted to QNaN */
   13567                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
   13568                          /* else:  if frB is a QNaN */
   13569                          IRExpr_ITE(mkexpr(frB_isQNaN),
   13570                                     /* then: result = frA */
   13571                                     mkexpr(frA_I64),
   13572                                     /* else:  frA is a QNaN, so result = frB */
   13573                                     mkexpr(frB_I64))));
   13574 }
   13575 
   13576 /*
   13577  * Helper function for get_max_min_fp.
   13578  */
   13579 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   13580 {
   13581    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   13582                                                   unop( Iop_ReinterpI64asF64,
   13583                                                         mkexpr( src1 ) ),
   13584                                                   unop( Iop_ReinterpI64asF64,
   13585                                                         mkexpr( src2 ) ) ) );
   13586 
   13587    return IRExpr_ITE( binop( Iop_CmpEQ32,
   13588                                mkexpr( src1cmpsrc2 ),
   13589                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
   13590                       /* then: use src1 */
   13591                       mkexpr( src1 ),
   13592                       /* else: use src2 */
   13593                       mkexpr( src2 ) );
   13594 }
   13595 
   13596 /*
   13597  * Helper function for "Maximum/Minimum Double Precision" operations.
   13598  * Arguments: frA and frb are Ity_I64
   13599  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   13600  */
   13601 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   13602 {
   13603    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   13604     * for ascertaining the maximum between two doubles:
   13605     *   1. The max/min of +0 and -0 is +0.
   13606     *   2. The max/min of a QNaN and any value is that value.
   13607     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   13608     * We perform the check for [+/-]0 here in this function and use the
   13609     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   13610     * to do the standard comparison function.
   13611     */
   13612    IRTemp anyNaN = newTemp(Ity_I1);
   13613    IRTemp frA_isZero = newTemp(Ity_I1);
   13614    IRTemp frB_isZero = newTemp(Ity_I1);
   13615    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
   13616    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
   13617    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
   13618 #define MINUS_ZERO 0x8000000000000000ULL
   13619 
   13620    return IRExpr_ITE( /* If both arguments are zero . . . */
   13621                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
   13622                      /* then: if frA is -0 and isMin==True, return -0;
   13623                       *     else if frA is +0 and isMin==False; return +0;
   13624                       *     otherwise, simply return frB. */
   13625                      IRExpr_ITE( binop( Iop_CmpEQ32,
   13626                                         unop( Iop_64HIto32,
   13627                                               mkexpr( frA_I64 ) ),
   13628                                         mkU32( isMin ? 0x80000000 : 0 ) ),
   13629                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
   13630                                  mkexpr( frB_I64 ) ),
   13631                      /* else: check if either input is a NaN*/
   13632                      IRExpr_ITE( mkexpr( anyNaN ),
   13633                                  /* then: use "NaN helper" */
   13634                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
   13635                                  /* else: use "comparison helper" */
   13636                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
   13637 }
   13638 
   13639 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
   13640 {
   13641    switch (opc2 & 0x7F) {
   13642       case 0x72:
   13643          return "m";
   13644       case 0x52:
   13645          return "p";
   13646       case 0x56:
   13647          return "c";
   13648       case 0x32:
   13649          return "z";
   13650       case 0x12:
   13651          return "";
   13652 
   13653       default: // Impossible to get here
   13654          vex_printf("Unrecognized opcode %x\n", opc2);
   13655          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
   13656    }
   13657 }
   13658 
   13659 /*
   13660  * Helper function for vector/scalar double precision fp round to integer instructions.
   13661  */
   13662 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
   13663 {
   13664 
   13665    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   13666    IRTemp frB = newTemp(Ity_F64);
   13667    IRTemp frD = newTemp(Ity_F64);
   13668    IRTemp intermediateResult = newTemp(Ity_I64);
   13669    IRTemp is_SNAN = newTemp(Ity_I1);
   13670    IRExpr * hi32;
   13671    IRExpr * rxpi_rm;
   13672    switch (opc2 & 0x7F) {
   13673       case 0x72:
   13674          rxpi_rm = mkU32(Irrm_NegINF);
   13675          break;
   13676       case 0x52:
   13677          rxpi_rm = mkU32(Irrm_PosINF);
   13678          break;
   13679       case 0x56:
   13680          rxpi_rm = get_IR_roundingmode();
   13681          break;
   13682       case 0x32:
   13683          rxpi_rm = mkU32(Irrm_ZERO);
   13684          break;
   13685       case 0x12:
   13686          rxpi_rm = mkU32(Irrm_NEAREST);
   13687          break;
   13688 
   13689       default: // Impossible to get here
   13690          vex_printf("Unrecognized opcode %x\n", opc2);
   13691          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
   13692    }
   13693    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   13694    assign( intermediateResult,
   13695            binop( Iop_F64toI64S, rxpi_rm,
   13696                   mkexpr( frB ) ) );
   13697 
   13698    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   13699    /* F64 has only log10(2**52) significant digits anyway */
   13700    /* need to preserve sign of zero */
   13701    /*   frD = (fabs(frB) > 9e18) ? frB :
   13702             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   13703    assign( frD,
   13704            IRExpr_ITE(
   13705               binop( Iop_CmpNE8,
   13706                      unop( Iop_32to8,
   13707                            binop( Iop_CmpF64,
   13708                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
   13709                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   13710                      mkU8(0) ),
   13711               mkexpr( frB ),
   13712               IRExpr_ITE(
   13713                  binop( Iop_CmpNE32,
   13714                         binop( Iop_Shr32,
   13715                                unop( Iop_64HIto32,
   13716                                      mkexpr( frB_I64 ) ),
   13717                                mkU8( 31 ) ),
   13718                         mkU32(0) ),
   13719                  unop( Iop_NegF64,
   13720                        unop( Iop_AbsF64,
   13721                              binop( Iop_I64StoF64,
   13722                                     mkU32( 0 ),
   13723                                     mkexpr( intermediateResult ) ) ) ),
   13724                  binop( Iop_I64StoF64,
   13725                         mkU32( 0 ),
   13726                         mkexpr( intermediateResult ) )
   13727               )
   13728            )
   13729    );
   13730 
   13731    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   13732     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   13733     */
   13734 #define SNAN_MASK 0x0008000000000000ULL
   13735    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   13736    assign( is_SNAN,
   13737            mkAND1( is_NaN( frB_I64 ),
   13738                    binop( Iop_CmpEQ32,
   13739                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   13740                           mkU32( 0 ) ) ) );
   13741 
   13742    return IRExpr_ITE( mkexpr( is_SNAN ),
   13743                         unop( Iop_ReinterpI64asF64,
   13744                               binop( Iop_Xor64,
   13745                                      mkU64( SNAN_MASK ),
   13746                                      mkexpr( frB_I64 ) ) ),
   13747                       mkexpr( frD ));
   13748 }
   13749 
   13750 /*
   13751  * Miscellaneous VSX vector instructions
   13752  */
   13753 static Bool
   13754 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   13755 {
   13756    /* XX3-Form */
   13757    UChar opc1 = ifieldOPC( theInstr );
   13758    UChar XT = ifieldRegXT( theInstr );
   13759    UChar XB = ifieldRegXB( theInstr );
   13760 
   13761    if (opc1 != 0x3C) {
   13762       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   13763       return False;
   13764    }
   13765 
   13766    switch (opc2) {
   13767       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   13768       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   13769                    //             Double-Precision)
   13770       {
   13771          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   13772          IRExpr* rm  = get_IR_roundingmode();
   13773          IRTemp frB = newTemp(Ity_I64);
   13774          IRTemp frB2 = newTemp(Ity_I64);
   13775          Bool redp = opc2 == 0x1B4;
   13776          IRTemp sqrtHi = newTemp(Ity_F64);
   13777          IRTemp sqrtLo = newTemp(Ity_F64);
   13778          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   13779          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   13780 
   13781          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
   13782          if (!redp) {
   13783             assign( sqrtHi,
   13784                     binop( Iop_SqrtF64,
   13785                            rm,
   13786                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   13787             assign( sqrtLo,
   13788                     binop( Iop_SqrtF64,
   13789                            rm,
   13790                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   13791          }
   13792          putVSReg( XT,
   13793                    binop( Iop_64HLtoV128,
   13794                           unop( Iop_ReinterpF64asI64,
   13795                                 triop( Iop_DivF64,
   13796                                        rm,
   13797                                        ieee_one,
   13798                                        redp ? unop( Iop_ReinterpI64asF64,
   13799                                                     mkexpr( frB ) )
   13800                                             : mkexpr( sqrtHi ) ) ),
   13801                           unop( Iop_ReinterpF64asI64,
   13802                                 triop( Iop_DivF64,
   13803                                        rm,
   13804                                        ieee_one,
   13805                                        redp ? unop( Iop_ReinterpI64asF64,
   13806                                                     mkexpr( frB2 ) )
   13807                                             : mkexpr( sqrtLo ) ) ) ) );
   13808          break;
   13809 
   13810       }
   13811       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   13812       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   13813       {
   13814          IRTemp b3, b2, b1, b0;
   13815          IRTemp res0 = newTemp(Ity_I32);
   13816          IRTemp res1 = newTemp(Ity_I32);
   13817          IRTemp res2 = newTemp(Ity_I32);
   13818          IRTemp res3 = newTemp(Ity_I32);
   13819          IRTemp sqrt3 = newTemp(Ity_F64);
   13820          IRTemp sqrt2 = newTemp(Ity_F64);
   13821          IRTemp sqrt1 = newTemp(Ity_F64);
   13822          IRTemp sqrt0 = newTemp(Ity_F64);
   13823          IRExpr* rm  = get_IR_roundingmode();
   13824          Bool resp = opc2 == 0x134;
   13825 
   13826          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   13827 
   13828          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   13829          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
   13830          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13831 
   13832          if (!resp) {
   13833             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   13834             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   13835             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   13836             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   13837          }
   13838 
   13839          assign( res0,
   13840                  unop( Iop_ReinterpF32asI32,
   13841                        unop( Iop_TruncF64asF32,
   13842                              triop( Iop_DivF64r32,
   13843                                     rm,
   13844                                     ieee_one,
   13845                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   13846          assign( res1,
   13847                  unop( Iop_ReinterpF32asI32,
   13848                        unop( Iop_TruncF64asF32,
   13849                              triop( Iop_DivF64r32,
   13850                                     rm,
   13851                                     ieee_one,
   13852                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   13853          assign( res2,
   13854                  unop( Iop_ReinterpF32asI32,
   13855                        unop( Iop_TruncF64asF32,
   13856                              triop( Iop_DivF64r32,
   13857                                     rm,
   13858                                     ieee_one,
   13859                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   13860          assign( res3,
   13861                  unop( Iop_ReinterpF32asI32,
   13862                        unop( Iop_TruncF64asF32,
   13863                              triop( Iop_DivF64r32,
   13864                                     rm,
   13865                                     ieee_one,
   13866                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   13867          putVSReg( XT,
   13868                    binop( Iop_64HLtoV128,
   13869                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13870                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13871          break;
   13872       }
   13873       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   13874       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   13875       {
   13876          UChar XA = ifieldRegXA( theInstr );
   13877          IRTemp a3, a2, a1, a0;
   13878          IRTemp b3, b2, b1, b0;
   13879          IRTemp res0 = newTemp( Ity_I32 );
   13880          IRTemp res1 = newTemp( Ity_I32 );
   13881          IRTemp res2 = newTemp( Ity_I32 );
   13882          IRTemp res3 = newTemp( Ity_I32 );
   13883          IRTemp a0_I64 = newTemp( Ity_I64 );
   13884          IRTemp a1_I64 = newTemp( Ity_I64 );
   13885          IRTemp a2_I64 = newTemp( Ity_I64 );
   13886          IRTemp a3_I64 = newTemp( Ity_I64 );
   13887          IRTemp b0_I64 = newTemp( Ity_I64 );
   13888          IRTemp b1_I64 = newTemp( Ity_I64 );
   13889          IRTemp b2_I64 = newTemp( Ity_I64 );
   13890          IRTemp b3_I64 = newTemp( Ity_I64 );
   13891 
   13892          Bool isMin = opc2 == 0x320 ? True : False;
   13893 
   13894          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   13895          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   13896          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
   13897          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13898          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13899          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   13900          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   13901          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   13902          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   13903          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   13904          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   13905          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   13906          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   13907          assign( res0,
   13908                  unop( Iop_ReinterpF32asI32,
   13909                        unop( Iop_TruncF64asF32,
   13910                              unop( Iop_ReinterpI64asF64,
   13911                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   13912          assign( res1,
   13913                  unop( Iop_ReinterpF32asI32,
   13914                        unop( Iop_TruncF64asF32,
   13915                              unop( Iop_ReinterpI64asF64,
   13916                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   13917          assign( res2,
   13918                  unop( Iop_ReinterpF32asI32,
   13919                        unop( Iop_TruncF64asF32,
   13920                              unop( Iop_ReinterpI64asF64,
   13921                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   13922          assign( res3,
   13923                  unop( Iop_ReinterpF32asI32,
   13924                        unop( Iop_TruncF64asF32,
   13925                              unop( Iop_ReinterpI64asF64,
   13926                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   13927          putVSReg( XT,
   13928                    binop( Iop_64HLtoV128,
   13929                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13930                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13931          break;
   13932       }
   13933       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   13934       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   13935       {
   13936          UChar XA = ifieldRegXA( theInstr );
   13937          IRTemp frA = newTemp(Ity_I64);
   13938          IRTemp frB = newTemp(Ity_I64);
   13939          IRTemp frA2 = newTemp(Ity_I64);
   13940          IRTemp frB2 = newTemp(Ity_I64);
   13941          Bool isMin = opc2 == 0x3A0 ? True : False;
   13942 
   13943          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   13944          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   13945          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   13946          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   13947          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
   13948          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   13949 
   13950          break;
   13951       }
   13952       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   13953       {
   13954          UChar XA = ifieldRegXA( theInstr );
   13955          IRTemp frA = newTemp(Ity_I64);
   13956          IRTemp frB = newTemp(Ity_I64);
   13957          IRTemp frA2 = newTemp(Ity_I64);
   13958          IRTemp frB2 = newTemp(Ity_I64);
   13959          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   13960          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   13961          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   13962          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   13963 
   13964          DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13965          putVSReg( XT,
   13966                    binop( Iop_64HLtoV128,
   13967                           binop( Iop_Or64,
   13968                                  binop( Iop_And64,
   13969                                         mkexpr( frA ),
   13970                                         mkU64( SIGN_BIT ) ),
   13971                                  binop( Iop_And64,
   13972                                         mkexpr( frB ),
   13973                                         mkU64( SIGN_MASK ) ) ),
   13974                           binop( Iop_Or64,
   13975                                  binop( Iop_And64,
   13976                                         mkexpr( frA2 ),
   13977                                         mkU64( SIGN_BIT ) ),
   13978                                  binop( Iop_And64,
   13979                                         mkexpr( frB2 ),
   13980                                         mkU64( SIGN_MASK ) ) ) ) );
   13981          break;
   13982       }
   13983       case 0x340: // xvcpsgnsp
   13984       {
   13985          UChar XA = ifieldRegXA( theInstr );
   13986          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   13987          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   13988          IRTemp resHi = newTemp(Ity_I64);
   13989          IRTemp resLo = newTemp(Ity_I64);
   13990 
   13991          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   13992          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   13993          DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
   13994          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   13995          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   13996 
   13997          assign( resHi,
   13998                  binop( Iop_32HLto64,
   13999                         binop( Iop_Or32,
   14000                                binop( Iop_And32,
   14001                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   14002                                       mkU32( SIGN_BIT32 ) ),
   14003                                binop( Iop_And32,
   14004                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   14005                                       mkU32( SIGN_MASK32) ) ),
   14006 
   14007                         binop( Iop_Or32,
   14008                                binop( Iop_And32,
   14009                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   14010                                       mkU32( SIGN_BIT32 ) ),
   14011                                binop( Iop_And32,
   14012                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   14013                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14014          assign( resLo,
   14015                  binop( Iop_32HLto64,
   14016                         binop( Iop_Or32,
   14017                                binop( Iop_And32,
   14018                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   14019                                       mkU32( SIGN_BIT32 ) ),
   14020                                binop( Iop_And32,
   14021                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   14022                                       mkU32( SIGN_MASK32 ) ) ),
   14023 
   14024                         binop( Iop_Or32,
   14025                                binop( Iop_And32,
   14026                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   14027                                       mkU32( SIGN_BIT32 ) ),
   14028                                binop( Iop_And32,
   14029                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   14030                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14031          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   14032          break;
   14033       }
   14034       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   14035       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   14036       {
   14037          IRTemp frB = newTemp(Ity_F64);
   14038          IRTemp frB2 = newTemp(Ity_F64);
   14039          IRTemp abs_resultHi = newTemp(Ity_F64);
   14040          IRTemp abs_resultLo = newTemp(Ity_F64);
   14041          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   14042          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14043          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14044 
   14045          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
   14046          if (make_negative) {
   14047             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   14048             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   14049 
   14050          } else {
   14051             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   14052             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   14053          }
   14054          putVSReg( XT, binop( Iop_64HLtoV128,
   14055                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   14056                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   14057          break;
   14058       }
   14059       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   14060       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   14061       {
   14062          /*
   14063           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   14064           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   14065           * of this function is so easy using shifts, I choose to emulate this instruction that
   14066           * way versus a native instruction method of implementation.
   14067           */
   14068          Bool make_negative = (opc2 == 0x352) ? True : False;
   14069          IRTemp shiftVector = newTemp(Ity_V128);
   14070          IRTemp absVal_vector = newTemp(Ity_V128);
   14071          assign( shiftVector,
   14072                  binop( Iop_64HLtoV128,
   14073                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   14074                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   14075          assign( absVal_vector,
   14076                    binop( Iop_Shr32x4,
   14077                           binop( Iop_Shl32x4,
   14078                                  getVSReg( XB ),
   14079                                  mkexpr( shiftVector ) ),
   14080                           mkexpr( shiftVector ) ) );
   14081          if (make_negative) {
   14082             IRTemp signBit_vector = newTemp(Ity_V128);
   14083             assign( signBit_vector,
   14084                     binop( Iop_64HLtoV128,
   14085                            binop( Iop_32HLto64,
   14086                                   mkU32( 0x80000000 ),
   14087                                   mkU32( 0x80000000 ) ),
   14088                            binop( Iop_32HLto64,
   14089                                   mkU32( 0x80000000 ),
   14090                                   mkU32( 0x80000000 ) ) ) );
   14091             putVSReg( XT,
   14092                       binop( Iop_OrV128,
   14093                              mkexpr( absVal_vector ),
   14094                              mkexpr( signBit_vector ) ) );
   14095          } else {
   14096             putVSReg( XT, mkexpr( absVal_vector ) );
   14097          }
   14098          break;
   14099       }
   14100       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   14101       {
   14102          IRTemp frB = newTemp(Ity_F64);
   14103          IRTemp frB2 = newTemp(Ity_F64);
   14104          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14105          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14106          DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
   14107          putVSReg( XT,
   14108                    binop( Iop_64HLtoV128,
   14109                           unop( Iop_ReinterpF64asI64,
   14110                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   14111                           unop( Iop_ReinterpF64asI64,
   14112                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   14113          break;
   14114       }
   14115       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   14116       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   14117       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   14118       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   14119       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   14120       {
   14121          IRTemp frBHi_I64 = newTemp(Ity_I64);
   14122          IRTemp frBLo_I64 = newTemp(Ity_I64);
   14123          IRExpr * frD_fp_roundHi = NULL;
   14124          IRExpr * frD_fp_roundLo = NULL;
   14125 
   14126          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   14127          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
   14128          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   14129          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
   14130 
   14131          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
   14132          putVSReg( XT,
   14133                    binop( Iop_64HLtoV128,
   14134                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   14135                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   14136          break;
   14137       }
   14138       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   14139       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   14140       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   14141       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   14142       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   14143       {
   14144          const HChar * insn_suffix = NULL;
   14145          IROp op;
   14146          if (opc2 != 0x156) {
   14147             // Use pre-defined IRop's for vrfi{m|n|p|z}
   14148             switch (opc2) {
   14149                case 0x112:
   14150                   insn_suffix = "";
   14151                   op = Iop_RoundF32x4_RN;
   14152                   break;
   14153                case 0x172:
   14154                   insn_suffix = "m";
   14155                   op = Iop_RoundF32x4_RM;
   14156                   break;
   14157                case 0x152:
   14158                   insn_suffix = "p";
   14159                   op = Iop_RoundF32x4_RP;
   14160                   break;
   14161                case 0x132:
   14162                   insn_suffix = "z";
   14163                   op = Iop_RoundF32x4_RZ;
   14164                   break;
   14165 
   14166                default:
   14167                   vex_printf("Unrecognized opcode %x\n", opc2);
   14168                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
   14169             }
   14170             DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   14171             putVSReg( XT, unop( op, getVSReg(XB) ) );
   14172          } else {
   14173             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   14174             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   14175             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   14176             IRTemp b3_I64 = newTemp(Ity_I64);
   14177             IRTemp b2_I64 = newTemp(Ity_I64);
   14178             IRTemp b1_I64 = newTemp(Ity_I64);
   14179             IRTemp b0_I64 = newTemp(Ity_I64);
   14180 
   14181             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   14182             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   14183             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   14184             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   14185             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   14186             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   14187             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   14188             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   14189                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
   14190             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   14191                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
   14192             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   14193                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
   14194             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   14195                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
   14196             DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
   14197             putVSReg( XT,
   14198                       binop( Iop_64HLtoV128,
   14199                              binop( Iop_32HLto64,
   14200                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   14201                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   14202                              binop( Iop_32HLto64,
   14203                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   14204                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   14205          }
   14206          break;
   14207       }
   14208 
   14209       default:
   14210          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   14211          return False;
   14212    }
   14213    return True;
   14214 }
   14215 
   14216 
   14217 /*
   14218  * VSX Scalar Floating Point Arithmetic Instructions
   14219  */
   14220 static Bool
   14221 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   14222 {
   14223    /* XX3-Form */
   14224    UChar opc1 = ifieldOPC( theInstr );
   14225    UChar XT = ifieldRegXT( theInstr );
   14226    UChar XA = ifieldRegXA( theInstr );
   14227    UChar XB = ifieldRegXB( theInstr );
   14228    IRExpr* rm = get_IR_roundingmode();
   14229    IRTemp frA = newTemp(Ity_F64);
   14230    IRTemp frB = newTemp(Ity_F64);
   14231 
   14232    if (opc1 != 0x3C) {
   14233       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   14234       return False;
   14235    }
   14236 
   14237    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14238    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14239 
   14240    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   14241     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   14242     * element to zero where it makes sense to do so.
   14243     */
   14244    switch (opc2) {
   14245       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
   14246          DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14247          putVSReg( XT, binop( Iop_64HLtoV128,
   14248                               unop( Iop_ReinterpF64asI64,
   14249                                     binop( Iop_RoundF64toF32, rm,
   14250                                            triop( Iop_AddF64, rm,
   14251                                                   mkexpr( frA ),
   14252                                                   mkexpr( frB ) ) ) ),
   14253                               mkU64( 0 ) ) );
   14254          break;
   14255       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
   14256          DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14257          putVSReg( XT, binop( Iop_64HLtoV128,
   14258                               unop( Iop_ReinterpF64asI64,
   14259                                     binop( Iop_RoundF64toF32, rm,
   14260                                            triop( Iop_SubF64, rm,
   14261                                                   mkexpr( frA ),
   14262                                                   mkexpr( frB ) ) ) ),
   14263                               mkU64( 0 ) ) );
   14264          break;
   14265       case 0x080: // xsadddp (VSX scalar add double-precision)
   14266          DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14267          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14268                                                     triop( Iop_AddF64, rm,
   14269                                                            mkexpr( frA ),
   14270                                                            mkexpr( frB ) ) ),
   14271                               mkU64( 0 ) ) );
   14272          break;
   14273       case 0x060: // xsdivsp (VSX scalar divide single-precision)
   14274          DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14275          putVSReg( XT, binop( Iop_64HLtoV128,
   14276                               unop( Iop_ReinterpF64asI64,
   14277                                     binop( Iop_RoundF64toF32, rm,
   14278                                            triop( Iop_DivF64, rm,
   14279                                                   mkexpr( frA ),
   14280                                                   mkexpr( frB ) ) ) ),
   14281                                mkU64( 0 ) ) );
   14282          break;
   14283       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   14284          DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14285          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14286                                                     triop( Iop_DivF64, rm,
   14287                                                            mkexpr( frA ),
   14288                                                            mkexpr( frB ) ) ),
   14289                               mkU64( 0 ) ) );
   14290          break;
   14291       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
   14292                                * single-precision)
   14293                                */
   14294       {
   14295          IRTemp frT = newTemp(Ity_F64);
   14296          Bool mdp = opc2 == 0x024;
   14297          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14298          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14299                                                         getVSReg( XT ) ) ) );
   14300          putVSReg( XT,
   14301                    binop( Iop_64HLtoV128,
   14302                           unop( Iop_ReinterpF64asI64,
   14303                                 binop( Iop_RoundF64toF32, rm,
   14304                                        qop( Iop_MAddF64, rm,
   14305                                             mkexpr( frA ),
   14306                                             mkexpr( mdp ? frT : frB ),
   14307                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14308                           mkU64( 0 ) ) );
   14309          break;
   14310       }
   14311       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   14312       {
   14313          IRTemp frT = newTemp(Ity_F64);
   14314          Bool mdp = opc2 == 0x0A4;
   14315          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14316          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14317                                                         getVSReg( XT ) ) ) );
   14318          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14319                                                     qop( Iop_MAddF64, rm,
   14320                                                          mkexpr( frA ),
   14321                                                          mkexpr( mdp ? frT : frB ),
   14322                                                          mkexpr( mdp ? frB : frT ) ) ),
   14323                               mkU64( 0 ) ) );
   14324          break;
   14325       }
   14326       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
   14327                                * multiply-subtract single-precision)
   14328 			       */
   14329       {
   14330          IRTemp frT = newTemp(Ity_F64);
   14331          Bool mdp = opc2 == 0x064;
   14332          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14333          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14334                                                         getVSReg( XT ) ) ) );
   14335          putVSReg( XT,
   14336                    binop( Iop_64HLtoV128,
   14337                           unop( Iop_ReinterpF64asI64,
   14338                                 binop( Iop_RoundF64toF32, rm,
   14339                                        qop( Iop_MSubF64, rm,
   14340                                             mkexpr( frA ),
   14341                                             mkexpr( mdp ? frT : frB ),
   14342                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14343                           mkU64( 0 ) ) );
   14344          break;
   14345       }
   14346       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   14347       {
   14348          IRTemp frT = newTemp(Ity_F64);
   14349          Bool mdp = opc2 == 0x0E4;
   14350          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14351          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14352                                                         getVSReg( XT ) ) ) );
   14353          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14354                                                     qop( Iop_MSubF64, rm,
   14355                                                          mkexpr( frA ),
   14356                                                          mkexpr( mdp ? frT : frB ),
   14357                                                          mkexpr( mdp ? frB : frT ) ) ),
   14358                               mkU64( 0 ) ) );
   14359          break;
   14360       }
   14361       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   14362       {
   14363          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   14364           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   14365           * way it blindly negates the signbit, even if the floating point result is a NaN.
   14366           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   14367           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
   14368           * bit for NaN result.
   14369           */
   14370          Bool mdp = opc2 == 0x2A4;
   14371          IRTemp frT = newTemp(Ity_F64);
   14372          IRTemp maddResult = newTemp(Ity_I64);
   14373 
   14374          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14375          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14376                                                         getVSReg( XT ) ) ) );
   14377          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   14378                                                               mkexpr( frA ),
   14379                                                               mkexpr( mdp ? frT : frB ),
   14380                                                               mkexpr( mdp ? frB : frT ) ) ) );
   14381 
   14382          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   14383                               mkU64( 0 ) ) );
   14384          break;
   14385       }
   14386       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
   14387                                * multiply-add single-precision)
   14388                                */
   14389       {
   14390          Bool mdp = opc2 == 0x224;
   14391          IRTemp frT = newTemp(Ity_F64);
   14392          IRTemp maddResult = newTemp(Ity_I64);
   14393 
   14394          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14395          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14396                                                         getVSReg( XT ) ) ) );
   14397          assign( maddResult,
   14398                  unop( Iop_ReinterpF64asI64,
   14399                        binop( Iop_RoundF64toF32, rm,
   14400                               qop( Iop_MAddF64, rm,
   14401                                    mkexpr( frA ),
   14402                                    mkexpr( mdp ? frT : frB ),
   14403                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14404 
   14405          putVSReg( XT, binop( Iop_64HLtoV128,
   14406                               mkexpr( getNegatedResult(maddResult) ),
   14407                               mkU64( 0 ) ) );
   14408          break;
   14409       }
   14410       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
   14411                                * Multiply-Subtract Single-Precision)
   14412                                */
   14413       {
   14414          IRTemp frT = newTemp(Ity_F64);
   14415          Bool mdp = opc2 == 0x264;
   14416          IRTemp msubResult = newTemp(Ity_I64);
   14417 
   14418          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14419          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14420                                                         getVSReg( XT ) ) ) );
   14421          assign( msubResult,
   14422                  unop( Iop_ReinterpF64asI64,
   14423                        binop( Iop_RoundF64toF32, rm,
   14424                               qop( Iop_MSubF64, rm,
   14425                                    mkexpr( frA ),
   14426                                    mkexpr( mdp ? frT : frB ),
   14427                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14428 
   14429          putVSReg( XT, binop( Iop_64HLtoV128,
   14430                               mkexpr( getNegatedResult(msubResult) ),
   14431                               mkU64( 0 ) ) );
   14432 
   14433          break;
   14434       }
   14435 
   14436       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   14437       {
   14438          IRTemp frT = newTemp(Ity_F64);
   14439          Bool mdp = opc2 == 0x2E4;
   14440          IRTemp msubResult = newTemp(Ity_I64);
   14441 
   14442          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   14443          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14444                                                         getVSReg( XT ) ) ) );
   14445          assign(msubResult, unop( Iop_ReinterpF64asI64,
   14446                                       qop( Iop_MSubF64,
   14447                                            rm,
   14448                                            mkexpr( frA ),
   14449                                            mkexpr( mdp ? frT : frB ),
   14450                                            mkexpr( mdp ? frB : frT ) ) ));
   14451 
   14452          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   14453 
   14454          break;
   14455       }
   14456 
   14457       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
   14458          DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14459          putVSReg( XT, binop( Iop_64HLtoV128,
   14460                               unop( Iop_ReinterpF64asI64,
   14461                                     binop( Iop_RoundF64toF32, rm,
   14462                                            triop( Iop_MulF64, rm,
   14463                                                    mkexpr( frA ),
   14464                                                    mkexpr( frB ) ) ) ),
   14465                               mkU64( 0 ) ) );
   14466          break;
   14467 
   14468       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   14469          DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14470          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14471                                                     triop( Iop_MulF64, rm,
   14472                                                            mkexpr( frA ),
   14473                                                            mkexpr( frB ) ) ),
   14474                               mkU64( 0 ) ) );
   14475          break;
   14476       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   14477          DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14478          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14479                                                     triop( Iop_SubF64, rm,
   14480                                                            mkexpr( frA ),
   14481                                                            mkexpr( frB ) ) ),
   14482                               mkU64( 0 ) ) );
   14483          break;
   14484 
   14485       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
   14486          DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14487          putVSReg( XT,
   14488                    binop( Iop_64HLtoV128,
   14489                           unop( Iop_ReinterpF64asI64,
   14490                                 binop( Iop_RoundF64toF32, rm,
   14491                                        binop( Iop_SqrtF64, rm,
   14492                                               mkexpr( frB ) ) ) ),
   14493                           mkU64( 0 ) ) );
   14494          break;
   14495 
   14496       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   14497          DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14498          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14499                                                      binop( Iop_SqrtF64, rm,
   14500                                                             mkexpr( frB ) ) ),
   14501                                mkU64( 0 ) ) );
   14502          break;
   14503 
   14504       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   14505       {
   14506          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14507          IRTemp frA_I64 = newTemp(Ity_I64);
   14508          IRTemp frB_I64 = newTemp(Ity_I64);
   14509          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
   14510          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   14511          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   14512          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   14513          break;
   14514       }
   14515       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   14516       {
   14517          IRTemp frB_I64 = newTemp(Ity_I64);
   14518          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14519          IRTemp flags = newTemp(Ity_I32);
   14520          IRTemp  fe_flag, fg_flag;
   14521          fe_flag = fg_flag = IRTemp_INVALID;
   14522          DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14523          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   14524          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   14525          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   14526           * where fl_flag == 1 on ppc64.
   14527           */
   14528          assign( flags,
   14529                  binop( Iop_Or32,
   14530                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   14531                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   14532                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   14533          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   14534          break;
   14535       }
   14536 
   14537       default:
   14538          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   14539          return False;
   14540    }
   14541 
   14542    return True;
   14543 }
   14544 
   14545 
   14546 /*
   14547  * VSX Floating Point Compare Instructions
   14548  */
   14549 static Bool
   14550 dis_vx_cmp( UInt theInstr, UInt opc2 )
   14551 {
   14552    /* XX3-Form and XX2-Form */
   14553    UChar opc1 = ifieldOPC( theInstr );
   14554    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14555    IRTemp ccPPC32;
   14556    UChar XA       = ifieldRegXA ( theInstr );
   14557    UChar XB       = ifieldRegXB ( theInstr );
   14558    IRTemp frA     = newTemp(Ity_F64);
   14559    IRTemp frB     = newTemp(Ity_F64);
   14560 
   14561    if (opc1 != 0x3C) {
   14562       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   14563       return False;
   14564    }
   14565 
   14566    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14567    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14568    switch (opc2) {
   14569       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   14570          /* Note: Differences between xscmpudp and xscmpodp are only in
   14571           * exception flag settings, which aren't supported anyway. */
   14572          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   14573                                            crfD, (UInt)XA, (UInt)XB);
   14574          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   14575          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   14576          break;
   14577 
   14578       default:
   14579          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   14580          return False;
   14581    }
   14582    return True;
   14583 }
   14584 
   14585 static void
   14586 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   14587                  ppc_cmp_t cmp_type )
   14588 {
   14589    IRTemp frA_hi     = newTemp(Ity_F64);
   14590    IRTemp frB_hi     = newTemp(Ity_F64);
   14591    IRTemp frA_lo     = newTemp(Ity_F64);
   14592    IRTemp frB_lo     = newTemp(Ity_F64);
   14593    IRTemp ccPPC32    = newTemp(Ity_I32);
   14594    IRTemp ccIR_hi;
   14595    IRTemp ccIR_lo;
   14596 
   14597    IRTemp hiResult = newTemp(Ity_I64);
   14598    IRTemp loResult = newTemp(Ity_I64);
   14599    IRTemp hiEQlo = newTemp(Ity_I1);
   14600    IRTemp all_elem_true = newTemp(Ity_I32);
   14601    IRTemp all_elem_false = newTemp(Ity_I32);
   14602 
   14603    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   14604    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   14605    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   14606    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   14607 
   14608    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   14609                                        mkexpr( frA_hi ),
   14610                                        mkexpr( frB_hi ) ) );
   14611    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   14612                                        mkexpr( frA_lo ),
   14613                                        mkexpr( frB_lo ) ) );
   14614 
   14615    if (cmp_type != PPC_CMP_GE) {
   14616       assign( hiResult,
   14617               unop( Iop_1Sto64,
   14618                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   14619       assign( loResult,
   14620               unop( Iop_1Sto64,
   14621                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   14622    } else {
   14623       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   14624       // the other element compare may return "2" (for "equal to").
   14625       IRTemp lo_GE = newTemp(Ity_I1);
   14626       IRTemp hi_GE = newTemp(Ity_I1);
   14627 
   14628       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   14629                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   14630       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   14631 
   14632       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   14633                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   14634       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   14635    }
   14636 
   14637    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   14638    assign( hiEQlo,
   14639            binop( Iop_CmpEQ32,
   14640                   unop( Iop_64to32, mkexpr( hiResult ) ),
   14641                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   14642    putVSReg( XT,
   14643              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   14644 
   14645    assign( all_elem_true,
   14646            unop( Iop_1Uto32,
   14647                  mkAND1( mkexpr( hiEQlo ),
   14648                          binop( Iop_CmpEQ32,
   14649                                 mkU32( 0xffffffff ),
   14650                                 unop( Iop_64to32,
   14651                                 mkexpr( hiResult ) ) ) ) ) );
   14652 
   14653    assign( all_elem_false,
   14654            unop( Iop_1Uto32,
   14655                  mkAND1( mkexpr( hiEQlo ),
   14656                          binop( Iop_CmpEQ32,
   14657                                 mkU32( 0 ),
   14658                                 unop( Iop_64to32,
   14659                                 mkexpr( hiResult ) ) ) ) ) );
   14660    assign( ccPPC32,
   14661            binop( Iop_Or32,
   14662                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   14663                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   14664 
   14665    if (flag_rC) {
   14666       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   14667    }
   14668 }
   14669 
   14670 /*
   14671  * VSX Vector Compare Instructions
   14672  */
   14673 static Bool
   14674 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   14675 {
   14676    /* XX3-Form */
   14677    UChar opc1 = ifieldOPC( theInstr );
   14678    UChar XT = ifieldRegXT ( theInstr );
   14679    UChar XA = ifieldRegXA ( theInstr );
   14680    UChar XB = ifieldRegXB ( theInstr );
   14681    UChar flag_rC  = ifieldBIT10(theInstr);
   14682    IRTemp vA = newTemp( Ity_V128 );
   14683    IRTemp vB = newTemp( Ity_V128 );
   14684 
   14685    if (opc1 != 0x3C) {
   14686       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   14687       return False;
   14688    }
   14689 
   14690    assign( vA, getVSReg( XA ) );
   14691    assign( vB, getVSReg( XB ) );
   14692 
   14693    switch (opc2) {
   14694       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   14695       {
   14696          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14697              (UInt)XT, (UInt)XA, (UInt)XB);
   14698          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   14699          break;
   14700       }
   14701 
   14702       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   14703       {
   14704          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14705              (UInt)XT, (UInt)XA, (UInt)XB);
   14706          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   14707          break;
   14708       }
   14709 
   14710       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   14711       {
   14712          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14713              (UInt)XT, (UInt)XA, (UInt)XB);
   14714          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   14715          break;
   14716       }
   14717 
   14718       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   14719       {
   14720          IRTemp vD = newTemp(Ity_V128);
   14721 
   14722          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14723              (UInt)XT, (UInt)XA, (UInt)XB);
   14724          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   14725          putVSReg( XT, mkexpr(vD) );
   14726          if (flag_rC) {
   14727             set_AV_CR6( mkexpr(vD), True );
   14728          }
   14729          break;
   14730       }
   14731 
   14732       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   14733       {
   14734          IRTemp vD = newTemp(Ity_V128);
   14735 
   14736          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14737              (UInt)XT, (UInt)XA, (UInt)XB);
   14738          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   14739          putVSReg( XT, mkexpr(vD) );
   14740          if (flag_rC) {
   14741             set_AV_CR6( mkexpr(vD), True );
   14742          }
   14743          break;
   14744       }
   14745 
   14746       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   14747       {
   14748          IRTemp vD = newTemp(Ity_V128);
   14749 
   14750          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   14751              (UInt)XT, (UInt)XA, (UInt)XB);
   14752          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   14753          putVSReg( XT, mkexpr(vD) );
   14754          if (flag_rC) {
   14755             set_AV_CR6( mkexpr(vD), True );
   14756          }
   14757          break;
   14758       }
   14759 
   14760       default:
   14761          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   14762          return False;
   14763    }
   14764    return True;
   14765 }
   14766 /*
   14767  * Miscellaneous VSX Scalar Instructions
   14768  */
   14769 static Bool
   14770 dis_vxs_misc( UInt theInstr, UInt opc2 )
   14771 {
   14772    /* XX3-Form and XX2-Form */
   14773    UChar opc1 = ifieldOPC( theInstr );
   14774    UChar XT = ifieldRegXT ( theInstr );
   14775    UChar XA = ifieldRegXA ( theInstr );
   14776    UChar XB = ifieldRegXB ( theInstr );
   14777    IRTemp vA = newTemp( Ity_V128 );
   14778    IRTemp vB = newTemp( Ity_V128 );
   14779 
   14780    if (opc1 != 0x3C) {
   14781       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   14782       return False;
   14783    }
   14784 
   14785    assign( vA, getVSReg( XA ) );
   14786    assign( vB, getVSReg( XB ) );
   14787 
   14788    /* For all the VSX move instructions, the contents of doubleword element 1
   14789     * of VSX[XT] are undefined after the operation; therefore, we can simply
   14790     * move the entire array element where it makes sense to do so.
   14791     */
   14792 
   14793    switch (opc2) {
   14794       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   14795       {
   14796          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   14797          IRTemp absVal = newTemp(Ity_V128);
   14798          assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
   14799          DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14800          putVSReg(XT, mkexpr(absVal));
   14801          break;
   14802       }
   14803       case 0x2C0: // xscpsgndp
   14804       {
   14805          /* Scalar copy sign double-precision */
   14806          IRTemp vecA_signbit = newTemp(Ity_V128);
   14807          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   14808          IRTemp vec_result = newTemp(Ity_V128);
   14809          DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   14810          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   14811                                                              mkexpr( vB ),
   14812                                                              mkU8( 1 ) ),
   14813                                          mkU8( 1 ) ) );
   14814          assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
   14815                                                           mkexpr( vA ),
   14816                                                           mkU8( 127 ) ),
   14817                                       mkU8( 127 ) ) );
   14818          assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
   14819          putVSReg(XT, mkexpr(vec_result));
   14820          break;
   14821       }
   14822       case 0x2D2: // xsnabsdp
   14823       {
   14824          /* Scalar negative absolute value double-precision */
   14825          IRTemp vec_neg_signbit = newTemp(Ity_V128);
   14826          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14827          assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
   14828                                                             mkV128( 0xffff ),
   14829                                                             mkU8( 1 ) ) ) );
   14830          putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
   14831          break;
   14832       }
   14833       case 0x2F2: // xsnegdp
   14834       {
   14835          /* Scalar negate double-precision */
   14836          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   14837          IRTemp vecB_signbit_comp = newTemp(Ity_V128);
   14838          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   14839          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   14840                                                              mkexpr( vB ),
   14841                                                              mkU8( 1 ) ),
   14842                                          mkU8( 1 ) ) );
   14843          assign( vecB_signbit_comp, binop( Iop_ShlV128,
   14844                                            unop( Iop_NotV128,
   14845                                                  binop( Iop_ShrV128,
   14846                                                         mkexpr( vB ),
   14847                                                         mkU8( 127 ) ) ),
   14848                                            mkU8( 127 ) ) );
   14849          putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
   14850                               mkexpr( vecB_signbit_comp ) ) );
   14851          break;
   14852       }
   14853       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   14854       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   14855       {
   14856          IRTemp frA     = newTemp(Ity_I64);
   14857          IRTemp frB     = newTemp(Ity_I64);
   14858          Bool isMin = opc2 == 0x2A0 ? True : False;
   14859          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
   14860 
   14861          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   14862          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   14863          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   14864 
   14865          break;
   14866       }
   14867       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   14868       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   14869       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   14870       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   14871       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   14872       {
   14873          IRTemp frB_I64 = newTemp(Ity_I64);
   14874          IRExpr * frD_fp_round = NULL;
   14875 
   14876          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   14877          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
   14878 
   14879          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
   14880          putVSReg( XT,
   14881                    binop( Iop_64HLtoV128,
   14882                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   14883                           mkU64( 0 ) ) );
   14884          break;
   14885       }
   14886       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
   14887       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
   14888                    * single-Precision)
   14889                    */
   14890       {
   14891          IRTemp frB = newTemp(Ity_F64);
   14892          IRTemp sqrt = newTemp(Ity_F64);
   14893          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14894          IRExpr* rm  = get_IR_roundingmode();
   14895          Bool redp = opc2 == 0x034;
   14896          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT,
   14897              (UInt)XB);
   14898 
   14899          assign( frB,
   14900                  unop( Iop_ReinterpI64asF64,
   14901                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   14902 
   14903          if (!redp)
   14904             assign( sqrt,
   14905                     binop( Iop_SqrtF64,
   14906                            rm,
   14907                            mkexpr(frB) ) );
   14908          putVSReg( XT,
   14909                       binop( Iop_64HLtoV128,
   14910                              unop( Iop_ReinterpF64asI64,
   14911                                    binop( Iop_RoundF64toF32, rm,
   14912                                           triop( Iop_DivF64,
   14913                                                  rm,
   14914                                                  ieee_one,
   14915                                                  redp ? mkexpr( frB ) :
   14916                                                         mkexpr( sqrt ) ) ) ),
   14917                              mkU64( 0 ) ) );
   14918          break;
   14919       }
   14920 
   14921       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   14922       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   14923 
   14924       {
   14925          IRTemp frB = newTemp(Ity_F64);
   14926          IRTemp sqrt = newTemp(Ity_F64);
   14927          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14928          IRExpr* rm  = get_IR_roundingmode();
   14929          Bool redp = opc2 == 0x0B4;
   14930          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
   14931          assign( frB,
   14932                  unop( Iop_ReinterpI64asF64,
   14933                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   14934 
   14935          if (!redp)
   14936             assign( sqrt,
   14937                     binop( Iop_SqrtF64,
   14938                            rm,
   14939                            mkexpr(frB) ) );
   14940          putVSReg( XT,
   14941                       binop( Iop_64HLtoV128,
   14942                              unop( Iop_ReinterpF64asI64,
   14943                                    triop( Iop_DivF64,
   14944                                           rm,
   14945                                           ieee_one,
   14946                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   14947                              mkU64( 0 ) ) );
   14948          break;
   14949       }
   14950 
   14951       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
   14952       {
   14953          IRTemp frB = newTemp(Ity_F64);
   14954          IRExpr* rm  = get_IR_roundingmode();
   14955          DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB);
   14956          assign( frB,
   14957                  unop( Iop_ReinterpI64asF64,
   14958                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   14959 
   14960          putVSReg( XT, binop( Iop_64HLtoV128,
   14961                               unop( Iop_ReinterpF64asI64,
   14962                                     binop( Iop_RoundF64toF32,
   14963                                            rm,
   14964                                            mkexpr( frB ) ) ),
   14965                               mkU64( 0 ) ) );
   14966          break;
   14967       }
   14968 
   14969       default:
   14970          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   14971          return False;
   14972    }
   14973    return True;
   14974 }
   14975 
   14976 /*
   14977  * VSX Logical Instructions
   14978  */
   14979 static Bool
   14980 dis_vx_logic ( UInt theInstr, UInt opc2 )
   14981 {
   14982    /* XX3-Form */
   14983    UChar opc1 = ifieldOPC( theInstr );
   14984    UChar XT = ifieldRegXT ( theInstr );
   14985    UChar XA = ifieldRegXA ( theInstr );
   14986    UChar XB = ifieldRegXB ( theInstr );
   14987    IRTemp vA = newTemp( Ity_V128 );
   14988    IRTemp vB = newTemp( Ity_V128 );
   14989 
   14990    if (opc1 != 0x3C) {
   14991       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   14992       return False;
   14993    }
   14994 
   14995    assign( vA, getVSReg( XA ) );
   14996    assign( vB, getVSReg( XB ) );
   14997 
   14998    switch (opc2) {
   14999       case 0x268: // xxlxor
   15000          DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15001          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   15002          break;
   15003       case 0x248: // xxlor
   15004          DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15005          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   15006          break;
   15007       case 0x288: // xxlnor
   15008          DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15009          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   15010                                                  mkexpr( vB ) ) ) );
   15011          break;
   15012       case 0x208: // xxland
   15013          DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15014          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   15015          break;
   15016       case 0x228: //xxlandc
   15017          DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15018          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   15019                                                                mkexpr( vB ) ) ) );
   15020          break;
   15021       case 0x2A8: // xxlorc (VSX Logical OR with complement)
   15022          DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15023          putVSReg( XT, binop( Iop_OrV128,
   15024                               mkexpr( vA ),
   15025                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
   15026          break;
   15027       case 0x2C8: // xxlnand (VSX Logical NAND)
   15028          DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15029          putVSReg( XT, unop( Iop_NotV128,
   15030                              binop( Iop_AndV128, mkexpr( vA ),
   15031                                     mkexpr( vB ) ) ) );
   15032          break;
   15033       case 0x2E8: // xxleqv (VSX Logical Equivalence)
   15034          DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   15035          putVSReg( XT, unop( Iop_NotV128,
   15036                              binop( Iop_XorV128,
   15037                              mkexpr( vA ), mkexpr( vB ) ) ) );
   15038          break;
   15039       default:
   15040          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   15041          return False;
   15042    }
   15043    return True;
   15044 }
   15045 
   15046 /*
   15047  * VSX Load Instructions
   15048  * NOTE: VSX supports word-aligned storage access.
   15049  */
   15050 static Bool
   15051 dis_vx_load ( UInt theInstr )
   15052 {
   15053    /* XX1-Form */
   15054    UChar opc1 = ifieldOPC( theInstr );
   15055    UChar XT = ifieldRegXT ( theInstr );
   15056    UChar rA_addr = ifieldRegA( theInstr );
   15057    UChar rB_addr = ifieldRegB( theInstr );
   15058    UInt opc2 = ifieldOPClo10( theInstr );
   15059 
   15060    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15061    IRTemp EA = newTemp( ty );
   15062 
   15063    if (opc1 != 0x1F) {
   15064       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   15065       return False;
   15066    }
   15067 
   15068    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15069 
   15070    switch (opc2) {
   15071    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
   15072    {
   15073       IRExpr * exp;
   15074       DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15075       exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
   15076       putVSReg( XT, binop( Iop_64HLtoV128,
   15077                            unop( Iop_32Uto64, exp),
   15078                            mkU64(0) ) );
   15079       break;
   15080    }
   15081    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
   15082    {
   15083       IRExpr * exp;
   15084       DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15085       exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
   15086       putVSReg( XT, binop( Iop_64HLtoV128,
   15087                            unop( Iop_32Sto64, exp),
   15088                            mkU64(0) ) );
   15089       break;
   15090    }
   15091    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
   15092    {
   15093       IRExpr * exp;
   15094       DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15095       /* Take 32-bit floating point value in the upper half of the fetched
   15096        * 64-bit value, convert to 64-bit floating point value and load into
   15097        * top word of V128.
   15098        */
   15099       exp = unop( Iop_ReinterpF64asI64,
   15100                   unop( Iop_F32toF64,
   15101                         unop( Iop_ReinterpI32asF32,
   15102                               unop( Iop_64HIto32,
   15103                                     loadBE( Ity_I64, mkexpr( EA ) ) ) ) ) );
   15104 
   15105       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
   15106       break;
   15107    }
   15108    case 0x24C: // lxsdx
   15109    {
   15110       IRExpr * exp;
   15111       DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15112       exp = loadBE( Ity_I64, mkexpr( EA ) );
   15113       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   15114       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   15115       // are undefined after this operation, we can just do a splat op.
   15116       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   15117       break;
   15118    }
   15119    case 0x34C: // lxvd2x
   15120    {
   15121       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   15122       IRExpr * high, *low;
   15123       ULong ea_off = 8;
   15124       IRExpr* high_addr;
   15125       DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15126       high = loadBE( Ity_I64, mkexpr( EA ) );
   15127       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   15128             : mkU32( ea_off ) );
   15129       low = loadBE( Ity_I64, high_addr );
   15130       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   15131       break;
   15132    }
   15133    case 0x14C: // lxvdsx
   15134    {
   15135       IRTemp data = newTemp(Ity_I64);
   15136       DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15137       assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
   15138       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   15139       break;
   15140    }
   15141    case 0x30C:
   15142    {
   15143       IRExpr * t3, *t2, *t1, *t0;
   15144       UInt ea_off = 0;
   15145       IRExpr* irx_addr;
   15146 
   15147       DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   15148       t3 = loadBE( Ity_I32,  mkexpr( EA ) );
   15149       ea_off += 4;
   15150       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15151                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15152       t2 = loadBE( Ity_I32, irx_addr );
   15153       ea_off += 4;
   15154       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15155                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15156       t1 = loadBE( Ity_I32, irx_addr );
   15157       ea_off += 4;
   15158       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15159                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15160       t0 = loadBE( Ity_I32, irx_addr );
   15161       putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
   15162                            binop( Iop_32HLto64, t1, t0 ) ) );
   15163       break;
   15164    }
   15165    default:
   15166       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   15167       return False;
   15168    }
   15169    return True;
   15170 }
   15171 
   15172 /*
   15173  * VSX Store Instructions
   15174  * NOTE: VSX supports word-aligned storage access.
   15175  */
   15176 static Bool
   15177 dis_vx_store ( UInt theInstr )
   15178 {
   15179    /* XX1-Form */
   15180    UChar opc1 = ifieldOPC( theInstr );
   15181    UChar XS = ifieldRegXS( theInstr );
   15182    UChar rA_addr = ifieldRegA( theInstr );
   15183    UChar rB_addr = ifieldRegB( theInstr );
   15184    IRTemp vS = newTemp( Ity_V128 );
   15185    UInt opc2 = ifieldOPClo10( theInstr );
   15186 
   15187    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15188    IRTemp EA = newTemp( ty );
   15189 
   15190    if (opc1 != 0x1F) {
   15191       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   15192       return False;
   15193    }
   15194 
   15195    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15196    assign( vS, getVSReg( XS ) );
   15197 
   15198    switch (opc2) {
   15199    case 0x08C:
   15200    {
   15201      /* Need the next to the most significant 32-bit word from
   15202       * the 128-bit vector.
   15203       */
   15204       IRExpr * high64, * low32;
   15205       DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15206       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15207       low32  = unop( Iop_64to32, high64 );
   15208       storeBE( mkexpr( EA ), low32 );
   15209       break;
   15210    }
   15211    case 0x28C:
   15212    {
   15213       IRTemp high64 = newTemp(Ity_F64);
   15214       IRTemp val32  = newTemp(Ity_I32);
   15215       DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15216       assign(high64, unop( Iop_ReinterpI64asF64,
   15217                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
   15218       assign(val32, unop( Iop_ReinterpF32asI32,
   15219                           unop( Iop_TruncF64asF32,
   15220                                 mkexpr(high64) ) ) );
   15221       storeBE( mkexpr( EA ), mkexpr( val32 ) );
   15222       break;
   15223    }
   15224    case 0x2CC:
   15225    {
   15226       IRExpr * high64;
   15227       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15228       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15229       storeBE( mkexpr( EA ), high64 );
   15230       break;
   15231    }
   15232    case 0x3CC:
   15233    {
   15234       IRExpr * high64, *low64;
   15235       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15236       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15237       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   15238       storeBE( mkexpr( EA ), high64 );
   15239       storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
   15240             : mkU32( 8 ) ), low64 );
   15241       break;
   15242    }
   15243    case 0x38C:
   15244    {
   15245       UInt ea_off = 0;
   15246       IRExpr* irx_addr;
   15247       IRTemp hi64 = newTemp( Ity_I64 );
   15248       IRTemp lo64 = newTemp( Ity_I64 );
   15249 
   15250       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   15251 
   15252       // This instruction supports word-aligned stores, so EA may not be
   15253       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   15254       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   15255       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   15256 
   15257       storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   15258       ea_off += 4;
   15259       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15260                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15261       storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   15262       ea_off += 4;
   15263       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15264                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15265       storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   15266       ea_off += 4;
   15267       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15268                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15269       storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   15270 
   15271       break;
   15272    }
   15273    default:
   15274       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   15275       return False;
   15276    }
   15277    return True;
   15278 }
   15279 
   15280 /*
   15281  * VSX permute and other miscealleous instructions
   15282  */
   15283 static Bool
   15284 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   15285 {
   15286    /* XX3-Form */
   15287    UChar opc1 = ifieldOPC( theInstr );
   15288    UChar XT = ifieldRegXT ( theInstr );
   15289    UChar XA = ifieldRegXA ( theInstr );
   15290    UChar XB = ifieldRegXB ( theInstr );
   15291    IRTemp vT = newTemp( Ity_V128 );
   15292    IRTemp vA = newTemp( Ity_V128 );
   15293    IRTemp vB = newTemp( Ity_V128 );
   15294 
   15295    if (opc1 != 0x3C) {
   15296       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   15297       return False;
   15298    }
   15299 
   15300    assign( vA, getVSReg( XA ) );
   15301    assign( vB, getVSReg( XB ) );
   15302 
   15303    switch (opc2) {
   15304       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   15305       {
   15306          UChar SHW = ifieldSHW ( theInstr );
   15307          IRTemp result = newTemp(Ity_V128);
   15308          if ( SHW != 0 ) {
   15309              IRTemp hi = newTemp(Ity_V128);
   15310              IRTemp lo = newTemp(Ity_V128);
   15311              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   15312              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   15313              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   15314          } else
   15315              assign ( result, mkexpr(vA) );
   15316          DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
   15317          putVSReg( XT, mkexpr(result) );
   15318          break;
   15319       }
   15320       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   15321       {
   15322          UChar DM = ifieldDM ( theInstr );
   15323          IRTemp hi = newTemp(Ity_I64);
   15324          IRTemp lo = newTemp(Ity_I64);
   15325 
   15326          if (DM & 0x2)
   15327            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   15328          else
   15329            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   15330 
   15331          if (DM & 0x1)
   15332            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   15333          else
   15334            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   15335 
   15336          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   15337 
   15338          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
   15339          putVSReg( XT, mkexpr( vT ) );
   15340          break;
   15341       }
   15342       case 0x48: // xxmrghw (VSX Merge High Word)
   15343       case 0xc8: // xxmrglw (VSX Merge Low Word)
   15344       {
   15345          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
   15346          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   15347          IRTemp a64 = newTemp(Ity_I64);
   15348          IRTemp ahi32 = newTemp(Ity_I32);
   15349          IRTemp alo32 = newTemp(Ity_I32);
   15350          IRTemp b64 = newTemp(Ity_I64);
   15351          IRTemp bhi32 = newTemp(Ity_I32);
   15352          IRTemp blo32 = newTemp(Ity_I32);
   15353 
   15354          assign( a64, unop(word_op, mkexpr(vA)) );
   15355          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   15356          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   15357 
   15358          assign( b64, unop(word_op, mkexpr(vB)) );
   15359          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   15360          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   15361 
   15362          assign( vT, binop(Iop_64HLtoV128,
   15363                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   15364                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   15365 
   15366          DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
   15367          putVSReg( XT, mkexpr( vT ) );
   15368          break;
   15369       }
   15370       case 0x018: // xxsel (VSX Select)
   15371       {
   15372          UChar XC = ifieldRegXC(theInstr);
   15373          IRTemp vC = newTemp( Ity_V128 );
   15374          assign( vC, getVSReg( XC ) );
   15375          DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
   15376          /* vD = (vA & ~vC) | (vB & vC) */
   15377          putVSReg( XT, binop(Iop_OrV128,
   15378             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   15379             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   15380          break;
   15381       }
   15382       case 0x148: // xxspltw (VSX Splat Word)
   15383       {
   15384          UChar UIM   = ifieldRegA(theInstr) & 3;
   15385          UChar sh_uim = (3 - (UIM)) * 32;
   15386          DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
   15387          putVSReg( XT,
   15388                    unop( Iop_Dup32x4,
   15389                          unop( Iop_V128to32,
   15390                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   15391          break;
   15392       }
   15393 
   15394       default:
   15395          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   15396          return False;
   15397    }
   15398    return True;
   15399 }
   15400 
   15401 /*
   15402   AltiVec Load Instructions
   15403 */
   15404 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
   15405 {
   15406    /* X-Form */
   15407    UChar opc1     = ifieldOPC(theInstr);
   15408    UChar vD_addr  = ifieldRegDS(theInstr);
   15409    UChar rA_addr  = ifieldRegA(theInstr);
   15410    UChar rB_addr  = ifieldRegB(theInstr);
   15411    UInt  opc2     = ifieldOPClo10(theInstr);
   15412    UChar b0       = ifieldBIT0(theInstr);
   15413 
   15414    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   15415    IRTemp EA         = newTemp(ty);
   15416    IRTemp EA_align16 = newTemp(ty);
   15417 
   15418    if (opc1 != 0x1F || b0 != 0) {
   15419       vex_printf("dis_av_load(ppc)(instr)\n");
   15420       return False;
   15421    }
   15422 
   15423    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   15424    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   15425 
   15426    switch (opc2) {
   15427 
   15428    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   15429       IRDirty* d;
   15430       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15431       IRExpr** args = mkIRExprVec_4(
   15432                          IRExpr_BBPTR(),
   15433                          mkU32(vD_off),
   15434                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15435                                           mkU32(0xF)),
   15436                          mkU32(0)/*left*/ );
   15437       if (!mode64) {
   15438          d = unsafeIRDirty_0_N (
   15439                         0/*regparms*/,
   15440                         "ppc32g_dirtyhelper_LVS",
   15441                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15442                         args );
   15443       } else {
   15444          d = unsafeIRDirty_0_N (
   15445                         0/*regparms*/,
   15446                         "ppc64g_dirtyhelper_LVS",
   15447                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15448                         args );
   15449       }
   15450       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15451       /* declare guest state effects */
   15452       d->nFxState = 1;
   15453       vex_bzero(&d->fxState, sizeof(d->fxState));
   15454       d->fxState[0].fx     = Ifx_Write;
   15455       d->fxState[0].offset = vD_off;
   15456       d->fxState[0].size   = sizeof(U128);
   15457 
   15458       /* execute the dirty call, side-effecting guest state */
   15459       stmt( IRStmt_Dirty(d) );
   15460       break;
   15461    }
   15462    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   15463       IRDirty* d;
   15464       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15465       IRExpr** args = mkIRExprVec_4(
   15466                          IRExpr_BBPTR(),
   15467                          mkU32(vD_off),
   15468                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15469                                           mkU32(0xF)),
   15470                          mkU32(1)/*right*/ );
   15471       if (!mode64) {
   15472          d = unsafeIRDirty_0_N (
   15473                         0/*regparms*/,
   15474                         "ppc32g_dirtyhelper_LVS",
   15475                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15476                         args );
   15477       } else {
   15478          d = unsafeIRDirty_0_N (
   15479                         0/*regparms*/,
   15480                         "ppc64g_dirtyhelper_LVS",
   15481                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15482                         args );
   15483       }
   15484       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15485       /* declare guest state effects */
   15486       d->nFxState = 1;
   15487       vex_bzero(&d->fxState, sizeof(d->fxState));
   15488       d->fxState[0].fx     = Ifx_Write;
   15489       d->fxState[0].offset = vD_off;
   15490       d->fxState[0].size   = sizeof(U128);
   15491 
   15492       /* execute the dirty call, side-effecting guest state */
   15493       stmt( IRStmt_Dirty(d) );
   15494       break;
   15495    }
   15496    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   15497       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15498       /* loads addressed byte into vector[EA[0:3]
   15499          since all other destination bytes are undefined,
   15500          can simply load entire vector from 16-aligned EA */
   15501       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   15502       break;
   15503 
   15504    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   15505       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15506       /* see note for lvebx */
   15507       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   15508       break;
   15509 
   15510    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   15511       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15512       /* see note for lvebx */
   15513       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   15514       break;
   15515 
   15516    case 0x067: // lvx (Load Vector Indexed, AV p127)
   15517       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15518       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   15519       break;
   15520 
   15521    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   15522       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15523       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   15524       break;
   15525 
   15526    default:
   15527       vex_printf("dis_av_load(ppc)(opc2)\n");
   15528       return False;
   15529    }
   15530    return True;
   15531 }
   15532 
   15533 /*
   15534   AltiVec Store Instructions
   15535 */
   15536 static Bool dis_av_store ( UInt theInstr )
   15537 {
   15538    /* X-Form */
   15539    UChar opc1     = ifieldOPC(theInstr);
   15540    UChar vS_addr  = ifieldRegDS(theInstr);
   15541    UChar rA_addr  = ifieldRegA(theInstr);
   15542    UChar rB_addr  = ifieldRegB(theInstr);
   15543    UInt  opc2     = ifieldOPClo10(theInstr);
   15544    UChar b0       = ifieldBIT0(theInstr);
   15545 
   15546    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   15547    IRTemp EA           = newTemp(ty);
   15548    IRTemp addr_aligned = newTemp(ty);
   15549    IRTemp vS           = newTemp(Ity_V128);
   15550    IRTemp eb           = newTemp(Ity_I8);
   15551    IRTemp idx          = newTemp(Ity_I8);
   15552 
   15553    if (opc1 != 0x1F || b0 != 0) {
   15554       vex_printf("dis_av_store(ppc)(instr)\n");
   15555       return False;
   15556    }
   15557 
   15558    assign( vS, getVReg(vS_addr));
   15559    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   15560 
   15561    switch (opc2) {
   15562    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   15563       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15564       assign( eb, binop(Iop_And8, mkU8(0xF),
   15565                         unop(Iop_32to8,
   15566                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   15567       assign( idx, binop(Iop_Shl8,
   15568                          binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   15569                          mkU8(3)) );
   15570       storeBE( mkexpr(EA),
   15571                unop(Iop_32to8, unop(Iop_V128to32,
   15572                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   15573       break;
   15574    }
   15575    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   15576       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15577       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   15578       assign( eb, binop(Iop_And8, mkU8(0xF),
   15579                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   15580       assign( idx, binop(Iop_Shl8,
   15581                          binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   15582                          mkU8(3)) );
   15583       storeBE( mkexpr(addr_aligned),
   15584                unop(Iop_32to16, unop(Iop_V128to32,
   15585                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   15586       break;
   15587    }
   15588    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   15589       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15590       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   15591       assign( eb, binop(Iop_And8, mkU8(0xF),
   15592                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   15593       assign( idx, binop(Iop_Shl8,
   15594                          binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   15595                          mkU8(3)) );
   15596       storeBE( mkexpr(addr_aligned),
   15597                unop(Iop_V128to32,
   15598                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   15599       break;
   15600    }
   15601 
   15602    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   15603       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15604       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   15605       break;
   15606 
   15607    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   15608       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   15609       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   15610       break;
   15611 
   15612    default:
   15613       vex_printf("dis_av_store(ppc)(opc2)\n");
   15614       return False;
   15615    }
   15616    return True;
   15617 }
   15618 
   15619 /*
   15620   AltiVec Arithmetic Instructions
   15621 */
   15622 static Bool dis_av_arith ( UInt theInstr )
   15623 {
   15624    /* VX-Form */
   15625    UChar opc1     = ifieldOPC(theInstr);
   15626    UChar vD_addr  = ifieldRegDS(theInstr);
   15627    UChar vA_addr  = ifieldRegA(theInstr);
   15628    UChar vB_addr  = ifieldRegB(theInstr);
   15629    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   15630 
   15631    IRTemp vA = newTemp(Ity_V128);
   15632    IRTemp vB = newTemp(Ity_V128);
   15633    IRTemp z3 = newTemp(Ity_I64);
   15634    IRTemp z2 = newTemp(Ity_I64);
   15635    IRTemp z1 = newTemp(Ity_I64);
   15636    IRTemp z0 = newTemp(Ity_I64);
   15637    IRTemp aEvn, aOdd;
   15638    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   15639    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   15640    IRTemp b3, b2, b1, b0;
   15641 
   15642    aEvn = aOdd = IRTemp_INVALID;
   15643    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   15644    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   15645    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   15646 
   15647    assign( vA, getVReg(vA_addr));
   15648    assign( vB, getVReg(vB_addr));
   15649 
   15650    if (opc1 != 0x4) {
   15651       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   15652       return False;
   15653    }
   15654 
   15655    switch (opc2) {
   15656    /* Add */
   15657    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   15658       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15659       /* unsigned_ov(x+y) = (y >u not(x)) */
   15660       putVReg( vD_addr, binop(Iop_ShrN32x4,
   15661                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   15662                                     unop(Iop_NotV128, mkexpr(vA))),
   15663                               mkU8(31)) );
   15664       break;
   15665    }
   15666    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   15667       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15668       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   15669       break;
   15670 
   15671    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   15672       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15673       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   15674       break;
   15675 
   15676    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   15677       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15678       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   15679       break;
   15680 
   15681    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
   15682       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15683       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
   15684       break;
   15685 
   15686    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   15687       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15688       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   15689       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   15690       break;
   15691 
   15692    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   15693       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15694       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   15695       // TODO: set VSCR[SAT]
   15696       break;
   15697 
   15698    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   15699       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15700       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   15701       // TODO: set VSCR[SAT]
   15702       break;
   15703 
   15704    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   15705       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15706       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   15707       // TODO: set VSCR[SAT]
   15708       break;
   15709 
   15710    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   15711       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15712       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   15713       // TODO: set VSCR[SAT]
   15714       break;
   15715 
   15716    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   15717       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15718       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   15719       // TODO: set VSCR[SAT]
   15720       break;
   15721 
   15722 
   15723    /* Subtract */
   15724    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   15725       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15726       /* unsigned_ov(x-y) = (y >u x) */
   15727       putVReg( vD_addr, binop(Iop_ShrN32x4,
   15728                               unop(Iop_NotV128,
   15729                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   15730                                          mkexpr(vA))),
   15731                               mkU8(31)) );
   15732       break;
   15733    }
   15734    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   15735       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15736       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   15737       break;
   15738 
   15739    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   15740       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15741       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   15742       break;
   15743 
   15744    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   15745       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15746       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   15747       break;
   15748 
   15749    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
   15750       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15751       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
   15752       break;
   15753 
   15754    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   15755       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15756       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   15757       // TODO: set VSCR[SAT]
   15758       break;
   15759 
   15760    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   15761       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15762       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   15763       // TODO: set VSCR[SAT]
   15764       break;
   15765 
   15766    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   15767       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15768       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   15769       // TODO: set VSCR[SAT]
   15770       break;
   15771 
   15772    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   15773       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15774       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   15775       // TODO: set VSCR[SAT]
   15776       break;
   15777 
   15778    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   15779       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15780       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   15781       // TODO: set VSCR[SAT]
   15782       break;
   15783 
   15784    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   15785       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15786       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   15787       // TODO: set VSCR[SAT]
   15788       break;
   15789 
   15790 
   15791    /* Maximum */
   15792    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   15793       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15794       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   15795       break;
   15796 
   15797    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   15798       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15799       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   15800       break;
   15801 
   15802    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   15803       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15804       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   15805       break;
   15806 
   15807    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
   15808       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15809       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
   15810       break;
   15811 
   15812    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   15813       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15814       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   15815       break;
   15816 
   15817    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   15818       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15819       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   15820       break;
   15821 
   15822    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   15823       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15824       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   15825       break;
   15826 
   15827    case 0x1C2: // vmaxsd (Maximum Signed Double word)
   15828       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15829       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
   15830       break;
   15831 
   15832    /* Minimum */
   15833    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   15834       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15835       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   15836       break;
   15837 
   15838    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   15839       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15840       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   15841       break;
   15842 
   15843    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   15844       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15845       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   15846       break;
   15847 
   15848    case 0x2C2: // vminud (Minimum Unsigned Double Word)
   15849       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15850       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
   15851       break;
   15852 
   15853    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   15854       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15855       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   15856       break;
   15857 
   15858    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   15859       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15860       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   15861       break;
   15862 
   15863    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   15864       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15865       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   15866       break;
   15867 
   15868    case 0x3C2: // vminsd (Minimum Signed Double Word)
   15869       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15870       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
   15871       break;
   15872 
   15873 
   15874    /* Average */
   15875    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   15876       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15877       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   15878       break;
   15879 
   15880    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   15881       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15882       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   15883       break;
   15884 
   15885    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   15886       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15887       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   15888       break;
   15889 
   15890    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   15891       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15892       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   15893       break;
   15894 
   15895    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   15896       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15897       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   15898       break;
   15899 
   15900    case 0x582: // vavgsw (Average Signed Word, AV p151)
   15901       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15902       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   15903       break;
   15904 
   15905 
   15906    /* Multiply */
   15907    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   15908       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15909       putVReg( vD_addr,
   15910                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   15911       break;
   15912 
   15913    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   15914       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15915       putVReg( vD_addr,
   15916                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   15917       break;
   15918 
   15919    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
   15920       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15921       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
   15922       break;
   15923 
   15924    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
   15925       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15926       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
   15927       break;
   15928 
   15929    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   15930       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15931       putVReg( vD_addr,
   15932                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   15933       break;
   15934 
   15935    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   15936       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15937       putVReg( vD_addr,
   15938                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   15939       break;
   15940 
   15941    case 0x188: // vmulosw (Multiply Odd Signed Word)
   15942       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15943       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
   15944       break;
   15945 
   15946    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   15947       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15948       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   15949       break;
   15950 
   15951    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   15952       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15953       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   15954       break;
   15955 
   15956    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
   15957       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15958       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
   15959       break;
   15960 
   15961    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   15962       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15963       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   15964       break;
   15965 
   15966    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   15967       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15968       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   15969       break;
   15970 
   15971    case 0x388: // vmulesw (Multiply Even Signed Word)
   15972       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15973       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
   15974       break;
   15975 
   15976    /* Sum Across Partial */
   15977    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   15978       IRTemp aEE, aEO, aOE, aOO;
   15979       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   15980       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15981 
   15982       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   15983       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   15984       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   15985       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   15986 
   15987       /* break V128 to 4xI32's, zero-extending to I64's */
   15988       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   15989       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   15990       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   15991       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   15992       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   15993 
   15994       /* add lanes */
   15995       assign( z3, binop(Iop_Add64, mkexpr(b3),
   15996                      binop(Iop_Add64,
   15997                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   15998                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   15999       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16000                      binop(Iop_Add64,
   16001                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16002                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16003       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16004                      binop(Iop_Add64,
   16005                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16006                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16007       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16008                      binop(Iop_Add64,
   16009                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16010                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16011 
   16012       /* saturate-narrow to 32bit, and combine to V128 */
   16013       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   16014                                          mkexpr(z1), mkexpr(z0)) );
   16015       break;
   16016    }
   16017    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   16018       IRTemp aEE, aEO, aOE, aOO;
   16019       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   16020       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16021 
   16022       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   16023       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   16024       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   16025       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   16026 
   16027       /* break V128 to 4xI32's, sign-extending to I64's */
   16028       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   16029       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   16030       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   16031       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   16032       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   16033 
   16034       /* add lanes */
   16035       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16036                      binop(Iop_Add64,
   16037                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   16038                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   16039       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16040                      binop(Iop_Add64,
   16041                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16042                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16043       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16044                      binop(Iop_Add64,
   16045                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16046                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16047       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16048                      binop(Iop_Add64,
   16049                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16050                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16051 
   16052       /* saturate-narrow to 32bit, and combine to V128 */
   16053       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16054                                          mkexpr(z1), mkexpr(z0)) );
   16055       break;
   16056    }
   16057    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   16058       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16059 
   16060       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   16061       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   16062 
   16063       /* break V128 to 4xI32's, sign-extending to I64's */
   16064       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   16065       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   16066       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   16067 
   16068       /* add lanes */
   16069       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16070                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   16071       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16072                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   16073       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16074                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   16075       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16076                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   16077 
   16078       /* saturate-narrow to 32bit, and combine to V128 */
   16079       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16080                                          mkexpr(z1), mkexpr(z0)) );
   16081       break;
   16082    }
   16083    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   16084       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16085 
   16086       /* break V128 to 4xI32's, sign-extending to I64's */
   16087       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16088       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16089 
   16090       /* add lanes */
   16091       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16092                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   16093       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16094                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   16095 
   16096       /* saturate-narrow to 32bit, and combine to V128 */
   16097       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   16098                                          mkU64(0), mkexpr(z0)) );
   16099       break;
   16100    }
   16101    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   16102       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16103 
   16104       /* break V128 to 4xI32's, sign-extending to I64's */
   16105       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16106       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16107 
   16108       /* add lanes */
   16109       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16110                      binop(Iop_Add64,
   16111                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16112                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16113 
   16114       /* saturate-narrow to 32bit, and combine to V128 */
   16115       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   16116                                          mkU64(0), mkexpr(z0)) );
   16117       break;
   16118    }
   16119    default:
   16120       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   16121       return False;
   16122    }
   16123    return True;
   16124 }
   16125 
   16126 /*
   16127   AltiVec Logic Instructions
   16128 */
   16129 static Bool dis_av_logic ( UInt theInstr )
   16130 {
   16131    /* VX-Form */
   16132    UChar opc1    = ifieldOPC(theInstr);
   16133    UChar vD_addr = ifieldRegDS(theInstr);
   16134    UChar vA_addr = ifieldRegA(theInstr);
   16135    UChar vB_addr = ifieldRegB(theInstr);
   16136    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   16137 
   16138    IRTemp vA = newTemp(Ity_V128);
   16139    IRTemp vB = newTemp(Ity_V128);
   16140    assign( vA, getVReg(vA_addr));
   16141    assign( vB, getVReg(vB_addr));
   16142 
   16143    if (opc1 != 0x4) {
   16144       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   16145       return False;
   16146    }
   16147 
   16148    switch (opc2) {
   16149    case 0x404: // vand (And, AV p147)
   16150       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16151       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   16152       break;
   16153 
   16154    case 0x444: // vandc (And, AV p148)
   16155       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16156       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   16157                               unop(Iop_NotV128, mkexpr(vB))) );
   16158       break;
   16159 
   16160    case 0x484: // vor (Or, AV p217)
   16161       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16162       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   16163       break;
   16164 
   16165    case 0x4C4: // vxor (Xor, AV p282)
   16166       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16167       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   16168       break;
   16169 
   16170    case 0x504: // vnor (Nor, AV p216)
   16171       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16172       putVReg( vD_addr,
   16173          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   16174       break;
   16175 
   16176    case 0x544: // vorc (vA Or'd with complement of vb)
   16177       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16178       putVReg( vD_addr, binop( Iop_OrV128,
   16179                                mkexpr( vA ),
   16180                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
   16181       break;
   16182 
   16183    case 0x584: // vnand (Nand)
   16184       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16185       putVReg( vD_addr, unop( Iop_NotV128,
   16186                               binop(Iop_AndV128, mkexpr( vA ),
   16187                               mkexpr( vB ) ) ) );
   16188       break;
   16189 
   16190    case 0x684: // veqv (complemented XOr)
   16191       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16192       putVReg( vD_addr, unop( Iop_NotV128,
   16193                               binop( Iop_XorV128, mkexpr( vA ),
   16194                               mkexpr( vB ) ) ) );
   16195       break;
   16196 
   16197    default:
   16198       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   16199       return False;
   16200    }
   16201    return True;
   16202 }
   16203 
   16204 /*
   16205   AltiVec Compare Instructions
   16206 */
   16207 static Bool dis_av_cmp ( UInt theInstr )
   16208 {
   16209    /* VXR-Form */
   16210    UChar opc1     = ifieldOPC(theInstr);
   16211    UChar vD_addr  = ifieldRegDS(theInstr);
   16212    UChar vA_addr  = ifieldRegA(theInstr);
   16213    UChar vB_addr  = ifieldRegB(theInstr);
   16214    UChar flag_rC  = ifieldBIT10(theInstr);
   16215    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   16216 
   16217    IRTemp vA = newTemp(Ity_V128);
   16218    IRTemp vB = newTemp(Ity_V128);
   16219    IRTemp vD = newTemp(Ity_V128);
   16220    assign( vA, getVReg(vA_addr));
   16221    assign( vB, getVReg(vB_addr));
   16222 
   16223    if (opc1 != 0x4) {
   16224       vex_printf("dis_av_cmp(ppc)(instr)\n");
   16225       return False;
   16226    }
   16227 
   16228    switch (opc2) {
   16229    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   16230       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16231                                       vD_addr, vA_addr, vB_addr);
   16232       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   16233       break;
   16234 
   16235    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   16236       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16237                                       vD_addr, vA_addr, vB_addr);
   16238       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   16239       break;
   16240 
   16241    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   16242       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16243                                       vD_addr, vA_addr, vB_addr);
   16244       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   16245       break;
   16246 
   16247    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
   16248       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16249                                       vD_addr, vA_addr, vB_addr);
   16250       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
   16251       break;
   16252 
   16253    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   16254       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16255                                       vD_addr, vA_addr, vB_addr);
   16256       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   16257       break;
   16258 
   16259    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   16260       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16261                                       vD_addr, vA_addr, vB_addr);
   16262       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   16263       break;
   16264 
   16265    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   16266       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16267                                        vD_addr, vA_addr, vB_addr);
   16268       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   16269       break;
   16270 
   16271    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
   16272       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16273                                       vD_addr, vA_addr, vB_addr);
   16274       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
   16275       break;
   16276 
   16277    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   16278       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16279                                        vD_addr, vA_addr, vB_addr);
   16280       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   16281       break;
   16282 
   16283    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   16284       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16285                                       vD_addr, vA_addr, vB_addr);
   16286       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   16287       break;
   16288 
   16289    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   16290       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16291                                       vD_addr, vA_addr, vB_addr);
   16292       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   16293       break;
   16294 
   16295    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
   16296       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16297                                       vD_addr, vA_addr, vB_addr);
   16298       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
   16299       break;
   16300 
   16301    default:
   16302       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   16303       return False;
   16304    }
   16305 
   16306    putVReg( vD_addr, mkexpr(vD) );
   16307 
   16308    if (flag_rC) {
   16309       set_AV_CR6( mkexpr(vD), True );
   16310    }
   16311    return True;
   16312 }
   16313 
   16314 /*
   16315   AltiVec Multiply-Sum Instructions
   16316 */
   16317 static Bool dis_av_multarith ( UInt theInstr )
   16318 {
   16319    /* VA-Form */
   16320    UChar opc1     = ifieldOPC(theInstr);
   16321    UChar vD_addr  = ifieldRegDS(theInstr);
   16322    UChar vA_addr  = ifieldRegA(theInstr);
   16323    UChar vB_addr  = ifieldRegB(theInstr);
   16324    UChar vC_addr  = ifieldRegC(theInstr);
   16325    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   16326 
   16327    IRTemp vA    = newTemp(Ity_V128);
   16328    IRTemp vB    = newTemp(Ity_V128);
   16329    IRTemp vC    = newTemp(Ity_V128);
   16330    IRTemp zeros = newTemp(Ity_V128);
   16331    IRTemp aLo   = newTemp(Ity_V128);
   16332    IRTemp bLo   = newTemp(Ity_V128);
   16333    IRTemp cLo   = newTemp(Ity_V128);
   16334    IRTemp zLo   = newTemp(Ity_V128);
   16335    IRTemp aHi   = newTemp(Ity_V128);
   16336    IRTemp bHi   = newTemp(Ity_V128);
   16337    IRTemp cHi   = newTemp(Ity_V128);
   16338    IRTemp zHi   = newTemp(Ity_V128);
   16339    IRTemp abEvn = newTemp(Ity_V128);
   16340    IRTemp abOdd = newTemp(Ity_V128);
   16341    IRTemp z3    = newTemp(Ity_I64);
   16342    IRTemp z2    = newTemp(Ity_I64);
   16343    IRTemp z1    = newTemp(Ity_I64);
   16344    IRTemp z0    = newTemp(Ity_I64);
   16345    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   16346    IRTemp c3, c2, c1, c0;
   16347 
   16348    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   16349    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   16350 
   16351    assign( vA, getVReg(vA_addr));
   16352    assign( vB, getVReg(vB_addr));
   16353    assign( vC, getVReg(vC_addr));
   16354    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   16355 
   16356    if (opc1 != 0x4) {
   16357       vex_printf("dis_av_multarith(ppc)(instr)\n");
   16358       return False;
   16359    }
   16360 
   16361    switch (opc2) {
   16362    /* Multiply-Add */
   16363    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   16364       IRTemp cSigns = newTemp(Ity_V128);
   16365       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   16366           vD_addr, vA_addr, vB_addr, vC_addr);
   16367       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   16368       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16369       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16370       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16371       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16372       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16373       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16374 
   16375       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16376                          binop(Iop_SarN32x4,
   16377                                binop(Iop_MullEven16Sx8,
   16378                                      mkexpr(aLo), mkexpr(bLo)),
   16379                                mkU8(15))) );
   16380 
   16381       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16382                          binop(Iop_SarN32x4,
   16383                                binop(Iop_MullEven16Sx8,
   16384                                      mkexpr(aHi), mkexpr(bHi)),
   16385                                mkU8(15))) );
   16386 
   16387       putVReg( vD_addr,
   16388                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16389       break;
   16390    }
   16391    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   16392       IRTemp zKonst = newTemp(Ity_V128);
   16393       IRTemp cSigns = newTemp(Ity_V128);
   16394       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   16395           vD_addr, vA_addr, vB_addr, vC_addr);
   16396       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   16397       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16398       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16399       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16400       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16401       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16402       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16403 
   16404       /* shifting our const avoids store/load version of Dup */
   16405       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   16406                             mkU8(14)) );
   16407 
   16408       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16409                          binop(Iop_SarN32x4,
   16410                                binop(Iop_Add32x4, mkexpr(zKonst),
   16411                                      binop(Iop_MullEven16Sx8,
   16412                                            mkexpr(aLo), mkexpr(bLo))),
   16413                                mkU8(15))) );
   16414 
   16415       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16416                          binop(Iop_SarN32x4,
   16417                                binop(Iop_Add32x4, mkexpr(zKonst),
   16418                                      binop(Iop_MullEven16Sx8,
   16419                                            mkexpr(aHi), mkexpr(bHi))),
   16420                                mkU8(15))) );
   16421 
   16422       putVReg( vD_addr,
   16423                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16424       break;
   16425    }
   16426    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   16427       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   16428           vD_addr, vA_addr, vB_addr, vC_addr);
   16429       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16430       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16431       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   16432       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16433       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16434       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   16435       assign(zLo, binop(Iop_Add32x4,
   16436                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   16437                      mkexpr(cLo)) );
   16438       assign(zHi, binop(Iop_Add32x4,
   16439                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   16440                      mkexpr(cHi)));
   16441       putVReg( vD_addr,
   16442                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   16443       break;
   16444    }
   16445 
   16446 
   16447    /* Multiply-Sum */
   16448    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   16449       IRTemp abEE, abEO, abOE, abOO;
   16450       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   16451       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   16452           vD_addr, vA_addr, vB_addr, vC_addr);
   16453 
   16454       /* multiply vA,vB (unsigned, widening) */
   16455       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   16456       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   16457 
   16458       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   16459       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   16460       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   16461 
   16462       putVReg( vD_addr,
   16463          binop(Iop_Add32x4, mkexpr(vC),
   16464                binop(Iop_Add32x4,
   16465                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   16466                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   16467       break;
   16468    }
   16469    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   16470       IRTemp aEvn, aOdd, bEvn, bOdd;
   16471       IRTemp abEE = newTemp(Ity_V128);
   16472       IRTemp abEO = newTemp(Ity_V128);
   16473       IRTemp abOE = newTemp(Ity_V128);
   16474       IRTemp abOO = newTemp(Ity_V128);
   16475       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   16476       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   16477           vD_addr, vA_addr, vB_addr, vC_addr);
   16478 
   16479       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   16480          (separating out adjacent lanes to different vectors) */
   16481       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   16482       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   16483 
   16484       /* multiply vA, vB, again separating adjacent lanes */
   16485       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   16486       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   16487       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   16488       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   16489 
   16490       /* add results together, + vC */
   16491       putVReg( vD_addr,
   16492          binop(Iop_QAdd32Sx4, mkexpr(vC),
   16493                binop(Iop_QAdd32Sx4,
   16494                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   16495                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   16496       break;
   16497    }
   16498    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   16499       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   16500           vD_addr, vA_addr, vB_addr, vC_addr);
   16501       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   16502       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   16503       putVReg( vD_addr,
   16504          binop(Iop_Add32x4, mkexpr(vC),
   16505                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   16506       break;
   16507    }
   16508    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   16509       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   16510           vD_addr, vA_addr, vB_addr, vC_addr);
   16511       /* widening multiply, separating lanes */
   16512       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   16513       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   16514 
   16515       /* break V128 to 4xI32's, zero-extending to I64's */
   16516       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   16517       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   16518       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   16519 
   16520       /* add lanes */
   16521       assign( z3, binop(Iop_Add64, mkexpr(c3),
   16522                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   16523       assign( z2, binop(Iop_Add64, mkexpr(c2),
   16524                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   16525       assign( z1, binop(Iop_Add64, mkexpr(c1),
   16526                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   16527       assign( z0, binop(Iop_Add64, mkexpr(c0),
   16528                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   16529 
   16530       /* saturate-narrow to 32bit, and combine to V128 */
   16531       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   16532                                          mkexpr(z1), mkexpr(z0)) );
   16533 
   16534       break;
   16535    }
   16536    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   16537       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   16538           vD_addr, vA_addr, vB_addr, vC_addr);
   16539       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16540       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   16541       putVReg( vD_addr,
   16542          binop(Iop_Add32x4, mkexpr(vC),
   16543                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   16544       break;
   16545    }
   16546    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   16547       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   16548           vD_addr, vA_addr, vB_addr, vC_addr);
   16549       /* widening multiply, separating lanes */
   16550       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16551       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   16552 
   16553       /* break V128 to 4xI32's, sign-extending to I64's */
   16554       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   16555       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   16556       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   16557 
   16558       /* add lanes */
   16559       assign( z3, binop(Iop_Add64, mkexpr(c3),
   16560                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   16561       assign( z2, binop(Iop_Add64, mkexpr(c2),
   16562                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   16563       assign( z1, binop(Iop_Add64, mkexpr(c1),
   16564                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   16565       assign( z0, binop(Iop_Add64, mkexpr(c0),
   16566                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   16567 
   16568       /* saturate-narrow to 32bit, and combine to V128 */
   16569       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16570                                          mkexpr(z1), mkexpr(z0)) );
   16571       break;
   16572    }
   16573    default:
   16574       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   16575       return False;
   16576    }
   16577    return True;
   16578 }
   16579 
   16580 /*
   16581   AltiVec Polynomial Multiply-Sum Instructions
   16582 */
   16583 static Bool dis_av_polymultarith ( UInt theInstr )
   16584 {
   16585    /* VA-Form */
   16586    UChar opc1     = ifieldOPC(theInstr);
   16587    UChar vD_addr  = ifieldRegDS(theInstr);
   16588    UChar vA_addr  = ifieldRegA(theInstr);
   16589    UChar vB_addr  = ifieldRegB(theInstr);
   16590    UChar vC_addr  = ifieldRegC(theInstr);
   16591    UInt  opc2     = IFIELD(theInstr, 0, 11);
   16592    IRTemp vA    = newTemp(Ity_V128);
   16593    IRTemp vB    = newTemp(Ity_V128);
   16594    IRTemp vC    = newTemp(Ity_V128);
   16595 
   16596    assign( vA, getVReg(vA_addr));
   16597    assign( vB, getVReg(vB_addr));
   16598    assign( vC, getVReg(vC_addr));
   16599 
   16600    if (opc1 != 0x4) {
   16601       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
   16602       return False;
   16603    }
   16604 
   16605    switch (opc2) {
   16606       /* Polynomial Multiply-Add */
   16607       case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
   16608          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16609          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
   16610                                  mkexpr(vA), mkexpr(vB)) );
   16611          break;
   16612       case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
   16613          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16614          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
   16615                                  mkexpr(vA), mkexpr(vB)) );
   16616          break;
   16617       case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
   16618          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16619          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
   16620                                  mkexpr(vA), mkexpr(vB)) );
   16621          break;
   16622       case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
   16623          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16624          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
   16625                                  mkexpr(vA), mkexpr(vB)) );
   16626          break;
   16627       default:
   16628          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
   16629          return False;
   16630    }
   16631    return True;
   16632 }
   16633 
   16634 /*
   16635   AltiVec Shift/Rotate Instructions
   16636 */
   16637 static Bool dis_av_shift ( UInt theInstr )
   16638 {
   16639    /* VX-Form */
   16640    UChar opc1    = ifieldOPC(theInstr);
   16641    UChar vD_addr = ifieldRegDS(theInstr);
   16642    UChar vA_addr = ifieldRegA(theInstr);
   16643    UChar vB_addr = ifieldRegB(theInstr);
   16644    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   16645 
   16646    IRTemp vA = newTemp(Ity_V128);
   16647    IRTemp vB = newTemp(Ity_V128);
   16648    assign( vA, getVReg(vA_addr));
   16649    assign( vB, getVReg(vB_addr));
   16650 
   16651    if (opc1 != 0x4){
   16652       vex_printf("dis_av_shift(ppc)(instr)\n");
   16653       return False;
   16654    }
   16655 
   16656    switch (opc2) {
   16657    /* Rotate */
   16658    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   16659       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16660       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   16661       break;
   16662 
   16663    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   16664       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16665       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   16666       break;
   16667 
   16668    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   16669       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16670       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   16671       break;
   16672 
   16673    case 0x0C4: // vrld (Rotate Left Integer Double Word)
   16674       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16675       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
   16676       break;
   16677 
   16678 
   16679    /* Shift Left */
   16680    case 0x104: // vslb (Shift Left Integer B, AV p240)
   16681       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16682       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   16683       break;
   16684 
   16685    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   16686       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16687       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   16688       break;
   16689 
   16690    case 0x184: // vslw (Shift Left Integer W, AV p244)
   16691       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16692       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   16693       break;
   16694 
   16695    case 0x5C4: // vsld (Shift Left Integer Double Word)
   16696       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16697       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
   16698       break;
   16699 
   16700    case 0x1C4: { // vsl (Shift Left, AV p239)
   16701       IRTemp sh = newTemp(Ity_I8);
   16702       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16703       assign( sh, binop(Iop_And8, mkU8(0x7),
   16704                         unop(Iop_32to8,
   16705                              unop(Iop_V128to32, mkexpr(vB)))) );
   16706       putVReg( vD_addr,
   16707                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   16708       break;
   16709    }
   16710    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   16711       IRTemp sh = newTemp(Ity_I8);
   16712       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16713       assign( sh, binop(Iop_And8, mkU8(0x78),
   16714                         unop(Iop_32to8,
   16715                              unop(Iop_V128to32, mkexpr(vB)))) );
   16716       putVReg( vD_addr,
   16717                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   16718       break;
   16719    }
   16720 
   16721 
   16722    /* Shift Right */
   16723    case 0x204: // vsrb (Shift Right B, AV p256)
   16724       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16725       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   16726       break;
   16727 
   16728    case 0x244: // vsrh (Shift Right HW, AV p257)
   16729       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16730       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   16731       break;
   16732 
   16733    case 0x284: // vsrw (Shift Right W, AV p259)
   16734       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16735       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   16736       break;
   16737 
   16738    case 0x2C4: { // vsr (Shift Right, AV p251)
   16739       IRTemp sh = newTemp(Ity_I8);
   16740       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16741       assign( sh, binop(Iop_And8, mkU8(0x7),
   16742                         unop(Iop_32to8,
   16743                              unop(Iop_V128to32, mkexpr(vB)))) );
   16744       putVReg( vD_addr,
   16745                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   16746       break;
   16747    }
   16748    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   16749       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16750       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   16751       break;
   16752 
   16753    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   16754       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16755       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   16756       break;
   16757 
   16758    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   16759       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16760       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   16761       break;
   16762 
   16763    case 0x3C4: // vsrad (Shift Right Alg Double Word)
   16764       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16765       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
   16766       break;
   16767 
   16768    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   16769       IRTemp sh = newTemp(Ity_I8);
   16770       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16771       assign( sh, binop(Iop_And8, mkU8(0x78),
   16772                         unop(Iop_32to8,
   16773                              unop(Iop_V128to32, mkexpr(vB)))) );
   16774       putVReg( vD_addr,
   16775                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   16776       break;
   16777    }
   16778 
   16779    case 0x6C4: // vsrd (Shift Right Double Word)
   16780       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16781       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
   16782       break;
   16783 
   16784 
   16785    default:
   16786       vex_printf("dis_av_shift(ppc)(opc2)\n");
   16787       return False;
   16788    }
   16789    return True;
   16790 }
   16791 
   16792 /*
   16793   AltiVec Permute Instructions
   16794 */
   16795 static Bool dis_av_permute ( UInt theInstr )
   16796 {
   16797    /* VA-Form, VX-Form */
   16798    UChar opc1      = ifieldOPC(theInstr);
   16799    UChar vD_addr   = ifieldRegDS(theInstr);
   16800    UChar vA_addr   = ifieldRegA(theInstr);
   16801    UChar UIMM_5    = vA_addr;
   16802    UChar vB_addr   = ifieldRegB(theInstr);
   16803    UChar vC_addr   = ifieldRegC(theInstr);
   16804    UChar b10       = ifieldBIT10(theInstr);
   16805    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   16806    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   16807 
   16808    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   16809 
   16810    IRTemp vA = newTemp(Ity_V128);
   16811    IRTemp vB = newTemp(Ity_V128);
   16812    IRTemp vC = newTemp(Ity_V128);
   16813    assign( vA, getVReg(vA_addr));
   16814    assign( vB, getVReg(vB_addr));
   16815    assign( vC, getVReg(vC_addr));
   16816 
   16817    if (opc1 != 0x4) {
   16818       vex_printf("dis_av_permute(ppc)(instr)\n");
   16819       return False;
   16820    }
   16821 
   16822    switch (opc2) {
   16823    case 0x2A: // vsel (Conditional Select, AV p238)
   16824       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   16825       /* vD = (vA & ~vC) | (vB & vC) */
   16826       putVReg( vD_addr, binop(Iop_OrV128,
   16827          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   16828          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   16829       return True;
   16830 
   16831    case 0x2B: { // vperm (Permute, AV p218)
   16832       /* limited to two args for IR, so have to play games... */
   16833       IRTemp a_perm  = newTemp(Ity_V128);
   16834       IRTemp b_perm  = newTemp(Ity_V128);
   16835       IRTemp mask    = newTemp(Ity_V128);
   16836       IRTemp vC_andF = newTemp(Ity_V128);
   16837       DIP("vperm v%d,v%d,v%d,v%d\n",
   16838           vD_addr, vA_addr, vB_addr, vC_addr);
   16839       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   16840          IR specifies, and also to hide irrelevant bits from
   16841          memcheck */
   16842       assign( vC_andF,
   16843               binop(Iop_AndV128, mkexpr(vC),
   16844                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   16845       assign( a_perm,
   16846               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   16847       assign( b_perm,
   16848               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   16849       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   16850       assign( mask, binop(Iop_SarN8x16,
   16851                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   16852                           mkU8(7)) );
   16853       // dst = (a & ~mask) | (b & mask)
   16854       putVReg( vD_addr, binop(Iop_OrV128,
   16855                               binop(Iop_AndV128, mkexpr(a_perm),
   16856                                     unop(Iop_NotV128, mkexpr(mask))),
   16857                               binop(Iop_AndV128, mkexpr(b_perm),
   16858                                     mkexpr(mask))) );
   16859       return True;
   16860    }
   16861    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   16862       if (b10 != 0) {
   16863          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   16864          return False;
   16865       }
   16866       DIP("vsldoi v%d,v%d,v%d,%d\n",
   16867           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   16868       if (SHB_uimm4 == 0)
   16869          putVReg( vD_addr, mkexpr(vA) );
   16870       else
   16871          putVReg( vD_addr,
   16872             binop(Iop_OrV128,
   16873                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   16874                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   16875       return True;
   16876    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
   16877       IRTemp a_perm  = newTemp(Ity_V128);
   16878       IRTemp b_perm  = newTemp(Ity_V128);
   16879       IRTemp vrc_a   = newTemp(Ity_V128);
   16880       IRTemp vrc_b   = newTemp(Ity_V128);
   16881 
   16882       /* IBM index  is 0:7, Change index value to index 7:0 */
   16883       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
   16884                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
   16885       assign( vrc_a, binop( Iop_ShrV128,
   16886                             binop( Iop_AndV128, mkexpr( vC ),
   16887                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
   16888                             mkU8 ( 4 ) ) );
   16889       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
   16890       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
   16891       putVReg( vD_addr, binop( Iop_XorV128,
   16892                                mkexpr( a_perm ), mkexpr( b_perm) ) );
   16893       return True;
   16894    }
   16895    default:
   16896      break; // Fall through...
   16897    }
   16898 
   16899    opc2 = IFIELD( theInstr, 0, 11 );
   16900    switch (opc2) {
   16901 
   16902    /* Merge */
   16903    case 0x00C: // vmrghb (Merge High B, AV p195)
   16904       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16905       putVReg( vD_addr,
   16906                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   16907       break;
   16908 
   16909    case 0x04C: // vmrghh (Merge High HW, AV p196)
   16910       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16911       putVReg( vD_addr,
   16912                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   16913       break;
   16914 
   16915    case 0x08C: // vmrghw (Merge High W, AV p197)
   16916       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16917       putVReg( vD_addr,
   16918                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   16919       break;
   16920 
   16921    case 0x10C: // vmrglb (Merge Low B, AV p198)
   16922       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16923       putVReg( vD_addr,
   16924                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   16925       break;
   16926 
   16927    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   16928       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16929       putVReg( vD_addr,
   16930                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   16931       break;
   16932 
   16933    case 0x18C: // vmrglw (Merge Low W, AV p200)
   16934       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16935       putVReg( vD_addr,
   16936                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   16937       break;
   16938 
   16939 
   16940    /* Splat */
   16941    case 0x20C: { // vspltb (Splat Byte, AV p245)
   16942       /* vD = Dup8x16( vB[UIMM_5] ) */
   16943       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   16944       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16945       putVReg( vD_addr, unop(Iop_Dup8x16,
   16946            unop(Iop_32to8, unop(Iop_V128to32,
   16947                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   16948       break;
   16949    }
   16950    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   16951       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   16952       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16953       putVReg( vD_addr, unop(Iop_Dup16x8,
   16954            unop(Iop_32to16, unop(Iop_V128to32,
   16955                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   16956       break;
   16957    }
   16958    case 0x28C: { // vspltw (Splat Word, AV p250)
   16959       /* vD = Dup32x4( vB[UIMM_5] ) */
   16960       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   16961       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16962       putVReg( vD_addr, unop(Iop_Dup32x4,
   16963          unop(Iop_V128to32,
   16964               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   16965       break;
   16966    }
   16967    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   16968       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   16969       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   16970       break;
   16971 
   16972    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   16973       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   16974       putVReg( vD_addr,
   16975                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   16976       break;
   16977 
   16978    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   16979       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   16980       putVReg( vD_addr,
   16981                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   16982       break;
   16983 
   16984    case 0x68C: // vmrgow (Merge Odd Word)
   16985      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16986       /*   VD[0] <- VA[1]
   16987            VD[1] <- VB[1]
   16988            VD[2] <- VA[3]
   16989            VD[3] <- VB[3]
   16990       */
   16991       putVReg( vD_addr,
   16992                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   16993       break;
   16994 
   16995    case 0x78C: // vmrgew (Merge Even Word)
   16996       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16997       /*   VD[0] <- VA[0]
   16998            VD[1] <- VB[0]
   16999            VD[2] <- VA[2]
   17000            VD[3] <- VB[2]
   17001       */
   17002       putVReg( vD_addr,
   17003                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   17004       break;
   17005 
   17006    default:
   17007       vex_printf("dis_av_permute(ppc)(opc2)\n");
   17008       return False;
   17009    }
   17010    return True;
   17011 }
   17012 
   17013 /*
   17014   AltiVec Pack/Unpack Instructions
   17015 */
   17016 static Bool dis_av_pack ( UInt theInstr )
   17017 {
   17018    /* VX-Form */
   17019    UChar opc1     = ifieldOPC(theInstr);
   17020    UChar vD_addr  = ifieldRegDS(theInstr);
   17021    UChar vA_addr  = ifieldRegA(theInstr);
   17022    UChar vB_addr  = ifieldRegB(theInstr);
   17023    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17024 
   17025    IRTemp signs = IRTemp_INVALID;
   17026    IRTemp zeros = IRTemp_INVALID;
   17027    IRTemp vA    = newTemp(Ity_V128);
   17028    IRTemp vB    = newTemp(Ity_V128);
   17029    assign( vA, getVReg(vA_addr));
   17030    assign( vB, getVReg(vB_addr));
   17031 
   17032    if (opc1 != 0x4) {
   17033       vex_printf("dis_av_pack(ppc)(instr)\n");
   17034       return False;
   17035    }
   17036    switch (opc2) {
   17037    /* Packing */
   17038    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   17039       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17040       putVReg( vD_addr,
   17041                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   17042       return True;
   17043 
   17044    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   17045       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17046       putVReg( vD_addr,
   17047                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   17048       return True;
   17049 
   17050    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   17051       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17052       putVReg( vD_addr,
   17053                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   17054       // TODO: set VSCR[SAT]
   17055       return True;
   17056 
   17057    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   17058       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17059       putVReg( vD_addr,
   17060                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   17061       // TODO: set VSCR[SAT]
   17062       return True;
   17063 
   17064    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   17065       // This insn does a signed->unsigned saturating conversion.
   17066       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17067       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   17068       IRTemp vA_tmp = newTemp(Ity_V128);
   17069       IRTemp vB_tmp = newTemp(Ity_V128);
   17070       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17071       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17072                             unop(Iop_NotV128,
   17073                                  binop(Iop_SarN16x8,
   17074                                        mkexpr(vA), mkU8(15)))) );
   17075       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17076                             unop(Iop_NotV128,
   17077                                  binop(Iop_SarN16x8,
   17078                                        mkexpr(vB), mkU8(15)))) );
   17079       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   17080                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17081       // TODO: set VSCR[SAT]
   17082       return True;
   17083    }
   17084    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   17085       // This insn does a signed->unsigned saturating conversion.
   17086       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17087       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17088       IRTemp vA_tmp = newTemp(Ity_V128);
   17089       IRTemp vB_tmp = newTemp(Ity_V128);
   17090       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17091       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17092                             unop(Iop_NotV128,
   17093                                  binop(Iop_SarN32x4,
   17094                                        mkexpr(vA), mkU8(31)))) );
   17095       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17096                             unop(Iop_NotV128,
   17097                                  binop(Iop_SarN32x4,
   17098                                        mkexpr(vB), mkU8(31)))) );
   17099       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   17100                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17101       // TODO: set VSCR[SAT]
   17102       return True;
   17103    }
   17104    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   17105       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17106       putVReg( vD_addr,
   17107                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   17108       // TODO: set VSCR[SAT]
   17109       return True;
   17110 
   17111    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   17112       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17113       putVReg( vD_addr,
   17114                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   17115       // TODO: set VSCR[SAT]
   17116       return True;
   17117 
   17118    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   17119       /* CAB: Worth a new primop? */
   17120       /* Using shifts to compact pixel elements, then packing them */
   17121       IRTemp a1 = newTemp(Ity_V128);
   17122       IRTemp a2 = newTemp(Ity_V128);
   17123       IRTemp a3 = newTemp(Ity_V128);
   17124       IRTemp a_tmp = newTemp(Ity_V128);
   17125       IRTemp b1 = newTemp(Ity_V128);
   17126       IRTemp b2 = newTemp(Ity_V128);
   17127       IRTemp b3 = newTemp(Ity_V128);
   17128       IRTemp b_tmp = newTemp(Ity_V128);
   17129       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17130       assign( a1, binop(Iop_ShlN16x8,
   17131                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   17132                         mkU8(10)) );
   17133       assign( a2, binop(Iop_ShlN16x8,
   17134                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   17135                         mkU8(5)) );
   17136       assign( a3,  binop(Iop_ShrN16x8,
   17137                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   17138                          mkU8(11)) );
   17139       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   17140                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   17141 
   17142       assign( b1, binop(Iop_ShlN16x8,
   17143                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   17144                         mkU8(10)) );
   17145       assign( b2, binop(Iop_ShlN16x8,
   17146                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   17147                         mkU8(5)) );
   17148       assign( b3,  binop(Iop_ShrN16x8,
   17149                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   17150                          mkU8(11)) );
   17151       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   17152                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   17153 
   17154       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   17155                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   17156       return True;
   17157    }
   17158 
   17159    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
   17160       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17161       putVReg( vD_addr,
   17162                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
   17163       return True;
   17164 
   17165    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
   17166       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17167       putVReg( vD_addr,
   17168                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
   17169       // TODO: set VSCR[SAT]
   17170       return True;
   17171 
   17172    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
   17173       // This insn does a doubled signed->double unsigned saturating conversion
   17174       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17175       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17176       // This is similar to the technique used for vpkswus, except done
   17177       // with double word integers versus word integers.
   17178       IRTemp vA_tmp = newTemp(Ity_V128);
   17179       IRTemp vB_tmp = newTemp(Ity_V128);
   17180       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17181       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17182                             unop(Iop_NotV128,
   17183                                  binop(Iop_SarN64x2,
   17184                                        mkexpr(vA), mkU8(63)))) );
   17185       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17186                             unop(Iop_NotV128,
   17187                                  binop(Iop_SarN64x2,
   17188                                        mkexpr(vB), mkU8(63)))) );
   17189       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
   17190                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17191       // TODO: set VSCR[SAT]
   17192       return True;
   17193    }
   17194 
   17195    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
   17196       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17197       putVReg( vD_addr,
   17198                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
   17199       // TODO: set VSCR[SAT]
   17200       return True;
   17201    default:
   17202       break; // Fall through...
   17203    }
   17204 
   17205 
   17206    if (vA_addr != 0) {
   17207       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   17208       return False;
   17209    }
   17210 
   17211    signs = newTemp(Ity_V128);
   17212    zeros = newTemp(Ity_V128);
   17213    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   17214 
   17215    switch (opc2) {
   17216    /* Unpacking */
   17217    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   17218       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   17219       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17220       putVReg( vD_addr,
   17221                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   17222       break;
   17223    }
   17224    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   17225       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   17226       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17227       putVReg( vD_addr,
   17228                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   17229       break;
   17230    }
   17231    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   17232       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   17233       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17234       putVReg( vD_addr,
   17235                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   17236       break;
   17237    }
   17238    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   17239       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   17240       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17241       putVReg( vD_addr,
   17242                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   17243       break;
   17244    }
   17245    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   17246       /* CAB: Worth a new primop? */
   17247       /* Using shifts to isolate pixel elements, then expanding them */
   17248       IRTemp z0  = newTemp(Ity_V128);
   17249       IRTemp z1  = newTemp(Ity_V128);
   17250       IRTemp z01 = newTemp(Ity_V128);
   17251       IRTemp z2  = newTemp(Ity_V128);
   17252       IRTemp z3  = newTemp(Ity_V128);
   17253       IRTemp z23 = newTemp(Ity_V128);
   17254       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   17255       assign( z0,  binop(Iop_ShlN16x8,
   17256                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17257                          mkU8(8)) );
   17258       assign( z1,  binop(Iop_ShrN16x8,
   17259                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17260                          mkU8(11)) );
   17261       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17262                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17263       assign( z2,  binop(Iop_ShrN16x8,
   17264                          binop(Iop_ShlN16x8,
   17265                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17266                                mkU8(11)),
   17267                          mkU8(3)) );
   17268       assign( z3,  binop(Iop_ShrN16x8,
   17269                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17270                          mkU8(11)) );
   17271       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17272                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17273       putVReg( vD_addr,
   17274                binop(Iop_OrV128,
   17275                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17276                      mkexpr(z23)) );
   17277       break;
   17278    }
   17279    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   17280       /* identical to vupkhpx, except interleaving LO */
   17281       IRTemp z0  = newTemp(Ity_V128);
   17282       IRTemp z1  = newTemp(Ity_V128);
   17283       IRTemp z01 = newTemp(Ity_V128);
   17284       IRTemp z2  = newTemp(Ity_V128);
   17285       IRTemp z3  = newTemp(Ity_V128);
   17286       IRTemp z23 = newTemp(Ity_V128);
   17287       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   17288       assign( z0,  binop(Iop_ShlN16x8,
   17289                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17290                          mkU8(8)) );
   17291       assign( z1,  binop(Iop_ShrN16x8,
   17292                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17293                          mkU8(11)) );
   17294       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17295                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17296       assign( z2,  binop(Iop_ShrN16x8,
   17297                          binop(Iop_ShlN16x8,
   17298                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17299                                mkU8(11)),
   17300                          mkU8(3)) );
   17301       assign( z3,  binop(Iop_ShrN16x8,
   17302                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17303                          mkU8(11)) );
   17304       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17305                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17306       putVReg( vD_addr,
   17307                binop(Iop_OrV128,
   17308                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17309                      mkexpr(z23)) );
   17310       break;
   17311    }
   17312    case 0x64E: { // vupkhsw (Unpack High Signed Word)
   17313       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
   17314       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17315       putVReg( vD_addr,
   17316                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
   17317       break;
   17318    }
   17319    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
   17320       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
   17321       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17322       putVReg( vD_addr,
   17323                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
   17324       break;
   17325    }
   17326    default:
   17327       vex_printf("dis_av_pack(ppc)(opc2)\n");
   17328       return False;
   17329    }
   17330    return True;
   17331 }
   17332 
   17333 /*
   17334   AltiVec Cipher Instructions
   17335 */
   17336 static Bool dis_av_cipher ( UInt theInstr )
   17337 {
   17338    /* VX-Form */
   17339    UChar opc1     = ifieldOPC(theInstr);
   17340    UChar vD_addr  = ifieldRegDS(theInstr);
   17341    UChar vA_addr  = ifieldRegA(theInstr);
   17342    UChar vB_addr  = ifieldRegB(theInstr);
   17343    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17344 
   17345    IRTemp vA    = newTemp(Ity_V128);
   17346    IRTemp vB    = newTemp(Ity_V128);
   17347    assign( vA, getVReg(vA_addr));
   17348    assign( vB, getVReg(vB_addr));
   17349 
   17350    if (opc1 != 0x4) {
   17351       vex_printf("dis_av_cipher(ppc)(instr)\n");
   17352       return False;
   17353    }
   17354    switch (opc2) {
   17355       case 0x508: // vcipher (Vector Inverser Cipher)
   17356          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17357          putVReg( vD_addr,
   17358                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
   17359          return True;
   17360 
   17361       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
   17362          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17363          putVReg( vD_addr,
   17364                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
   17365          return True;
   17366 
   17367       case 0x548: // vncipher (Vector Inverser Cipher)
   17368          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17369          putVReg( vD_addr,
   17370                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
   17371          return True;
   17372 
   17373       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
   17374          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17375          putVReg( vD_addr,
   17376                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
   17377          return True;
   17378 
   17379       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
   17380        * subBytes transform)
   17381        */
   17382          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
   17383          putVReg( vD_addr,
   17384                   unop(Iop_CipherSV128, mkexpr(vA) ) );
   17385          return True;
   17386 
   17387       default:
   17388          vex_printf("dis_av_cipher(ppc)(opc2)\n");
   17389          return False;
   17390    }
   17391    return True;
   17392 }
   17393 
   17394 /*
   17395   AltiVec Secure Hash Instructions
   17396 */
   17397 static Bool dis_av_hash ( UInt theInstr )
   17398 {
   17399    /* VX-Form */
   17400    UChar opc1     = ifieldOPC(theInstr);
   17401    UChar vRT_addr = ifieldRegDS(theInstr);
   17402    UChar vRA_addr  = ifieldRegA(theInstr);
   17403    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
   17404    UChar st       = IFIELD( theInstr, 15, 1 );  // st
   17405    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
   17406    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17407 
   17408    IRTemp vA    = newTemp(Ity_V128);
   17409    IRTemp dst    = newTemp(Ity_V128);
   17410    assign( vA, getVReg(vRA_addr));
   17411 
   17412    if (opc1 != 0x4) {
   17413       vex_printf("dis_av_hash(ppc)(instr)\n");
   17414       return False;
   17415    }
   17416 
   17417    switch (opc2) {
   17418       case 0x682:  // vshasigmaw
   17419          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17420          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
   17421          putVReg( vRT_addr, mkexpr(dst));
   17422          return True;
   17423 
   17424       case 0x6C2:  // vshasigmad,
   17425          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17426          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
   17427          return True;
   17428 
   17429       default:
   17430          vex_printf("dis_av_hash(ppc)(opc2)\n");
   17431          return False;
   17432    }
   17433    return True;
   17434 }
   17435 
   17436 /*
   17437  * This function is used by the Vector add/subtract [extended] modulo/carry
   17438  * instructions.
   17439  *   - For the non-extended add instructions, the cin arg is set to zero.
   17440  *   - For the extended add instructions, cin is the integer value of
   17441  *     src3.bit[127].
   17442  *   - For the non-extended subtract instructions, src1 is added to the one's
   17443  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
   17444  *     value for this operation.
   17445  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
   17446  */
   17447 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
   17448                                         IRExpr * cin, Bool modulo)
   17449 {
   17450    IRTemp _vecA_32   = IRTemp_INVALID;
   17451    IRTemp _vecB_32   = IRTemp_INVALID;
   17452    IRTemp res_32     = IRTemp_INVALID;
   17453    IRTemp result     = IRTemp_INVALID;
   17454    IRTemp tmp_result = IRTemp_INVALID;
   17455    IRTemp carry      = IRTemp_INVALID;
   17456    Int i;
   17457    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
   17458    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
   17459    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
   17460    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
   17461 
   17462    for (i = 0; i < 4; i++) {
   17463       _vecA_32 = newTemp(Ity_I32);
   17464       _vecB_32 = newTemp(Ity_I32);
   17465       res_32   = newTemp(Ity_I32);
   17466       switch (i) {
   17467       case 0:
   17468          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
   17469          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
   17470          break;
   17471       case 1:
   17472          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
   17473          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
   17474          break;
   17475       case 2:
   17476          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
   17477          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
   17478          break;
   17479       case 3:
   17480          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
   17481          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
   17482          break;
   17483       }
   17484 
   17485       assign(res_32, binop( Iop_Add32,
   17486                             binop( Iop_Add32,
   17487                                    binop ( Iop_Add32,
   17488                                            mkexpr(_vecA_32),
   17489                                            mkexpr(_vecB_32) ),
   17490                                    (i == 0) ? mkU32(0) : mkexpr(carry) ),
   17491                             (i == 0) ? cin : mkU32(0) ) );
   17492       if (modulo) {
   17493          result = newTemp(Ity_V128);
   17494          assign(result, binop( Iop_OrV128,
   17495                               (i == 0) ? binop( Iop_64HLtoV128,
   17496                                                 mkU64(0),
   17497                                                 mkU64(0) ) : mkexpr(tmp_result),
   17498                               binop( Iop_ShlV128,
   17499                                      binop( Iop_64HLtoV128,
   17500                                             mkU64(0),
   17501                                             binop( Iop_32HLto64,
   17502                                                    mkU32(0),
   17503                                                    mkexpr(res_32) ) ),
   17504                                      mkU8(i * 32) ) ) );
   17505          tmp_result = newTemp(Ity_V128);
   17506          assign(tmp_result, mkexpr(result));
   17507       }
   17508       carry = newTemp(Ity_I32);
   17509       assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
   17510                                             mkexpr(res_32),
   17511                                             mkexpr(_vecA_32 ) ) ) );
   17512    }
   17513    if (modulo)
   17514       return result;
   17515    else
   17516       return carry;
   17517 }
   17518 
   17519 
   17520 static Bool dis_av_quad ( UInt theInstr )
   17521 {
   17522    /* VX-Form */
   17523    UChar opc1     = ifieldOPC(theInstr);
   17524    UChar vRT_addr = ifieldRegDS(theInstr);
   17525    UChar vRA_addr = ifieldRegA(theInstr);
   17526    UChar vRB_addr = ifieldRegB(theInstr);
   17527    UChar vRC_addr;
   17528    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17529 
   17530    IRTemp vA    = newTemp(Ity_V128);
   17531    IRTemp vB    = newTemp(Ity_V128);
   17532    IRTemp vC    = IRTemp_INVALID;
   17533    IRTemp cin    = IRTemp_INVALID;
   17534    assign( vA, getVReg(vRA_addr));
   17535    assign( vB, getVReg(vRB_addr));
   17536 
   17537    if (opc1 != 0x4) {
   17538       vex_printf("dis_av_quad(ppc)(instr)\n");
   17539       return False;
   17540    }
   17541 
   17542    switch (opc2) {
   17543    case 0x140:  // vaddcuq
   17544      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17545      putVReg( vRT_addr, unop( Iop_32UtoV128,
   17546                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17547                                                                mkexpr(vB),
   17548                                                                mkU32(0), False) ) ) );
   17549      return True;
   17550    case 0x100: // vadduqm
   17551       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17552       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17553                                                           mkexpr(vB), mkU32(0), True) ) );
   17554       return True;
   17555    case 0x540: // vsubcuq
   17556       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17557       putVReg( vRT_addr,
   17558                unop( Iop_32UtoV128,
   17559                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17560                                                       unop( Iop_NotV128,
   17561                                                             mkexpr(vB) ),
   17562                                                       mkU32(1), False) ) ) );
   17563       return True;
   17564    case 0x500: // vsubuqm
   17565       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17566       putVReg( vRT_addr,
   17567                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17568                                                 unop( Iop_NotV128, mkexpr(vB) ),
   17569                                                 mkU32(1), True) ) );
   17570       return True;
   17571    case 0x054C: // vbpermq
   17572    {
   17573 #define BPERMD_IDX_MASK 0x00000000000000FFULL
   17574 #define BPERMD_BIT_MASK 0x8000000000000000ULL
   17575       int i;
   17576       IRExpr * vB_expr = mkexpr(vB);
   17577       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
   17578       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   17579       for (i = 0; i < 16; i++) {
   17580          IRTemp idx_tmp = newTemp( Ity_V128 );
   17581          IRTemp perm_bit = newTemp( Ity_V128 );
   17582          IRTemp idx = newTemp( Ity_I8 );
   17583          IRTemp idx_LT127 = newTemp( Ity_I1 );
   17584          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
   17585 
   17586          assign( idx_tmp,
   17587                  binop( Iop_AndV128,
   17588                         binop( Iop_64HLtoV128,
   17589                                mkU64(0),
   17590                                mkU64(BPERMD_IDX_MASK) ),
   17591                         vB_expr ) );
   17592          assign( idx_LT127,
   17593                  binop( Iop_CmpEQ32,
   17594                         unop ( Iop_64to32,
   17595                                unop( Iop_V128to64, binop( Iop_ShrV128,
   17596                                                           mkexpr(idx_tmp),
   17597                                                           mkU8(7) ) ) ),
   17598                         mkU32(0) ) );
   17599 
   17600          /* Below, we set idx to determine which bit of vA to use for the
   17601           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
   17602           */
   17603          assign( idx,
   17604                  binop( Iop_And8,
   17605                         unop( Iop_1Sto8,
   17606                               mkexpr(idx_LT127) ),
   17607                         unop( Iop_32to8,
   17608                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
   17609 
   17610          assign( idx_LT127_ity128,
   17611                  binop( Iop_64HLtoV128,
   17612                         mkU64(0),
   17613                         unop( Iop_32Uto64,
   17614                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
   17615          assign( perm_bit,
   17616                  binop( Iop_AndV128,
   17617                         mkexpr( idx_LT127_ity128 ),
   17618                         binop( Iop_ShrV128,
   17619                                binop( Iop_AndV128,
   17620                                       binop (Iop_64HLtoV128,
   17621                                              mkU64( BPERMD_BIT_MASK ),
   17622                                              mkU64(0)),
   17623                                       binop( Iop_ShlV128,
   17624                                              mkexpr( vA ),
   17625                                              mkexpr( idx ) ) ),
   17626                                mkU8( 127 ) ) ) );
   17627          res = binop( Iop_OrV128,
   17628                       res,
   17629                       binop( Iop_ShlV128,
   17630                              mkexpr( perm_bit ),
   17631                              mkU8( i ) ) );
   17632          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
   17633       }
   17634       putVReg( vRT_addr, res);
   17635       return True;
   17636 #undef BPERMD_IDX_MASK
   17637 #undef BPERMD_BIT_MASK
   17638    }
   17639 
   17640    default:
   17641       break;  // fall through
   17642    }
   17643 
   17644    opc2     = IFIELD( theInstr, 0, 6 );
   17645    vRC_addr = ifieldRegC(theInstr);
   17646    vC = newTemp(Ity_V128);
   17647    cin = newTemp(Ity_I32);
   17648    switch (opc2) {
   17649       case 0x3D: // vaddecuq
   17650          assign( vC, getVReg(vRC_addr));
   17651          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   17652              vRC_addr);
   17653          assign(cin, binop( Iop_And32,
   17654                             unop( Iop_64to32,
   17655                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   17656                             mkU32(1) ) );
   17657          putVReg( vRT_addr,
   17658                   unop( Iop_32UtoV128,
   17659                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   17660                                                          mkexpr(cin),
   17661                                                          False) ) ) );
   17662          return True;
   17663       case 0x3C: // vaddeuqm
   17664          assign( vC, getVReg(vRC_addr));
   17665          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   17666              vRC_addr);
   17667          assign(cin, binop( Iop_And32,
   17668                             unop( Iop_64to32,
   17669                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   17670                             mkU32(1) ) );
   17671          putVReg( vRT_addr,
   17672                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   17673                                                    mkexpr(cin),
   17674                                                    True) ) );
   17675          return True;
   17676       case 0x3F: // vsubecuq
   17677          assign( vC, getVReg(vRC_addr));
   17678          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   17679              vRC_addr);
   17680          assign(cin, binop( Iop_And32,
   17681                             unop( Iop_64to32,
   17682                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   17683                             mkU32(1) ) );
   17684          putVReg( vRT_addr,
   17685                   unop( Iop_32UtoV128,
   17686                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17687                                                          unop( Iop_NotV128,
   17688                                                                mkexpr(vB) ),
   17689                                                          mkexpr(cin),
   17690                                                          False) ) ) );
   17691          return True;
   17692       case 0x3E: // vsubeuqm
   17693          assign( vC, getVReg(vRC_addr));
   17694          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   17695              vRC_addr);
   17696          assign(cin, binop( Iop_And32,
   17697                             unop( Iop_64to32,
   17698                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   17699                             mkU32(1) ) );
   17700          putVReg( vRT_addr,
   17701                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   17702                                                    unop( Iop_NotV128, mkexpr(vB) ),
   17703                                                    mkexpr(cin),
   17704                                                    True) ) );
   17705          return True;
   17706       default:
   17707          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
   17708          return False;
   17709    }
   17710 
   17711    return True;
   17712 }
   17713 
   17714 
   17715 /*
   17716   AltiVec BCD Arithmetic instructions.
   17717   These instructions modify CR6 for various conditions in the result,
   17718   including when an overflow occurs.  We could easily detect all conditions
   17719   except when an overflow occurs.  But since we can't be 100% accurate
   17720   in our emulation of CR6, it seems best to just not support it all.
   17721 */
   17722 static Bool dis_av_bcd ( UInt theInstr )
   17723 {
   17724    /* VX-Form */
   17725    UChar opc1     = ifieldOPC(theInstr);
   17726    UChar vRT_addr = ifieldRegDS(theInstr);
   17727    UChar vRA_addr = ifieldRegA(theInstr);
   17728    UChar vRB_addr = ifieldRegB(theInstr);
   17729    UChar ps       = IFIELD( theInstr, 9, 1 );
   17730    UInt  opc2     = IFIELD( theInstr, 0, 9 );
   17731 
   17732    IRTemp vA    = newTemp(Ity_V128);
   17733    IRTemp vB    = newTemp(Ity_V128);
   17734    IRTemp dst    = newTemp(Ity_V128);
   17735    assign( vA, getVReg(vRA_addr));
   17736    assign( vB, getVReg(vRB_addr));
   17737 
   17738    if (opc1 != 0x4) {
   17739       vex_printf("dis_av_bcd(ppc)(instr)\n");
   17740       return False;
   17741    }
   17742 
   17743    switch (opc2) {
   17744    case 0x1:  // bcdadd
   17745      DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   17746      assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
   17747                          mkexpr( vB ), mkU8( ps ) ) );
   17748      putVReg( vRT_addr, mkexpr(dst));
   17749      return True;
   17750 
   17751    case 0x41:  // bcdsub
   17752      DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   17753      assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
   17754                          mkexpr( vB ), mkU8( ps ) ) );
   17755      putVReg( vRT_addr, mkexpr(dst));
   17756      return True;
   17757 
   17758    default:
   17759       vex_printf("dis_av_bcd(ppc)(opc2)\n");
   17760       return False;
   17761    }
   17762    return True;
   17763 }
   17764 
   17765 /*
   17766   AltiVec Floating Point Arithmetic Instructions
   17767 */
   17768 static Bool dis_av_fp_arith ( UInt theInstr )
   17769 {
   17770    /* VA-Form */
   17771    UChar opc1     = ifieldOPC(theInstr);
   17772    UChar vD_addr  = ifieldRegDS(theInstr);
   17773    UChar vA_addr  = ifieldRegA(theInstr);
   17774    UChar vB_addr  = ifieldRegB(theInstr);
   17775    UChar vC_addr  = ifieldRegC(theInstr);
   17776    UInt  opc2=0;
   17777 
   17778    IRTemp vA = newTemp(Ity_V128);
   17779    IRTemp vB = newTemp(Ity_V128);
   17780    IRTemp vC = newTemp(Ity_V128);
   17781    assign( vA, getVReg(vA_addr));
   17782    assign( vB, getVReg(vB_addr));
   17783    assign( vC, getVReg(vC_addr));
   17784 
   17785    if (opc1 != 0x4) {
   17786       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   17787       return False;
   17788    }
   17789 
   17790    IRTemp rm = newTemp(Ity_I32);
   17791    assign(rm, get_IR_roundingmode());
   17792 
   17793    opc2 = IFIELD( theInstr, 0, 6 );
   17794    switch (opc2) {
   17795    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   17796       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   17797           vD_addr, vA_addr, vC_addr, vB_addr);
   17798       putVReg( vD_addr,
   17799                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
   17800                      mkexpr(vB),
   17801                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   17802                            mkexpr(vA), mkexpr(vC))) );
   17803       return True;
   17804 
   17805    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   17806       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   17807           vD_addr, vA_addr, vC_addr, vB_addr);
   17808       putVReg( vD_addr,
   17809                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   17810                      mkexpr(vB),
   17811                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   17812                            mkexpr(vA), mkexpr(vC))) );
   17813       return True;
   17814    }
   17815 
   17816    default:
   17817      break; // Fall through...
   17818    }
   17819 
   17820    opc2 = IFIELD( theInstr, 0, 11 );
   17821    switch (opc2) {
   17822    case 0x00A: // vaddfp (Add FP, AV p137)
   17823       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17824       putVReg( vD_addr, triop(Iop_Add32Fx4,
   17825                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   17826       return True;
   17827 
   17828   case 0x04A: // vsubfp (Subtract FP, AV p261)
   17829       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17830       putVReg( vD_addr, triop(Iop_Sub32Fx4,
   17831                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   17832       return True;
   17833 
   17834    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   17835       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17836       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   17837       return True;
   17838 
   17839    case 0x44A: // vminfp (Minimum FP, AV p187)
   17840       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17841       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   17842       return True;
   17843 
   17844    default:
   17845       break; // Fall through...
   17846    }
   17847 
   17848 
   17849    if (vA_addr != 0) {
   17850       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   17851       return False;
   17852    }
   17853 
   17854    switch (opc2) {
   17855    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   17856       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   17857       putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
   17858       return True;
   17859 
   17860    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   17861       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   17862       putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
   17863       return True;
   17864 
   17865    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   17866       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   17867       DIP(" => not implemented\n");
   17868       return False;
   17869 
   17870    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   17871       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   17872       DIP(" => not implemented\n");
   17873       return False;
   17874 
   17875    default:
   17876       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   17877       return False;
   17878    }
   17879    return True;
   17880 }
   17881 
   17882 /*
   17883   AltiVec Floating Point Compare Instructions
   17884 */
   17885 static Bool dis_av_fp_cmp ( UInt theInstr )
   17886 {
   17887    /* VXR-Form */
   17888    UChar opc1     = ifieldOPC(theInstr);
   17889    UChar vD_addr  = ifieldRegDS(theInstr);
   17890    UChar vA_addr  = ifieldRegA(theInstr);
   17891    UChar vB_addr  = ifieldRegB(theInstr);
   17892    UChar flag_rC  = ifieldBIT10(theInstr);
   17893    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   17894 
   17895    Bool cmp_bounds = False;
   17896 
   17897    IRTemp vA = newTemp(Ity_V128);
   17898    IRTemp vB = newTemp(Ity_V128);
   17899    IRTemp vD = newTemp(Ity_V128);
   17900    assign( vA, getVReg(vA_addr));
   17901    assign( vB, getVReg(vB_addr));
   17902 
   17903    if (opc1 != 0x4) {
   17904       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   17905       return False;
   17906    }
   17907 
   17908    switch (opc2) {
   17909    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   17910       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   17911                                       vD_addr, vA_addr, vB_addr);
   17912       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   17913       break;
   17914 
   17915    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   17916       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   17917                                       vD_addr, vA_addr, vB_addr);
   17918       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   17919       break;
   17920 
   17921    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   17922       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   17923                                       vD_addr, vA_addr, vB_addr);
   17924       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   17925       break;
   17926 
   17927    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   17928       IRTemp gt      = newTemp(Ity_V128);
   17929       IRTemp lt      = newTemp(Ity_V128);
   17930       IRTemp zeros   = newTemp(Ity_V128);
   17931       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   17932                                      vD_addr, vA_addr, vB_addr);
   17933       cmp_bounds = True;
   17934       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   17935 
   17936       /* Note: making use of fact that the ppc backend for compare insns
   17937          return zero'd lanes if either of the corresponding arg lanes is
   17938          a nan.
   17939 
   17940          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   17941          need this for the other compares too (vcmpeqfp etc)...
   17942          Better still, tighten down the spec for compare irops.
   17943        */
   17944       assign( gt, unop(Iop_NotV128,
   17945                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   17946       assign( lt, unop(Iop_NotV128,
   17947                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   17948                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   17949                                    mkexpr(zeros),
   17950                                    mkexpr(vB)))) );
   17951 
   17952       // finally, just shift gt,lt to correct position
   17953       assign( vD, binop(Iop_ShlN32x4,
   17954                         binop(Iop_OrV128,
   17955                               binop(Iop_AndV128, mkexpr(gt),
   17956                                     unop(Iop_Dup32x4, mkU32(0x2))),
   17957                               binop(Iop_AndV128, mkexpr(lt),
   17958                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   17959                         mkU8(30)) );
   17960       break;
   17961    }
   17962 
   17963    default:
   17964       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   17965       return False;
   17966    }
   17967 
   17968    putVReg( vD_addr, mkexpr(vD) );
   17969 
   17970    if (flag_rC) {
   17971       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   17972    }
   17973    return True;
   17974 }
   17975 
   17976 /*
   17977   AltiVec Floating Point Convert/Round Instructions
   17978 */
   17979 static Bool dis_av_fp_convert ( UInt theInstr )
   17980 {
   17981    /* VX-Form */
   17982    UChar opc1     = ifieldOPC(theInstr);
   17983    UChar vD_addr  = ifieldRegDS(theInstr);
   17984    UChar UIMM_5   = ifieldRegA(theInstr);
   17985    UChar vB_addr  = ifieldRegB(theInstr);
   17986    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17987 
   17988    IRTemp vB        = newTemp(Ity_V128);
   17989    IRTemp vScale    = newTemp(Ity_V128);
   17990    IRTemp vInvScale = newTemp(Ity_V128);
   17991 
   17992    float scale, inv_scale;
   17993 
   17994    assign( vB, getVReg(vB_addr));
   17995 
   17996    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   17997    scale = (float)( (unsigned int) 1<<UIMM_5 );
   17998    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   17999    inv_scale = 1/scale;
   18000    assign( vInvScale,
   18001            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   18002 
   18003    if (opc1 != 0x4) {
   18004       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   18005       return False;
   18006    }
   18007 
   18008    switch (opc2) {
   18009    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   18010       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18011       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18012                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   18013                               mkexpr(vInvScale)) );
   18014       return True;
   18015 
   18016    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   18017       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18018 
   18019       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18020                               unop(Iop_I32StoFx4, mkexpr(vB)),
   18021                               mkexpr(vInvScale)) );
   18022       return True;
   18023 
   18024    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   18025       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18026       putVReg( vD_addr,
   18027                unop(Iop_QFtoI32Ux4_RZ,
   18028                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18029                           mkexpr(vB), mkexpr(vScale))) );
   18030       return True;
   18031 
   18032    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   18033       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18034       putVReg( vD_addr,
   18035                unop(Iop_QFtoI32Sx4_RZ,
   18036                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18037                            mkexpr(vB), mkexpr(vScale))) );
   18038       return True;
   18039 
   18040    default:
   18041      break;    // Fall through...
   18042    }
   18043 
   18044    if (UIMM_5 != 0) {
   18045       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   18046       return False;
   18047    }
   18048 
   18049    switch (opc2) {
   18050    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   18051       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   18052       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   18053       break;
   18054 
   18055    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   18056       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   18057       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   18058       break;
   18059 
   18060    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   18061       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   18062       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   18063       break;
   18064 
   18065    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   18066       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   18067       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   18068       break;
   18069 
   18070    default:
   18071       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   18072       return False;
   18073    }
   18074    return True;
   18075 }
   18076 
   18077 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
   18078                                        VexAbiInfo* vbi,
   18079                                        /*OUT*/DisResult* dres,
   18080                                        Bool (*resteerOkFn)(void*,Addr64),
   18081                                        void* callback_opaque )
   18082 {
   18083    UInt   opc2      = IFIELD( theInstr, 1, 10 );
   18084 
   18085    switch (opc2) {
   18086    case 0x28E: {        //tbegin.
   18087       /* The current implementation is to just fail the tbegin and execute
   18088        * the failure path.  The failure path is assumed to be functionaly
   18089        * equivalent to the transactional path with the needed data locking
   18090        * to ensure correctness.  The tend is just a noop and shouldn't
   18091        * actually get executed.
   18092        *   1) set cr0 to 0x2
   18093        *   2) Initialize TFHAR to CIA+4
   18094        *   3) Initialize TEXASR
   18095        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
   18096        *   5) Continue executing at the next instruction.
   18097        */
   18098       UInt R = IFIELD( theInstr, 21, 1 );
   18099 
   18100       ULong tm_reason;
   18101       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
   18102                                * or treclaim.
   18103                                */
   18104       UInt persistant = 1;    /* set persistant since we are always failing
   18105                                * the tbegin.
   18106                                */
   18107       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
   18108                                  as the reason for failing the trasaction */
   18109       UInt tm_exact   = 1;    /* have exact address for failure */
   18110 
   18111       DIP("tbegin. %d\n", R);
   18112 
   18113       /* Set the CR0 field to indicate the tbegin failed.  Then let
   18114        * the code do the branch to the failure path.
   18115        *
   18116        * 000 || 0  Transaction initiation successful,
   18117        *           unnested (Transaction state of
   18118        *           Non-transactional prior to tbegin.)
   18119        * 010 || 0  Transaction initiation successful, nested
   18120        *           (Transaction state of Transactional
   18121        *           prior to tbegin.)
   18122        * 001 || 0  Transaction initiation unsuccessful,
   18123        *           (Transaction state of Suspended prior
   18124        *           to tbegin.)
   18125        */
   18126       putCR321( 0, mkU8( 0x2 ) );
   18127 
   18128       tm_reason = generate_TMreason( failure_code, persistant,
   18129                                      nest_overflow, tm_exact );
   18130 
   18131       storeTMfailure( guest_CIA_curr_instr, tm_reason,
   18132                       guest_CIA_curr_instr+4 );
   18133 
   18134       return True;
   18135 
   18136       break;
   18137    }
   18138 
   18139    case 0x2AE: {        //tend.
   18140       /* The tend. is just a noop.  Do nothing */
   18141       UInt A = IFIELD( theInstr, 25, 1 );
   18142 
   18143       DIP("tend. %d\n", A);
   18144       break;
   18145    }
   18146 
   18147    case 0x2EE: {        //tsr.
   18148       /* The tsr. is just a noop.  Do nothing */
   18149       UInt L = IFIELD( theInstr, 21, 1 );
   18150 
   18151       DIP("tsr. %d\n", L);
   18152       break;
   18153    }
   18154 
   18155    case 0x2CE: {        //tcheck.
   18156       /* The tcheck. is just a noop.  Do nothing */
   18157       UInt BF = IFIELD( theInstr, 25, 1 );
   18158 
   18159       DIP("tcheck. %d\n", BF);
   18160       break;
   18161    }
   18162 
   18163    case 0x30E: {        //tbortwc.
   18164       /* The tabortwc. is just a noop.  Do nothing */
   18165       UInt TO = IFIELD( theInstr, 25, 1 );
   18166       UInt RA = IFIELD( theInstr, 16, 5 );
   18167       UInt RB = IFIELD( theInstr, 11, 5 );
   18168 
   18169       DIP("tabortwc. %d,%d,%d\n", TO, RA, RB);
   18170       break;
   18171    }
   18172 
   18173    case 0x32E: {        //tbortdc.
   18174       /* The tabortdc. is just a noop.  Do nothing */
   18175       UInt TO = IFIELD( theInstr, 25, 1 );
   18176       UInt RA = IFIELD( theInstr, 16, 5 );
   18177       UInt RB = IFIELD( theInstr, 11, 5 );
   18178 
   18179       DIP("tabortdc. %d,%d,%d\n", TO, RA, RB);
   18180       break;
   18181    }
   18182 
   18183    case 0x34E: {        //tbortwci.
   18184       /* The tabortwci. is just a noop.  Do nothing */
   18185       UInt TO = IFIELD( theInstr, 25, 1 );
   18186       UInt RA = IFIELD( theInstr, 16, 5 );
   18187       UInt SI = IFIELD( theInstr, 11, 5 );
   18188 
   18189       DIP("tabortwci. %d,%d,%d\n", TO, RA, SI);
   18190       break;
   18191    }
   18192 
   18193    case 0x36E: {        //tbortdci.
   18194       /* The tabortdci. is just a noop.  Do nothing */
   18195       UInt TO = IFIELD( theInstr, 25, 1 );
   18196       UInt RA = IFIELD( theInstr, 16, 5 );
   18197       UInt SI = IFIELD( theInstr, 11, 5 );
   18198 
   18199       DIP("tabortdci. %d,%d,%d\n", TO, RA, SI);
   18200       break;
   18201    }
   18202 
   18203    case 0x38E: {        //tbort.
   18204       /* The tabort. is just a noop.  Do nothing */
   18205       UInt RA = IFIELD( theInstr, 16, 5 );
   18206 
   18207       DIP("tabort. %d\n", RA);
   18208       break;
   18209    }
   18210 
   18211    case 0x3AE: {        //treclaim.
   18212       /* The treclaim. is just a noop.  Do nothing */
   18213       UInt RA = IFIELD( theInstr, 16, 5 );
   18214 
   18215       DIP("treclaim. %d\n", RA);
   18216       break;
   18217    }
   18218 
   18219    case 0x3EE: {        //trechkpt.
   18220       /* The trechkpt. is just a noop.  Do nothing */
   18221       DIP("trechkpt.\n");
   18222       break;
   18223    }
   18224 
   18225    default:
   18226       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
   18227       return False;
   18228    }
   18229 
   18230    return True;
   18231 }
   18232 
   18233 
   18234 /* The 0x3C primary opcode (VSX category) uses several different forms of
   18235  * extended opcodes:
   18236  *   o XX2-form:
   18237  *      - [10:2] (IBM notation [21:29])
   18238  *   o XX3-form variants:
   18239  *       - variant 1: [10:3] (IBM notation [21:28])
   18240  *       - variant 2: [9:3] (IBM notation [22:28])
   18241  *       - variant 3: [7:3] (IBM notation [24:28])
   18242  *   o XX-4 form:
   18243  *      - [10:6] (IBM notation [21:25])
   18244  *
   18245  * The XX2-form needs bit 0 masked from the standard extended opcode
   18246  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   18247  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   18248  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   18249  * front end since their encoding does not begin at bit 21 like the standard
   18250  * format.
   18251  *
   18252  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   18253  * secondary opcode for such VSX instructions.
   18254  *
   18255 */
   18256 
   18257 
   18258 struct vsx_insn {
   18259    UInt opcode;
   18260    const HChar * name;
   18261 };
   18262 
   18263 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   18264 static struct vsx_insn vsx_all[] = {
   18265       { 0x0, "xsaddsp" },
   18266       { 0x4, "xsmaddasp" },
   18267       { 0x8, "xxsldwi" },
   18268       { 0x14, "xsrsqrtesp" },
   18269       { 0x16, "xssqrtsp" },
   18270       { 0x18, "xxsel" },
   18271       { 0x20, "xssubsp" },
   18272       { 0x24, "xsmaddmsp" },
   18273       { 0x28, "xxpermdi" },
   18274       { 0x34, "xsresp" },
   18275       { 0x40, "xsmulsp" },
   18276       { 0x44, "xsmsubasp" },
   18277       { 0x48, "xxmrghw" },
   18278       { 0x60, "xsdivsp" },
   18279       { 0x64, "xsmsubmsp" },
   18280       { 0x80, "xsadddp" },
   18281       { 0x84, "xsmaddadp" },
   18282       { 0x8c, "xscmpudp" },
   18283       { 0x90, "xscvdpuxws" },
   18284       { 0x92, "xsrdpi" },
   18285       { 0x94, "xsrsqrtedp" },
   18286       { 0x96, "xssqrtdp" },
   18287       { 0xa0, "xssubdp" },
   18288       { 0xa4, "xsmaddmdp" },
   18289       { 0xac, "xscmpodp" },
   18290       { 0xb0, "xscvdpsxws" },
   18291       { 0xb2, "xsrdpiz" },
   18292       { 0xb4, "xsredp" },
   18293       { 0xc0, "xsmuldp" },
   18294       { 0xc4, "xsmsubadp" },
   18295       { 0xc8, "xxmrglw" },
   18296       { 0xd2, "xsrdpip" },
   18297       { 0xd4, "xstsqrtdp" },
   18298       { 0xd6, "xsrdpic" },
   18299       { 0xe0, "xsdivdp" },
   18300       { 0xe4, "xsmsubmdp" },
   18301       { 0xf2, "xsrdpim" },
   18302       { 0xf4, "xstdivdp" },
   18303       { 0x100, "xvaddsp" },
   18304       { 0x104, "xvmaddasp" },
   18305       { 0x10c, "xvcmpeqsp" },
   18306       { 0x110, "xvcvspuxws" },
   18307       { 0x112, "xvrspi" },
   18308       { 0x114, "xvrsqrtesp" },
   18309       { 0x116, "xvsqrtsp" },
   18310       { 0x120, "xvsubsp" },
   18311       { 0x124, "xvmaddmsp" },
   18312       { 0x12c, "xvcmpgtsp" },
   18313       { 0x130, "xvcvspsxws" },
   18314       { 0x132, "xvrspiz" },
   18315       { 0x134, "xvresp" },
   18316       { 0x140, "xvmulsp" },
   18317       { 0x144, "xvmsubasp" },
   18318       { 0x148, "xxspltw" },
   18319       { 0x14c, "xvcmpgesp" },
   18320       { 0x150, "xvcvuxwsp" },
   18321       { 0x152, "xvrspip" },
   18322       { 0x154, "xvtsqrtsp" },
   18323       { 0x156, "xvrspic" },
   18324       { 0x160, "xvdivsp" },
   18325       { 0x164, "xvmsubmsp" },
   18326       { 0x170, "xvcvsxwsp" },
   18327       { 0x172, "xvrspim" },
   18328       { 0x174, "xvtdivsp" },
   18329       { 0x180, "xvadddp" },
   18330       { 0x184, "xvmaddadp" },
   18331       { 0x18c, "xvcmpeqdp" },
   18332       { 0x190, "xvcvdpuxws" },
   18333       { 0x192, "xvrdpi" },
   18334       { 0x194, "xvrsqrtedp" },
   18335       { 0x196, "xvsqrtdp" },
   18336       { 0x1a0, "xvsubdp" },
   18337       { 0x1a4, "xvmaddmdp" },
   18338       { 0x1ac, "xvcmpgtdp" },
   18339       { 0x1b0, "xvcvdpsxws" },
   18340       { 0x1b2, "xvrdpiz" },
   18341       { 0x1b4, "xvredp" },
   18342       { 0x1c0, "xvmuldp" },
   18343       { 0x1c4, "xvmsubadp" },
   18344       { 0x1cc, "xvcmpgedp" },
   18345       { 0x1d0, "xvcvuxwdp" },
   18346       { 0x1d2, "xvrdpip" },
   18347       { 0x1d4, "xvtsqrtdp" },
   18348       { 0x1d6, "xvrdpic" },
   18349       { 0x1e0, "xvdivdp" },
   18350       { 0x1e4, "xvmsubmdp" },
   18351       { 0x1f0, "xvcvsxwdp" },
   18352       { 0x1f2, "xvrdpim" },
   18353       { 0x1f4, "xvtdivdp" },
   18354       { 0x204, "xsnmaddasp" },
   18355       { 0x208, "xxland" },
   18356       { 0x212, "xscvdpsp" },
   18357       { 0x216, "xscvdpspn" },
   18358       { 0x224, "xsnmaddmsp" },
   18359       { 0x228, "xxlandc" },
   18360       { 0x232, "xxrsp" },
   18361       { 0x244, "xsnmsubasp" },
   18362       { 0x248, "xxlor" },
   18363       { 0x250, "xscvuxdsp" },
   18364       { 0x264, "xsnmsubmsp" },
   18365       { 0x268, "xxlxor" },
   18366       { 0x270, "xscvsxdsp" },
   18367       { 0x280, "xsmaxdp" },
   18368       { 0x284, "xsnmaddadp" },
   18369       { 0x288, "xxlnor" },
   18370       { 0x290, "xscvdpuxds" },
   18371       { 0x292, "xscvspdp" },
   18372       { 0x296, "xscvspdpn" },
   18373       { 0x2a0, "xsmindp" },
   18374       { 0x2a4, "xsnmaddmdp" },
   18375       { 0x2a8, "xxlorc" },
   18376       { 0x2b0, "xscvdpsxds" },
   18377       { 0x2b2, "xsabsdp" },
   18378       { 0x2c0, "xscpsgndp" },
   18379       { 0x2c4, "xsnmsubadp" },
   18380       { 0x2c8, "xxlnand" },
   18381       { 0x2d0, "xscvuxddp" },
   18382       { 0x2d2, "xsnabsdp" },
   18383       { 0x2e4, "xsnmsubmdp" },
   18384       { 0x2e8, "xxleqv" },
   18385       { 0x2f0, "xscvsxddp" },
   18386       { 0x2f2, "xsnegdp" },
   18387       { 0x300, "xvmaxsp" },
   18388       { 0x304, "xvnmaddasp" },
   18389       { 0x30c, "xvcmpeqsp." },
   18390       { 0x310, "xvcvspuxds" },
   18391       { 0x312, "xvcvdpsp" },
   18392       { 0x320, "xvminsp" },
   18393       { 0x324, "xvnmaddmsp" },
   18394       { 0x32c, "xvcmpgtsp." },
   18395       { 0x330, "xvcvspsxds" },
   18396       { 0x332, "xvabssp" },
   18397       { 0x340, "xvcpsgnsp" },
   18398       { 0x344, "xvnmsubasp" },
   18399       { 0x34c, "xvcmpgesp." },
   18400       { 0x350, "xvcvuxdsp" },
   18401       { 0x352, "xvnabssp" },
   18402       { 0x364, "xvnmsubmsp" },
   18403       { 0x370, "xvcvsxdsp" },
   18404       { 0x372, "xvnegsp" },
   18405       { 0x380, "xvmaxdp" },
   18406       { 0x384, "xvnmaddadp" },
   18407       { 0x38c, "xvcmpeqdp." },
   18408       { 0x390, "xvcvdpuxds" },
   18409       { 0x392, "xvcvspdp" },
   18410       { 0x3a0, "xvmindp" },
   18411       { 0x3a4, "xvnmaddmdp" },
   18412       { 0x3ac, "xvcmpgtdp." },
   18413       { 0x3b0, "xvcvdpsxds" },
   18414       { 0x3b2, "xvabsdp" },
   18415       { 0x3c0, "xvcpsgndp" },
   18416       { 0x3c4, "xvnmsubadp" },
   18417       { 0x3cc, "xvcmpgedp." },
   18418       { 0x3d0, "xvcvuxddp" },
   18419       { 0x3d2, "xvnabsdp" },
   18420       { 0x3e4, "xvnmsubmdp" },
   18421       { 0x3f0, "xvcvsxddp" },
   18422       { 0x3f2, "xvnegdp" }
   18423 };
   18424 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
   18425 
   18426 
   18427 // ATTENTION: This search function assumes vsx_all array is sorted.
   18428 static Int findVSXextOpCode(UInt opcode)
   18429 {
   18430    Int low, mid, high;
   18431    low = 0;
   18432    high = VSX_ALL_LEN - 1;
   18433    while (low <= high) {
   18434       mid = (low + high)/2;
   18435       if (opcode < vsx_all[mid].opcode)
   18436          high = mid - 1;
   18437       else if (opcode > vsx_all[mid].opcode)
   18438          low = mid + 1;
   18439       else
   18440          return mid;
   18441    }
   18442    return -1;
   18443 }
   18444 
   18445 
   18446 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   18447  * passed, and we then try to match it up with one of the VSX forms
   18448  * below.
   18449  */
   18450 static UInt get_VSX60_opc2(UInt opc2_full)
   18451 {
   18452 #define XX2_MASK 0x000003FE
   18453 #define XX3_1_MASK 0x000003FC
   18454 #define XX3_2_MASK 0x000001FC
   18455 #define XX3_3_MASK 0x0000007C
   18456 #define XX4_MASK 0x00000018
   18457    Int ret;
   18458    UInt vsxExtOpcode = 0;
   18459 
   18460    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
   18461       vsxExtOpcode = vsx_all[ret].opcode;
   18462    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
   18463       vsxExtOpcode = vsx_all[ret].opcode;
   18464    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
   18465       vsxExtOpcode = vsx_all[ret].opcode;
   18466    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
   18467       vsxExtOpcode = vsx_all[ret].opcode;
   18468    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
   18469       vsxExtOpcode = vsx_all[ret].opcode;
   18470 
   18471    return vsxExtOpcode;
   18472 }
   18473 
   18474 /*------------------------------------------------------------*/
   18475 /*--- Disassemble a single instruction                     ---*/
   18476 /*------------------------------------------------------------*/
   18477 
   18478 /* Disassemble a single instruction into IR.  The instruction
   18479    is located in host memory at &guest_code[delta]. */
   18480 
   18481 static
   18482 DisResult disInstr_PPC_WRK (
   18483              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   18484              Bool         resteerCisOk,
   18485              void*        callback_opaque,
   18486              Long         delta64,
   18487              VexArchInfo* archinfo,
   18488              VexAbiInfo*  abiinfo,
   18489              Bool         sigill_diag
   18490           )
   18491 {
   18492    UChar     opc1;
   18493    UInt      opc2;
   18494    DisResult dres;
   18495    UInt      theInstr;
   18496    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   18497    Bool      allow_F  = False;
   18498    Bool      allow_V  = False;
   18499    Bool      allow_FX = False;
   18500    Bool      allow_GX = False;
   18501    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   18502    Bool      allow_DFP = False;
   18503    Bool      allow_isa_2_07 = False;
   18504    UInt      hwcaps = archinfo->hwcaps;
   18505    Long      delta;
   18506 
   18507    /* What insn variants are we supporting today? */
   18508    if (mode64) {
   18509       allow_F  = True;
   18510       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   18511       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   18512       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   18513       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   18514       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
   18515       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
   18516    } else {
   18517       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   18518       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   18519       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   18520       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   18521       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   18522       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
   18523       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
   18524    }
   18525 
   18526    /* The running delta */
   18527    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   18528 
   18529    /* Set result defaults. */
   18530    dres.whatNext    = Dis_Continue;
   18531    dres.len         = 0;
   18532    dres.continueAt  = 0;
   18533    dres.jk_StopHere = Ijk_INVALID;
   18534 
   18535    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   18536       4-aligned.  So just fish the whole thing out of memory right now
   18537       and have done. */
   18538    theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
   18539 
   18540    if (0) vex_printf("insn: 0x%x\n", theInstr);
   18541 
   18542    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   18543 
   18544    /* Spot "Special" instructions (see comment at top of file). */
   18545    {
   18546       UChar* code = (UChar*)(guest_code + delta);
   18547       /* Spot the 16-byte preamble:
   18548          32-bit mode:
   18549             5400183E  rlwinm 0,0,3,0,31
   18550             5400683E  rlwinm 0,0,13,0,31
   18551             5400E83E  rlwinm 0,0,29,0,31
   18552             5400983E  rlwinm 0,0,19,0,31
   18553          64-bit mode:
   18554             78001800  rotldi 0,0,3
   18555             78006800  rotldi 0,0,13
   18556             7800E802  rotldi 0,0,61
   18557             78009802  rotldi 0,0,51
   18558       */
   18559       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
   18560       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
   18561       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
   18562       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
   18563       if (getUIntBigendianly(code+ 0) == word1 &&
   18564           getUIntBigendianly(code+ 4) == word2 &&
   18565           getUIntBigendianly(code+ 8) == word3 &&
   18566           getUIntBigendianly(code+12) == word4) {
   18567          /* Got a "Special" instruction preamble.  Which one is it? */
   18568          if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   18569             /* %R3 = client_request ( %R4 ) */
   18570             DIP("r3 = client_request ( %%r4 )\n");
   18571             delta += 20;
   18572             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   18573             dres.jk_StopHere = Ijk_ClientReq;
   18574             dres.whatNext    = Dis_StopHere;
   18575             goto decode_success;
   18576          }
   18577          else
   18578          if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   18579             /* %R3 = guest_NRADDR */
   18580             DIP("r3 = guest_NRADDR\n");
   18581             delta += 20;
   18582             dres.len = 20;
   18583             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   18584             goto decode_success;
   18585          }
   18586          else
   18587          if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   18588             /*  branch-and-link-to-noredir %R11 */
   18589             DIP("branch-and-link-to-noredir r11\n");
   18590             delta += 20;
   18591             putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   18592             putGST( PPC_GST_CIA, getIReg(11));
   18593             dres.jk_StopHere = Ijk_NoRedir;
   18594             dres.whatNext    = Dis_StopHere;
   18595             goto decode_success;
   18596          }
   18597          else
   18598          if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   18599             /* %R3 = guest_NRADDR_GPR2 */
   18600             DIP("r3 = guest_NRADDR_GPR2\n");
   18601             delta += 20;
   18602             dres.len = 20;
   18603             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   18604             goto decode_success;
   18605          }
   18606          else
   18607          if (getUIntBigendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
   18608             DIP("IR injection\n");
   18609 
   18610             vex_inject_ir(irsb, Iend_BE);
   18611 
   18612             delta += 20;
   18613             dres.len = 20;
   18614 
   18615             // Invalidate the current insn. The reason is that the IRop we're
   18616             // injecting here can change. In which case the translation has to
   18617             // be redone. For ease of handling, we simply invalidate all the
   18618             // time.
   18619 
   18620             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
   18621             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
   18622 
   18623             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   18624             dres.whatNext    = Dis_StopHere;
   18625             dres.jk_StopHere = Ijk_InvalICache;
   18626             goto decode_success;
   18627          }
   18628          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   18629             can print the insn following the Special-insn preamble. */
   18630          theInstr = getUIntBigendianly(code+16);
   18631          opc1     = ifieldOPC(theInstr);
   18632          opc2     = ifieldOPClo10(theInstr);
   18633          goto decode_failure;
   18634          /*NOTREACHED*/
   18635       }
   18636    }
   18637 
   18638    opc1 = ifieldOPC(theInstr);
   18639    opc2 = ifieldOPClo10(theInstr);
   18640 
   18641    // Note: all 'reserved' bits must be cleared, else invalid
   18642    switch (opc1) {
   18643 
   18644    /* Integer Arithmetic Instructions */
   18645    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   18646    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   18647       if (dis_int_arith( theInstr )) goto decode_success;
   18648       goto decode_failure;
   18649 
   18650    /* Integer Compare Instructions */
   18651    case 0x0B: case 0x0A: // cmpi, cmpli
   18652       if (dis_int_cmp( theInstr )) goto decode_success;
   18653       goto decode_failure;
   18654 
   18655    /* Integer Logical Instructions */
   18656    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   18657    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   18658       if (dis_int_logic( theInstr )) goto decode_success;
   18659       goto decode_failure;
   18660 
   18661    /* Integer Rotate Instructions */
   18662    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   18663       if (dis_int_rot( theInstr )) goto decode_success;
   18664       goto decode_failure;
   18665 
   18666    /* 64bit Integer Rotate Instructions */
   18667    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   18668       if (!mode64) goto decode_failure;
   18669       if (dis_int_rot( theInstr )) goto decode_success;
   18670       goto decode_failure;
   18671 
   18672    /* Integer Load Instructions */
   18673    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   18674    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   18675    case 0x20: case 0x21:            // lwz,  lwzu
   18676       if (dis_int_load( theInstr )) goto decode_success;
   18677       goto decode_failure;
   18678 
   18679    /* Integer Store Instructions */
   18680    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   18681    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   18682       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   18683       goto decode_failure;
   18684 
   18685    /* Integer Load and Store Multiple Instructions */
   18686    case 0x2E: case 0x2F: // lmw, stmw
   18687       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   18688       goto decode_failure;
   18689 
   18690    /* Branch Instructions */
   18691    case 0x12: case 0x10: // b, bc
   18692       if (dis_branch(theInstr, abiinfo, &dres,
   18693                                resteerOkFn, callback_opaque))
   18694          goto decode_success;
   18695       goto decode_failure;
   18696 
   18697    /* System Linkage Instructions */
   18698    case 0x11: // sc
   18699       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   18700       goto decode_failure;
   18701 
   18702    /* Trap Instructions */
   18703    case 0x02:    // tdi
   18704       if (!mode64) goto decode_failure;
   18705       if (dis_trapi(theInstr, &dres)) goto decode_success;
   18706       goto decode_failure;
   18707 
   18708    case 0x03:   // twi
   18709       if (dis_trapi(theInstr, &dres)) goto decode_success;
   18710       goto decode_failure;
   18711 
   18712    /* Floating Point Load Instructions */
   18713    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   18714    case 0x33:                       // lfdu
   18715       if (!allow_F) goto decode_noF;
   18716       if (dis_fp_load( theInstr )) goto decode_success;
   18717       goto decode_failure;
   18718 
   18719    /* Floating Point Store Instructions */
   18720    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   18721    case 0x37:                       // stfdux
   18722       if (!allow_F) goto decode_noF;
   18723       if (dis_fp_store( theInstr )) goto decode_success;
   18724       goto decode_failure;
   18725 
   18726       /* Floating Point Load Double Pair Instructions */
   18727    case 0x39: case 0x3D:
   18728       if (!allow_F) goto decode_noF;
   18729       if (dis_fp_pair( theInstr )) goto decode_success;
   18730       goto decode_failure;
   18731 
   18732    /* 128-bit Integer Load */
   18733    case 0x38:  // lq
   18734       if (dis_int_load( theInstr )) goto decode_success;
   18735       goto decode_failure;
   18736 
   18737    /* 64bit Integer Loads */
   18738    case 0x3A:  // ld, ldu, lwa
   18739       if (!mode64) goto decode_failure;
   18740       if (dis_int_load( theInstr )) goto decode_success;
   18741       goto decode_failure;
   18742 
   18743    case 0x3B:
   18744       if (!allow_F) goto decode_noF;
   18745       opc2 = ifieldOPClo10(theInstr);
   18746 
   18747       switch (opc2) {
   18748          case 0x2:    // dadd - DFP Add
   18749          case 0x202:  // dsub - DFP Subtract
   18750          case 0x22:   // dmul - DFP Mult
   18751          case 0x222:  // ddiv - DFP Divide
   18752             if (!allow_DFP) goto decode_noDFP;
   18753             if (dis_dfp_arith( theInstr ))
   18754                goto decode_success;
   18755          case 0x82:   // dcmpo, DFP comparison ordered instruction
   18756          case 0x282:  // dcmpu, DFP comparison unordered instruction
   18757             if (!allow_DFP)
   18758                goto decode_failure;
   18759             if (dis_dfp_compare( theInstr ) )
   18760                goto decode_success;
   18761             goto decode_failure;
   18762          case 0x102: // dctdp  - DFP convert to DFP long
   18763          case 0x302: // drsp   - DFP round to dfp short
   18764          case 0x122: // dctfix - DFP convert to fixed
   18765             if (!allow_DFP)
   18766                goto decode_failure;
   18767             if (dis_dfp_fmt_conv( theInstr ))
   18768                goto decode_success;
   18769             goto decode_failure;
   18770          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
   18771             if (!allow_VX)
   18772                goto decode_failure;
   18773             if (dis_dfp_fmt_conv( theInstr ))
   18774                goto decode_success;
   18775             goto decode_failure;
   18776          case 0x2A2: // dtstsf - DFP number of significant digits
   18777             if (!allow_DFP)
   18778                goto decode_failure;
   18779             if (dis_dfp_significant_digits(theInstr))
   18780                goto decode_success;
   18781             goto decode_failure;
   18782          case 0x142: // ddedpd   DFP Decode DPD to BCD
   18783          case 0x342: // denbcd   DFP Encode BCD to DPD
   18784             if (!allow_DFP)
   18785                goto decode_failure;
   18786             if (dis_dfp_bcd(theInstr))
   18787                goto decode_success;
   18788             goto decode_failure;
   18789          case 0x162:  // dxex - Extract exponent
   18790          case 0x362:  // diex - Insert exponent
   18791             if (!allow_DFP)
   18792                goto decode_failure;
   18793             if (dis_dfp_extract_insert( theInstr ) )
   18794                goto decode_success;
   18795             goto decode_failure;
   18796          case 0x3CE: // fcfidus (implemented as native insn)
   18797             if (!allow_VX)
   18798                goto decode_noVX;
   18799             if (dis_fp_round( theInstr ))
   18800                goto decode_success;
   18801             goto decode_failure;
   18802          case 0x34E: // fcfids
   18803             if (dis_fp_round( theInstr ))
   18804                goto decode_success;
   18805             goto decode_failure;
   18806       }
   18807 
   18808       opc2 = ifieldOPClo9( theInstr );
   18809       switch (opc2) {
   18810       case 0x42: // dscli, DFP shift left
   18811       case 0x62: // dscri, DFP shift right
   18812          if (!allow_DFP)
   18813             goto decode_failure;
   18814          if (dis_dfp_shift( theInstr ))
   18815             goto decode_success;
   18816          goto decode_failure;
   18817       case 0xc2:  // dtstdc, DFP test data class
   18818       case 0xe2:  // dtstdg, DFP test data group
   18819          if (!allow_DFP)
   18820             goto decode_failure;
   18821          if (dis_dfp_class_test( theInstr ))
   18822             goto decode_success;
   18823          goto decode_failure;
   18824       }
   18825 
   18826       opc2 = ifieldOPClo8( theInstr );
   18827       switch (opc2) {
   18828       case 0x3:   // dqua  - DFP Quantize
   18829       case 0x23:  // drrnd - DFP Reround
   18830       case 0x43:  // dquai - DFP Quantize immediate
   18831          if (!allow_DFP)
   18832             goto decode_failure;
   18833          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
   18834             goto decode_success;
   18835          goto decode_failure;
   18836       case 0xA2: // dtstex - DFP Test exponent
   18837          if (!allow_DFP)
   18838             goto decode_failure;
   18839          if (dis_dfp_exponent_test( theInstr ) )
   18840             goto decode_success;
   18841          goto decode_failure;
   18842       case 0x63: // drintx - Round to an integer value
   18843       case 0xE3: // drintn - Round to an integer value
   18844          if (!allow_DFP)
   18845             goto decode_failure;
   18846          if (dis_dfp_round( theInstr ) ) {
   18847             goto decode_success;
   18848          }
   18849          goto decode_failure;
   18850       default:
   18851          break;  /* fall through to next opc2 check */
   18852       }
   18853 
   18854       opc2 = IFIELD(theInstr, 1, 5);
   18855       switch (opc2) {
   18856       /* Floating Point Arith Instructions */
   18857       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   18858       case 0x19:                       // fmuls
   18859          if (dis_fp_arith(theInstr)) goto decode_success;
   18860          goto decode_failure;
   18861       case 0x16:                       // fsqrts
   18862          if (!allow_FX) goto decode_noFX;
   18863          if (dis_fp_arith(theInstr)) goto decode_success;
   18864          goto decode_failure;
   18865       case 0x18:                       // fres
   18866          if (!allow_GX) goto decode_noGX;
   18867          if (dis_fp_arith(theInstr)) goto decode_success;
   18868          goto decode_failure;
   18869 
   18870       /* Floating Point Mult-Add Instructions */
   18871       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   18872       case 0x1F:                       // fnmadds
   18873          if (dis_fp_multadd(theInstr)) goto decode_success;
   18874          goto decode_failure;
   18875 
   18876       case 0x1A:                       // frsqrtes
   18877          if (!allow_GX) goto decode_noGX;
   18878          if (dis_fp_arith(theInstr)) goto decode_success;
   18879          goto decode_failure;
   18880 
   18881       default:
   18882          goto decode_failure;
   18883       }
   18884       break;
   18885 
   18886    case 0x3C: // VSX instructions (except load/store)
   18887    {
   18888       // All of these VSX instructions use some VMX facilities, so
   18889       // if allow_V is not set, we'll skip trying to decode.
   18890       if (!allow_V) goto decode_noVX;
   18891 
   18892       UInt vsxOpc2 = get_VSX60_opc2(opc2);
   18893       /* The vsxOpc2 returned is the "normalized" value, representing the
   18894        * instructions secondary opcode as taken from the standard secondary
   18895        * opcode field [21:30] (IBM notatition), even if the actual field
   18896        * is non-standard.  These normalized values are given in the opcode
   18897        * appendices of the ISA 2.06 document.
   18898        */
   18899 
   18900       switch (vsxOpc2) {
   18901          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   18902          case 0x018: case 0x148: // xxsel, xxspltw
   18903             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   18904             goto decode_failure;
   18905          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
   18906          case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
   18907          case 0x2C8: case 0x2E8: // xxlnand, xxleqv
   18908             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   18909             goto decode_failure;
   18910          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   18911          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   18912          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   18913          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   18914          case 0x034: case 0x014: // xsresp, xsrsqrtesp
   18915          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   18916          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   18917          case 0x092: case 0x232: // xsrdpi, xsrsp
   18918             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
   18919             goto decode_failure;
   18920          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   18921             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   18922             goto decode_failure;
   18923          case 0x0:   case 0x020: // xsaddsp, xssubsp
   18924          case 0x080:             // xsadddp
   18925          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
   18926          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
   18927          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   18928          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
   18929          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   18930          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
   18931          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   18932          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
   18933          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   18934          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
   18935          case 0x0A0:             // xssubdp
   18936          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
   18937          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
   18938             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   18939             goto decode_failure;
   18940          case 0x180: // xvadddp
   18941          case 0x1E0: // xvdivdp
   18942          case 0x1C0: // xvmuldp
   18943          case 0x1A0: // xvsubdp
   18944          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   18945          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   18946          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   18947          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   18948          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   18949          case 0x196: // xvsqrtdp
   18950             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   18951             goto decode_failure;
   18952          case 0x100: // xvaddsp
   18953          case 0x160: // xvdivsp
   18954          case 0x140: // xvmulsp
   18955          case 0x120: // xvsubsp
   18956          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   18957          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   18958          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   18959          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   18960          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   18961          case 0x116: // xvsqrtsp
   18962             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   18963             goto decode_failure;
   18964 
   18965          case 0x250:             // xscvuxdsp
   18966          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
   18967          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
   18968          case 0x090: // xscvdpuxws
   18969             // The above VSX conversion instructions employ some ISA 2.06
   18970             // floating point conversion instructions under the covers,
   18971             // so if allow_VX (which means "supports ISA 2.06") is not set,
   18972             // we'll skip the decode.
   18973             if (!allow_VX) goto decode_noVX;
   18974             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   18975             goto decode_failure;
   18976 
   18977          case 0x2B0: // xscvdpsxds
   18978          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
   18979          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   18980          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   18981          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
   18982          case 0x292: case 0x296: // xscvspdp, xscvspdpn
   18983          case 0x312: // xvcvdpsp
   18984          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   18985          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   18986          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   18987          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   18988          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   18989          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   18990             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   18991             goto decode_failure;
   18992 
   18993          case 0x18C: case 0x38C: // xvcmpeqdp[.]
   18994          case 0x10C: case 0x30C: // xvcmpeqsp[.]
   18995          case 0x14C: case 0x34C: // xvcmpgesp[.]
   18996          case 0x12C: case 0x32C: // xvcmpgtsp[.]
   18997          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
   18998          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
   18999              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   19000              goto decode_failure;
   19001 
   19002          case 0x134:  // xvresp
   19003          case 0x1B4:  // xvredp
   19004          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   19005          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   19006          case 0x300: case 0x320: // xvmaxsp, xvminsp
   19007          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   19008          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   19009          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   19010          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   19011          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   19012          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   19013          case 0x112: case 0x156: // xvrspi, xvrspic
   19014          case 0x172: case 0x152: // xvrspim, xvrspip
   19015          case 0x132: // xvrspiz
   19016             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   19017             goto decode_failure;
   19018 
   19019          default:
   19020             goto decode_failure;
   19021       }
   19022       break;
   19023    }
   19024 
   19025    /* 64bit Integer Stores */
   19026    case 0x3E:  // std, stdu, stq
   19027       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19028       goto decode_failure;
   19029 
   19030    case 0x3F:
   19031       if (!allow_F) goto decode_noF;
   19032       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   19033          so we can simply fall through the first switch statement */
   19034 
   19035       opc2 = IFIELD(theInstr, 1, 5);
   19036       switch (opc2) {
   19037       /* Floating Point Arith Instructions */
   19038       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   19039       case 0x19:                       // fmul
   19040          if (dis_fp_arith(theInstr)) goto decode_success;
   19041          goto decode_failure;
   19042       case 0x16:                       // fsqrt
   19043          if (!allow_FX) goto decode_noFX;
   19044          if (dis_fp_arith(theInstr)) goto decode_success;
   19045          goto decode_failure;
   19046       case 0x17: case 0x1A:            // fsel, frsqrte
   19047          if (!allow_GX) goto decode_noGX;
   19048          if (dis_fp_arith(theInstr)) goto decode_success;
   19049          goto decode_failure;
   19050 
   19051       /* Floating Point Mult-Add Instructions */
   19052       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   19053       case 0x1F:                       // fnmadd
   19054          if (dis_fp_multadd(theInstr)) goto decode_success;
   19055          goto decode_failure;
   19056 
   19057       case 0x18:                       // fre
   19058          if (!allow_GX) goto decode_noGX;
   19059          if (dis_fp_arith(theInstr)) goto decode_success;
   19060          goto decode_failure;
   19061 
   19062       default:
   19063          break; // Fall through
   19064       }
   19065 
   19066       opc2 = IFIELD(theInstr, 1, 10);
   19067       switch (opc2) {
   19068       /* 128-bit DFP instructions */
   19069       case 0x2:    // daddq - DFP Add
   19070       case 0x202:  // dsubq - DFP Subtract
   19071       case 0x22:   // dmulq - DFP Mult
   19072       case 0x222:  // ddivq - DFP Divide
   19073          if (!allow_DFP) goto decode_noDFP;
   19074          if (dis_dfp_arithq( theInstr ))
   19075             goto decode_success;
   19076          goto decode_failure;
   19077       case 0x162:  // dxexq - DFP Extract exponent
   19078       case 0x362:  // diexq - DFP Insert exponent
   19079          if (!allow_DFP)
   19080             goto decode_failure;
   19081          if (dis_dfp_extract_insertq( theInstr ))
   19082             goto decode_success;
   19083          goto decode_failure;
   19084 
   19085       case 0x82:   // dcmpoq, DFP comparison ordered instruction
   19086       case 0x282:  // dcmpuq, DFP comparison unordered instruction
   19087          if (!allow_DFP)
   19088             goto decode_failure;
   19089          if (dis_dfp_compare( theInstr ) )
   19090             goto decode_success;
   19091          goto decode_failure;
   19092 
   19093       case 0x102: // dctqpq  - DFP convert to DFP extended
   19094       case 0x302: // drdpq   - DFP round to dfp Long
   19095       case 0x122: // dctfixq - DFP convert to fixed quad
   19096       case 0x322: // dcffixq - DFP convert from fixed quad
   19097          if (!allow_DFP)
   19098             goto decode_failure;
   19099          if (dis_dfp_fmt_convq( theInstr ))
   19100             goto decode_success;
   19101          goto decode_failure;
   19102 
   19103       case 0x2A2: // dtstsfq - DFP number of significant digits
   19104          if (!allow_DFP)
   19105             goto decode_failure;
   19106          if (dis_dfp_significant_digits(theInstr))
   19107             goto decode_success;
   19108          goto decode_failure;
   19109 
   19110       case 0x142: // ddedpdq   DFP Decode DPD to BCD
   19111       case 0x342: // denbcdq   DFP Encode BCD to DPD
   19112          if (!allow_DFP)
   19113             goto decode_failure;
   19114          if (dis_dfp_bcdq(theInstr))
   19115             goto decode_success;
   19116          goto decode_failure;
   19117 
   19118       /* Floating Point Compare Instructions */
   19119       case 0x000: // fcmpu
   19120       case 0x020: // fcmpo
   19121          if (dis_fp_cmp(theInstr)) goto decode_success;
   19122          goto decode_failure;
   19123 
   19124       case 0x080: // ftdiv
   19125       case 0x0A0: // ftsqrt
   19126          if (dis_fp_tests(theInstr)) goto decode_success;
   19127          goto decode_failure;
   19128 
   19129       /* Floating Point Rounding/Conversion Instructions */
   19130       case 0x00C: // frsp
   19131       case 0x00E: // fctiw
   19132       case 0x00F: // fctiwz
   19133       case 0x32E: // fctid
   19134       case 0x32F: // fctidz
   19135       case 0x34E: // fcfid
   19136          if (dis_fp_round(theInstr)) goto decode_success;
   19137          goto decode_failure;
   19138       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   19139       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   19140          if (!allow_VX) goto decode_noVX;
   19141          if (dis_fp_round(theInstr)) goto decode_success;
   19142          goto decode_failure;
   19143 
   19144       /* Power6 rounding stuff */
   19145       case 0x1E8: // frim
   19146       case 0x1C8: // frip
   19147       case 0x188: // frin
   19148       case 0x1A8: // friz
   19149          /* A hack to check for P6 capability . . . */
   19150          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   19151              (dis_fp_round(theInstr)))
   19152             goto decode_success;
   19153          goto decode_failure;
   19154 
   19155       /* Floating Point Move Instructions */
   19156       case 0x008: // fcpsgn
   19157       case 0x028: // fneg
   19158       case 0x048: // fmr
   19159       case 0x088: // fnabs
   19160       case 0x108: // fabs
   19161          if (dis_fp_move( theInstr )) goto decode_success;
   19162          goto decode_failure;
   19163 
   19164       case 0x3c6: case 0x346:          // fmrgew, fmrgow
   19165          if (dis_fp_merge( theInstr )) goto decode_success;
   19166          goto decode_failure;
   19167 
   19168       /* Floating Point Status/Control Register Instructions */
   19169       case 0x026: // mtfsb1
   19170       case 0x040: // mcrfs
   19171       case 0x046: // mtfsb0
   19172       case 0x086: // mtfsfi
   19173       case 0x247: // mffs
   19174       case 0x2C7: // mtfsf
   19175          // Some of the above instructions need to know more about the
   19176          // ISA level supported by the host.
   19177          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
   19178          goto decode_failure;
   19179 
   19180       default:
   19181          break; // Fall through...
   19182       }
   19183 
   19184       opc2 = ifieldOPClo9( theInstr );
   19185       switch (opc2) {
   19186       case 0x42: // dscli, DFP shift left
   19187       case 0x62: // dscri, DFP shift right
   19188          if (!allow_DFP)
   19189             goto decode_failure;
   19190          if (dis_dfp_shiftq( theInstr ))
   19191             goto decode_success;
   19192          goto decode_failure;
   19193       case 0xc2:  // dtstdc, DFP test data class
   19194       case 0xe2:  // dtstdg, DFP test data group
   19195          if (!allow_DFP)
   19196             goto decode_failure;
   19197          if (dis_dfp_class_test( theInstr ))
   19198             goto decode_success;
   19199          goto decode_failure;
   19200       default:
   19201          break;
   19202       }
   19203 
   19204       opc2 = ifieldOPClo8( theInstr );
   19205       switch (opc2) {
   19206       case 0x3:   // dquaq  - DFP Quantize Quad
   19207       case 0x23:  // drrndq - DFP Reround Quad
   19208       case 0x43:  // dquaiq - DFP Quantize immediate Quad
   19209          if (!allow_DFP)
   19210             goto decode_failure;
   19211          if (dis_dfp_quantize_sig_rrndq( theInstr ))
   19212             goto decode_success;
   19213          goto decode_failure;
   19214       case 0xA2: // dtstexq - DFP Test exponent Quad
   19215          if (dis_dfp_exponent_test( theInstr ) )
   19216             goto decode_success;
   19217          goto decode_failure;
   19218       case 0x63:  // drintxq - DFP Round to an integer value
   19219       case 0xE3:  // drintnq - DFP Round to an integer value
   19220          if (!allow_DFP)
   19221             goto decode_failure;
   19222          if (dis_dfp_roundq( theInstr ))
   19223             goto decode_success;
   19224          goto decode_failure;
   19225 
   19226       default:
   19227          goto decode_failure;
   19228       }
   19229       break;
   19230 
   19231    case 0x13:
   19232       switch (opc2) {
   19233 
   19234       /* Condition Register Logical Instructions */
   19235       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   19236       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   19237       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   19238          if (dis_cond_logic( theInstr )) goto decode_success;
   19239          goto decode_failure;
   19240 
   19241       /* Branch Instructions */
   19242       case 0x210: case 0x010: // bcctr, bclr
   19243          if (dis_branch(theInstr, abiinfo, &dres,
   19244                                   resteerOkFn, callback_opaque))
   19245             goto decode_success;
   19246          goto decode_failure;
   19247 
   19248       /* Memory Synchronization Instructions */
   19249       case 0x096: // isync
   19250          if (dis_memsync( theInstr )) goto decode_success;
   19251          goto decode_failure;
   19252 
   19253       default:
   19254          goto decode_failure;
   19255       }
   19256       break;
   19257 
   19258 
   19259    case 0x1F:
   19260 
   19261       /* For arith instns, bit10 is the OE flag (overflow enable) */
   19262 
   19263       opc2 = IFIELD(theInstr, 1, 9);
   19264       switch (opc2) {
   19265       /* Integer Arithmetic Instructions */
   19266       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   19267       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   19268       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   19269       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   19270       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   19271       case 0x0C8: // subfze
   19272          if (dis_int_arith( theInstr )) goto decode_success;
   19273          goto decode_failure;
   19274 
   19275       case 0x18B: // divweu (implemented as native insn)
   19276       case 0x1AB: // divwe (implemented as native insn)
   19277          if (!allow_VX) goto decode_noVX;
   19278          if (dis_int_arith( theInstr )) goto decode_success;
   19279          goto decode_failure;
   19280 
   19281       /* 64bit Integer Arithmetic */
   19282       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   19283       case 0x1C9: case 0x1E9: // divdu, divd
   19284          if (!mode64) goto decode_failure;
   19285          if (dis_int_arith( theInstr )) goto decode_success;
   19286          goto decode_failure;
   19287 
   19288       case 0x1A9: //  divde (implemented as native insn)
   19289       case 0x189: //  divdeuo (implemented as native insn)
   19290          if (!allow_VX) goto decode_noVX;
   19291          if (!mode64) goto decode_failure;
   19292          if (dis_int_arith( theInstr )) goto decode_success;
   19293          goto decode_failure;
   19294 
   19295       case 0x1FC:                         // cmpb
   19296          if (dis_int_logic( theInstr )) goto decode_success;
   19297          goto decode_failure;
   19298 
   19299       default:
   19300          break;  // Fall through...
   19301       }
   19302 
   19303       /* All remaining opcodes use full 10 bits. */
   19304 
   19305       opc2 = IFIELD(theInstr, 1, 10);
   19306       switch (opc2) {
   19307       /* Integer Compare Instructions  */
   19308       case 0x000: case 0x020: // cmp, cmpl
   19309          if (dis_int_cmp( theInstr )) goto decode_success;
   19310          goto decode_failure;
   19311 
   19312       /* Integer Logical Instructions */
   19313       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   19314       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   19315       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   19316       case 0x19C: case 0x13C:             // orc,  xor
   19317       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   19318          if (dis_int_logic( theInstr )) goto decode_success;
   19319          goto decode_failure;
   19320 
   19321       case 0x28E: case 0x2AE:             // tbegin., tend.
   19322       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
   19323       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
   19324       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
   19325       if (dis_transactional_memory( theInstr,
   19326                                     getUIntBigendianly( (UChar*)(&guest_code[delta + 4])),
   19327                                     abiinfo, &dres,
   19328                                     resteerOkFn, callback_opaque))
   19329             goto decode_success;
   19330          goto decode_failure;
   19331 
   19332       /* 64bit Integer Logical Instructions */
   19333       case 0x3DA: case 0x03A: // extsw, cntlzd
   19334          if (!mode64) goto decode_failure;
   19335          if (dis_int_logic( theInstr )) goto decode_success;
   19336          goto decode_failure;
   19337 
   19338          /* 64bit Integer Parity Instructions */
   19339       case 0xba: // prtyd
   19340          if (!mode64) goto decode_failure;
   19341          if (dis_int_parity( theInstr )) goto decode_success;
   19342          goto decode_failure;
   19343 
   19344       case 0x9a: // prtyw
   19345          if (dis_int_parity( theInstr )) goto decode_success;
   19346          goto decode_failure;
   19347 
   19348       /* Integer Shift Instructions */
   19349       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   19350       case 0x218:                         // srw
   19351          if (dis_int_shift( theInstr )) goto decode_success;
   19352          goto decode_failure;
   19353 
   19354       /* 64bit Integer Shift Instructions */
   19355       case 0x01B: case 0x31A: // sld, srad
   19356       case 0x33A: case 0x33B: // sradi
   19357       case 0x21B:             // srd
   19358          if (!mode64) goto decode_failure;
   19359          if (dis_int_shift( theInstr )) goto decode_success;
   19360          goto decode_failure;
   19361 
   19362       /* Integer Load Instructions */
   19363       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   19364       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   19365       case 0x017: case 0x037:             // lwzx,  lwzux
   19366          if (dis_int_load( theInstr )) goto decode_success;
   19367          goto decode_failure;
   19368 
   19369       /* 64bit Integer Load Instructions */
   19370       case 0x035: case 0x015:             // ldux,  ldx
   19371       case 0x175: case 0x155:             // lwaux, lwax
   19372          if (!mode64) goto decode_failure;
   19373          if (dis_int_load( theInstr )) goto decode_success;
   19374          goto decode_failure;
   19375 
   19376       /* Integer Store Instructions */
   19377       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   19378       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   19379          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19380          goto decode_failure;
   19381 
   19382       /* 64bit Integer Store Instructions */
   19383       case 0x0B5: case 0x095: // stdux, stdx
   19384          if (!mode64) goto decode_failure;
   19385          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19386          goto decode_failure;
   19387 
   19388       /* Integer Load and Store with Byte Reverse Instructions */
   19389       case 0x214: case 0x294: // ldbrx, stdbrx
   19390          if (!mode64) goto decode_failure;
   19391          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19392          goto decode_failure;
   19393 
   19394       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
   19395       case 0x396:                            // sthbrx
   19396          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19397          goto decode_failure;
   19398 
   19399       /* Integer Load and Store String Instructions */
   19400       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   19401       case 0x295: {                       // stswx
   19402          Bool stopHere = False;
   19403          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   19404          if (!ok) goto decode_failure;
   19405          if (stopHere) {
   19406             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
   19407             dres.jk_StopHere = Ijk_Boring;
   19408             dres.whatNext    = Dis_StopHere;
   19409          }
   19410          goto decode_success;
   19411       }
   19412 
   19413       /* Memory Synchronization Instructions */
   19414       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   19415       case 0x256:                         // sync
   19416          if (dis_memsync( theInstr )) goto decode_success;
   19417          goto decode_failure;
   19418 
   19419       /* 64bit Memory Synchronization Instructions */
   19420       case 0x054: case 0x0D6: // ldarx, stdcx.
   19421          if (!mode64) goto decode_failure;
   19422          if (dis_memsync( theInstr )) goto decode_success;
   19423          goto decode_failure;
   19424 
   19425       case 0x114: case 0x0B6: // lqarx, stqcx.
   19426          if (dis_memsync( theInstr )) goto decode_success;
   19427          goto decode_failure;
   19428 
   19429       /* Processor Control Instructions */
   19430       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
   19431       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
   19432       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   19433       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   19434       case 0x220:                         // mcrxrt
   19435          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   19436          goto decode_failure;
   19437 
   19438       /* Cache Management Instructions */
   19439       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   19440       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   19441       case 0x3D6:                         // icbi
   19442          if (dis_cache_manage( theInstr, &dres, archinfo ))
   19443             goto decode_success;
   19444          goto decode_failure;
   19445 
   19446 //zz       /* External Control Instructions */
   19447 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   19448 //zz          DIP("external control op => not implemented\n");
   19449 //zz          goto decode_failure;
   19450 
   19451       /* Trap Instructions */
   19452       case 0x004:             // tw
   19453          if (dis_trap(theInstr, &dres)) goto decode_success;
   19454          goto decode_failure;
   19455 
   19456       case 0x044:             // td
   19457          if (!mode64) goto decode_failure;
   19458          if (dis_trap(theInstr, &dres)) goto decode_success;
   19459          goto decode_failure;
   19460 
   19461       /* Floating Point Load Instructions */
   19462       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   19463       case 0x277:                         // lfdux
   19464          if (!allow_F) goto decode_noF;
   19465          if (dis_fp_load( theInstr )) goto decode_success;
   19466          goto decode_failure;
   19467 
   19468       /* Floating Point Store Instructions */
   19469       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   19470       case 0x2F7:                         // stfdu, stfiwx
   19471          if (!allow_F) goto decode_noF;
   19472          if (dis_fp_store( theInstr )) goto decode_success;
   19473          goto decode_failure;
   19474       case 0x3D7:                         // stfiwx
   19475          if (!allow_F) goto decode_noF;
   19476          if (!allow_GX) goto decode_noGX;
   19477          if (dis_fp_store( theInstr )) goto decode_success;
   19478          goto decode_failure;
   19479 
   19480          /* Floating Point Double Pair Indexed Instructions */
   19481       case 0x317: // lfdpx (Power6)
   19482       case 0x397: // stfdpx (Power6)
   19483          if (!allow_F) goto decode_noF;
   19484          if (dis_fp_pair(theInstr)) goto decode_success;
   19485          goto decode_failure;
   19486 
   19487       case 0x357:                         // lfiwax
   19488          if (!allow_F) goto decode_noF;
   19489          if (dis_fp_load( theInstr )) goto decode_success;
   19490          goto decode_failure;
   19491 
   19492       case 0x377:                         // lfiwzx
   19493          if (!allow_F) goto decode_noF;
   19494          if (dis_fp_load( theInstr )) goto decode_success;
   19495          goto decode_failure;
   19496 
   19497       /* AltiVec instructions */
   19498 
   19499       /* AV Cache Control - Data streams */
   19500       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   19501          if (!allow_V) goto decode_noV;
   19502          if (dis_av_datastream( theInstr )) goto decode_success;
   19503          goto decode_failure;
   19504 
   19505       /* AV Load */
   19506       case 0x006: case 0x026:             // lvsl, lvsr
   19507       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   19508       case 0x067: case 0x167:             // lvx, lvxl
   19509          if (!allow_V) goto decode_noV;
   19510          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   19511          goto decode_failure;
   19512 
   19513       /* AV Store */
   19514       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   19515       case 0x0E7: case 0x1E7:             // stvx, stvxl
   19516          if (!allow_V) goto decode_noV;
   19517          if (dis_av_store( theInstr )) goto decode_success;
   19518          goto decode_failure;
   19519 
   19520       /* VSX Load */
   19521       case 0x00C: // lxsiwzx
   19522       case 0x04C: // lxsiwax
   19523       case 0x20C: // lxsspx
   19524       case 0x24C: // lxsdx
   19525       case 0x34C: // lxvd2x
   19526       case 0x14C: // lxvdsx
   19527       case 0x30C: // lxvw4x
   19528         // All of these VSX load instructions use some VMX facilities, so
   19529         // if allow_V is not set, we'll skip trying to decode.
   19530         if (!allow_V) goto decode_noV;
   19531 
   19532     	  if (dis_vx_load( theInstr )) goto decode_success;
   19533           goto decode_failure;
   19534 
   19535       /* VSX Store */
   19536       case 0x08C: // stxsiwx
   19537       case 0x28C: // stxsspx
   19538       case 0x2CC: // stxsdx
   19539       case 0x3CC: // stxvd2x
   19540       case 0x38C: // stxvw4x
   19541         // All of these VSX store instructions use some VMX facilities, so
   19542         // if allow_V is not set, we'll skip trying to decode.
   19543         if (!allow_V) goto decode_noV;
   19544 
   19545     	  if (dis_vx_store( theInstr )) goto decode_success;
   19546     	  goto decode_failure;
   19547 
   19548       /* Miscellaneous ISA 2.06 instructions */
   19549       case 0x1FA: // popcntd
   19550       case 0x17A: // popcntw
   19551       case 0x7A:  // popcntb
   19552     	  if (dis_int_logic( theInstr )) goto decode_success;
   19553     	  goto decode_failure;
   19554 
   19555       case 0x0FC: // bpermd
   19556          if (!mode64) goto decode_failure;
   19557          if (dis_int_logic( theInstr )) goto decode_success;
   19558          goto decode_failure;
   19559 
   19560       default:
   19561          /* Deal with some other cases that we would otherwise have
   19562             punted on. */
   19563          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   19564          /* only decode this insn when reserved bit 0 (31 in IBM's
   19565             notation) is zero */
   19566          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   19567             UInt rT = ifieldRegDS( theInstr );
   19568             UInt rA = ifieldRegA( theInstr );
   19569             UInt rB = ifieldRegB( theInstr );
   19570             UInt bi = ifieldRegC( theInstr );
   19571             putIReg(
   19572                rT,
   19573                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
   19574                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   19575                                    : getIReg(rA),
   19576                            getIReg(rB))
   19577 
   19578             );
   19579             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   19580             goto decode_success;
   19581          }
   19582          goto decode_failure;
   19583       }
   19584       break;
   19585 
   19586 
   19587    case 0x04:
   19588       /* AltiVec instructions */
   19589 
   19590       opc2 = IFIELD(theInstr, 0, 6);
   19591       switch (opc2) {
   19592       /* AV Mult-Add, Mult-Sum */
   19593       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   19594       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   19595       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   19596          if (!allow_V) goto decode_noV;
   19597          if (dis_av_multarith( theInstr )) goto decode_success;
   19598          goto decode_failure;
   19599 
   19600       /* AV Permutations */
   19601       case 0x2A:                       // vsel
   19602       case 0x2B:                       // vperm
   19603       case 0x2C:                       // vsldoi
   19604          if (!allow_V) goto decode_noV;
   19605          if (dis_av_permute( theInstr )) goto decode_success;
   19606          goto decode_failure;
   19607 
   19608       case 0x2D:                       // vpermxor
   19609          if (!allow_isa_2_07) goto decode_noP8;
   19610          if (dis_av_permute( theInstr )) goto decode_success;
   19611          goto decode_failure;
   19612 
   19613       /* AV Floating Point Mult-Add/Sub */
   19614       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   19615          if (!allow_V) goto decode_noV;
   19616          if (dis_av_fp_arith( theInstr )) goto decode_success;
   19617          goto decode_failure;
   19618 
   19619       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
   19620       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
   19621          if (!allow_V) goto decode_noV;
   19622          if (dis_av_quad( theInstr)) goto decode_success;
   19623          goto decode_failure;
   19624 
   19625       default:
   19626          break;  // Fall through...
   19627       }
   19628 
   19629       opc2 = IFIELD(theInstr, 0, 9);
   19630       switch (opc2) {
   19631       /* BCD arithmetic */
   19632       case 0x1: case 0x41:             // bcdadd, bcdsub
   19633          if (!allow_isa_2_07) goto decode_noP8;
   19634          if (dis_av_bcd( theInstr )) goto decode_success;
   19635          goto decode_failure;
   19636 
   19637       default:
   19638          break;  // Fall through...
   19639       }
   19640 
   19641       opc2 = IFIELD(theInstr, 0, 11);
   19642       switch (opc2) {
   19643       /* AV Arithmetic */
   19644       case 0x180:                         // vaddcuw
   19645       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   19646       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   19647       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   19648       case 0x580:                         // vsubcuw
   19649       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   19650       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   19651       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   19652       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   19653       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   19654       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   19655       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   19656       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   19657       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   19658       case 0x008: case 0x048:             // vmuloub, vmulouh
   19659       case 0x108: case 0x148:             // vmulosb, vmulosh
   19660       case 0x208: case 0x248:             // vmuleub, vmuleuh
   19661       case 0x308: case 0x348:             // vmulesb, vmulesh
   19662       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   19663       case 0x688: case 0x788:             // vsum2sws, vsumsws
   19664          if (!allow_V) goto decode_noV;
   19665          if (dis_av_arith( theInstr )) goto decode_success;
   19666          goto decode_failure;
   19667 
   19668       case 0x088: case 0x089:             // vmulouw, vmuluwm
   19669       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
   19670       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
   19671       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
   19672       case 0x4C0:                         // vsubudm
   19673          if (!allow_isa_2_07) goto decode_noP8;
   19674          if (dis_av_arith( theInstr )) goto decode_success;
   19675          goto decode_failure;
   19676 
   19677       /* AV Polynomial Vector Multiply Add */
   19678       case 0x408: case 0x448:            // vpmsumb, vpmsumd
   19679       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
   19680          if (!allow_isa_2_07) goto decode_noP8;
   19681          if (dis_av_polymultarith( theInstr )) goto decode_success;
   19682          goto decode_failure;
   19683 
   19684       /* AV Rotate, Shift */
   19685       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   19686       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   19687       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   19688       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   19689       case 0x1C4: case 0x2C4:             // vsl, vsr
   19690       case 0x40C: case 0x44C:             // vslo, vsro
   19691          if (!allow_V) goto decode_noV;
   19692          if (dis_av_shift( theInstr )) goto decode_success;
   19693          goto decode_failure;
   19694 
   19695       case 0x0C4:                         // vrld
   19696       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
   19697           if (!allow_isa_2_07) goto decode_noP8;
   19698           if (dis_av_shift( theInstr )) goto decode_success;
   19699           goto decode_failure;
   19700 
   19701       /* AV Logic */
   19702       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   19703       case 0x4C4: case 0x504:             // vxor, vnor
   19704          if (!allow_V) goto decode_noV;
   19705          if (dis_av_logic( theInstr )) goto decode_success;
   19706          goto decode_failure;
   19707 
   19708       case 0x544:                         // vorc
   19709       case 0x584: case 0x684:             // vnand, veqv
   19710          if (!allow_isa_2_07) goto decode_noP8;
   19711          if (dis_av_logic( theInstr )) goto decode_success;
   19712          goto decode_failure;
   19713 
   19714       /* AV Processor Control */
   19715       case 0x604: case 0x644:             // mfvscr, mtvscr
   19716          if (!allow_V) goto decode_noV;
   19717          if (dis_av_procctl( theInstr )) goto decode_success;
   19718          goto decode_failure;
   19719 
   19720       /* AV Floating Point Arithmetic */
   19721       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   19722       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   19723       case 0x1CA:                         // vlogefp
   19724       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   19725          if (!allow_V) goto decode_noV;
   19726          if (dis_av_fp_arith( theInstr )) goto decode_success;
   19727          goto decode_failure;
   19728 
   19729       /* AV Floating Point Round/Convert */
   19730       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   19731       case 0x2CA:                         // vrfim
   19732       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   19733       case 0x3CA:                         // vctsxs
   19734          if (!allow_V) goto decode_noV;
   19735          if (dis_av_fp_convert( theInstr )) goto decode_success;
   19736          goto decode_failure;
   19737 
   19738       /* AV Merge, Splat */
   19739       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   19740       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   19741       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   19742       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   19743          if (!allow_V) goto decode_noV;
   19744          if (dis_av_permute( theInstr )) goto decode_success;
   19745          goto decode_failure;
   19746 
   19747       case 0x68C: case 0x78C:             // vmrgow, vmrgew
   19748           if (!allow_isa_2_07) goto decode_noP8;
   19749           if (dis_av_permute( theInstr )) goto decode_success;
   19750           goto decode_failure;
   19751 
   19752       /* AV Pack, Unpack */
   19753       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   19754       case 0x0CE:                         // vpkuwus
   19755       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   19756       case 0x1CE:                         // vpkswss
   19757       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   19758       case 0x2CE:                         // vupklsh
   19759       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   19760           if (!allow_V) goto decode_noV;
   19761           if (dis_av_pack( theInstr )) goto decode_success;
   19762           goto decode_failure;
   19763 
   19764       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
   19765       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
   19766          if (!allow_isa_2_07) goto decode_noP8;
   19767          if (dis_av_pack( theInstr )) goto decode_success;
   19768          goto decode_failure;
   19769 
   19770       case 0x508: case 0x509:             // vcipher, vcipherlast
   19771       case 0x548: case 0x549:             // vncipher, vncipherlast
   19772       case 0x5C8:                         // vsbox
   19773          if (!allow_isa_2_07) goto decode_noP8;
   19774          if (dis_av_cipher( theInstr )) goto decode_success;
   19775          goto decode_failure;
   19776 
   19777       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
   19778          if (!allow_isa_2_07) goto decode_noP8;
   19779          if (dis_av_hash( theInstr )) goto decode_success;
   19780          goto decode_failure;
   19781 
   19782       case 0x702: case 0x742:             // vclzb, vclzh
   19783       case 0x782: case 0x7c2:             // vclzw, vclzd
   19784          if (!allow_isa_2_07) goto decode_noP8;
   19785          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   19786          goto decode_failure;
   19787 
   19788       case 0x703: case 0x743:             // vpopcntb, vpopcnth
   19789       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
   19790          if (!allow_isa_2_07) goto decode_noP8;
   19791          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   19792          goto decode_failure;
   19793 
   19794       case 0x50c:                         // vgbbd
   19795          if (!allow_isa_2_07) goto decode_noP8;
   19796          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   19797          goto decode_failure;
   19798 
   19799       case 0x140: case 0x100:             // vaddcuq, vadduqm
   19800       case 0x540: case 0x500:             // vsubcuq, vsubuqm
   19801       case 0x54C:                         // vbpermq
   19802          if (!allow_V) goto decode_noV;
   19803          if (dis_av_quad( theInstr)) goto decode_success;
   19804          goto decode_failure;
   19805 
   19806       default:
   19807          break;  // Fall through...
   19808       }
   19809 
   19810       opc2 = IFIELD(theInstr, 0, 10);
   19811       switch (opc2) {
   19812 
   19813       /* AV Compare */
   19814       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   19815       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   19816       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   19817          if (!allow_V) goto decode_noV;
   19818          if (dis_av_cmp( theInstr )) goto decode_success;
   19819          goto decode_failure;
   19820 
   19821       case 0x0C7:                         // vcmpequd
   19822       case 0x2C7:                         // vcmpgtud
   19823       case 0x3C7:                         // vcmpgtsd
   19824           if (!allow_isa_2_07) goto decode_noP8;
   19825           if (dis_av_cmp( theInstr )) goto decode_success;
   19826           goto decode_failure;
   19827 
   19828       /* AV Floating Point Compare */
   19829       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   19830       case 0x3C6:                         // vcmpbfp
   19831          if (!allow_V) goto decode_noV;
   19832          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   19833          goto decode_failure;
   19834 
   19835       default:
   19836          goto decode_failure;
   19837       }
   19838       break;
   19839 
   19840    default:
   19841       goto decode_failure;
   19842 
   19843    decode_noF:
   19844       vassert(!allow_F);
   19845       vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
   19846       goto decode_failure;
   19847    decode_noV:
   19848       vassert(!allow_V);
   19849       vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
   19850       goto decode_failure;
   19851    decode_noVX:
   19852       vassert(!allow_VX);
   19853       vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
   19854       goto decode_failure;
   19855    decode_noFX:
   19856       vassert(!allow_FX);
   19857       vex_printf("disInstr(ppc): "
   19858                  "declined to decode a GeneralPurpose-Optional insn.\n");
   19859       goto decode_failure;
   19860    decode_noGX:
   19861       vassert(!allow_GX);
   19862       vex_printf("disInstr(ppc): "
   19863                  "declined to decode a Graphics-Optional insn.\n");
   19864       goto decode_failure;
   19865    decode_noDFP:
   19866       vassert(!allow_DFP);
   19867       vex_printf("disInstr(ppc): "
   19868                "declined to decode a Decimal Floating Point insn.\n");
   19869       goto decode_failure;
   19870    decode_noP8:
   19871       vassert(!allow_isa_2_07);
   19872       vex_printf("disInstr(ppc): "
   19873                "declined to decode a Power 8 insn.\n");
   19874       goto decode_failure;
   19875 
   19876 
   19877    decode_failure:
   19878    /* All decode failures end up here. */
   19879    opc2 = (theInstr) & 0x7FF;
   19880    if (sigill_diag) {
   19881       vex_printf("disInstr(ppc): unhandled instruction: "
   19882                  "0x%x\n", theInstr);
   19883       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   19884                  opc1, opc1, opc2, opc2);
   19885    }
   19886 
   19887    /* Tell the dispatcher that this insn cannot be decoded, and so has
   19888       not been executed, and (is currently) the next to be executed.
   19889       CIA should be up-to-date since it made so at the start of each
   19890       insn, but nevertheless be paranoid and update it again right
   19891       now. */
   19892    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   19893    dres.whatNext    = Dis_StopHere;
   19894    dres.jk_StopHere = Ijk_NoDecode;
   19895    dres.len         = 0;
   19896    return dres;
   19897 
   19898    } /* switch (opc) for the main (primary) opcode switch. */
   19899 
   19900   decode_success:
   19901    /* All decode successes end up here. */
   19902    switch (dres.whatNext) {
   19903       case Dis_Continue:
   19904          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
   19905          break;
   19906       case Dis_ResteerU:
   19907       case Dis_ResteerC:
   19908          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
   19909          break;
   19910       case Dis_StopHere:
   19911          break;
   19912       default:
   19913          vassert(0);
   19914    }
   19915    DIP("\n");
   19916 
   19917    if (dres.len == 0) {
   19918       dres.len = 4;
   19919    } else {
   19920       vassert(dres.len == 20);
   19921    }
   19922    return dres;
   19923 }
   19924 
   19925 #undef DIP
   19926 #undef DIS
   19927 
   19928 
   19929 /*------------------------------------------------------------*/
   19930 /*--- Top-level fn                                         ---*/
   19931 /*------------------------------------------------------------*/
   19932 
   19933 /* Disassemble a single instruction into IR.  The instruction
   19934    is located in host memory at &guest_code[delta]. */
   19935 
   19936 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   19937                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   19938                          Bool         resteerCisOk,
   19939                          void*        callback_opaque,
   19940                          UChar*       guest_code_IN,
   19941                          Long         delta,
   19942                          Addr64       guest_IP,
   19943                          VexArch      guest_arch,
   19944                          VexArchInfo* archinfo,
   19945                          VexAbiInfo*  abiinfo,
   19946                          Bool         host_bigendian_IN,
   19947                          Bool         sigill_diag_IN )
   19948 {
   19949    IRType     ty;
   19950    DisResult  dres;
   19951    UInt       mask32, mask64;
   19952    UInt hwcaps_guest = archinfo->hwcaps;
   19953 
   19954    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   19955 
   19956    /* global -- ick */
   19957    mode64 = guest_arch == VexArchPPC64;
   19958    ty = mode64 ? Ity_I64 : Ity_I32;
   19959 
   19960    /* do some sanity checks */
   19961    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   19962             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   19963             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
   19964 
   19965    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   19966             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
   19967             | VEX_HWCAPS_PPC64_ISA2_07;
   19968 
   19969    if (mode64) {
   19970       vassert((hwcaps_guest & mask32) == 0);
   19971    } else {
   19972       vassert((hwcaps_guest & mask64) == 0);
   19973    }
   19974 
   19975    /* Set globals (see top of this file) */
   19976    guest_code           = guest_code_IN;
   19977    irsb                 = irsb_IN;
   19978    host_is_bigendian    = host_bigendian_IN;
   19979 
   19980    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   19981    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   19982 
   19983    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
   19984                              delta, archinfo, abiinfo, sigill_diag_IN );
   19985 
   19986    return dres;
   19987 }
   19988 
   19989 
   19990 /*------------------------------------------------------------*/
   19991 /*--- Unused stuff                                         ---*/
   19992 /*------------------------------------------------------------*/
   19993 
   19994 ///* A potentially more memcheck-friendly implementation of Clz32, with
   19995 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   19996 //
   19997 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   19998 //{
   19999 //   /* Welcome ... to SSA R Us. */
   20000 //   IRTemp n1  = newTemp(Ity_I32);
   20001 //   IRTemp n2  = newTemp(Ity_I32);
   20002 //   IRTemp n3  = newTemp(Ity_I32);
   20003 //   IRTemp n4  = newTemp(Ity_I32);
   20004 //   IRTemp n5  = newTemp(Ity_I32);
   20005 //   IRTemp n6  = newTemp(Ity_I32);
   20006 //   IRTemp n7  = newTemp(Ity_I32);
   20007 //   IRTemp n8  = newTemp(Ity_I32);
   20008 //   IRTemp n9  = newTemp(Ity_I32);
   20009 //   IRTemp n10 = newTemp(Ity_I32);
   20010 //   IRTemp n11 = newTemp(Ity_I32);
   20011 //   IRTemp n12 = newTemp(Ity_I32);
   20012 //
   20013 //   /* First, propagate the most significant 1-bit into all lower
   20014 //      positions in the word. */
   20015 //   /* unsigned int clz ( unsigned int n )
   20016 //      {
   20017 //         n |= (n >> 1);
   20018 //         n |= (n >> 2);
   20019 //         n |= (n >> 4);
   20020 //         n |= (n >> 8);
   20021 //         n |= (n >> 16);
   20022 //         return bitcount(~n);
   20023 //      }
   20024 //   */
   20025 //   assign(n1, mkexpr(arg));
   20026 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   20027 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   20028 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   20029 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   20030 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   20031 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   20032 //      a word of the form 1---10---0, then do a population-count idiom
   20033 //      (to count the 1s, which is the number of leading zeroes, or 32
   20034 //      if the original word was 0. */
   20035 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   20036 //
   20037 //   /* unsigned int bitcount ( unsigned int n )
   20038 //      {
   20039 //         n = n - ((n >> 1) & 0x55555555);
   20040 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   20041 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   20042 //         n = n + (n >> 8);
   20043 //         n = (n + (n >> 16)) & 0x3F;
   20044 //         return n;
   20045 //      }
   20046 //   */
   20047 //   assign(n8,
   20048 //          binop(Iop_Sub32,
   20049 //                mkexpr(n7),
   20050 //                binop(Iop_And32,
   20051 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   20052 //                      mkU32(0x55555555))));
   20053 //   assign(n9,
   20054 //          binop(Iop_Add32,
   20055 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   20056 //                binop(Iop_And32,
   20057 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   20058 //                      mkU32(0x33333333))));
   20059 //   assign(n10,
   20060 //          binop(Iop_And32,
   20061 //                binop(Iop_Add32,
   20062 //                      mkexpr(n9),
   20063 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   20064 //                mkU32(0x0F0F0F0F)));
   20065 //   assign(n11,
   20066 //          binop(Iop_Add32,
   20067 //                mkexpr(n10),
   20068 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   20069 //   assign(n12,
   20070 //          binop(Iop_Add32,
   20071 //                mkexpr(n11),
   20072 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   20073 //   return
   20074 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   20075 //}
   20076 
   20077 /*--------------------------------------------------------------------*/
   20078 /*--- end                                         guest_ppc_toIR.c ---*/
   20079 /*--------------------------------------------------------------------*/
   20080