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-2012 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 
     74 /* "Special" instructions.
     75 
     76    This instruction decoder can decode four special instructions
     77    which mean nothing natively (are no-ops as far as regs/mem are
     78    concerned) but have meaning for supporting Valgrind.  A special
     79    instruction is flagged by a 16-byte preamble:
     80 
     81       32-bit mode: 54001800 54006800 5400E800 54009800
     82                    (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0;
     83                     rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
     84 
     85       64-bit mode: 78001800 78006800 7800E802 78009802
     86                    (rotldi 0,0,3; rotldi 0,0,13;
     87                     rotldi 0,0,61; rotldi 0,0,51)
     88 
     89    Following that, one of the following 3 are allowed
     90    (standard interpretation in parentheses):
     91 
     92       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
     93       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
     94       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
     95       7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
     96 
     97    Any other bytes following the 16-byte preamble are illegal and
     98    constitute a failure in instruction decoding.  This all assumes
     99    that the preamble will never occur except in specific code
    100    fragments designed for Valgrind to catch.
    101 */
    102 
    103 
    104 /* Translates PPC32/64 code to IR. */
    105 
    106 /* References
    107 
    108 #define PPC32
    109    "PowerPC Microprocessor Family:
    110     The Programming Environments Manual for 32-Bit Microprocessors"
    111     02/21/2000
    112     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
    113 
    114 #define PPC64
    115    "PowerPC Microprocessor Family:
    116     Programming Environments Manual for 64-Bit Microprocessors"
    117     06/10/2003
    118    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
    119 
    120 #define AV
    121    "PowerPC Microprocessor Family:
    122     AltiVec(TM) Technology Programming Environments Manual"
    123     07/10/2003
    124    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
    125 */
    126 
    127 #include "libvex_basictypes.h"
    128 #include "libvex_ir.h"
    129 #include "libvex.h"
    130 #include "libvex_guest_ppc32.h"
    131 #include "libvex_guest_ppc64.h"
    132 
    133 #include "main_util.h"
    134 #include "main_globals.h"
    135 #include "guest_generic_bb_to_IR.h"
    136 #include "guest_ppc_defs.h"
    137 
    138 
    139 /*------------------------------------------------------------*/
    140 /*--- Globals                                              ---*/
    141 /*------------------------------------------------------------*/
    142 
    143 /* These are set at the start of the translation of an insn, right
    144    down in disInstr_PPC, so that we don't have to pass them around
    145    endlessly.  They are all constant during the translation of any
    146    given insn. */
    147 
    148 /* We need to know this to do sub-register accesses correctly. */
    149 static Bool host_is_bigendian;
    150 
    151 /* Pointer to the guest code area. */
    152 static UChar* guest_code;
    153 
    154 /* The guest address corresponding to guest_code[0]. */
    155 static Addr64 guest_CIA_bbstart;
    156 
    157 /* The guest address for the instruction currently being
    158    translated. */
    159 static Addr64 guest_CIA_curr_instr;
    160 
    161 /* The IRSB* into which we're generating code. */
    162 static IRSB* irsb;
    163 
    164 /* Is our guest binary 32 or 64bit?  Set at each call to
    165    disInstr_PPC below. */
    166 static Bool mode64 = False;
    167 
    168 // Given a pointer to a function as obtained by "& functionname" in C,
    169 // produce a pointer to the actual entry point for the function.  For
    170 // most platforms it's the identity function.  Unfortunately, on
    171 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
    172 // ppc64-aix5.
    173 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
    174 {
    175    if (vbi->host_ppc_calls_use_fndescrs) {
    176       /* f is a pointer to a 3-word function descriptor, of which the
    177          first word is the entry address. */
    178       /* note, this is correct even with cross-jitting, since this is
    179          purely a host issue, not a guest one. */
    180       HWord* fdescr = (HWord*)f;
    181       return (void*)(fdescr[0]);
    182    } else {
    183       /* Simple; "& f" points directly at the code for f. */
    184       return f;
    185    }
    186 }
    187 
    188 #define SIGN_BIT  0x8000000000000000ULL
    189 #define SIGN_MASK 0x7fffffffffffffffULL
    190 #define SIGN_BIT32  0x80000000
    191 #define SIGN_MASK32 0x7fffffff
    192 
    193 
    194 /*------------------------------------------------------------*/
    195 /*--- Debugging output                                     ---*/
    196 /*------------------------------------------------------------*/
    197 
    198 #define DIP(format, args...)           \
    199    if (vex_traceflags & VEX_TRACE_FE)  \
    200       vex_printf(format, ## args)
    201 
    202 #define DIS(buf, format, args...)      \
    203    if (vex_traceflags & VEX_TRACE_FE)  \
    204       vex_sprintf(buf, format, ## args)
    205 
    206 
    207 /*------------------------------------------------------------*/
    208 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
    209 /*------------------------------------------------------------*/
    210 
    211 #define offsetofPPCGuestState(_x) \
    212    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
    213              offsetof(VexGuestPPC32State, _x))
    214 
    215 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
    216 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
    217 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
    218 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
    219 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
    220 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
    221 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
    222 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
    223 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
    224 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
    225 #define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
    226 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
    227 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
    228 #define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
    229 #define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
    230 #define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
    231 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
    232 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
    233 
    234 
    235 /*------------------------------------------------------------*/
    236 /*--- Extract instruction fields                          --- */
    237 /*------------------------------------------------------------*/
    238 
    239 /* Extract field from insn, given idx (zero = lsb) and field length */
    240 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    241 
    242 /* Extract primary opcode, instr[31:26] */
    243 static UChar ifieldOPC( UInt instr ) {
    244    return toUChar( IFIELD( instr, 26, 6 ) );
    245 }
    246 
    247 /* Extract 10-bit secondary opcode, instr[10:1] */
    248 static UInt ifieldOPClo10 ( UInt instr) {
    249    return IFIELD( instr, 1, 10 );
    250 }
    251 
    252 /* Extract 9-bit secondary opcode, instr[9:1] */
    253 static UInt ifieldOPClo9 ( UInt instr) {
    254    return IFIELD( instr, 1, 9 );
    255 }
    256 
    257 /* Extract 8-bit secondary opcode, instr[8:1] */
    258 static UInt ifieldOPClo8 ( UInt instr) {
    259    return IFIELD( instr, 1, 8 );
    260 }
    261 
    262 /* Extract 5-bit secondary opcode, instr[5:1] */
    263 static UInt ifieldOPClo5 ( UInt instr) {
    264    return IFIELD( instr, 1, 5 );
    265 }
    266 
    267 /* Extract RD (destination register) field, instr[25:21] */
    268 static UChar ifieldRegDS( UInt instr ) {
    269    return toUChar( IFIELD( instr, 21, 5 ) );
    270 }
    271 
    272 /* Extract XT (destination register) field, instr[0,25:21] */
    273 static UChar ifieldRegXT ( UInt instr )
    274 {
    275   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
    276   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
    277   return (upper_bit << 5) | lower_bits;
    278 }
    279 
    280 /* Extract XS (store source register) field, instr[0,25:21] */
    281 static inline UChar ifieldRegXS ( UInt instr )
    282 {
    283   return ifieldRegXT ( instr );
    284 }
    285 
    286 /* Extract RA (1st source register) field, instr[20:16] */
    287 static UChar ifieldRegA ( UInt instr ) {
    288    return toUChar( IFIELD( instr, 16, 5 ) );
    289 }
    290 
    291 /* Extract XA (1st source register) field, instr[2,20:16] */
    292 static UChar ifieldRegXA ( UInt instr )
    293 {
    294   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
    295   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
    296   return (upper_bit << 5) | lower_bits;
    297 }
    298 
    299 /* Extract RB (2nd source register) field, instr[15:11] */
    300 static UChar ifieldRegB ( UInt instr ) {
    301    return toUChar( IFIELD( instr, 11, 5 ) );
    302 }
    303 
    304 /* Extract XB (2nd source register) field, instr[1,15:11] */
    305 static UChar ifieldRegXB ( UInt instr )
    306 {
    307   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
    308   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
    309   return (upper_bit << 5) | lower_bits;
    310 }
    311 
    312 /* Extract RC (3rd source register) field, instr[10:6] */
    313 static UChar ifieldRegC ( UInt instr ) {
    314    return toUChar( IFIELD( instr, 6, 5 ) );
    315 }
    316 
    317 /* Extract XC (3rd source register) field, instr[3,10:6] */
    318 static UChar ifieldRegXC ( UInt instr )
    319 {
    320   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
    321   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
    322   return (upper_bit << 5) | lower_bits;
    323 }
    324 
    325 /* Extract bit 10, instr[10] */
    326 static UChar ifieldBIT10 ( UInt instr ) {
    327    return toUChar( IFIELD( instr, 10, 1 ) );
    328 }
    329 
    330 /* Extract 2nd lowest bit, instr[1] */
    331 static UChar ifieldBIT1 ( UInt instr ) {
    332    return toUChar( IFIELD( instr, 1, 1 ) );
    333 }
    334 
    335 /* Extract lowest bit, instr[0] */
    336 static UChar ifieldBIT0 ( UInt instr ) {
    337    return toUChar( instr & 0x1 );
    338 }
    339 
    340 /* Extract unsigned bottom half, instr[15:0] */
    341 static UInt ifieldUIMM16 ( UInt instr ) {
    342    return instr & 0xFFFF;
    343 }
    344 
    345 /* Extract unsigned bottom 26 bits, instr[25:0] */
    346 static UInt ifieldUIMM26 ( UInt instr ) {
    347    return instr & 0x3FFFFFF;
    348 }
    349 
    350 /* Extract DM field, instr[9:8] */
    351 static UChar ifieldDM ( UInt instr ) {
    352    return toUChar( IFIELD( instr, 8, 2 ) );
    353 }
    354 
    355 /* Extract SHW field, instr[9:8] */
    356 static inline UChar ifieldSHW ( UInt instr )
    357 {
    358   return ifieldDM ( instr );
    359 }
    360 
    361 /*------------------------------------------------------------*/
    362 /*--- Guest-state identifiers                              ---*/
    363 /*------------------------------------------------------------*/
    364 
    365 typedef enum {
    366     PPC_GST_CIA,    // Current Instruction Address
    367     PPC_GST_LR,     // Link Register
    368     PPC_GST_CTR,    // Count Register
    369     PPC_GST_XER,    // Overflow, carry flags, byte count
    370     PPC_GST_CR,     // Condition Register
    371     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    372     PPC_GST_VRSAVE, // Vector Save/Restore Register
    373     PPC_GST_VSCR,   // Vector Status and Control Register
    374     PPC_GST_EMWARN, // Emulation warnings
    375     PPC_GST_TISTART,// For icbi: start of area to invalidate
    376     PPC_GST_TILEN,  // For icbi: length of area to invalidate
    377     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    378     PPC_GST_SPRG3_RO, // SPRG3
    379     PPC_GST_MAX
    380 } PPC_GST;
    381 
    382 #define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
    383 #define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
    384 #define MASK_VSCR_VALID 0x00010001
    385 
    386 
    387 /*------------------------------------------------------------*/
    388 /*---  FP Helpers                                          ---*/
    389 /*------------------------------------------------------------*/
    390 
    391 /* Produce the 32-bit pattern corresponding to the supplied
    392    float. */
    393 static UInt float_to_bits ( Float f )
    394 {
    395    union { UInt i; Float f; } u;
    396    vassert(4 == sizeof(UInt));
    397    vassert(4 == sizeof(Float));
    398    vassert(4 == sizeof(u));
    399    u.f = f;
    400    return u.i;
    401 }
    402 
    403 
    404 /*------------------------------------------------------------*/
    405 /*--- Misc Helpers                                         ---*/
    406 /*------------------------------------------------------------*/
    407 
    408 /* Generate mask with 1's from 'begin' through 'end',
    409    wrapping if begin > end.
    410    begin->end works from right to left, 0=lsb
    411 */
    412 static UInt MASK32( UInt begin, UInt end )
    413 {
    414    UInt m1, m2, mask;
    415    vassert(begin < 32);
    416    vassert(end < 32);
    417    m1   = ((UInt)(-1)) << begin;
    418    m2   = ((UInt)(-1)) << end << 1;
    419    mask = m1 ^ m2;
    420    if (begin > end) mask = ~mask;  // wrap mask
    421    return mask;
    422 }
    423 
    424 static ULong MASK64( UInt begin, UInt end )
    425 {
    426    ULong m1, m2, mask;
    427    vassert(begin < 64);
    428    vassert(end < 64);
    429    m1   = ((ULong)(-1)) << begin;
    430    m2   = ((ULong)(-1)) << end << 1;
    431    mask = m1 ^ m2;
    432    if (begin > end) mask = ~mask;  // wrap mask
    433    return mask;
    434 }
    435 
    436 static Addr64 nextInsnAddr( void )
    437 {
    438    return guest_CIA_curr_instr + 4;
    439 }
    440 
    441 
    442 /*------------------------------------------------------------*/
    443 /*--- Helper bits and pieces for deconstructing the        ---*/
    444 /*--- ppc32/64 insn stream.                                ---*/
    445 /*------------------------------------------------------------*/
    446 
    447 /* Add a statement to the list held by "irsb". */
    448 static void stmt ( IRStmt* st )
    449 {
    450    addStmtToIRSB( irsb, st );
    451 }
    452 
    453 /* Generate a new temporary of the given type. */
    454 static IRTemp newTemp ( IRType ty )
    455 {
    456    vassert(isPlausibleIRType(ty));
    457    return newIRTemp( irsb->tyenv, ty );
    458 }
    459 
    460 /* Various simple conversions */
    461 
    462 static UChar extend_s_5to8 ( UChar x )
    463 {
    464    return toUChar((((Int)x) << 27) >> 27);
    465 }
    466 
    467 static UInt extend_s_8to32( UChar x )
    468 {
    469    return (UInt)((((Int)x) << 24) >> 24);
    470 }
    471 
    472 static UInt extend_s_16to32 ( UInt x )
    473 {
    474    return (UInt)((((Int)x) << 16) >> 16);
    475 }
    476 
    477 static ULong extend_s_16to64 ( UInt x )
    478 {
    479    return (ULong)((((Long)x) << 48) >> 48);
    480 }
    481 
    482 static ULong extend_s_26to64 ( UInt x )
    483 {
    484    return (ULong)((((Long)x) << 38) >> 38);
    485 }
    486 
    487 static ULong extend_s_32to64 ( UInt x )
    488 {
    489    return (ULong)((((Long)x) << 32) >> 32);
    490 }
    491 
    492 /* Do a big-endian load of a 32-bit word, regardless of the endianness
    493    of the underlying host. */
    494 static UInt getUIntBigendianly ( UChar* p )
    495 {
    496    UInt w = 0;
    497    w = (w << 8) | p[0];
    498    w = (w << 8) | p[1];
    499    w = (w << 8) | p[2];
    500    w = (w << 8) | p[3];
    501    return w;
    502 }
    503 
    504 
    505 /*------------------------------------------------------------*/
    506 /*--- Helpers for constructing IR.                         ---*/
    507 /*------------------------------------------------------------*/
    508 
    509 static void assign ( IRTemp dst, IRExpr* e )
    510 {
    511    stmt( IRStmt_WrTmp(dst, e) );
    512 }
    513 
    514 /* This generates a normal (non store-conditional) store. */
    515 static void storeBE ( IRExpr* addr, IRExpr* data )
    516 {
    517    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    518    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    519    stmt( IRStmt_Store(Iend_BE, addr, data) );
    520 }
    521 
    522 static IRExpr* unop ( IROp op, IRExpr* a )
    523 {
    524    return IRExpr_Unop(op, a);
    525 }
    526 
    527 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    528 {
    529    return IRExpr_Binop(op, a1, a2);
    530 }
    531 
    532 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    533 {
    534    return IRExpr_Triop(op, a1, a2, a3);
    535 }
    536 
    537 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    538                               IRExpr* a3, IRExpr* a4 )
    539 {
    540    return IRExpr_Qop(op, a1, a2, a3, a4);
    541 }
    542 
    543 static IRExpr* mkexpr ( IRTemp tmp )
    544 {
    545    return IRExpr_RdTmp(tmp);
    546 }
    547 
    548 static IRExpr* mkU8 ( UChar i )
    549 {
    550    return IRExpr_Const(IRConst_U8(i));
    551 }
    552 
    553 static IRExpr* mkU16 ( UInt i )
    554 {
    555    return IRExpr_Const(IRConst_U16(i));
    556 }
    557 
    558 static IRExpr* mkU32 ( UInt i )
    559 {
    560    return IRExpr_Const(IRConst_U32(i));
    561 }
    562 
    563 static IRExpr* mkU64 ( ULong i )
    564 {
    565    return IRExpr_Const(IRConst_U64(i));
    566 }
    567 
    568 static IRExpr* mkV128 ( UShort i )
    569 {
    570    vassert(i == 0 || i == 0xffff);
    571    return IRExpr_Const(IRConst_V128(i));
    572 }
    573 
    574 /* This generates a normal (non load-linked) load. */
    575 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
    576 {
    577    return IRExpr_Load(Iend_BE, ty, addr);
    578 }
    579 
    580 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    581 {
    582    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    583    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    584    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    585                                           unop(Iop_1Uto32, arg2)));
    586 }
    587 
    588 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    589 {
    590    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    591    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    592    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    593                                            unop(Iop_1Uto32, arg2)));
    594 }
    595 
    596 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    597 static void expand8Ux16( IRExpr* vIn,
    598                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    599 {
    600    IRTemp ones8x16 = newTemp(Ity_V128);
    601 
    602    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    603    vassert(vEvn && *vEvn == IRTemp_INVALID);
    604    vassert(vOdd && *vOdd == IRTemp_INVALID);
    605    *vEvn = newTemp(Ity_V128);
    606    *vOdd = newTemp(Ity_V128);
    607 
    608    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    609    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    610    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    611                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    612 }
    613 
    614 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    615 static void expand8Sx16( IRExpr* vIn,
    616                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    617 {
    618    IRTemp ones8x16 = newTemp(Ity_V128);
    619 
    620    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    621    vassert(vEvn && *vEvn == IRTemp_INVALID);
    622    vassert(vOdd && *vOdd == IRTemp_INVALID);
    623    *vEvn = newTemp(Ity_V128);
    624    *vOdd = newTemp(Ity_V128);
    625 
    626    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    627    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    628    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    629                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    630 }
    631 
    632 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    633 static void expand16Ux8( IRExpr* vIn,
    634                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    635 {
    636    IRTemp ones16x8 = newTemp(Ity_V128);
    637 
    638    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    639    vassert(vEvn && *vEvn == IRTemp_INVALID);
    640    vassert(vOdd && *vOdd == IRTemp_INVALID);
    641    *vEvn = newTemp(Ity_V128);
    642    *vOdd = newTemp(Ity_V128);
    643 
    644    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    645    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    646    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    647                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    648 }
    649 
    650 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    651 static void expand16Sx8( IRExpr* vIn,
    652                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    653 {
    654    IRTemp ones16x8 = newTemp(Ity_V128);
    655 
    656    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    657    vassert(vEvn && *vEvn == IRTemp_INVALID);
    658    vassert(vOdd && *vOdd == IRTemp_INVALID);
    659    *vEvn = newTemp(Ity_V128);
    660    *vOdd = newTemp(Ity_V128);
    661 
    662    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    663    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    664    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    665                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    666 }
    667 
    668 /* break V128 to 4xF64's*/
    669 static void breakV128to4xF64( IRExpr* t128,
    670                               /*OUTs*/
    671                               IRTemp* t3, IRTemp* t2,
    672                               IRTemp* t1, IRTemp* t0 )
    673 {
    674    IRTemp hi64 = newTemp(Ity_I64);
    675    IRTemp lo64 = newTemp(Ity_I64);
    676 
    677    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    678    vassert(t0 && *t0 == IRTemp_INVALID);
    679    vassert(t1 && *t1 == IRTemp_INVALID);
    680    vassert(t2 && *t2 == IRTemp_INVALID);
    681    vassert(t3 && *t3 == IRTemp_INVALID);
    682    *t0 = newTemp(Ity_F64);
    683    *t1 = newTemp(Ity_F64);
    684    *t2 = newTemp(Ity_F64);
    685    *t3 = newTemp(Ity_F64);
    686 
    687    assign( hi64, unop(Iop_V128HIto64, t128) );
    688    assign( lo64, unop(Iop_V128to64,   t128) );
    689    assign( *t3,
    690            unop( Iop_F32toF64,
    691                  unop( Iop_ReinterpI32asF32,
    692                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
    693    assign( *t2,
    694            unop( Iop_F32toF64,
    695                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
    696    assign( *t1,
    697            unop( Iop_F32toF64,
    698                  unop( Iop_ReinterpI32asF32,
    699                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
    700    assign( *t0,
    701            unop( Iop_F32toF64,
    702                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
    703 }
    704 
    705 
    706 /* break V128 to 4xI32's, then sign-extend to I64's */
    707 static void breakV128to4x64S( IRExpr* t128,
    708                               /*OUTs*/
    709                               IRTemp* t3, IRTemp* t2,
    710                               IRTemp* t1, IRTemp* t0 )
    711 {
    712    IRTemp hi64 = newTemp(Ity_I64);
    713    IRTemp lo64 = newTemp(Ity_I64);
    714 
    715    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    716    vassert(t0 && *t0 == IRTemp_INVALID);
    717    vassert(t1 && *t1 == IRTemp_INVALID);
    718    vassert(t2 && *t2 == IRTemp_INVALID);
    719    vassert(t3 && *t3 == IRTemp_INVALID);
    720    *t0 = newTemp(Ity_I64);
    721    *t1 = newTemp(Ity_I64);
    722    *t2 = newTemp(Ity_I64);
    723    *t3 = newTemp(Ity_I64);
    724 
    725    assign( hi64, unop(Iop_V128HIto64, t128) );
    726    assign( lo64, unop(Iop_V128to64,   t128) );
    727    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    728    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    729    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    730    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    731 }
    732 
    733 /* break V128 to 4xI32's, then zero-extend to I64's */
    734 static void breakV128to4x64U ( IRExpr* t128,
    735                                /*OUTs*/
    736                                IRTemp* t3, IRTemp* t2,
    737                                IRTemp* t1, IRTemp* t0 )
    738 {
    739    IRTemp hi64 = newTemp(Ity_I64);
    740    IRTemp lo64 = newTemp(Ity_I64);
    741 
    742    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    743    vassert(t0 && *t0 == IRTemp_INVALID);
    744    vassert(t1 && *t1 == IRTemp_INVALID);
    745    vassert(t2 && *t2 == IRTemp_INVALID);
    746    vassert(t3 && *t3 == IRTemp_INVALID);
    747    *t0 = newTemp(Ity_I64);
    748    *t1 = newTemp(Ity_I64);
    749    *t2 = newTemp(Ity_I64);
    750    *t3 = newTemp(Ity_I64);
    751 
    752    assign( hi64, unop(Iop_V128HIto64, t128) );
    753    assign( lo64, unop(Iop_V128to64,   t128) );
    754    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    755    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    756    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    757    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    758 }
    759 
    760 static void breakV128to4x32( IRExpr* t128,
    761                               /*OUTs*/
    762                               IRTemp* t3, IRTemp* t2,
    763                               IRTemp* t1, IRTemp* t0 )
    764 {
    765    IRTemp hi64 = newTemp(Ity_I64);
    766    IRTemp lo64 = newTemp(Ity_I64);
    767 
    768    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    769    vassert(t0 && *t0 == IRTemp_INVALID);
    770    vassert(t1 && *t1 == IRTemp_INVALID);
    771    vassert(t2 && *t2 == IRTemp_INVALID);
    772    vassert(t3 && *t3 == IRTemp_INVALID);
    773    *t0 = newTemp(Ity_I32);
    774    *t1 = newTemp(Ity_I32);
    775    *t2 = newTemp(Ity_I32);
    776    *t3 = newTemp(Ity_I32);
    777 
    778    assign( hi64, unop(Iop_V128HIto64, t128) );
    779    assign( lo64, unop(Iop_V128to64,   t128) );
    780    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
    781    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
    782    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
    783    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
    784 }
    785 
    786 
    787 /* Signed saturating narrow 64S to 32 */
    788 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    789 {
    790    IRTemp hi32 = newTemp(Ity_I32);
    791    IRTemp lo32 = newTemp(Ity_I32);
    792 
    793    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    794 
    795    assign( hi32, unop(Iop_64HIto32, t64));
    796    assign( lo32, unop(Iop_64to32,   t64));
    797 
    798    return IRExpr_Mux0X(
    799              /* if (hi32 == (lo32 >>s 31)) */
    800              unop(Iop_1Uto8,
    801                   binop(Iop_CmpEQ32, mkexpr(hi32),
    802                         binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
    803              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    804              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    805                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
    806              /* then: within signed-32 range: lo half good enough */
    807              mkexpr(lo32) );
    808 }
    809 
    810 /* Unsigned saturating narrow 64S to 32 */
    811 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    812 {
    813    IRTemp hi32 = newTemp(Ity_I32);
    814    IRTemp lo32 = newTemp(Ity_I32);
    815 
    816    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    817 
    818    assign( hi32, unop(Iop_64HIto32, t64));
    819    assign( lo32, unop(Iop_64to32,   t64));
    820 
    821    return IRExpr_Mux0X(
    822             /* if (top 32 bits of t64 are 0) */
    823             unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
    824             /* else: positive saturate -> 0xFFFFFFFF */
    825             mkU32(0xFFFFFFFF),
    826             /* then: within unsigned-32 range: lo half good enough */
    827             mkexpr(lo32) );
    828 }
    829 
    830 /* Signed saturate narrow 64->32, combining to V128 */
    831 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    832                                  IRExpr* t1, IRExpr* t0 )
    833 {
    834    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    835    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    836    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    837    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    838    return binop(Iop_64HLtoV128,
    839                 binop(Iop_32HLto64,
    840                       mkQNarrow64Sto32( t3 ),
    841                       mkQNarrow64Sto32( t2 )),
    842                 binop(Iop_32HLto64,
    843                       mkQNarrow64Sto32( t1 ),
    844                       mkQNarrow64Sto32( t0 )));
    845 }
    846 
    847 /* Unsigned saturate narrow 64->32, combining to V128 */
    848 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    849                                  IRExpr* t1, IRExpr* t0 )
    850 {
    851    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    852    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    853    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    854    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    855    return binop(Iop_64HLtoV128,
    856                 binop(Iop_32HLto64,
    857                       mkQNarrow64Uto32( t3 ),
    858                       mkQNarrow64Uto32( t2 )),
    859                 binop(Iop_32HLto64,
    860                       mkQNarrow64Uto32( t1 ),
    861                       mkQNarrow64Uto32( t0 )));
    862 }
    863 
    864 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    865 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    866       binop(Iop_MullEven8Ux16, \
    867             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    868             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    869 
    870 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    871       binop(Iop_MullEven8Sx16, \
    872             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    873             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    874 
    875 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    876       binop(Iop_MullEven16Ux8, \
    877             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    878             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    879 
    880 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    881       binop(Iop_MullEven16Sx8, \
    882             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    883             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    884 
    885 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
    886 {
    887    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    888    return unop(Iop_32Sto64, unop(Iop_64to32, src));
    889 }
    890 
    891 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
    892 {
    893    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    894    return unop(Iop_32Uto64, unop(Iop_64to32, src));
    895 }
    896 
    897 static IROp mkSzOp ( IRType ty, IROp op8 )
    898 {
    899    Int adj;
    900    vassert(ty == Ity_I8  || ty == Ity_I16 ||
    901            ty == Ity_I32 || ty == Ity_I64);
    902    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
    903            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
    904            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
    905            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
    906            op8 == Iop_Not8 );
    907    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
    908    return adj + op8;
    909 }
    910 
    911 /* Make sure we get valid 32 and 64bit addresses */
    912 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
    913 {
    914    vassert(ty == Ity_I32 || ty == Ity_I64);
    915    return ( ty == Ity_I64 ?
    916             (Addr64)addr :
    917             (Addr64)extend_s_32to64( toUInt(addr) ) );
    918 }
    919 
    920 /* sz, ULong -> IRExpr */
    921 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
    922 {
    923    vassert(ty == Ity_I32 || ty == Ity_I64);
    924    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
    925 }
    926 
    927 /* sz, ULong -> IRConst */
    928 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
    929 {
    930    vassert(ty == Ity_I32 || ty == Ity_I64);
    931    return ( ty == Ity_I64 ?
    932             IRConst_U64(imm64) :
    933             IRConst_U32((UInt)imm64) );
    934 }
    935 
    936 /* Sign extend imm16 -> IRExpr* */
    937 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
    938 {
    939    vassert(ty == Ity_I32 || ty == Ity_I64);
    940    return ( ty == Ity_I64 ?
    941             mkU64(extend_s_16to64(imm16)) :
    942             mkU32(extend_s_16to32(imm16)) );
    943 }
    944 
    945 /* Sign extend imm32 -> IRExpr* */
    946 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
    947 {
    948    vassert(ty == Ity_I32 || ty == Ity_I64);
    949    return ( ty == Ity_I64 ?
    950             mkU64(extend_s_32to64(imm32)) :
    951             mkU32(imm32) );
    952 }
    953 
    954 /* IR narrows I32/I64 -> I8/I16/I32 */
    955 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
    956 {
    957    vassert(ty == Ity_I32 || ty == Ity_I64);
    958    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
    959 }
    960 
    961 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
    962 {
    963    vassert(ty == Ity_I32 || ty == Ity_I64);
    964    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
    965 }
    966 
    967 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
    968 {
    969    vassert(ty == Ity_I32 || ty == Ity_I64);
    970    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
    971 }
    972 
    973 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
    974 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
    975 {
    976    IROp op;
    977    vassert(ty == Ity_I32 || ty == Ity_I64);
    978    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
    979    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
    980    return unop(op, src);
    981 }
    982 
    983 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
    984 {
    985    IROp op;
    986    vassert(ty == Ity_I32 || ty == Ity_I64);
    987    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
    988    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
    989    return unop(op, src);
    990 }
    991 
    992 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
    993 {
    994    vassert(ty == Ity_I32 || ty == Ity_I64);
    995    if (ty == Ity_I32)
    996       return src;
    997    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
    998 }
    999 
   1000 
   1001 static Int integerGuestRegOffset ( UInt archreg )
   1002 {
   1003    vassert(archreg < 32);
   1004 
   1005    // jrs: probably not necessary; only matters if we reference sub-parts
   1006    // of the ppc registers, but that isn't the case
   1007    // later: this might affect Altivec though?
   1008    vassert(host_is_bigendian);
   1009 
   1010    switch (archreg) {
   1011    case  0: return offsetofPPCGuestState(guest_GPR0);
   1012    case  1: return offsetofPPCGuestState(guest_GPR1);
   1013    case  2: return offsetofPPCGuestState(guest_GPR2);
   1014    case  3: return offsetofPPCGuestState(guest_GPR3);
   1015    case  4: return offsetofPPCGuestState(guest_GPR4);
   1016    case  5: return offsetofPPCGuestState(guest_GPR5);
   1017    case  6: return offsetofPPCGuestState(guest_GPR6);
   1018    case  7: return offsetofPPCGuestState(guest_GPR7);
   1019    case  8: return offsetofPPCGuestState(guest_GPR8);
   1020    case  9: return offsetofPPCGuestState(guest_GPR9);
   1021    case 10: return offsetofPPCGuestState(guest_GPR10);
   1022    case 11: return offsetofPPCGuestState(guest_GPR11);
   1023    case 12: return offsetofPPCGuestState(guest_GPR12);
   1024    case 13: return offsetofPPCGuestState(guest_GPR13);
   1025    case 14: return offsetofPPCGuestState(guest_GPR14);
   1026    case 15: return offsetofPPCGuestState(guest_GPR15);
   1027    case 16: return offsetofPPCGuestState(guest_GPR16);
   1028    case 17: return offsetofPPCGuestState(guest_GPR17);
   1029    case 18: return offsetofPPCGuestState(guest_GPR18);
   1030    case 19: return offsetofPPCGuestState(guest_GPR19);
   1031    case 20: return offsetofPPCGuestState(guest_GPR20);
   1032    case 21: return offsetofPPCGuestState(guest_GPR21);
   1033    case 22: return offsetofPPCGuestState(guest_GPR22);
   1034    case 23: return offsetofPPCGuestState(guest_GPR23);
   1035    case 24: return offsetofPPCGuestState(guest_GPR24);
   1036    case 25: return offsetofPPCGuestState(guest_GPR25);
   1037    case 26: return offsetofPPCGuestState(guest_GPR26);
   1038    case 27: return offsetofPPCGuestState(guest_GPR27);
   1039    case 28: return offsetofPPCGuestState(guest_GPR28);
   1040    case 29: return offsetofPPCGuestState(guest_GPR29);
   1041    case 30: return offsetofPPCGuestState(guest_GPR30);
   1042    case 31: return offsetofPPCGuestState(guest_GPR31);
   1043    default: break;
   1044    }
   1045    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
   1046 }
   1047 
   1048 static IRExpr* getIReg ( UInt archreg )
   1049 {
   1050    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1051    vassert(archreg < 32);
   1052    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
   1053 }
   1054 
   1055 /* Ditto, but write to a reg instead. */
   1056 static void putIReg ( UInt archreg, IRExpr* e )
   1057 {
   1058    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1059    vassert(archreg < 32);
   1060    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
   1061    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
   1062 }
   1063 
   1064 
   1065 /* Floating point egisters are mapped to VSX registers[0..31]. */
   1066 static Int floatGuestRegOffset ( UInt archreg )
   1067 {
   1068    vassert(archreg < 32);
   1069 
   1070    switch (archreg) {
   1071    case  0: return offsetofPPCGuestState(guest_VSR0);
   1072    case  1: return offsetofPPCGuestState(guest_VSR1);
   1073    case  2: return offsetofPPCGuestState(guest_VSR2);
   1074    case  3: return offsetofPPCGuestState(guest_VSR3);
   1075    case  4: return offsetofPPCGuestState(guest_VSR4);
   1076    case  5: return offsetofPPCGuestState(guest_VSR5);
   1077    case  6: return offsetofPPCGuestState(guest_VSR6);
   1078    case  7: return offsetofPPCGuestState(guest_VSR7);
   1079    case  8: return offsetofPPCGuestState(guest_VSR8);
   1080    case  9: return offsetofPPCGuestState(guest_VSR9);
   1081    case 10: return offsetofPPCGuestState(guest_VSR10);
   1082    case 11: return offsetofPPCGuestState(guest_VSR11);
   1083    case 12: return offsetofPPCGuestState(guest_VSR12);
   1084    case 13: return offsetofPPCGuestState(guest_VSR13);
   1085    case 14: return offsetofPPCGuestState(guest_VSR14);
   1086    case 15: return offsetofPPCGuestState(guest_VSR15);
   1087    case 16: return offsetofPPCGuestState(guest_VSR16);
   1088    case 17: return offsetofPPCGuestState(guest_VSR17);
   1089    case 18: return offsetofPPCGuestState(guest_VSR18);
   1090    case 19: return offsetofPPCGuestState(guest_VSR19);
   1091    case 20: return offsetofPPCGuestState(guest_VSR20);
   1092    case 21: return offsetofPPCGuestState(guest_VSR21);
   1093    case 22: return offsetofPPCGuestState(guest_VSR22);
   1094    case 23: return offsetofPPCGuestState(guest_VSR23);
   1095    case 24: return offsetofPPCGuestState(guest_VSR24);
   1096    case 25: return offsetofPPCGuestState(guest_VSR25);
   1097    case 26: return offsetofPPCGuestState(guest_VSR26);
   1098    case 27: return offsetofPPCGuestState(guest_VSR27);
   1099    case 28: return offsetofPPCGuestState(guest_VSR28);
   1100    case 29: return offsetofPPCGuestState(guest_VSR29);
   1101    case 30: return offsetofPPCGuestState(guest_VSR30);
   1102    case 31: return offsetofPPCGuestState(guest_VSR31);
   1103    default: break;
   1104    }
   1105    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
   1106 }
   1107 
   1108 static IRExpr* getFReg ( UInt archreg )
   1109 {
   1110    vassert(archreg < 32);
   1111    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
   1112 }
   1113 
   1114 /* Ditto, but write to a reg instead. */
   1115 static void putFReg ( UInt archreg, IRExpr* e )
   1116 {
   1117    vassert(archreg < 32);
   1118    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1119    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
   1120 }
   1121 
   1122 /* get Decimal float value.  Note, they share floating point register file. */
   1123 static IRExpr* getDReg(UInt archreg) {
   1124    IRExpr *e;
   1125    vassert( archreg < 32 );
   1126    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
   1127    return e;
   1128 }
   1129 
   1130 /* Read a floating point register pair and combine their contents into a
   1131  128-bit value */
   1132 static IRExpr *getDReg_pair(UInt archreg) {
   1133    IRExpr *high = getDReg( archreg );
   1134    IRExpr *low = getDReg( archreg + 1 );
   1135 
   1136    return binop( Iop_D64HLtoD128, high, low );
   1137 }
   1138 
   1139 /* Ditto, but write to a reg instead. */
   1140 static void putDReg(UInt archreg, IRExpr* e) {
   1141    vassert( archreg < 32 );
   1142    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
   1143    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1144 }
   1145 
   1146 /* Write a 128-bit floating point value into a register pair. */
   1147 static void putDReg_pair(UInt archreg, IRExpr *e) {
   1148    IRTemp low = newTemp( Ity_D64 );
   1149    IRTemp high = newTemp( Ity_D64 );
   1150 
   1151    vassert( archreg < 32 );
   1152    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
   1153 
   1154    assign( low, unop( Iop_D128LOtoD64, e ) );
   1155    assign( high, unop( Iop_D128HItoD64, e ) );
   1156 
   1157    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
   1158    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
   1159 }
   1160 
   1161 static Int vsxGuestRegOffset ( UInt archreg )
   1162 {
   1163    vassert(archreg < 64);
   1164    switch (archreg) {
   1165    case  0: return offsetofPPCGuestState(guest_VSR0);
   1166    case  1: return offsetofPPCGuestState(guest_VSR1);
   1167    case  2: return offsetofPPCGuestState(guest_VSR2);
   1168    case  3: return offsetofPPCGuestState(guest_VSR3);
   1169    case  4: return offsetofPPCGuestState(guest_VSR4);
   1170    case  5: return offsetofPPCGuestState(guest_VSR5);
   1171    case  6: return offsetofPPCGuestState(guest_VSR6);
   1172    case  7: return offsetofPPCGuestState(guest_VSR7);
   1173    case  8: return offsetofPPCGuestState(guest_VSR8);
   1174    case  9: return offsetofPPCGuestState(guest_VSR9);
   1175    case 10: return offsetofPPCGuestState(guest_VSR10);
   1176    case 11: return offsetofPPCGuestState(guest_VSR11);
   1177    case 12: return offsetofPPCGuestState(guest_VSR12);
   1178    case 13: return offsetofPPCGuestState(guest_VSR13);
   1179    case 14: return offsetofPPCGuestState(guest_VSR14);
   1180    case 15: return offsetofPPCGuestState(guest_VSR15);
   1181    case 16: return offsetofPPCGuestState(guest_VSR16);
   1182    case 17: return offsetofPPCGuestState(guest_VSR17);
   1183    case 18: return offsetofPPCGuestState(guest_VSR18);
   1184    case 19: return offsetofPPCGuestState(guest_VSR19);
   1185    case 20: return offsetofPPCGuestState(guest_VSR20);
   1186    case 21: return offsetofPPCGuestState(guest_VSR21);
   1187    case 22: return offsetofPPCGuestState(guest_VSR22);
   1188    case 23: return offsetofPPCGuestState(guest_VSR23);
   1189    case 24: return offsetofPPCGuestState(guest_VSR24);
   1190    case 25: return offsetofPPCGuestState(guest_VSR25);
   1191    case 26: return offsetofPPCGuestState(guest_VSR26);
   1192    case 27: return offsetofPPCGuestState(guest_VSR27);
   1193    case 28: return offsetofPPCGuestState(guest_VSR28);
   1194    case 29: return offsetofPPCGuestState(guest_VSR29);
   1195    case 30: return offsetofPPCGuestState(guest_VSR30);
   1196    case 31: return offsetofPPCGuestState(guest_VSR31);
   1197    case 32: return offsetofPPCGuestState(guest_VSR32);
   1198    case 33: return offsetofPPCGuestState(guest_VSR33);
   1199    case 34: return offsetofPPCGuestState(guest_VSR34);
   1200    case 35: return offsetofPPCGuestState(guest_VSR35);
   1201    case 36: return offsetofPPCGuestState(guest_VSR36);
   1202    case 37: return offsetofPPCGuestState(guest_VSR37);
   1203    case 38: return offsetofPPCGuestState(guest_VSR38);
   1204    case 39: return offsetofPPCGuestState(guest_VSR39);
   1205    case 40: return offsetofPPCGuestState(guest_VSR40);
   1206    case 41: return offsetofPPCGuestState(guest_VSR41);
   1207    case 42: return offsetofPPCGuestState(guest_VSR42);
   1208    case 43: return offsetofPPCGuestState(guest_VSR43);
   1209    case 44: return offsetofPPCGuestState(guest_VSR44);
   1210    case 45: return offsetofPPCGuestState(guest_VSR45);
   1211    case 46: return offsetofPPCGuestState(guest_VSR46);
   1212    case 47: return offsetofPPCGuestState(guest_VSR47);
   1213    case 48: return offsetofPPCGuestState(guest_VSR48);
   1214    case 49: return offsetofPPCGuestState(guest_VSR49);
   1215    case 50: return offsetofPPCGuestState(guest_VSR50);
   1216    case 51: return offsetofPPCGuestState(guest_VSR51);
   1217    case 52: return offsetofPPCGuestState(guest_VSR52);
   1218    case 53: return offsetofPPCGuestState(guest_VSR53);
   1219    case 54: return offsetofPPCGuestState(guest_VSR54);
   1220    case 55: return offsetofPPCGuestState(guest_VSR55);
   1221    case 56: return offsetofPPCGuestState(guest_VSR56);
   1222    case 57: return offsetofPPCGuestState(guest_VSR57);
   1223    case 58: return offsetofPPCGuestState(guest_VSR58);
   1224    case 59: return offsetofPPCGuestState(guest_VSR59);
   1225    case 60: return offsetofPPCGuestState(guest_VSR60);
   1226    case 61: return offsetofPPCGuestState(guest_VSR61);
   1227    case 62: return offsetofPPCGuestState(guest_VSR62);
   1228    case 63: return offsetofPPCGuestState(guest_VSR63);
   1229    default: break;
   1230    }
   1231    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
   1232 }
   1233 
   1234 /* Vector registers are mapped to VSX registers[32..63]. */
   1235 static Int vectorGuestRegOffset ( UInt archreg )
   1236 {
   1237    vassert(archreg < 32);
   1238 
   1239    switch (archreg) {
   1240    case  0: return offsetofPPCGuestState(guest_VSR32);
   1241    case  1: return offsetofPPCGuestState(guest_VSR33);
   1242    case  2: return offsetofPPCGuestState(guest_VSR34);
   1243    case  3: return offsetofPPCGuestState(guest_VSR35);
   1244    case  4: return offsetofPPCGuestState(guest_VSR36);
   1245    case  5: return offsetofPPCGuestState(guest_VSR37);
   1246    case  6: return offsetofPPCGuestState(guest_VSR38);
   1247    case  7: return offsetofPPCGuestState(guest_VSR39);
   1248    case  8: return offsetofPPCGuestState(guest_VSR40);
   1249    case  9: return offsetofPPCGuestState(guest_VSR41);
   1250    case 10: return offsetofPPCGuestState(guest_VSR42);
   1251    case 11: return offsetofPPCGuestState(guest_VSR43);
   1252    case 12: return offsetofPPCGuestState(guest_VSR44);
   1253    case 13: return offsetofPPCGuestState(guest_VSR45);
   1254    case 14: return offsetofPPCGuestState(guest_VSR46);
   1255    case 15: return offsetofPPCGuestState(guest_VSR47);
   1256    case 16: return offsetofPPCGuestState(guest_VSR48);
   1257    case 17: return offsetofPPCGuestState(guest_VSR49);
   1258    case 18: return offsetofPPCGuestState(guest_VSR50);
   1259    case 19: return offsetofPPCGuestState(guest_VSR51);
   1260    case 20: return offsetofPPCGuestState(guest_VSR52);
   1261    case 21: return offsetofPPCGuestState(guest_VSR53);
   1262    case 22: return offsetofPPCGuestState(guest_VSR54);
   1263    case 23: return offsetofPPCGuestState(guest_VSR55);
   1264    case 24: return offsetofPPCGuestState(guest_VSR56);
   1265    case 25: return offsetofPPCGuestState(guest_VSR57);
   1266    case 26: return offsetofPPCGuestState(guest_VSR58);
   1267    case 27: return offsetofPPCGuestState(guest_VSR59);
   1268    case 28: return offsetofPPCGuestState(guest_VSR60);
   1269    case 29: return offsetofPPCGuestState(guest_VSR61);
   1270    case 30: return offsetofPPCGuestState(guest_VSR62);
   1271    case 31: return offsetofPPCGuestState(guest_VSR63);
   1272    default: break;
   1273    }
   1274    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1275 }
   1276 
   1277 static IRExpr* getVReg ( UInt archreg )
   1278 {
   1279    vassert(archreg < 32);
   1280    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1281 }
   1282 
   1283 /* Ditto, but write to a reg instead. */
   1284 static void putVReg ( UInt archreg, IRExpr* e )
   1285 {
   1286    vassert(archreg < 32);
   1287    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1288    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1289 }
   1290 
   1291 /* Get contents of VSX guest register */
   1292 static IRExpr* getVSReg ( UInt archreg )
   1293 {
   1294    vassert(archreg < 64);
   1295    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
   1296 }
   1297 
   1298 /* Ditto, but write to a VSX reg instead. */
   1299 static void putVSReg ( UInt archreg, IRExpr* e )
   1300 {
   1301    vassert(archreg < 64);
   1302    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1303    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
   1304 }
   1305 
   1306 
   1307 static Int guestCR321offset ( UInt cr )
   1308 {
   1309    switch (cr) {
   1310    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1311    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1312    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1313    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1314    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1315    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1316    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1317    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1318    default: vpanic("guestCR321offset(ppc)");
   1319    }
   1320 }
   1321 
   1322 static Int guestCR0offset ( UInt cr )
   1323 {
   1324    switch (cr) {
   1325    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1326    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1327    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1328    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1329    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1330    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1331    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1332    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1333    default: vpanic("guestCR3offset(ppc)");
   1334    }
   1335 }
   1336 
   1337 /* Generate an IR sequence to do a popcount operation on the supplied
   1338    IRTemp, and return a new IRTemp holding the result.  'ty' may be
   1339    Ity_I32 or Ity_I64 only. */
   1340 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, Bool byte_count )
   1341 {
   1342    Int i, shift[6], max;
   1343    IRTemp mask[6];
   1344    IRTemp old = IRTemp_INVALID;
   1345    IRTemp nyu = IRTemp_INVALID;
   1346 
   1347    vassert(ty == Ity_I64 || ty == Ity_I32);
   1348 
   1349    if (ty == Ity_I32) {
   1350       if (byte_count)
   1351          /* Return the population count across each byte not across the entire
   1352           * 32-bit value.  Stop after third iteration.
   1353           */
   1354          max = 3;
   1355       else
   1356          max = 5;
   1357 
   1358       for (i = 0; i < 5; i++) {
   1359          mask[i]  = newTemp(ty);
   1360          shift[i] = 1 << i;
   1361       }
   1362       assign(mask[0], mkU32(0x55555555));
   1363       assign(mask[1], mkU32(0x33333333));
   1364       assign(mask[2], mkU32(0x0F0F0F0F));
   1365       assign(mask[3], mkU32(0x00FF00FF));
   1366       assign(mask[4], mkU32(0x0000FFFF));
   1367       old = src;
   1368       for (i = 0; i < max; i++) {
   1369          nyu = newTemp(ty);
   1370          assign(nyu,
   1371                 binop(Iop_Add32,
   1372                       binop(Iop_And32,
   1373                             mkexpr(old),
   1374                             mkexpr(mask[i])),
   1375                       binop(Iop_And32,
   1376                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1377                             mkexpr(mask[i]))));
   1378          old = nyu;
   1379       }
   1380       return nyu;
   1381    }
   1382 // else, ty == Ity_I64
   1383    if (byte_count)
   1384       /* Return the population count across each byte not across the entire
   1385        * 64-bit value.  Stop after third iteration.
   1386        */
   1387       max = 3;
   1388    else
   1389       max = 6;
   1390 
   1391    for (i = 0; i < 6; i++) {
   1392       mask[i] = newTemp( Ity_I64 );
   1393       shift[i] = 1 << i;
   1394    }
   1395    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
   1396    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
   1397    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
   1398    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
   1399    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
   1400    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
   1401    old = src;
   1402    for (i = 0; i < max; i++) {
   1403       nyu = newTemp( Ity_I64 );
   1404       assign( nyu,
   1405               binop( Iop_Add64,
   1406                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
   1407                      binop( Iop_And64,
   1408                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
   1409                             mkexpr( mask[i] ) ) ) );
   1410       old = nyu;
   1411    }
   1412    return nyu;
   1413 }
   1414 
   1415 
   1416 // ROTL(src32/64, rot_amt5/6)
   1417 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1418                                           IRExpr* rot_amt )
   1419 {
   1420    IRExpr *mask, *rot;
   1421    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1422 
   1423    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1424       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1425       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1426       rot  = binop(Iop_Or64,
   1427                 binop(Iop_Shl64, src, mask),
   1428                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1429    } else {
   1430       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1431       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1432       rot  = binop(Iop_Or32,
   1433                 binop(Iop_Shl32, src, mask),
   1434                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1435    }
   1436    /* Note: the MuxOX is not merely an optimisation; it's needed
   1437       because otherwise the Shr is a shift by the word size when
   1438       mask denotes zero.  For rotates by immediates, a lot of
   1439       this junk gets folded out. */
   1440    return IRExpr_Mux0X( mask, /*     zero rotate */ src,
   1441                               /* non-zero rotate */ rot );
   1442 }
   1443 
   1444 /* Standard effective address calc: (rA + rB) */
   1445 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1446 {
   1447    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1448    vassert(rA < 32);
   1449    vassert(rB < 32);
   1450    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1451 }
   1452 
   1453 /* Standard effective address calc: (rA + simm) */
   1454 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1455 {
   1456    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1457    vassert(rA < 32);
   1458    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1459                 mkSzExtendS16(ty, simm16));
   1460 }
   1461 
   1462 /* Standard effective address calc: (rA|0) */
   1463 static IRExpr* ea_rAor0 ( UInt rA )
   1464 {
   1465    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1466    vassert(rA < 32);
   1467    if (rA == 0) {
   1468       return mkSzImm(ty, 0);
   1469    } else {
   1470       return getIReg(rA);
   1471    }
   1472 }
   1473 
   1474 /* Standard effective address calc: (rA|0) + rB */
   1475 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1476 {
   1477    vassert(rA < 32);
   1478    vassert(rB < 32);
   1479    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1480 }
   1481 
   1482 /* Standard effective address calc: (rA|0) + simm16 */
   1483 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1484 {
   1485    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1486    vassert(rA < 32);
   1487    if (rA == 0) {
   1488       return mkSzExtendS16(ty, simm16);
   1489    } else {
   1490       return ea_rA_simm( rA, simm16 );
   1491    }
   1492 }
   1493 
   1494 
   1495 /* Align effective address */
   1496 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1497 {
   1498    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1499    Long mask;
   1500    switch (align) {
   1501    case 1:  return addr;                    // byte aligned
   1502    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
   1503    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
   1504    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
   1505    default:
   1506       vex_printf("addr_align: align = %u\n", align);
   1507       vpanic("addr_align(ppc)");
   1508    }
   1509 
   1510    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1511    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1512 }
   1513 
   1514 
   1515 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1516    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1517    restart of the current insn. */
   1518 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1519 {
   1520    vassert(align == 4 || align == 8);
   1521    if (mode64) {
   1522       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1523       stmt(
   1524          IRStmt_Exit(
   1525             binop(Iop_CmpNE64,
   1526                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1527                   mkU64(0)),
   1528             Ijk_SigBUS,
   1529             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
   1530          )
   1531       );
   1532    } else {
   1533       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1534       stmt(
   1535          IRStmt_Exit(
   1536             binop(Iop_CmpNE32,
   1537                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1538                   mkU32(0)),
   1539             Ijk_SigBUS,
   1540             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
   1541          )
   1542       );
   1543    }
   1544 }
   1545 
   1546 
   1547 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1548    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1549    N) becomes undefined.  That is at function calls and returns.  ELF
   1550    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1551    the address of the next instruction to be executed.
   1552 */
   1553 static void make_redzone_AbiHint ( VexAbiInfo* vbi,
   1554                                    IRTemp nia, HChar* who )
   1555 {
   1556    Int szB = vbi->guest_stack_redzone_size;
   1557    if (0) vex_printf("AbiHint: %s\n", who);
   1558    vassert(szB >= 0);
   1559    if (szB > 0) {
   1560       if (mode64) {
   1561          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1562          stmt( IRStmt_AbiHint(
   1563                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1564                   szB,
   1565                   mkexpr(nia)
   1566          ));
   1567       } else {
   1568          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1569          stmt( IRStmt_AbiHint(
   1570                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1571                   szB,
   1572                   mkexpr(nia)
   1573          ));
   1574       }
   1575    }
   1576 }
   1577 
   1578 
   1579 /*------------------------------------------------------------*/
   1580 /*--- Helpers for condition codes.                         ---*/
   1581 /*------------------------------------------------------------*/
   1582 
   1583 /* Condition register layout.
   1584 
   1585    In the hardware, CR is laid out like this.  The leftmost end is the
   1586    most significant bit in the register; however the IBM documentation
   1587    numbers the bits backwards for some reason.
   1588 
   1589    CR0      CR1    ..........   CR6       CR7
   1590    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1591    31  28                             3    0     (normal bit numbering)
   1592 
   1593    Each CR field is 4 bits:  [<,>,==,SO]
   1594 
   1595    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1596 
   1597    Indexing from BI to guest state:
   1598 
   1599      let    n = BI / 4
   1600           off = BI % 4
   1601      this references CR n:
   1602 
   1603         off==0   ->  guest_CRn_321 >> 3
   1604         off==1   ->  guest_CRn_321 >> 2
   1605         off==2   ->  guest_CRn_321 >> 1
   1606         off==3   ->  guest_CRn_SO
   1607 
   1608    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1609    (normal notation) and in guest_CRn_321 the significant bits are
   1610    3, 2 and 1 (normal notation).
   1611 */
   1612 
   1613 static void putCR321 ( UInt cr, IRExpr* e )
   1614 {
   1615    vassert(cr < 8);
   1616    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1617    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1618 }
   1619 
   1620 static void putCR0 ( UInt cr, IRExpr* e )
   1621 {
   1622    vassert(cr < 8);
   1623    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1624    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1625 }
   1626 
   1627 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1628 {
   1629    vassert(cr < 8);
   1630    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1631 }
   1632 
   1633 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1634 {
   1635    vassert(cr < 8);
   1636    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1637 }
   1638 
   1639 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1640    return it at the bottom of an I32; the top 31 bits are guaranteed
   1641    to be zero. */
   1642 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1643 {
   1644    UInt n   = bi / 4;
   1645    UInt off = bi % 4;
   1646    vassert(bi < 32);
   1647    if (off == 3) {
   1648       /* Fetch the SO bit for this CR field */
   1649       /* Note: And32 is redundant paranoia iff guest state only has 0
   1650          or 1 in that slot. */
   1651       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1652    } else {
   1653       /* Fetch the <, > or == bit for this CR field */
   1654       return binop( Iop_And32,
   1655                     binop( Iop_Shr32,
   1656                            unop(Iop_8Uto32, getCR321(n)),
   1657                            mkU8(toUChar(3-off)) ),
   1658                     mkU32(1) );
   1659    }
   1660 }
   1661 
   1662 /* Dually, write the least significant bit of BIT to the specified CR
   1663    bit.  Indexing as per getCRbit. */
   1664 static void putCRbit ( UInt bi, IRExpr* bit )
   1665 {
   1666    UInt    n, off;
   1667    IRExpr* safe;
   1668    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1669    safe = binop(Iop_And32, bit, mkU32(1));
   1670    n   = bi / 4;
   1671    off = bi % 4;
   1672    vassert(bi < 32);
   1673    if (off == 3) {
   1674       /* This is the SO bit for this CR field */
   1675       putCR0(n, unop(Iop_32to8, safe));
   1676    } else {
   1677       off = 3 - off;
   1678       vassert(off == 1 || off == 2 || off == 3);
   1679       putCR321(
   1680          n,
   1681          unop( Iop_32to8,
   1682                binop( Iop_Or32,
   1683                       /* old value with field masked out */
   1684                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1685                                        mkU32(~(1 << off))),
   1686                       /* new value in the right place */
   1687                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1688                )
   1689          )
   1690       );
   1691    }
   1692 }
   1693 
   1694 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1695    return it somewhere in an I32; it does not matter where, but
   1696    whichever bit it is, all other bits are guaranteed to be zero.  In
   1697    other words, the I32-typed expression will be zero if the bit is
   1698    zero and nonzero if the bit is 1.  Write into *where the index
   1699    of where the bit will be. */
   1700 
   1701 static
   1702 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   1703 {
   1704    UInt n   = bi / 4;
   1705    UInt off = bi % 4;
   1706    vassert(bi < 32);
   1707    if (off == 3) {
   1708       /* Fetch the SO bit for this CR field */
   1709       /* Note: And32 is redundant paranoia iff guest state only has 0
   1710          or 1 in that slot. */
   1711       *where = 0;
   1712       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1713    } else {
   1714       /* Fetch the <, > or == bit for this CR field */
   1715       *where = 3-off;
   1716       return binop( Iop_And32,
   1717                     unop(Iop_8Uto32, getCR321(n)),
   1718                     mkU32(1 << (3-off)) );
   1719    }
   1720 }
   1721 
   1722 /* Set the CR0 flags following an arithmetic operation.
   1723    (Condition Register CR0 Field Definition, PPC32 p60)
   1724 */
   1725 static IRExpr* getXER_SO ( void );
   1726 static void set_CR0 ( IRExpr* result )
   1727 {
   1728    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1729            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1730    if (mode64) {
   1731       putCR321( 0, unop(Iop_64to8,
   1732                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1733    } else {
   1734       putCR321( 0, unop(Iop_32to8,
   1735                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1736    }
   1737    putCR0( 0, getXER_SO() );
   1738 }
   1739 
   1740 
   1741 /* Set the CR6 flags following an AltiVec compare operation.
   1742  * NOTE: This also works for VSX single-precision compares.
   1743  * */
   1744 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1745 {
   1746    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1747       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1748       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1749    */
   1750    IRTemp v0 = newTemp(Ity_V128);
   1751    IRTemp v1 = newTemp(Ity_V128);
   1752    IRTemp v2 = newTemp(Ity_V128);
   1753    IRTemp v3 = newTemp(Ity_V128);
   1754    IRTemp rOnes  = newTemp(Ity_I8);
   1755    IRTemp rZeros = newTemp(Ity_I8);
   1756 
   1757    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1758 
   1759    assign( v0, result );
   1760    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1761    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1762    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1763 
   1764    assign( rZeros, unop(Iop_1Uto8,
   1765        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1766              unop(Iop_Not32,
   1767                   unop(Iop_V128to32,
   1768                        binop(Iop_OrV128,
   1769                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1770                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1771                   ))) );
   1772 
   1773    if (test_all_ones) {
   1774       assign( rOnes, unop(Iop_1Uto8,
   1775          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1776                unop(Iop_V128to32,
   1777                     binop(Iop_AndV128,
   1778                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   1779                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   1780                     ))) );
   1781       putCR321( 6, binop(Iop_Or8,
   1782                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   1783                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   1784    } else {
   1785       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   1786    }
   1787    putCR0( 6, mkU8(0) );
   1788 }
   1789 
   1790 
   1791 
   1792 /*------------------------------------------------------------*/
   1793 /*--- Helpers for XER flags.                               ---*/
   1794 /*------------------------------------------------------------*/
   1795 
   1796 static void putXER_SO ( IRExpr* e )
   1797 {
   1798    IRExpr* so;
   1799    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1800    so = binop(Iop_And8, e, mkU8(1));
   1801    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   1802 }
   1803 
   1804 static void putXER_OV ( IRExpr* e )
   1805 {
   1806    IRExpr* ov;
   1807    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1808    ov = binop(Iop_And8, e, mkU8(1));
   1809    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   1810 }
   1811 
   1812 static void putXER_CA ( IRExpr* e )
   1813 {
   1814    IRExpr* ca;
   1815    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1816    ca = binop(Iop_And8, e, mkU8(1));
   1817    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   1818 }
   1819 
   1820 static void putXER_BC ( IRExpr* e )
   1821 {
   1822    IRExpr* bc;
   1823    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1824    bc = binop(Iop_And8, e, mkU8(0x7F));
   1825    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   1826 }
   1827 
   1828 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   1829 {
   1830    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   1831 }
   1832 
   1833 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   1834 {
   1835    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   1836 }
   1837 
   1838 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   1839 {
   1840    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   1841 }
   1842 
   1843 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   1844 {
   1845    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   1846 }
   1847 
   1848 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   1849 {
   1850    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   1851    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   1852 }
   1853 
   1854 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   1855 {
   1856    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1857 }
   1858 
   1859 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   1860 {
   1861    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1862    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   1863 }
   1864 
   1865 
   1866 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   1867    %XER.SO accordingly. */
   1868 
   1869 static void set_XER_OV_32( UInt op, IRExpr* res,
   1870                            IRExpr* argL, IRExpr* argR )
   1871 {
   1872    IRTemp  t64;
   1873    IRExpr* xer_ov;
   1874    vassert(op < PPCG_FLAG_OP_NUMBER);
   1875    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   1876    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   1877    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   1878 
   1879 #  define INT32_MIN 0x80000000
   1880 
   1881 #  define XOR2(_aa,_bb) \
   1882       binop(Iop_Xor32,(_aa),(_bb))
   1883 
   1884 #  define XOR3(_cc,_dd,_ee) \
   1885       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   1886 
   1887 #  define AND3(_ff,_gg,_hh) \
   1888       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   1889 
   1890 #define NOT(_jj) \
   1891       unop(Iop_Not32, (_jj))
   1892 
   1893    switch (op) {
   1894    case /* 0  */ PPCG_FLAG_OP_ADD:
   1895    case /* 1  */ PPCG_FLAG_OP_ADDE:
   1896       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   1897       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   1898       xer_ov
   1899          = AND3( XOR3(argL,argR,mkU32(-1)),
   1900                  XOR2(argL,res),
   1901                  mkU32(INT32_MIN) );
   1902       /* xer_ov can only be 0 or 1<<31 */
   1903       xer_ov
   1904          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1905       break;
   1906 
   1907    case /* 2  */ PPCG_FLAG_OP_DIVW:
   1908       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   1909       xer_ov
   1910          = mkOR1(
   1911               mkAND1(
   1912                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   1913                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   1914               ),
   1915               binop(Iop_CmpEQ32, argR, mkU32(0) )
   1916            );
   1917       xer_ov
   1918          = unop(Iop_1Uto32, xer_ov);
   1919       break;
   1920 
   1921    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   1922       /* argR == 0 */
   1923       xer_ov
   1924          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   1925       break;
   1926 
   1927    case /* 4  */ PPCG_FLAG_OP_MULLW:
   1928       /* OV true if result can't be represented in 32 bits
   1929          i.e sHi != sign extension of sLo */
   1930       t64 = newTemp(Ity_I64);
   1931       assign( t64, binop(Iop_MullS32, argL, argR) );
   1932       xer_ov
   1933          = binop( Iop_CmpNE32,
   1934                   unop(Iop_64HIto32, mkexpr(t64)),
   1935                   binop( Iop_Sar32,
   1936                          unop(Iop_64to32, mkexpr(t64)),
   1937                          mkU8(31))
   1938                   );
   1939       xer_ov
   1940          = unop(Iop_1Uto32, xer_ov);
   1941       break;
   1942 
   1943    case /* 5  */ PPCG_FLAG_OP_NEG:
   1944       /* argL == INT32_MIN */
   1945       xer_ov
   1946          = unop( Iop_1Uto32,
   1947                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   1948       break;
   1949 
   1950    case /* 6  */ PPCG_FLAG_OP_SUBF:
   1951    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   1952    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   1953       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   1954       xer_ov
   1955          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   1956                  XOR2(NOT(argL),res),
   1957                  mkU32(INT32_MIN) );
   1958       /* xer_ov can only be 0 or 1<<31 */
   1959       xer_ov
   1960          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1961       break;
   1962 
   1963    case PPCG_FLAG_OP_DIVWEU:
   1964       xer_ov
   1965                = binop( Iop_Or32,
   1966                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   1967                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
   1968       break;
   1969 
   1970    case PPCG_FLAG_OP_DIVWE:
   1971 
   1972       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
   1973        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
   1974        * an overflow is implied.
   1975        */
   1976       xer_ov = binop( Iop_Or32,
   1977                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   1978                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
   1979                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
   1980                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
   1981       break;
   1982 
   1983 
   1984 
   1985    default:
   1986       vex_printf("set_XER_OV: op = %u\n", op);
   1987       vpanic("set_XER_OV(ppc)");
   1988    }
   1989 
   1990    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   1991    putXER_OV( unop(Iop_32to8, xer_ov) );
   1992 
   1993    /* Update the summary overflow */
   1994    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   1995 
   1996 #  undef INT32_MIN
   1997 #  undef AND3
   1998 #  undef XOR3
   1999 #  undef XOR2
   2000 #  undef NOT
   2001 }
   2002 
   2003 static void set_XER_OV_64( UInt op, IRExpr* res,
   2004                            IRExpr* argL, IRExpr* argR )
   2005 {
   2006    IRExpr* xer_ov;
   2007    vassert(op < PPCG_FLAG_OP_NUMBER);
   2008    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   2009    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   2010    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   2011 
   2012 #  define INT64_MIN 0x8000000000000000ULL
   2013 
   2014 #  define XOR2(_aa,_bb) \
   2015       binop(Iop_Xor64,(_aa),(_bb))
   2016 
   2017 #  define XOR3(_cc,_dd,_ee) \
   2018       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   2019 
   2020 #  define AND3(_ff,_gg,_hh) \
   2021       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   2022 
   2023 #define NOT(_jj) \
   2024       unop(Iop_Not64, (_jj))
   2025 
   2026    switch (op) {
   2027    case /* 0  */ PPCG_FLAG_OP_ADD:
   2028    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2029       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   2030       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2031       xer_ov
   2032          = AND3( XOR3(argL,argR,mkU64(-1)),
   2033                  XOR2(argL,res),
   2034                  mkU64(INT64_MIN) );
   2035       /* xer_ov can only be 0 or 1<<63 */
   2036       xer_ov
   2037          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2038       break;
   2039 
   2040    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2041       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   2042       xer_ov
   2043          = mkOR1(
   2044               mkAND1(
   2045                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   2046                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   2047               ),
   2048               binop(Iop_CmpEQ64, argR, mkU64(0) )
   2049            );
   2050       break;
   2051 
   2052    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2053       /* argR == 0 */
   2054       xer_ov
   2055          = binop(Iop_CmpEQ64, argR, mkU64(0));
   2056       break;
   2057 
   2058    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   2059       /* OV true if result can't be represented in 64 bits
   2060          i.e sHi != sign extension of sLo */
   2061       xer_ov
   2062          = binop( Iop_CmpNE32,
   2063                   unop(Iop_64HIto32, res),
   2064                   binop( Iop_Sar32,
   2065                          unop(Iop_64to32, res),
   2066                          mkU8(31))
   2067                   );
   2068       break;
   2069    }
   2070 
   2071    case /* 5  */ PPCG_FLAG_OP_NEG:
   2072       /* argL == INT64_MIN */
   2073       xer_ov
   2074          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   2075       break;
   2076 
   2077    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2078    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2079    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2080       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   2081       xer_ov
   2082          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   2083                  XOR2(NOT(argL),res),
   2084                  mkU64(INT64_MIN) );
   2085       /* xer_ov can only be 0 or 1<<63 */
   2086       xer_ov
   2087          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2088       break;
   2089 
   2090    case PPCG_FLAG_OP_DIVDE:
   2091 
   2092       /* If argR == 0, we must set the OV bit.  But there's another condition
   2093        * where we can get overflow set for divde . . . when the
   2094        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
   2095        * both dividend and divisor are non-zero, it implies an overflow.
   2096        */
   2097       xer_ov
   2098                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2099                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
   2100                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
   2101                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
   2102       break;
   2103 
   2104    case PPCG_FLAG_OP_DIVDEU:
   2105      /* If argR == 0 or if argL >= argR, set OV. */
   2106      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2107                          binop( Iop_CmpLE64U, argR, argL ) );
   2108      break;
   2109 
   2110    default:
   2111       vex_printf("set_XER_OV: op = %u\n", op);
   2112       vpanic("set_XER_OV(ppc64)");
   2113    }
   2114 
   2115    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2116    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   2117 
   2118    /* Update the summary overflow */
   2119    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2120 
   2121 #  undef INT64_MIN
   2122 #  undef AND3
   2123 #  undef XOR3
   2124 #  undef XOR2
   2125 #  undef NOT
   2126 }
   2127 
   2128 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   2129                          IRExpr* argL, IRExpr* argR )
   2130 {
   2131    if (ty == Ity_I32)
   2132       set_XER_OV_32( op, res, argL, argR );
   2133    else
   2134       set_XER_OV_64( op, res, argL, argR );
   2135 }
   2136 
   2137 
   2138 
   2139 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   2140    value being OLDCA.  Set %XER.CA accordingly. */
   2141 
   2142 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   2143                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2144 {
   2145    IRExpr* xer_ca;
   2146    vassert(op < PPCG_FLAG_OP_NUMBER);
   2147    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   2148    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   2149    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   2150    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   2151 
   2152    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2153       seems reasonable given that it's always generated by
   2154       getXER_CA32(), which masks it accordingly.  In any case it being
   2155       0 or 1 is an invariant of the ppc guest state representation;
   2156       if it has any other value, that invariant has been violated. */
   2157 
   2158    switch (op) {
   2159    case /* 0 */ PPCG_FLAG_OP_ADD:
   2160       /* res <u argL */
   2161       xer_ca
   2162          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   2163       break;
   2164 
   2165    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2166       /* res <u argL || (old_ca==1 && res==argL) */
   2167       xer_ca
   2168          = mkOR1(
   2169               binop(Iop_CmpLT32U, res, argL),
   2170               mkAND1(
   2171                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2172                  binop(Iop_CmpEQ32, res, argL)
   2173               )
   2174            );
   2175       xer_ca
   2176          = unop(Iop_1Uto32, xer_ca);
   2177       break;
   2178 
   2179    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2180       /* res <u argR || (old_ca==1 && res==argR) */
   2181       xer_ca
   2182          = mkOR1(
   2183               binop(Iop_CmpLT32U, res, argR),
   2184               mkAND1(
   2185                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2186                  binop(Iop_CmpEQ32, res, argR)
   2187               )
   2188            );
   2189       xer_ca
   2190          = unop(Iop_1Uto32, xer_ca);
   2191       break;
   2192 
   2193    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2194    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2195       /* res <=u argR */
   2196       xer_ca
   2197          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   2198       break;
   2199 
   2200    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2201       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2202          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2203          bit of argL. */
   2204       /* This term valid for shift amount < 32 only */
   2205       xer_ca
   2206          = binop(
   2207               Iop_And32,
   2208               binop(Iop_Sar32, argL, mkU8(31)),
   2209               binop( Iop_And32,
   2210                      argL,
   2211                      binop( Iop_Sub32,
   2212                             binop(Iop_Shl32, mkU32(1),
   2213                                              unop(Iop_32to8,argR)),
   2214                             mkU32(1) )
   2215                      )
   2216               );
   2217       xer_ca
   2218          = IRExpr_Mux0X(
   2219               /* shift amt > 31 ? */
   2220               unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
   2221               /* no -- be like srawi */
   2222               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
   2223               /* yes -- get sign bit of argL */
   2224               binop(Iop_Shr32, argL, mkU8(31))
   2225            );
   2226       break;
   2227 
   2228    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2229       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   2230          0.  Since the shift amount is known to be in the range
   2231          0 .. 31 inclusive the following seems viable:
   2232          xer.ca == 1 iff the following is nonzero:
   2233          (argL >>s 31)           -- either all 0s or all 1s
   2234          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2235       xer_ca
   2236          = binop(
   2237               Iop_And32,
   2238               binop(Iop_Sar32, argL, mkU8(31)),
   2239               binop( Iop_And32,
   2240                      argL,
   2241                      binop( Iop_Sub32,
   2242                             binop(Iop_Shl32, mkU32(1),
   2243                                              unop(Iop_32to8,argR)),
   2244                             mkU32(1) )
   2245                      )
   2246               );
   2247       xer_ca
   2248          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   2249       break;
   2250 
   2251    default:
   2252       vex_printf("set_XER_CA: op = %u\n", op);
   2253       vpanic("set_XER_CA(ppc)");
   2254    }
   2255 
   2256    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2257    putXER_CA( unop(Iop_32to8, xer_ca) );
   2258 }
   2259 
   2260 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   2261                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2262 {
   2263    IRExpr* xer_ca;
   2264    vassert(op < PPCG_FLAG_OP_NUMBER);
   2265    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   2266    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   2267    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   2268    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   2269 
   2270    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2271       seems reasonable given that it's always generated by
   2272       getXER_CA32(), which masks it accordingly.  In any case it being
   2273       0 or 1 is an invariant of the ppc guest state representation;
   2274       if it has any other value, that invariant has been violated. */
   2275 
   2276    switch (op) {
   2277    case /* 0 */ PPCG_FLAG_OP_ADD:
   2278       /* res <u argL */
   2279       xer_ca
   2280          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   2281       break;
   2282 
   2283    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2284       /* res <u argL || (old_ca==1 && res==argL) */
   2285       xer_ca
   2286          = mkOR1(
   2287               binop(Iop_CmpLT64U, res, argL),
   2288               mkAND1(
   2289                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2290                  binop(Iop_CmpEQ64, res, argL)
   2291                  )
   2292               );
   2293       xer_ca
   2294          = unop(Iop_1Uto32, xer_ca);
   2295       break;
   2296 
   2297    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2298       /* res <u argR || (old_ca==1 && res==argR) */
   2299       xer_ca
   2300          = mkOR1(
   2301               binop(Iop_CmpLT64U, res, argR),
   2302               mkAND1(
   2303                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2304                  binop(Iop_CmpEQ64, res, argR)
   2305               )
   2306            );
   2307       xer_ca
   2308          = unop(Iop_1Uto32, xer_ca);
   2309       break;
   2310 
   2311    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2312    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2313       /* res <=u argR */
   2314       xer_ca
   2315          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   2316       break;
   2317 
   2318 
   2319    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2320       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   2321          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2322          bit of argL. */
   2323          /* This term valid for shift amount < 31 only */
   2324 
   2325       xer_ca
   2326          = binop(
   2327               Iop_And64,
   2328               binop(Iop_Sar64, argL, mkU8(31)),
   2329               binop( Iop_And64,
   2330                      argL,
   2331                      binop( Iop_Sub64,
   2332                             binop(Iop_Shl64, mkU64(1),
   2333                                              unop(Iop_64to8,argR)),
   2334                             mkU64(1) )
   2335               )
   2336            );
   2337       xer_ca
   2338          = IRExpr_Mux0X(
   2339               /* shift amt > 31 ? */
   2340               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
   2341               /* no -- be like srawi */
   2342               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   2343               /* yes -- get sign bit of argL */
   2344               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   2345            );
   2346       break;
   2347 
   2348    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2349       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2350          Since the shift amount is known to be in the range 0 .. 31
   2351          inclusive the following seems viable:
   2352          xer.ca == 1 iff the following is nonzero:
   2353          (argL >>s 31)           -- either all 0s or all 1s
   2354          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2355 
   2356       xer_ca
   2357          = binop(
   2358               Iop_And64,
   2359               binop(Iop_Sar64, argL, mkU8(31)),
   2360               binop( Iop_And64,
   2361                      argL,
   2362                      binop( Iop_Sub64,
   2363                             binop(Iop_Shl64, mkU64(1),
   2364                                              unop(Iop_64to8,argR)),
   2365                             mkU64(1) )
   2366               )
   2367            );
   2368       xer_ca
   2369          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2370       break;
   2371 
   2372 
   2373    case /* 12 */ PPCG_FLAG_OP_SRAD:
   2374       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2375          If it is <= 63, behave like SRADI; else XER.CA is the sign
   2376          bit of argL. */
   2377          /* This term valid for shift amount < 63 only */
   2378 
   2379       xer_ca
   2380          = binop(
   2381               Iop_And64,
   2382               binop(Iop_Sar64, argL, mkU8(63)),
   2383               binop( Iop_And64,
   2384                      argL,
   2385                      binop( Iop_Sub64,
   2386                             binop(Iop_Shl64, mkU64(1),
   2387                                              unop(Iop_64to8,argR)),
   2388                             mkU64(1) )
   2389               )
   2390            );
   2391       xer_ca
   2392          = IRExpr_Mux0X(
   2393               /* shift amt > 63 ? */
   2394               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
   2395               /* no -- be like sradi */
   2396               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   2397               /* yes -- get sign bit of argL */
   2398               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   2399            );
   2400       break;
   2401 
   2402 
   2403    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2404       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2405          Since the shift amount is known to be in the range 0 .. 63
   2406          inclusive, the following seems viable:
   2407          xer.ca == 1 iff the following is nonzero:
   2408          (argL >>s 63)           -- either all 0s or all 1s
   2409          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2410 
   2411       xer_ca
   2412          = binop(
   2413               Iop_And64,
   2414               binop(Iop_Sar64, argL, mkU8(63)),
   2415               binop( Iop_And64,
   2416                      argL,
   2417                      binop( Iop_Sub64,
   2418                             binop(Iop_Shl64, mkU64(1),
   2419                                              unop(Iop_64to8,argR)),
   2420                             mkU64(1) )
   2421               )
   2422            );
   2423       xer_ca
   2424          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2425       break;
   2426 
   2427    default:
   2428       vex_printf("set_XER_CA: op = %u\n", op);
   2429       vpanic("set_XER_CA(ppc64)");
   2430    }
   2431 
   2432    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2433    putXER_CA( unop(Iop_32to8, xer_ca) );
   2434 }
   2435 
   2436 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2437                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2438 {
   2439    if (ty == Ity_I32)
   2440       set_XER_CA_32( op, res, argL, argR, oldca );
   2441    else
   2442       set_XER_CA_64( op, res, argL, argR, oldca );
   2443 }
   2444 
   2445 
   2446 
   2447 /*------------------------------------------------------------*/
   2448 /*--- Read/write to guest-state                           --- */
   2449 /*------------------------------------------------------------*/
   2450 
   2451 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2452 {
   2453    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2454    switch (reg) {
   2455    case PPC_GST_SPRG3_RO:
   2456       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2457 
   2458    case PPC_GST_CIA:
   2459       return IRExpr_Get( OFFB_CIA, ty );
   2460 
   2461    case PPC_GST_LR:
   2462       return IRExpr_Get( OFFB_LR, ty );
   2463 
   2464    case PPC_GST_CTR:
   2465       return IRExpr_Get( OFFB_CTR, ty );
   2466 
   2467    case PPC_GST_VRSAVE:
   2468       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2469 
   2470    case PPC_GST_VSCR:
   2471       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2472                               mkU32(MASK_VSCR_VALID));
   2473 
   2474    case PPC_GST_CR: {
   2475       /* Synthesise the entire CR into a single word.  Expensive. */
   2476 #     define FIELD(_n)                                               \
   2477          binop(Iop_Shl32,                                            \
   2478                unop(Iop_8Uto32,                                      \
   2479                     binop(Iop_Or8,                                   \
   2480                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2481                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2482                     )                                                \
   2483                ),                                                    \
   2484                mkU8(4 * (7-(_n)))                                    \
   2485          )
   2486       return binop(Iop_Or32,
   2487                    binop(Iop_Or32,
   2488                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2489                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2490                          ),
   2491                    binop(Iop_Or32,
   2492                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2493                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2494                          )
   2495                    );
   2496 #     undef FIELD
   2497    }
   2498 
   2499    case PPC_GST_XER:
   2500       return binop(Iop_Or32,
   2501                    binop(Iop_Or32,
   2502                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2503                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2504                    binop(Iop_Or32,
   2505                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2506                          getXER_BC32()));
   2507 
   2508    default:
   2509       vex_printf("getGST(ppc): reg = %u", reg);
   2510       vpanic("getGST(ppc)");
   2511    }
   2512 }
   2513 
   2514 /* Get a masked word from the given reg */
   2515 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2516 {
   2517    IRTemp val = newTemp(Ity_I32);
   2518    vassert( reg < PPC_GST_MAX );
   2519 
   2520    switch (reg) {
   2521 
   2522    case PPC_GST_FPSCR: {
   2523       /* Vex-generated code expects the FPSCR to be set as follows:
   2524          all exceptions masked, round-to-nearest.
   2525          This corresponds to a FPSCR value of 0x0. */
   2526 
   2527       /* In the lower 32 bits of FPSCR, we're only keeping track of
   2528        * the binary floating point rounding mode, so if the mask isn't
   2529        * asking for this, just return 0x0.
   2530        */
   2531       if (mask & MASK_FPSCR_RN) {
   2532          assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
   2533       } else {
   2534          assign( val, mkU32(0x0) );
   2535       }
   2536       break;
   2537    }
   2538 
   2539    default:
   2540       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2541       vpanic("getGST_masked(ppc)");
   2542    }
   2543 
   2544    if (mask != 0xFFFFFFFF) {
   2545       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2546    } else {
   2547       return mkexpr(val);
   2548    }
   2549 }
   2550 
   2551 /* Get a masked word from the given reg */
   2552 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
   2553    IRExpr * val;
   2554    vassert( reg < PPC_GST_MAX );
   2555 
   2556    switch (reg) {
   2557 
   2558    case PPC_GST_FPSCR: {
   2559       /* In the upper 32 bits of FPSCR, we're only keeping track
   2560        * of the decimal floating point rounding mode, so if the mask
   2561        * isn't asking for this, just return 0x0.
   2562        */
   2563       if (mask & MASK_FPSCR_DRN) {
   2564          val = binop( Iop_And32,
   2565                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
   2566                       unop( Iop_64HIto32, mkU64( mask ) ) );
   2567       } else {
   2568          val = mkU32( 0x0ULL );
   2569       }
   2570       break;
   2571    }
   2572 
   2573    default:
   2574       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
   2575       vpanic( "getGST_masked_upper(ppc)" );
   2576    }
   2577    return val;
   2578 }
   2579 
   2580 
   2581 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2582    and return it at the bottom of an I32; the top 27 bits are
   2583    guaranteed to be zero. */
   2584 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2585 {
   2586    UInt shft, mask;
   2587 
   2588    vassert( fld < 8 );
   2589    vassert( reg < PPC_GST_MAX );
   2590 
   2591    shft = 4*(7-fld);
   2592    mask = 0xF<<shft;
   2593 
   2594    switch (reg) {
   2595    case PPC_GST_XER:
   2596       vassert(fld ==7);
   2597       return binop(Iop_Or32,
   2598                    binop(Iop_Or32,
   2599                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2600                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2601                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2602       break;
   2603 
   2604    default:
   2605       if (shft == 0)
   2606          return getGST_masked( reg, mask );
   2607       else
   2608          return binop(Iop_Shr32,
   2609                       getGST_masked( reg, mask ),
   2610                       mkU8(toUChar( shft )));
   2611    }
   2612 }
   2613 
   2614 static void putGST ( PPC_GST reg, IRExpr* src )
   2615 {
   2616    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2617    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2618    vassert( reg < PPC_GST_MAX );
   2619    switch (reg) {
   2620    case PPC_GST_IP_AT_SYSCALL:
   2621       vassert( ty_src == ty );
   2622       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2623       break;
   2624    case PPC_GST_CIA:
   2625       vassert( ty_src == ty );
   2626       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2627       break;
   2628    case PPC_GST_LR:
   2629       vassert( ty_src == ty );
   2630       stmt( IRStmt_Put( OFFB_LR, src ) );
   2631       break;
   2632    case PPC_GST_CTR:
   2633       vassert( ty_src == ty );
   2634       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2635       break;
   2636    case PPC_GST_VRSAVE:
   2637       vassert( ty_src == Ity_I32 );
   2638       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2639       break;
   2640    case PPC_GST_VSCR:
   2641       vassert( ty_src == Ity_I32 );
   2642       stmt( IRStmt_Put( OFFB_VSCR,
   2643                         binop(Iop_And32, src,
   2644                               mkU32(MASK_VSCR_VALID)) ) );
   2645       break;
   2646    case PPC_GST_XER:
   2647       vassert( ty_src == Ity_I32 );
   2648       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2649       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2650       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2651       putXER_BC( unop(Iop_32to8, src) );
   2652       break;
   2653 
   2654    case PPC_GST_EMWARN:
   2655       vassert( ty_src == Ity_I32 );
   2656       stmt( IRStmt_Put( OFFB_EMWARN,src) );
   2657       break;
   2658 
   2659    case PPC_GST_TISTART:
   2660       vassert( ty_src == ty );
   2661       stmt( IRStmt_Put( OFFB_TISTART, src) );
   2662       break;
   2663 
   2664    case PPC_GST_TILEN:
   2665       vassert( ty_src == ty );
   2666       stmt( IRStmt_Put( OFFB_TILEN, src) );
   2667       break;
   2668 
   2669    default:
   2670       vex_printf("putGST(ppc): reg = %u", reg);
   2671       vpanic("putGST(ppc)");
   2672    }
   2673 }
   2674 
   2675 /* Write masked src to the given reg */
   2676 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
   2677 {
   2678    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2679    vassert( reg < PPC_GST_MAX );
   2680    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
   2681 
   2682    switch (reg) {
   2683    case PPC_GST_FPSCR: {
   2684       /* Allow writes to either binary or decimal floating point
   2685        * Rounding Mode
   2686        */
   2687       if (mask & MASK_FPSCR_RN) {
   2688          stmt( IRStmt_Put( OFFB_FPROUND,
   2689                            unop( Iop_32to8,
   2690                                  binop( Iop_And32,
   2691                                         unop( Iop_64to32, src ),
   2692                                         mkU32( MASK_FPSCR_RN & mask ) ) ) ) );
   2693       } else if (mask & MASK_FPSCR_DRN) {
   2694          stmt( IRStmt_Put( OFFB_DFPROUND,
   2695                            unop( Iop_32to8,
   2696                                  binop( Iop_And32,
   2697                                         unop( Iop_64HIto32, src ),
   2698                                         mkU32( ( MASK_FPSCR_DRN & mask )
   2699                                                  >> 32 ) ) ) ) );
   2700       }
   2701 
   2702       /* Give EmWarn for attempted writes to:
   2703          - Exception Controls
   2704          - Non-IEEE Mode
   2705       */
   2706       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   2707          VexEmWarn ew = EmWarn_PPCexns;
   2708 
   2709          /* If any of the src::exception_control bits are actually set,
   2710             side-exit to the next insn, reporting the warning,
   2711             so that Valgrind's dispatcher sees the warning. */
   2712          putGST( PPC_GST_EMWARN, mkU32(ew) );
   2713          stmt(
   2714             IRStmt_Exit(
   2715                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
   2716                Ijk_EmWarn,
   2717                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   2718       }
   2719 
   2720       /* Ignore all other writes */
   2721       break;
   2722    }
   2723 
   2724    default:
   2725       vex_printf("putGST_masked(ppc): reg = %u", reg);
   2726       vpanic("putGST_masked(ppc)");
   2727    }
   2728 }
   2729 
   2730 /* Write the least significant nibble of src to the specified
   2731    REG[FLD] (as per IBM/hardware notation). */
   2732 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   2733 {
   2734    UInt shft;
   2735    ULong mask;
   2736 
   2737    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2738    vassert( fld < 16 );
   2739    vassert( reg < PPC_GST_MAX );
   2740 
   2741    if (fld < 8)
   2742       shft = 4*(7-fld);
   2743    else
   2744       shft = 4*(15-fld);
   2745    mask = 0xF<<shft;
   2746 
   2747    switch (reg) {
   2748    case PPC_GST_CR:
   2749       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   2750       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   2751       break;
   2752 
   2753    default:
   2754       {
   2755          IRExpr * src64 = unop( Iop_32Uto64, src );
   2756 
   2757          if (shft == 0) {
   2758             putGST_masked( reg, src64, mask );
   2759          } else {
   2760             putGST_masked( reg,
   2761                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
   2762                            mask );
   2763          }
   2764       }
   2765    }
   2766 }
   2767 
   2768 /*------------------------------------------------------------*/
   2769 /* Helpers for VSX instructions that do floating point
   2770  * operations and need to determine if a src contains a
   2771  * special FP value.
   2772  *
   2773  *------------------------------------------------------------*/
   2774 
   2775 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
   2776 #define FP_FRAC_PART(x) binop( Iop_And64, \
   2777                                mkexpr( x ), \
   2778                                mkU64( NONZERO_FRAC_MASK ) )
   2779 
   2780 // Returns exponent part of a single precision floating point as I32
   2781 static IRExpr * fp_exp_part_sp(IRTemp src)
   2782 {
   2783    return binop( Iop_And32,
   2784                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   2785                  mkU32( 0xff ) );
   2786 }
   2787 
   2788 // Returns exponent part of floating point as I32
   2789 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
   2790 {
   2791    IRExpr * exp;
   2792    if (sp)
   2793       return fp_exp_part_sp(src);
   2794 
   2795    if (!mode64)
   2796       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
   2797                                                       mkexpr( src ) ),
   2798                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
   2799    else
   2800       exp = unop( Iop_64to32,
   2801                   binop( Iop_And64,
   2802                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
   2803                          mkU64( 0x7ff ) ) );
   2804    return exp;
   2805 }
   2806 
   2807 static IRExpr * is_Inf_sp(IRTemp src)
   2808 {
   2809    IRTemp frac_part = newTemp(Ity_I32);
   2810    IRExpr * Inf_exp;
   2811 
   2812    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
   2813    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
   2814    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
   2815 }
   2816 
   2817 
   2818 // Infinity: exp = 7ff and fraction is zero; s = 0/1
   2819 static IRExpr * is_Inf(IRTemp src, Bool sp)
   2820 {
   2821    IRExpr * Inf_exp, * hi32, * low32;
   2822    IRTemp frac_part;
   2823 
   2824    if (sp)
   2825       return is_Inf_sp(src);
   2826 
   2827    frac_part = newTemp(Ity_I64);
   2828    assign( frac_part, FP_FRAC_PART(src) );
   2829    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
   2830    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   2831    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   2832    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   2833                                   mkU32( 0 ) ) );
   2834 }
   2835 
   2836 static IRExpr * is_Zero_sp(IRTemp src)
   2837 {
   2838    IRTemp sign_less_part = newTemp(Ity_I32);
   2839    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
   2840    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
   2841 }
   2842 
   2843 // Zero: exp is zero and fraction is zero; s = 0/1
   2844 static IRExpr * is_Zero(IRTemp src, Bool sp)
   2845 {
   2846    IRExpr * hi32, * low32;
   2847    IRTemp sign_less_part;
   2848    if (sp)
   2849       return is_Zero_sp(src);
   2850 
   2851    sign_less_part = newTemp(Ity_I64);
   2852 
   2853    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
   2854    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
   2855    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
   2856    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   2857                               mkU32( 0 ) );
   2858 }
   2859 
   2860 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
   2861  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
   2862  *  This function returns an IRExpr value of '1' for any type of NaN.
   2863  */
   2864 static IRExpr * is_NaN(IRTemp src)
   2865 {
   2866    IRExpr * NaN_exp, * hi32, * low32;
   2867    IRTemp frac_part = newTemp(Ity_I64);
   2868 
   2869    assign( frac_part, FP_FRAC_PART(src) );
   2870    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   2871    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   2872    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
   2873                     mkU32( 0x7ff ) );
   2874 
   2875    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   2876                                                mkU32( 0 ) ) );
   2877 }
   2878 
   2879 /* This function returns an IRExpr value of '1' for any type of NaN.
   2880  * The passed 'src' argument is assumed to be Ity_I32.
   2881  */
   2882 static IRExpr * is_NaN_32(IRTemp src)
   2883 {
   2884 #define NONZERO_FRAC_MASK32 0x007fffffULL
   2885 #define FP_FRAC_PART32(x) binop( Iop_And32, \
   2886                                  mkexpr( x ), \
   2887                                  mkU32( NONZERO_FRAC_MASK32 ) )
   2888 
   2889    IRExpr * frac_part = FP_FRAC_PART32(src);
   2890    IRExpr * exp_part = binop( Iop_And32,
   2891                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   2892                               mkU32( 0x0ff ) );
   2893    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
   2894 
   2895    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
   2896 }
   2897 
   2898 /* This helper function performs the negation part of operations of the form:
   2899  *    "Negate Multiply-<op>"
   2900  *  where "<op>" is either "Add" or "Sub".
   2901  *
   2902  * This function takes one argument -- the floating point intermediate result (converted to
   2903  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
   2904  * the operation described above.
   2905  */
   2906 static IRTemp getNegatedResult(IRTemp intermediateResult)
   2907 {
   2908    ULong signbit_mask = 0x8000000000000000ULL;
   2909    IRTemp signbit_32 = newTemp(Ity_I32);
   2910    IRTemp resultantSignbit = newTemp(Ity_I1);
   2911    IRTemp negatedResult = newTemp(Ity_I64);
   2912    assign( signbit_32, binop( Iop_Shr32,
   2913                           unop( Iop_64HIto32,
   2914                                  binop( Iop_And64, mkexpr( intermediateResult ),
   2915                                         mkU64( signbit_mask ) ) ),
   2916                                  mkU8( 31 ) ) );
   2917    /* We negate the signbit if and only if the intermediate result from the
   2918     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   2919     */
   2920    assign( resultantSignbit,
   2921         unop( Iop_Not1,
   2922               binop( Iop_CmpEQ32,
   2923                      binop( Iop_Xor32,
   2924                             mkexpr( signbit_32 ),
   2925                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
   2926                      mkU32( 1 ) ) ) );
   2927 
   2928    assign( negatedResult,
   2929         binop( Iop_Or64,
   2930                binop( Iop_And64,
   2931                       mkexpr( intermediateResult ),
   2932                       mkU64( ~signbit_mask ) ),
   2933                binop( Iop_32HLto64,
   2934                       binop( Iop_Shl32,
   2935                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   2936                              mkU8( 31 ) ),
   2937                       mkU32( 0 ) ) ) );
   2938 
   2939    return negatedResult;
   2940 }
   2941 
   2942 /* This helper function performs the negation part of operations of the form:
   2943  *    "Negate Multiply-<op>"
   2944  *  where "<op>" is either "Add" or "Sub".
   2945  *
   2946  * This function takes one argument -- the floating point intermediate result (converted to
   2947  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
   2948  * the operation described above.
   2949  */
   2950 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
   2951 {
   2952    UInt signbit_mask = 0x80000000;
   2953    IRTemp signbit_32 = newTemp(Ity_I32);
   2954    IRTemp resultantSignbit = newTemp(Ity_I1);
   2955    IRTemp negatedResult = newTemp(Ity_I32);
   2956    assign( signbit_32, binop( Iop_Shr32,
   2957                                  binop( Iop_And32, mkexpr( intermediateResult ),
   2958                                         mkU32( signbit_mask ) ),
   2959                                  mkU8( 31 ) ) );
   2960    /* We negate the signbit if and only if the intermediate result from the
   2961     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   2962     */
   2963    assign( resultantSignbit,
   2964         unop( Iop_Not1,
   2965               binop( Iop_CmpEQ32,
   2966                      binop( Iop_Xor32,
   2967                             mkexpr( signbit_32 ),
   2968                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
   2969                      mkU32( 1 ) ) ) );
   2970 
   2971    assign( negatedResult,
   2972            binop( Iop_Or32,
   2973                   binop( Iop_And32,
   2974                          mkexpr( intermediateResult ),
   2975                          mkU32( ~signbit_mask ) ),
   2976                   binop( Iop_Shl32,
   2977                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   2978                          mkU8( 31 ) ) ) );
   2979 
   2980    return negatedResult;
   2981 }
   2982 
   2983 /*------------------------------------------------------------*/
   2984 /*--- Integer Instruction Translation                     --- */
   2985 /*------------------------------------------------------------*/
   2986 
   2987 /*
   2988   Integer Arithmetic Instructions
   2989 */
   2990 static Bool dis_int_arith ( UInt theInstr )
   2991 {
   2992    /* D-Form, XO-Form */
   2993    UChar opc1    = ifieldOPC(theInstr);
   2994    UChar rD_addr = ifieldRegDS(theInstr);
   2995    UChar rA_addr = ifieldRegA(theInstr);
   2996    UInt  uimm16  = ifieldUIMM16(theInstr);
   2997    UChar rB_addr = ifieldRegB(theInstr);
   2998    UChar flag_OE = ifieldBIT10(theInstr);
   2999    UInt  opc2    = ifieldOPClo9(theInstr);
   3000    UChar flag_rC = ifieldBIT0(theInstr);
   3001 
   3002    Long   simm16 = extend_s_16to64(uimm16);
   3003    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3004    IRTemp rA     = newTemp(ty);
   3005    IRTemp rB     = newTemp(ty);
   3006    IRTemp rD     = newTemp(ty);
   3007 
   3008    Bool do_rc = False;
   3009 
   3010    assign( rA, getIReg(rA_addr) );
   3011    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   3012 
   3013    switch (opc1) {
   3014    /* D-Form */
   3015    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   3016       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3017       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3018                          mkSzExtendS16(ty, uimm16) ) );
   3019       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3020                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3021                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3022       break;
   3023 
   3024    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   3025       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3026       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3027                          mkSzExtendS16(ty, uimm16) ) );
   3028       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3029                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3030                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3031       do_rc = True;  // Always record to CR
   3032       flag_rC = 1;
   3033       break;
   3034 
   3035    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   3036       // li rD,val   == addi rD,0,val
   3037       // la disp(rA) == addi rD,rA,disp
   3038       if ( rA_addr == 0 ) {
   3039          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   3040          assign( rD, mkSzExtendS16(ty, uimm16) );
   3041       } else {
   3042          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3043          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3044                             mkSzExtendS16(ty, uimm16) ) );
   3045       }
   3046       break;
   3047 
   3048    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   3049       // lis rD,val == addis rD,0,val
   3050       if ( rA_addr == 0 ) {
   3051          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   3052          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   3053       } else {
   3054          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
   3055          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3056                             mkSzExtendS32(ty, uimm16 << 16) ) );
   3057       }
   3058       break;
   3059 
   3060    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   3061       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3062       if (mode64)
   3063          assign( rD, unop(Iop_128to64,
   3064                           binop(Iop_MullS64, mkexpr(rA),
   3065                                 mkSzExtendS16(ty, uimm16))) );
   3066       else
   3067          assign( rD, unop(Iop_64to32,
   3068                           binop(Iop_MullS32, mkexpr(rA),
   3069                                 mkSzExtendS16(ty, uimm16))) );
   3070       break;
   3071 
   3072    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   3073       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3074       // rD = simm16 - rA
   3075       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3076                          mkSzExtendS16(ty, uimm16),
   3077                          mkexpr(rA)) );
   3078       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   3079                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3080                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3081       break;
   3082 
   3083    /* XO-Form */
   3084    case 0x1F:
   3085       do_rc = True;    // All below record to CR
   3086 
   3087       switch (opc2) {
   3088       case 0x10A: // add  (Add, PPC32 p347)
   3089          DIP("add%s%s r%u,r%u,r%u\n",
   3090              flag_OE ? "o" : "", flag_rC ? ".":"",
   3091              rD_addr, rA_addr, rB_addr);
   3092          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3093                             mkexpr(rA), mkexpr(rB) ) );
   3094          if (flag_OE) {
   3095             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3096                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3097          }
   3098          break;
   3099 
   3100       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   3101          DIP("addc%s%s r%u,r%u,r%u\n",
   3102              flag_OE ? "o" : "", flag_rC ? ".":"",
   3103              rD_addr, rA_addr, rB_addr);
   3104          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3105                             mkexpr(rA), mkexpr(rB)) );
   3106          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3107                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3108                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3109          if (flag_OE) {
   3110             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3111                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3112          }
   3113          break;
   3114 
   3115       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   3116          IRTemp old_xer_ca = newTemp(ty);
   3117          DIP("adde%s%s r%u,r%u,r%u\n",
   3118              flag_OE ? "o" : "", flag_rC ? ".":"",
   3119              rD_addr, rA_addr, rB_addr);
   3120          // rD = rA + rB + XER[CA]
   3121          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3122          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3123                             binop( mkSzOp(ty, Iop_Add8),
   3124                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3125          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3126                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3127                      mkexpr(old_xer_ca) );
   3128          if (flag_OE) {
   3129             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3130                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3131          }
   3132          break;
   3133       }
   3134 
   3135       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   3136          IRTemp old_xer_ca = newTemp(ty);
   3137          IRExpr *min_one;
   3138          if (rB_addr != 0) {
   3139             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   3140             return False;
   3141          }
   3142          DIP("addme%s%s r%u,r%u,r%u\n",
   3143              flag_OE ? "o" : "", flag_rC ? ".":"",
   3144              rD_addr, rA_addr, rB_addr);
   3145          // rD = rA + (-1) + XER[CA]
   3146          // => Just another form of adde
   3147          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3148          min_one = mkSzImm(ty, (Long)-1);
   3149          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3150                             binop( mkSzOp(ty, Iop_Add8),
   3151                                    min_one, mkexpr(old_xer_ca)) ));
   3152          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3153                      mkexpr(rD), mkexpr(rA), min_one,
   3154                      mkexpr(old_xer_ca) );
   3155          if (flag_OE) {
   3156             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3157                         mkexpr(rD), mkexpr(rA), min_one );
   3158          }
   3159          break;
   3160       }
   3161 
   3162       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   3163          IRTemp old_xer_ca = newTemp(ty);
   3164          if (rB_addr != 0) {
   3165             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   3166             return False;
   3167          }
   3168          DIP("addze%s%s r%u,r%u,r%u\n",
   3169              flag_OE ? "o" : "", flag_rC ? ".":"",
   3170              rD_addr, rA_addr, rB_addr);
   3171          // rD = rA + (0) + XER[CA]
   3172          // => Just another form of adde
   3173          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3174          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3175                             mkexpr(rA), mkexpr(old_xer_ca)) );
   3176          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3177                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3178                      mkexpr(old_xer_ca) );
   3179          if (flag_OE) {
   3180             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3181                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3182          }
   3183          break;
   3184       }
   3185 
   3186       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   3187          DIP("divw%s%s r%u,r%u,r%u\n",
   3188              flag_OE ? "o" : "", flag_rC ? ".":"",
   3189              rD_addr, rA_addr, rB_addr);
   3190          if (mode64) {
   3191             /* Note:
   3192                XER settings are mode independent, and reflect the
   3193                overflow of the low-order 32bit result
   3194                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3195             */
   3196             /* rD[hi32] are undefined: setting them to sign of lo32
   3197                 - makes set_CR0 happy */
   3198             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   3199             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   3200             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   3201                                                          divisor) ) );
   3202             if (flag_OE) {
   3203                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3204                            mkexpr(rD), dividend, divisor );
   3205             }
   3206          } else {
   3207             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   3208             if (flag_OE) {
   3209                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3210                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3211             }
   3212          }
   3213          /* Note:
   3214             if (0x8000_0000 / -1) or (x / 0)
   3215             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3216             => But _no_ exception raised. */
   3217          break;
   3218 
   3219       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   3220          DIP("divwu%s%s r%u,r%u,r%u\n",
   3221              flag_OE ? "o" : "", flag_rC ? ".":"",
   3222              rD_addr, rA_addr, rB_addr);
   3223          if (mode64) {
   3224             /* Note:
   3225                XER settings are mode independent, and reflect the
   3226                overflow of the low-order 32bit result
   3227                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3228             */
   3229             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   3230             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   3231             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   3232                                                          divisor) ) );
   3233             if (flag_OE) {
   3234                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3235                            mkexpr(rD), dividend, divisor );
   3236             }
   3237          } else {
   3238             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   3239             if (flag_OE) {
   3240                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3241                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3242             }
   3243          }
   3244          /* Note: ditto comment divw, for (x / 0) */
   3245          break;
   3246 
   3247       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   3248          if (flag_OE != 0) {
   3249             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   3250             return False;
   3251          }
   3252          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3253              rD_addr, rA_addr, rB_addr);
   3254          if (mode64) {
   3255             /* rD[hi32] are undefined: setting them to sign of lo32
   3256                 - makes set_CR0 happy */
   3257             assign( rD, binop(Iop_Sar64,
   3258                            binop(Iop_Mul64,
   3259                                  mk64lo32Sto64( mkexpr(rA) ),
   3260                                  mk64lo32Sto64( mkexpr(rB) )),
   3261                               mkU8(32)) );
   3262          } else {
   3263             assign( rD, unop(Iop_64HIto32,
   3264                              binop(Iop_MullS32,
   3265                                    mkexpr(rA), mkexpr(rB))) );
   3266          }
   3267          break;
   3268 
   3269       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   3270          if (flag_OE != 0) {
   3271             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   3272             return False;
   3273          }
   3274          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3275              rD_addr, rA_addr, rB_addr);
   3276          if (mode64) {
   3277             /* rD[hi32] are undefined: setting them to sign of lo32
   3278                 - makes set_CR0 happy */
   3279             assign( rD, binop(Iop_Sar64,
   3280                            binop(Iop_Mul64,
   3281                                  mk64lo32Uto64( mkexpr(rA) ),
   3282                                  mk64lo32Uto64( mkexpr(rB) ) ),
   3283                               mkU8(32)) );
   3284          } else {
   3285             assign( rD, unop(Iop_64HIto32,
   3286                              binop(Iop_MullU32,
   3287                                    mkexpr(rA), mkexpr(rB))) );
   3288          }
   3289          break;
   3290 
   3291       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   3292          DIP("mullw%s%s r%u,r%u,r%u\n",
   3293              flag_OE ? "o" : "", flag_rC ? ".":"",
   3294              rD_addr, rA_addr, rB_addr);
   3295          if (mode64) {
   3296             /* rD[hi32] are undefined: setting them to sign of lo32
   3297                 - set_XER_OV() and set_CR0() depend on this */
   3298             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   3299             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   3300             assign( rD, binop(Iop_MullS32, a, b) );
   3301             if (flag_OE) {
   3302                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3303                            mkexpr(rD),
   3304                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   3305             }
   3306          } else {
   3307             assign( rD, unop(Iop_64to32,
   3308                              binop(Iop_MullU32,
   3309                                    mkexpr(rA), mkexpr(rB))) );
   3310             if (flag_OE) {
   3311                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3312                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3313             }
   3314          }
   3315          break;
   3316 
   3317       case 0x068: // neg        (Negate, PPC32 p493)
   3318          if (rB_addr != 0) {
   3319             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   3320             return False;
   3321          }
   3322          DIP("neg%s%s r%u,r%u\n",
   3323              flag_OE ? "o" : "", flag_rC ? ".":"",
   3324              rD_addr, rA_addr);
   3325          // rD = (~rA) + 1
   3326          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3327                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   3328                             mkSzImm(ty, 1)) );
   3329          if (flag_OE) {
   3330             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   3331                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3332          }
   3333          break;
   3334 
   3335       case 0x028: // subf       (Subtract From, PPC32 p537)
   3336          DIP("subf%s%s r%u,r%u,r%u\n",
   3337              flag_OE ? "o" : "", flag_rC ? ".":"",
   3338              rD_addr, rA_addr, rB_addr);
   3339          // rD = rB - rA
   3340          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3341                             mkexpr(rB), mkexpr(rA)) );
   3342          if (flag_OE) {
   3343             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   3344                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3345          }
   3346          break;
   3347 
   3348       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   3349          DIP("subfc%s%s r%u,r%u,r%u\n",
   3350              flag_OE ? "o" : "", flag_rC ? ".":"",
   3351              rD_addr, rA_addr, rB_addr);
   3352          // rD = rB - rA
   3353          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3354                             mkexpr(rB), mkexpr(rA)) );
   3355          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   3356                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3357                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3358          if (flag_OE) {
   3359             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   3360                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3361          }
   3362          break;
   3363 
   3364       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   3365          IRTemp old_xer_ca = newTemp(ty);
   3366          DIP("subfe%s%s r%u,r%u,r%u\n",
   3367              flag_OE ? "o" : "", flag_rC ? ".":"",
   3368              rD_addr, rA_addr, rB_addr);
   3369          // rD = (log not)rA + rB + XER[CA]
   3370          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3371          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3372                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3373                             binop( mkSzOp(ty, Iop_Add8),
   3374                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3375          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3376                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3377                      mkexpr(old_xer_ca) );
   3378          if (flag_OE) {
   3379             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3380                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3381          }
   3382          break;
   3383       }
   3384 
   3385       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   3386          IRTemp old_xer_ca = newTemp(ty);
   3387          IRExpr *min_one;
   3388          if (rB_addr != 0) {
   3389             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   3390             return False;
   3391          }
   3392          DIP("subfme%s%s r%u,r%u\n",
   3393              flag_OE ? "o" : "", flag_rC ? ".":"",
   3394              rD_addr, rA_addr);
   3395          // rD = (log not)rA + (-1) + XER[CA]
   3396          // => Just another form of subfe
   3397          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3398          min_one = mkSzImm(ty, (Long)-1);
   3399          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3400                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3401                             binop( mkSzOp(ty, Iop_Add8),
   3402                                    min_one, mkexpr(old_xer_ca))) );
   3403          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3404                      mkexpr(rD), mkexpr(rA), min_one,
   3405                      mkexpr(old_xer_ca) );
   3406          if (flag_OE) {
   3407             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3408                         mkexpr(rD), mkexpr(rA), min_one );
   3409          }
   3410          break;
   3411       }
   3412 
   3413       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   3414          IRTemp old_xer_ca = newTemp(ty);
   3415          if (rB_addr != 0) {
   3416             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   3417             return False;
   3418          }
   3419          DIP("subfze%s%s r%u,r%u\n",
   3420              flag_OE ? "o" : "", flag_rC ? ".":"",
   3421              rD_addr, rA_addr);
   3422          // rD = (log not)rA + (0) + XER[CA]
   3423          // => Just another form of subfe
   3424          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3425          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3426                            unop( mkSzOp(ty, Iop_Not8),
   3427                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   3428          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3429                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3430                      mkexpr(old_xer_ca) );
   3431          if (flag_OE) {
   3432             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3433                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3434          }
   3435          break;
   3436       }
   3437 
   3438 
   3439       /* 64bit Arithmetic */
   3440       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   3441          if (flag_OE != 0) {
   3442             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   3443             return False;
   3444          }
   3445          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3446              rD_addr, rA_addr, rB_addr);
   3447          assign( rD, unop(Iop_128HIto64,
   3448                           binop(Iop_MullS64,
   3449                                 mkexpr(rA), mkexpr(rB))) );
   3450 
   3451          break;
   3452 
   3453       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   3454          if (flag_OE != 0) {
   3455             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   3456             return False;
   3457          }
   3458          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3459              rD_addr, rA_addr, rB_addr);
   3460          assign( rD, unop(Iop_128HIto64,
   3461                           binop(Iop_MullU64,
   3462                                 mkexpr(rA), mkexpr(rB))) );
   3463          break;
   3464 
   3465       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   3466          DIP("mulld%s%s r%u,r%u,r%u\n",
   3467              flag_OE ? "o" : "", flag_rC ? ".":"",
   3468              rD_addr, rA_addr, rB_addr);
   3469          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   3470          if (flag_OE) {
   3471             set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3472                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3473          }
   3474          break;
   3475 
   3476       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   3477          DIP("divd%s%s r%u,r%u,r%u\n",
   3478              flag_OE ? "o" : "", flag_rC ? ".":"",
   3479              rD_addr, rA_addr, rB_addr);
   3480          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   3481          if (flag_OE) {
   3482             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3483                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3484          }
   3485          break;
   3486          /* Note:
   3487             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   3488             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3489             => But _no_ exception raised. */
   3490 
   3491       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   3492          DIP("divdu%s%s r%u,r%u,r%u\n",
   3493              flag_OE ? "o" : "", flag_rC ? ".":"",
   3494              rD_addr, rA_addr, rB_addr);
   3495          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   3496          if (flag_OE) {
   3497             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3498                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3499          }
   3500          break;
   3501          /* Note: ditto comment divd, for (x / 0) */
   3502 
   3503       case 0x18B: // divweu (Divide Word Extended Unsigned)
   3504       {
   3505         /*
   3506          *  If (RA) >= (RB), or if an attempt is made to perform the division
   3507          *         <anything> / 0
   3508          * then the contents of register RD are undefined as are (if Rc=1) the contents of
   3509          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
   3510          * to 1.
   3511          */
   3512          IRTemp res = newTemp(Ity_I32);
   3513          IRExpr * dividend, * divisor;
   3514          DIP("divweu%s%s r%u,r%u,r%u\n",
   3515              flag_OE ? "o" : "", flag_rC ? ".":"",
   3516                                          rD_addr, rA_addr, rB_addr);
   3517          if (mode64) {
   3518             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3519             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3520             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3521             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3522          } else {
   3523             dividend = mkexpr( rA );
   3524             divisor =  mkexpr( rB );
   3525             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3526             assign( rD, mkexpr( res) );
   3527          }
   3528 
   3529          if (flag_OE) {
   3530             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
   3531                            mkexpr(res), dividend, divisor );
   3532          }
   3533          break;
   3534       }
   3535 
   3536       case 0x1AB: // divwe (Divide Word Extended)
   3537       {
   3538          /*
   3539           * If the quotient cannot be represented in 32 bits, or if an
   3540           * attempt is made to perform the division
   3541           *      <anything> / 0
   3542           * then the contents of register RD are undefined as are (if
   3543           * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3544           * Field 0. In these cases, if OE=1 then OV is set to 1.
   3545           */
   3546 
   3547          IRTemp res = newTemp(Ity_I32);
   3548          IRExpr * dividend, * divisor;
   3549          DIP("divwe%s%s r%u,r%u,r%u\n",
   3550              flag_OE ? "o" : "", flag_rC ? ".":"",
   3551                                          rD_addr, rA_addr, rB_addr);
   3552          if (mode64) {
   3553             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3554             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3555             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3556             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3557          } else {
   3558             dividend = mkexpr( rA );
   3559             divisor =  mkexpr( rB );
   3560             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3561             assign( rD, mkexpr( res) );
   3562          }
   3563 
   3564          if (flag_OE) {
   3565             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
   3566                            mkexpr(res), dividend, divisor );
   3567          }
   3568          break;
   3569       }
   3570 
   3571 
   3572       case 0x1A9: // divde (Divide Doubleword Extended)
   3573         /*
   3574          * If the quotient cannot be represented in 64 bits, or if an
   3575          * attempt is made to perform the division
   3576          *      <anything> / 0
   3577          * then the contents of register RD are undefined as are (if
   3578          * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3579          * Field 0. In these cases, if OE=1 then OV is set to 1.
   3580          */
   3581          DIP("divde%s%s r%u,r%u,r%u\n",
   3582              flag_OE ? "o" : "", flag_rC ? ".":"",
   3583              rD_addr, rA_addr, rB_addr);
   3584          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
   3585          if (flag_OE) {
   3586             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
   3587                            mkexpr( rA ), mkexpr( rB ) );
   3588          }
   3589          break;
   3590 
   3591       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
   3592         // Same CR and OV rules as given for divweu above
   3593         DIP("divdeu%s%s r%u,r%u,r%u\n",
   3594             flag_OE ? "o" : "", flag_rC ? ".":"",
   3595             rD_addr, rA_addr, rB_addr);
   3596         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
   3597         if (flag_OE) {
   3598            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
   3599                           mkexpr( rA ), mkexpr( rB ) );
   3600         }
   3601         break;
   3602 
   3603       default:
   3604          vex_printf("dis_int_arith(ppc)(opc2)\n");
   3605          return False;
   3606       }
   3607       break;
   3608 
   3609    default:
   3610       vex_printf("dis_int_arith(ppc)(opc1)\n");
   3611       return False;
   3612    }
   3613 
   3614    putIReg( rD_addr, mkexpr(rD) );
   3615 
   3616    if (do_rc && flag_rC) {
   3617       set_CR0( mkexpr(rD) );
   3618    }
   3619    return True;
   3620 }
   3621 
   3622 
   3623 
   3624 /*
   3625   Integer Compare Instructions
   3626 */
   3627 static Bool dis_int_cmp ( UInt theInstr )
   3628 {
   3629    /* D-Form, X-Form */
   3630    UChar opc1    = ifieldOPC(theInstr);
   3631    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   3632    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   3633    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   3634    UChar rA_addr = ifieldRegA(theInstr);
   3635    UInt  uimm16  = ifieldUIMM16(theInstr);
   3636    UChar rB_addr = ifieldRegB(theInstr);
   3637    UInt  opc2    = ifieldOPClo10(theInstr);
   3638    UChar b0      = ifieldBIT0(theInstr);
   3639 
   3640    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   3641    IRExpr *a = getIReg(rA_addr);
   3642    IRExpr *b;
   3643 
   3644    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   3645       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   3646       return False;
   3647    }
   3648 
   3649    if (b22 != 0) {
   3650       vex_printf("dis_int_cmp(ppc)(b22)\n");
   3651       return False;
   3652    }
   3653 
   3654    switch (opc1) {
   3655    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   3656       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   3657           (Int)extend_s_16to32(uimm16));
   3658       b = mkSzExtendS16( ty, uimm16 );
   3659       if (flag_L == 1) {
   3660          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3661       } else {
   3662          a = mkNarrowTo32( ty, a );
   3663          b = mkNarrowTo32( ty, b );
   3664          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   3665       }
   3666       putCR0( crfD, getXER_SO() );
   3667       break;
   3668 
   3669    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   3670       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   3671       b = mkSzImm( ty, uimm16 );
   3672       if (flag_L == 1) {
   3673          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3674       } else {
   3675          a = mkNarrowTo32( ty, a );
   3676          b = mkNarrowTo32( ty, b );
   3677          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3678       }
   3679       putCR0( crfD, getXER_SO() );
   3680       break;
   3681 
   3682    /* X Form */
   3683    case 0x1F:
   3684       if (b0 != 0) {
   3685          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   3686          return False;
   3687       }
   3688       b = getIReg(rB_addr);
   3689 
   3690       switch (opc2) {
   3691       case 0x000: // cmp (Compare, PPC32 p367)
   3692          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3693          /* Comparing a reg with itself produces a result which
   3694             doesn't depend on the contents of the reg.  Therefore
   3695             remove the false dependency, which has been known to cause
   3696             memcheck to produce false errors. */
   3697          if (rA_addr == rB_addr)
   3698             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3699                     ? mkU64(0)  : mkU32(0);
   3700          if (flag_L == 1) {
   3701             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3702          } else {
   3703             a = mkNarrowTo32( ty, a );
   3704             b = mkNarrowTo32( ty, b );
   3705             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   3706          }
   3707          putCR0( crfD, getXER_SO() );
   3708          break;
   3709 
   3710       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   3711          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3712          /* Comparing a reg with itself produces a result which
   3713             doesn't depend on the contents of the reg.  Therefore
   3714             remove the false dependency, which has been known to cause
   3715             memcheck to produce false errors. */
   3716          if (rA_addr == rB_addr)
   3717             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3718                     ? mkU64(0)  : mkU32(0);
   3719          if (flag_L == 1) {
   3720             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3721          } else {
   3722             a = mkNarrowTo32( ty, a );
   3723             b = mkNarrowTo32( ty, b );
   3724             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3725          }
   3726          putCR0( crfD, getXER_SO() );
   3727          break;
   3728 
   3729       default:
   3730          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   3731          return False;
   3732       }
   3733       break;
   3734 
   3735    default:
   3736       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   3737       return False;
   3738    }
   3739 
   3740    return True;
   3741 }
   3742 
   3743 
   3744 /*
   3745   Integer Logical Instructions
   3746 */
   3747 static Bool dis_int_logic ( UInt theInstr )
   3748 {
   3749    /* D-Form, X-Form */
   3750    UChar opc1    = ifieldOPC(theInstr);
   3751    UChar rS_addr = ifieldRegDS(theInstr);
   3752    UChar rA_addr = ifieldRegA(theInstr);
   3753    UInt  uimm16  = ifieldUIMM16(theInstr);
   3754    UChar rB_addr = ifieldRegB(theInstr);
   3755    UInt  opc2    = ifieldOPClo10(theInstr);
   3756    UChar flag_rC = ifieldBIT0(theInstr);
   3757 
   3758    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3759    IRTemp rS     = newTemp(ty);
   3760    IRTemp rA     = newTemp(ty);
   3761    IRTemp rB     = newTemp(ty);
   3762    IRExpr* irx;
   3763    Bool do_rc    = False;
   3764 
   3765    assign( rS, getIReg(rS_addr) );
   3766    assign( rB, getIReg(rB_addr) );
   3767 
   3768    switch (opc1) {
   3769    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   3770       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3771       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3772                          mkSzImm(ty, uimm16)) );
   3773       do_rc = True;  // Always record to CR
   3774       flag_rC = 1;
   3775       break;
   3776 
   3777    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   3778       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3779       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3780                          mkSzImm(ty, uimm16 << 16)) );
   3781       do_rc = True;  // Always record to CR
   3782       flag_rC = 1;
   3783       break;
   3784 
   3785    case 0x18: // ori (OR Immediate, PPC32 p497)
   3786       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3787       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3788                          mkSzImm(ty, uimm16)) );
   3789       break;
   3790 
   3791    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   3792       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3793       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3794                          mkSzImm(ty, uimm16 << 16)) );
   3795       break;
   3796 
   3797    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   3798       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3799       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3800                          mkSzImm(ty, uimm16)) );
   3801       break;
   3802 
   3803    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   3804       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3805       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3806                          mkSzImm(ty, uimm16 << 16)) );
   3807       break;
   3808 
   3809    /* X Form */
   3810    case 0x1F:
   3811       do_rc = True; // All below record to CR, except for where we return at case end.
   3812 
   3813       switch (opc2) {
   3814       case 0x01C: // and (AND, PPC32 p356)
   3815          DIP("and%s r%u,r%u,r%u\n",
   3816              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3817          assign(rA, binop( mkSzOp(ty, Iop_And8),
   3818                            mkexpr(rS), mkexpr(rB)));
   3819          break;
   3820 
   3821       case 0x03C: // andc (AND with Complement, PPC32 p357)
   3822          DIP("andc%s r%u,r%u,r%u\n",
   3823              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3824          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3825                            unop( mkSzOp(ty, Iop_Not8),
   3826                                  mkexpr(rB))));
   3827          break;
   3828 
   3829       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   3830          IRExpr* lo32;
   3831          if (rB_addr!=0) {
   3832             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   3833             return False;
   3834          }
   3835          DIP("cntlzw%s r%u,r%u\n",
   3836              flag_rC ? ".":"", rA_addr, rS_addr);
   3837 
   3838          // mode64: count in low word only
   3839          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   3840 
   3841          // Iop_Clz32 undefined for arg==0, so deal with that case:
   3842          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   3843          assign(rA, mkWidenFrom32(ty,
   3844                          IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3845                                        mkU32(32),
   3846                                        unop(Iop_Clz32, lo32)),
   3847                          False));
   3848 
   3849          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   3850          break;
   3851       }
   3852 
   3853       case 0x11C: // eqv (Equivalent, PPC32 p396)
   3854          DIP("eqv%s r%u,r%u,r%u\n",
   3855              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3856          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3857                            binop( mkSzOp(ty, Iop_Xor8),
   3858                                   mkexpr(rS), mkexpr(rB))) );
   3859          break;
   3860 
   3861       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   3862          if (rB_addr!=0) {
   3863             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   3864             return False;
   3865          }
   3866          DIP("extsb%s r%u,r%u\n",
   3867              flag_rC ? ".":"", rA_addr, rS_addr);
   3868          if (mode64)
   3869             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   3870          else
   3871             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   3872          break;
   3873 
   3874       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   3875          if (rB_addr!=0) {
   3876             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   3877             return False;
   3878          }
   3879          DIP("extsh%s r%u,r%u\n",
   3880              flag_rC ? ".":"", rA_addr, rS_addr);
   3881          if (mode64)
   3882             assign( rA, unop(Iop_16Sto64,
   3883                              unop(Iop_64to16, mkexpr(rS))) );
   3884          else
   3885             assign( rA, unop(Iop_16Sto32,
   3886                              unop(Iop_32to16, mkexpr(rS))) );
   3887          break;
   3888 
   3889       case 0x1DC: // nand (NAND, PPC32 p492)
   3890          DIP("nand%s r%u,r%u,r%u\n",
   3891              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3892          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3893                            binop( mkSzOp(ty, Iop_And8),
   3894                                   mkexpr(rS), mkexpr(rB))) );
   3895          break;
   3896 
   3897       case 0x07C: // nor (NOR, PPC32 p494)
   3898          DIP("nor%s r%u,r%u,r%u\n",
   3899              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3900          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3901                            binop( mkSzOp(ty, Iop_Or8),
   3902                                   mkexpr(rS), mkexpr(rB))) );
   3903          break;
   3904 
   3905       case 0x1BC: // or (OR, PPC32 p495)
   3906          if ((!flag_rC) && rS_addr == rB_addr) {
   3907             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   3908             assign( rA, mkexpr(rS) );
   3909          } else {
   3910             DIP("or%s r%u,r%u,r%u\n",
   3911                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3912             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   3913                                mkexpr(rS), mkexpr(rB)) );
   3914          }
   3915          break;
   3916 
   3917       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   3918          DIP("orc%s r%u,r%u,r%u\n",
   3919              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3920          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3921                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   3922          break;
   3923 
   3924       case 0x13C: // xor (XOR, PPC32 p549)
   3925          DIP("xor%s r%u,r%u,r%u\n",
   3926              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3927          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   3928                             mkexpr(rS), mkexpr(rB)) );
   3929          break;
   3930 
   3931 
   3932       /* 64bit Integer Logical Instructions */
   3933       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   3934          if (rB_addr!=0) {
   3935             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   3936             return False;
   3937          }
   3938          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   3939          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   3940          break;
   3941 
   3942       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   3943          if (rB_addr!=0) {
   3944             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   3945             return False;
   3946          }
   3947          DIP("cntlzd%s r%u,r%u\n",
   3948              flag_rC ? ".":"", rA_addr, rS_addr);
   3949          // Iop_Clz64 undefined for arg==0, so deal with that case:
   3950          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   3951          assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3952                                   mkU64(64),
   3953                                   unop(Iop_Clz64, mkexpr(rS)) ));
   3954          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   3955          break;
   3956 
   3957       case 0x1FC: // cmpb (Power6: compare bytes)
   3958          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   3959 
   3960          if (mode64)
   3961             assign( rA, unop( Iop_V128to64,
   3962                               binop( Iop_CmpEQ8x16,
   3963                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   3964                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   3965                                      )) );
   3966          else
   3967             assign( rA, unop( Iop_V128to32,
   3968                               binop( Iop_CmpEQ8x16,
   3969                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   3970                                      unop( Iop_32UtoV128, mkexpr(rB) )
   3971                                      )) );
   3972          break;
   3973 
   3974       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   3975          IRTemp frB = newTemp(Ity_F64);
   3976          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   3977 
   3978          assign( frB, getFReg(rB_addr));  // always F64
   3979          if (mode64)
   3980             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   3981          else
   3982             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   3983 
   3984          putIReg( rS_addr, mkexpr(rA));
   3985          return True;
   3986       }
   3987 
   3988       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   3989          IRTemp frA = newTemp(Ity_F64);
   3990          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   3991 
   3992          if (mode64)
   3993             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   3994          else
   3995             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   3996 
   3997          putFReg( rS_addr, mkexpr(frA));
   3998          return True;
   3999       }
   4000       case 0x1FA: // popcntd (population count doubleword
   4001       {
   4002     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
   4003     	  IRTemp result = gen_POPCOUNT(ty, rS, False);
   4004     	  putIReg( rA_addr, mkexpr(result) );
   4005     	  return True;
   4006       }
   4007       case 0x17A: // popcntw (Population Count Words)
   4008       {
   4009          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
   4010          if (mode64) {
   4011             IRTemp resultHi, resultLo;
   4012             IRTemp argLo = newTemp(Ity_I32);
   4013             IRTemp argHi = newTemp(Ity_I32);
   4014             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4015             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4016             resultLo = gen_POPCOUNT(Ity_I32, argLo, False);
   4017             resultHi = gen_POPCOUNT(Ity_I32, argHi, False);
   4018             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
   4019          } else {
   4020             IRTemp result = gen_POPCOUNT(ty, rS, False);
   4021             putIReg( rA_addr, mkexpr(result) );
   4022          }
   4023          return True;
   4024       }
   4025       case 0x7A: // popcntb (Population Count Byte)
   4026       {
   4027          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
   4028 
   4029          if (mode64) {
   4030             IRTemp resultHi, resultLo;
   4031             IRTemp argLo = newTemp(Ity_I32);
   4032             IRTemp argHi = newTemp(Ity_I32);
   4033             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4034             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4035             resultLo = gen_POPCOUNT(Ity_I32, argLo, True);
   4036             resultHi = gen_POPCOUNT(Ity_I32, argHi, True);
   4037             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
   4038                                     mkexpr(resultLo)));
   4039          } else {
   4040             IRTemp result = gen_POPCOUNT(ty, rS, True);
   4041             putIReg( rA_addr, mkexpr(result) );
   4042          }
   4043          return True;
   4044       }
   4045        case 0x0FC: // bpermd (Bit Permute Doubleword)
   4046        {
   4047           /* This is a lot of rigmarole to emulate bpermd like this, as it
   4048            * could be done much faster by implementing a call to the native
   4049            * instruction.  However, where possible I want to avoid using new
   4050            * native instructions so that we can use valgrind to emulate those
   4051            * instructions on older PPC64 hardware.
   4052            */
   4053  #define BPERMD_IDX_MASK 0x00000000000000FFULL
   4054  #define BPERMD_BIT_MASK 0x8000000000000000ULL
   4055           int i;
   4056           IRExpr * rS_expr = mkexpr(rS);
   4057           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
   4058           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4059           for (i = 0; i < 8; i++) {
   4060              IRTemp idx_tmp = newTemp( Ity_I64 );
   4061              IRTemp perm_bit = newTemp( Ity_I64 );
   4062              IRTemp idx = newTemp( Ity_I8 );
   4063              IRTemp idx_LT64 = newTemp( Ity_I1 );
   4064              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
   4065 
   4066              assign( idx_tmp,
   4067                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
   4068              assign( idx_LT64,
   4069                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
   4070              assign( idx,
   4071                            binop( Iop_And8,
   4072                                   unop( Iop_1Sto8,
   4073                                         mkexpr(idx_LT64) ),
   4074                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
   4075              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
   4076               * to determine which bit of rB to use for the perm bit, and then we shift
   4077               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
   4078               * to set the final perm bit.
   4079               */
   4080              assign( idx_LT64_ity64,
   4081                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
   4082              assign( perm_bit,
   4083                            binop( Iop_And64,
   4084                                   mkexpr( idx_LT64_ity64 ),
   4085                                   binop( Iop_Shr64,
   4086                                          binop( Iop_And64,
   4087                                                 mkU64( BPERMD_BIT_MASK ),
   4088                                                 binop( Iop_Shl64,
   4089                                                        mkexpr( rB ),
   4090                                                        mkexpr( idx ) ) ),
   4091                                          mkU8( 63 ) ) ) );
   4092              res = binop( Iop_Or64,
   4093                                 res,
   4094                                 binop( Iop_Shl64,
   4095                                        mkexpr( perm_bit ),
   4096                                        mkU8( i ) ) );
   4097              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
   4098           }
   4099           putIReg(rA_addr, res);
   4100           return True;
   4101        }
   4102 
   4103       default:
   4104          vex_printf("dis_int_logic(ppc)(opc2)\n");
   4105          return False;
   4106       }
   4107       break;
   4108 
   4109    default:
   4110       vex_printf("dis_int_logic(ppc)(opc1)\n");
   4111       return False;
   4112    }
   4113 
   4114    putIReg( rA_addr, mkexpr(rA) );
   4115 
   4116    if (do_rc && flag_rC) {
   4117       set_CR0( mkexpr(rA) );
   4118    }
   4119    return True;
   4120 }
   4121 
   4122 /*
   4123   Integer Parity Instructions
   4124 */
   4125 static Bool dis_int_parity ( UInt theInstr )
   4126 {
   4127    /* X-Form */
   4128    UChar opc1    = ifieldOPC(theInstr);
   4129    UChar rS_addr = ifieldRegDS(theInstr);
   4130    UChar rA_addr = ifieldRegA(theInstr);
   4131    UChar rB_addr = ifieldRegB(theInstr);
   4132    UInt  opc2    = ifieldOPClo10(theInstr);
   4133    UChar b0      = ifieldBIT0(theInstr);
   4134    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4135 
   4136    IRTemp rS     = newTemp(ty);
   4137    IRTemp rA     = newTemp(ty);
   4138    IRTemp iTot1  = newTemp(Ity_I32);
   4139    IRTemp iTot2  = newTemp(Ity_I32);
   4140    IRTemp iTot3  = newTemp(Ity_I32);
   4141    IRTemp iTot4  = newTemp(Ity_I32);
   4142    IRTemp iTot5  = newTemp(Ity_I32);
   4143    IRTemp iTot6  = newTemp(Ity_I32);
   4144    IRTemp iTot7  = newTemp(Ity_I32);
   4145    IRTemp iTot8  = newTemp(Ity_I32);
   4146    IRTemp rS1    = newTemp(ty);
   4147    IRTemp rS2    = newTemp(ty);
   4148    IRTemp rS3    = newTemp(ty);
   4149    IRTemp rS4    = newTemp(ty);
   4150    IRTemp rS5    = newTemp(ty);
   4151    IRTemp rS6    = newTemp(ty);
   4152    IRTemp rS7    = newTemp(ty);
   4153    IRTemp iHi    = newTemp(Ity_I32);
   4154    IRTemp iLo    = newTemp(Ity_I32);
   4155    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   4156    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   4157 
   4158    if (opc1 != 0x1f || rB_addr || b0) {
   4159       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   4160       return False;
   4161    }
   4162 
   4163    assign( rS, getIReg(rS_addr) );
   4164 
   4165    switch (opc2) {
   4166    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   4167       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   4168       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4169       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4170       assign( iTot2, binop(Iop_Add32,
   4171                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4172                            mkexpr(iTot1)) );
   4173       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4174       assign( iTot3, binop(Iop_Add32,
   4175                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4176                            mkexpr(iTot2)) );
   4177       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4178       assign( iTot4, binop(Iop_Add32,
   4179                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4180                            mkexpr(iTot3)) );
   4181       if (mode64) {
   4182          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4183          assign( iTot5, binop(Iop_Add32,
   4184                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   4185                               mkexpr(iTot4)) );
   4186          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4187          assign( iTot6, binop(Iop_Add32,
   4188                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4189                               mkexpr(iTot5)) );
   4190          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4191          assign( iTot7, binop(Iop_Add32,
   4192                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4193                               mkexpr(iTot6)) );
   4194          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   4195          assign( iTot8, binop(Iop_Add32,
   4196                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4197                               mkexpr(iTot7)) );
   4198          assign( rA, unop(Iop_32Uto64,
   4199                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   4200       } else
   4201          assign( rA, mkexpr(iTot4) );
   4202 
   4203       break;
   4204    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   4205       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4206       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4207       assign( iTot2, binop(Iop_Add32,
   4208                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4209                            mkexpr(iTot1)) );
   4210       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4211       assign( iTot3, binop(Iop_Add32,
   4212                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4213                            mkexpr(iTot2)) );
   4214       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4215       assign( iTot4, binop(Iop_Add32,
   4216                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4217                            mkexpr(iTot3)) );
   4218       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   4219 
   4220       if (mode64) {
   4221          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4222          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   4223          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4224          assign( iTot6, binop(Iop_Add32,
   4225                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4226                               mkexpr(iTot5)) );
   4227          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4228          assign( iTot7, binop(Iop_Add32,
   4229                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4230                               mkexpr(iTot6)) );
   4231          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   4232          assign( iTot8, binop(Iop_Add32,
   4233                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4234                               mkexpr(iTot7)) );
   4235          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   4236             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   4237       } else
   4238          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   4239       break;
   4240    default:
   4241       vex_printf("dis_int_parity(ppc)(opc2)\n");
   4242       return False;
   4243    }
   4244 
   4245    putIReg( rA_addr, mkexpr(rA) );
   4246 
   4247    return True;
   4248 }
   4249 
   4250 
   4251 /*
   4252   Integer Rotate Instructions
   4253 */
   4254 static Bool dis_int_rot ( UInt theInstr )
   4255 {
   4256    /* M-Form, MDS-Form */
   4257    UChar opc1    = ifieldOPC(theInstr);
   4258    UChar rS_addr = ifieldRegDS(theInstr);
   4259    UChar rA_addr = ifieldRegA(theInstr);
   4260    UChar rB_addr = ifieldRegB(theInstr);
   4261    UChar sh_imm  = rB_addr;
   4262    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   4263    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   4264    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   4265    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   4266    UChar b1      = ifieldBIT1(theInstr);
   4267    UChar flag_rC = ifieldBIT0(theInstr);
   4268 
   4269    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4270    IRTemp rS     = newTemp(ty);
   4271    IRTemp rA     = newTemp(ty);
   4272    IRTemp rB     = newTemp(ty);
   4273    IRTemp rot    = newTemp(ty);
   4274    IRExpr *r;
   4275    UInt   mask32;
   4276    ULong  mask64;
   4277 
   4278    assign( rS, getIReg(rS_addr) );
   4279    assign( rB, getIReg(rB_addr) );
   4280 
   4281    switch (opc1) {
   4282    case 0x14: {
   4283       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   4284       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4285           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4286       if (mode64) {
   4287          // tmp32 = (ROTL(rS_Lo32, Imm)
   4288          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   4289          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4290          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4291          r = unop(Iop_32Uto64, r);
   4292          assign( rot, binop(Iop_Or64, r,
   4293                             binop(Iop_Shl64, r, mkU8(32))) );
   4294          assign( rA,
   4295             binop(Iop_Or64,
   4296                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   4297                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   4298       }
   4299       else {
   4300          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   4301          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4302          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4303          assign( rA,
   4304             binop(Iop_Or32,
   4305                   binop(Iop_And32, mkU32(mask32), r),
   4306                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   4307       }
   4308       break;
   4309    }
   4310 
   4311    case 0x15: {
   4312       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   4313       vassert(MaskBeg < 32);
   4314       vassert(MaskEnd < 32);
   4315       vassert(sh_imm  < 32);
   4316 
   4317       if (mode64) {
   4318          IRTemp rTmp = newTemp(Ity_I64);
   4319          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4320          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4321              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4322          // tmp32 = (ROTL(rS_Lo32, Imm)
   4323          // rA = ((tmp32 || tmp32) & mask64)
   4324          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4325          r = unop(Iop_32Uto64, r);
   4326          assign( rTmp, r );
   4327          r = NULL;
   4328          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   4329                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   4330          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4331       }
   4332       else {
   4333          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   4334             /* Special-case the ,n,0,31-n form as that is just n-bit
   4335                shift left, PPC32 p501 */
   4336             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4337                 rA_addr, rS_addr, sh_imm);
   4338             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   4339          }
   4340          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   4341             /* Special-case the ,32-n,n,31 form as that is just n-bit
   4342                unsigned shift right, PPC32 p501 */
   4343             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4344                 rA_addr, rS_addr, MaskBeg);
   4345             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   4346          }
   4347          else {
   4348             /* General case. */
   4349             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4350             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4351                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4352             // rA = ROTL(rS, Imm) & mask
   4353             assign( rA, binop(Iop_And32,
   4354                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   4355                               mkU32(mask32)) );
   4356          }
   4357       }
   4358       break;
   4359    }
   4360 
   4361    case 0x17: {
   4362       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   4363       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   4364           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   4365       if (mode64) {
   4366          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4367          /* weird insn alert!
   4368             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   4369             rA = ((tmp32 || tmp32) & mask64)
   4370          */
   4371          // note, ROTL does the masking, so we don't do it here
   4372          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   4373                    unop(Iop_64to8, mkexpr(rB)) );
   4374          r = unop(Iop_32Uto64, r);
   4375          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   4376          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4377       } else {
   4378          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4379          // rA = ROTL(rS, rB[0-4]) & mask
   4380          // note, ROTL does the masking, so we don't do it here
   4381          assign( rA, binop(Iop_And32,
   4382                            ROTL(mkexpr(rS),
   4383                                 unop(Iop_32to8, mkexpr(rB))),
   4384                            mkU32(mask32)) );
   4385       }
   4386       break;
   4387    }
   4388 
   4389    /* 64bit Integer Rotates */
   4390    case 0x1E: {
   4391       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   4392       sh_imm |= b1 << 5;
   4393 
   4394       vassert( msk_imm < 64 );
   4395       vassert( sh_imm < 64 );
   4396 
   4397       switch (opc2) {
   4398       case 0x4: {
   4399          /* r = ROTL64( rS, rB_lo6) */
   4400          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   4401 
   4402          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   4403             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4404                 rA_addr, rS_addr, rB_addr, msk_imm);
   4405             // note, ROTL does the masking, so we don't do it here
   4406             mask64 = MASK64(0, 63-msk_imm);
   4407             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4408             break;
   4409          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   4410             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4411                 rA_addr, rS_addr, rB_addr, msk_imm);
   4412             mask64 = MASK64(63-msk_imm, 63);
   4413             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4414             break;
   4415          }
   4416          break;
   4417       }
   4418       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   4419          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4420              rA_addr, rS_addr, sh_imm, msk_imm);
   4421          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4422          mask64 = MASK64(sh_imm, 63-msk_imm);
   4423          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4424          break;
   4425          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   4426          /*
   4427            Hmm... looks like this'll do the job more simply:
   4428            r = SHL(rS, sh_imm)
   4429            m = ~(1 << (63-msk_imm))
   4430            assign(rA, r & m);
   4431          */
   4432 
   4433       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   4434          if (mode64
   4435              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   4436             /* special-case the ,64-n,n form as that is just
   4437                unsigned shift-right by n */
   4438             DIP("srdi%s r%u,r%u,%u\n",
   4439                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   4440             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   4441          } else {
   4442             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4443                 rA_addr, rS_addr, sh_imm, msk_imm);
   4444             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4445             mask64 = MASK64(0, 63-msk_imm);
   4446             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4447          }
   4448          break;
   4449 
   4450       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   4451          if (mode64
   4452              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   4453             /* special-case the ,n,63-n form as that is just
   4454                shift-left by n */
   4455             DIP("sldi%s r%u,r%u,%u\n",
   4456                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   4457             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   4458          } else {
   4459             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4460                 rA_addr, rS_addr, sh_imm, msk_imm);
   4461             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4462             mask64 = MASK64(63-msk_imm, 63);
   4463             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4464          }
   4465          break;
   4466 
   4467       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   4468          IRTemp rA_orig = newTemp(ty);
   4469          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4470              rA_addr, rS_addr, sh_imm, msk_imm);
   4471          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4472          mask64 = MASK64(sh_imm, 63-msk_imm);
   4473          assign( rA_orig, getIReg(rA_addr) );
   4474          assign( rA, binop(Iop_Or64,
   4475                            binop(Iop_And64, mkU64(mask64),  r),
   4476                            binop(Iop_And64, mkU64(~mask64),
   4477                                             mkexpr(rA_orig))) );
   4478          break;
   4479       }
   4480       default:
   4481          vex_printf("dis_int_rot(ppc)(opc2)\n");
   4482          return False;
   4483       }
   4484       break;
   4485    }
   4486 
   4487    default:
   4488       vex_printf("dis_int_rot(ppc)(opc1)\n");
   4489       return False;
   4490    }
   4491 
   4492    putIReg( rA_addr, mkexpr(rA) );
   4493 
   4494    if (flag_rC) {
   4495       set_CR0( mkexpr(rA) );
   4496    }
   4497    return True;
   4498 }
   4499 
   4500 
   4501 /*
   4502   Integer Load Instructions
   4503 */
   4504 static Bool dis_int_load ( UInt theInstr )
   4505 {
   4506    /* D-Form, X-Form, DS-Form */
   4507    UChar opc1     = ifieldOPC(theInstr);
   4508    UChar rD_addr  = ifieldRegDS(theInstr);
   4509    UChar rA_addr  = ifieldRegA(theInstr);
   4510    UInt  uimm16   = ifieldUIMM16(theInstr);
   4511    UChar rB_addr  = ifieldRegB(theInstr);
   4512    UInt  opc2     = ifieldOPClo10(theInstr);
   4513    UChar b1       = ifieldBIT1(theInstr);
   4514    UChar b0       = ifieldBIT0(theInstr);
   4515 
   4516    Int     simm16 = extend_s_16to32(uimm16);
   4517    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4518    IRTemp  EA     = newTemp(ty);
   4519    IRExpr* val;
   4520 
   4521    switch (opc1) {
   4522    case 0x1F: // register offset
   4523       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4524       break;
   4525    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   4526               // lowest 2 bits of immediate before forming EA
   4527       simm16 = simm16 & 0xFFFFFFFC;
   4528    default:   // immediate offset
   4529       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4530       break;
   4531    }
   4532 
   4533    switch (opc1) {
   4534    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   4535       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4536       val = loadBE(Ity_I8, mkexpr(EA));
   4537       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4538       break;
   4539 
   4540    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   4541       if (rA_addr == 0 || rA_addr == rD_addr) {
   4542          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   4543          return False;
   4544       }
   4545       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4546       val = loadBE(Ity_I8, mkexpr(EA));
   4547       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4548       putIReg( rA_addr, mkexpr(EA) );
   4549       break;
   4550 
   4551    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   4552       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4553       val = loadBE(Ity_I16, mkexpr(EA));
   4554       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4555       break;
   4556 
   4557    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   4558       if (rA_addr == 0 || rA_addr == rD_addr) {
   4559          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   4560          return False;
   4561       }
   4562       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4563       val = loadBE(Ity_I16, mkexpr(EA));
   4564       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4565       putIReg( rA_addr, mkexpr(EA) );
   4566       break;
   4567 
   4568    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   4569       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4570       val = loadBE(Ity_I16, mkexpr(EA));
   4571       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4572       break;
   4573 
   4574    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   4575       if (rA_addr == 0 || rA_addr == rD_addr) {
   4576          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   4577          return False;
   4578       }
   4579       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4580       val = loadBE(Ity_I16, mkexpr(EA));
   4581       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4582       putIReg( rA_addr, mkexpr(EA) );
   4583       break;
   4584 
   4585    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   4586       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4587       val = loadBE(Ity_I32, mkexpr(EA));
   4588       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4589       break;
   4590 
   4591    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   4592       if (rA_addr == 0 || rA_addr == rD_addr) {
   4593          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   4594          return False;
   4595       }
   4596       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4597       val = loadBE(Ity_I32, mkexpr(EA));
   4598       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4599       putIReg( rA_addr, mkexpr(EA) );
   4600       break;
   4601 
   4602    /* X Form */
   4603    case 0x1F:
   4604       if (b0 != 0) {
   4605          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   4606          return False;
   4607       }
   4608 
   4609       switch (opc2) {
   4610       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   4611          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4612          if (rA_addr == 0 || rA_addr == rD_addr) {
   4613             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4614             return False;
   4615          }
   4616          val = loadBE(Ity_I8, mkexpr(EA));
   4617          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4618          putIReg( rA_addr, mkexpr(EA) );
   4619          break;
   4620 
   4621       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   4622          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4623          val = loadBE(Ity_I8, mkexpr(EA));
   4624          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4625          break;
   4626 
   4627       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   4628          if (rA_addr == 0 || rA_addr == rD_addr) {
   4629             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   4630             return False;
   4631          }
   4632          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4633          val = loadBE(Ity_I16, mkexpr(EA));
   4634          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4635          putIReg( rA_addr, mkexpr(EA) );
   4636          break;
   4637 
   4638       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   4639          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4640          val = loadBE(Ity_I16, mkexpr(EA));
   4641          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4642          break;
   4643 
   4644       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   4645          if (rA_addr == 0 || rA_addr == rD_addr) {
   4646             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   4647             return False;
   4648          }
   4649          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4650          val = loadBE(Ity_I16, mkexpr(EA));
   4651          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4652          putIReg( rA_addr, mkexpr(EA) );
   4653          break;
   4654 
   4655       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   4656          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4657          val = loadBE(Ity_I16, mkexpr(EA));
   4658          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4659          break;
   4660 
   4661       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   4662          if (rA_addr == 0 || rA_addr == rD_addr) {
   4663             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4664             return False;
   4665          }
   4666          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4667          val = loadBE(Ity_I32, mkexpr(EA));
   4668          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4669          putIReg( rA_addr, mkexpr(EA) );
   4670          break;
   4671 
   4672       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   4673          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4674          val = loadBE(Ity_I32, mkexpr(EA));
   4675          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4676          break;
   4677 
   4678 
   4679       /* 64bit Loads */
   4680       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   4681          if (rA_addr == 0 || rA_addr == rD_addr) {
   4682             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   4683             return False;
   4684          }
   4685          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4686          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4687          putIReg( rA_addr, mkexpr(EA) );
   4688          break;
   4689 
   4690       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   4691          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4692          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4693          break;
   4694 
   4695       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   4696          if (rA_addr == 0 || rA_addr == rD_addr) {
   4697             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   4698             return False;
   4699          }
   4700          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4701          putIReg( rD_addr,
   4702                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4703          putIReg( rA_addr, mkexpr(EA) );
   4704          break;
   4705 
   4706       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   4707          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4708          putIReg( rD_addr,
   4709                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4710          break;
   4711 
   4712       default:
   4713          vex_printf("dis_int_load(ppc)(opc2)\n");
   4714          return False;
   4715       }
   4716       break;
   4717 
   4718    /* DS Form - 64bit Loads.  In each case EA will have been formed
   4719       with the lowest 2 bits masked off the immediate offset. */
   4720    case 0x3A:
   4721       switch ((b1<<1) | b0) {
   4722       case 0x0: // ld (Load DWord, PPC64 p472)
   4723          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4724          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4725          break;
   4726 
   4727       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   4728          if (rA_addr == 0 || rA_addr == rD_addr) {
   4729             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   4730             return False;
   4731          }
   4732          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4733          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4734          putIReg( rA_addr, mkexpr(EA) );
   4735          break;
   4736 
   4737       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   4738          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4739          putIReg( rD_addr,
   4740                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4741          break;
   4742 
   4743       default:
   4744          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4745          return False;
   4746       }
   4747       break;
   4748 
   4749    default:
   4750       vex_printf("dis_int_load(ppc)(opc1)\n");
   4751       return False;
   4752    }
   4753    return True;
   4754 }
   4755 
   4756 
   4757 
   4758 /*
   4759   Integer Store Instructions
   4760 */
   4761 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
   4762 {
   4763    /* D-Form, X-Form, DS-Form */
   4764    UChar opc1    = ifieldOPC(theInstr);
   4765    UInt  rS_addr = ifieldRegDS(theInstr);
   4766    UInt  rA_addr = ifieldRegA(theInstr);
   4767    UInt  uimm16  = ifieldUIMM16(theInstr);
   4768    UInt  rB_addr = ifieldRegB(theInstr);
   4769    UInt  opc2    = ifieldOPClo10(theInstr);
   4770    UChar b1      = ifieldBIT1(theInstr);
   4771    UChar b0      = ifieldBIT0(theInstr);
   4772 
   4773    Int    simm16 = extend_s_16to32(uimm16);
   4774    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4775    IRTemp rS     = newTemp(ty);
   4776    IRTemp rB     = newTemp(ty);
   4777    IRTemp EA     = newTemp(ty);
   4778 
   4779    assign( rB, getIReg(rB_addr) );
   4780    assign( rS, getIReg(rS_addr) );
   4781 
   4782    switch (opc1) {
   4783    case 0x1F: // register offset
   4784       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4785       break;
   4786    case 0x3E: // immediate offset: 64bit: std/stdu: mask off
   4787               // lowest 2 bits of immediate before forming EA
   4788       simm16 = simm16 & 0xFFFFFFFC;
   4789    default:   // immediate offset
   4790       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4791       break;
   4792    }
   4793 
   4794    switch (opc1) {
   4795    case 0x26: // stb (Store B, PPC32 p509)
   4796       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4797       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4798       break;
   4799 
   4800    case 0x27: // stbu (Store B, Update, PPC32 p510)
   4801       if (rA_addr == 0 ) {
   4802          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   4803          return False;
   4804       }
   4805       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4806       putIReg( rA_addr, mkexpr(EA) );
   4807       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4808       break;
   4809 
   4810    case 0x2C: // sth (Store HW, PPC32 p522)
   4811       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4812       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4813       break;
   4814 
   4815    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   4816       if (rA_addr == 0) {
   4817          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   4818          return False;
   4819       }
   4820       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4821       putIReg( rA_addr, mkexpr(EA) );
   4822       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4823       break;
   4824 
   4825    case 0x24: // stw (Store W, PPC32 p530)
   4826       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4827       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4828       break;
   4829 
   4830    case 0x25: // stwu (Store W, Update, PPC32 p534)
   4831       if (rA_addr == 0) {
   4832          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   4833          return False;
   4834       }
   4835       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4836       putIReg( rA_addr, mkexpr(EA) );
   4837       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4838       break;
   4839 
   4840    /* X Form : all these use EA_indexed */
   4841    case 0x1F:
   4842       if (b0 != 0) {
   4843          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   4844          return False;
   4845       }
   4846 
   4847       switch (opc2) {
   4848       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   4849          if (rA_addr == 0) {
   4850             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   4851             return False;
   4852          }
   4853          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4854          putIReg( rA_addr, mkexpr(EA) );
   4855          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4856          break;
   4857 
   4858       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   4859          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4860          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4861          break;
   4862 
   4863       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   4864          if (rA_addr == 0) {
   4865             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   4866             return False;
   4867          }
   4868          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4869          putIReg( rA_addr, mkexpr(EA) );
   4870          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4871          break;
   4872 
   4873       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   4874          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4875          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4876          break;
   4877 
   4878       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   4879          if (rA_addr == 0) {
   4880             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   4881             return False;
   4882          }
   4883          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4884          putIReg( rA_addr, mkexpr(EA) );
   4885          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4886          break;
   4887 
   4888       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   4889          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4890          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4891          break;
   4892 
   4893 
   4894       /* 64bit Stores */
   4895       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   4896          if (rA_addr == 0) {
   4897             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   4898             return False;
   4899          }
   4900          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4901          putIReg( rA_addr, mkexpr(EA) );
   4902          storeBE( mkexpr(EA), mkexpr(rS) );
   4903          break;
   4904 
   4905       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   4906          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4907          storeBE( mkexpr(EA), mkexpr(rS) );
   4908          break;
   4909 
   4910       default:
   4911          vex_printf("dis_int_store(ppc)(opc2)\n");
   4912          return False;
   4913       }
   4914       break;
   4915 
   4916    /* DS Form - 64bit Stores.  In each case EA will have been formed
   4917       with the lowest 2 bits masked off the immediate offset. */
   4918    case 0x3E:
   4919       switch ((b1<<1) | b0) {
   4920       case 0x0: // std (Store DWord, PPC64 p580)
   4921          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4922          storeBE( mkexpr(EA), mkexpr(rS) );
   4923          break;
   4924 
   4925       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   4926          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4927          putIReg( rA_addr, mkexpr(EA) );
   4928          storeBE( mkexpr(EA), mkexpr(rS) );
   4929          break;
   4930 
   4931       default:
   4932          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4933          return False;
   4934       }
   4935       break;
   4936 
   4937    default:
   4938       vex_printf("dis_int_store(ppc)(opc1)\n");
   4939       return False;
   4940    }
   4941    return True;
   4942 }
   4943 
   4944 
   4945 
   4946 /*
   4947   Integer Load/Store Multiple Instructions
   4948 */
   4949 static Bool dis_int_ldst_mult ( UInt theInstr )
   4950 {
   4951    /* D-Form */
   4952    UChar opc1     = ifieldOPC(theInstr);
   4953    UChar rD_addr  = ifieldRegDS(theInstr);
   4954    UChar rS_addr  = rD_addr;
   4955    UChar rA_addr  = ifieldRegA(theInstr);
   4956    UInt  uimm16   = ifieldUIMM16(theInstr);
   4957 
   4958    Int     simm16 = extend_s_16to32(uimm16);
   4959    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4960    IRTemp  EA     = newTemp(ty);
   4961    UInt    r      = 0;
   4962    UInt    ea_off = 0;
   4963    IRExpr* irx_addr;
   4964 
   4965    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   4966 
   4967    switch (opc1) {
   4968    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   4969       if (rA_addr >= rD_addr) {
   4970          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   4971          return False;
   4972       }
   4973       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4974       for (r = rD_addr; r <= 31; r++) {
   4975          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4976          putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
   4977                                        False) );
   4978          ea_off += 4;
   4979       }
   4980       break;
   4981 
   4982    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   4983       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4984       for (r = rS_addr; r <= 31; r++) {
   4985          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4986          storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   4987          ea_off += 4;
   4988       }
   4989       break;
   4990 
   4991    default:
   4992       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   4993       return False;
   4994    }
   4995    return True;
   4996 }
   4997 
   4998 
   4999 
   5000 /*
   5001   Integer Load/Store String Instructions
   5002 */
   5003 static
   5004 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5005                              IRTemp EA,        // EA
   5006                              Int    rD,        // first dst register
   5007                              Int    maxBytes ) // 32 or 128
   5008 {
   5009    Int     i, shift = 24;
   5010    IRExpr* e_nbytes = mkexpr(tNBytes);
   5011    IRExpr* e_EA     = mkexpr(EA);
   5012    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5013 
   5014    vassert(rD >= 0 && rD < 32);
   5015    rD--; if (rD < 0) rD = 31;
   5016 
   5017    for (i = 0; i < maxBytes; i++) {
   5018       /* if (nBytes < (i+1)) goto NIA; */
   5019       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5020                          Ijk_Boring,
   5021                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   5022       /* when crossing into a new dest register, set it to zero. */
   5023       if ((i % 4) == 0) {
   5024          rD++; if (rD == 32) rD = 0;
   5025          putIReg(rD, mkSzImm(ty, 0));
   5026          shift = 24;
   5027       }
   5028       /* rD |=  (8Uto32(*(EA+i))) << shift */
   5029       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5030       putIReg(
   5031          rD,
   5032          mkWidenFrom32(
   5033             ty,
   5034             binop(
   5035                Iop_Or32,
   5036                mkNarrowTo32(ty, getIReg(rD)),
   5037                binop(
   5038                   Iop_Shl32,
   5039                   unop(
   5040                      Iop_8Uto32,
   5041                      loadBE(Ity_I8,
   5042                             binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
   5043                   ),
   5044                   mkU8(toUChar(shift))
   5045                )
   5046             ),
   5047             /*Signed*/False
   5048 	 )
   5049       );
   5050       shift -= 8;
   5051    }
   5052 }
   5053 
   5054 static
   5055 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5056                               IRTemp EA,        // EA
   5057                               Int    rS,        // first src register
   5058                               Int    maxBytes ) // 32 or 128
   5059 {
   5060    Int     i, shift = 24;
   5061    IRExpr* e_nbytes = mkexpr(tNBytes);
   5062    IRExpr* e_EA     = mkexpr(EA);
   5063    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5064 
   5065    vassert(rS >= 0 && rS < 32);
   5066    rS--; if (rS < 0) rS = 31;
   5067 
   5068    for (i = 0; i < maxBytes; i++) {
   5069       /* if (nBytes < (i+1)) goto NIA; */
   5070       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5071                          Ijk_Boring,
   5072                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
   5073       /* check for crossing into a new src register. */
   5074       if ((i % 4) == 0) {
   5075          rS++; if (rS == 32) rS = 0;
   5076          shift = 24;
   5077       }
   5078       /* *(EA+i) = 32to8(rS >> shift) */
   5079       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5080       storeBE(
   5081          binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   5082          unop(Iop_32to8,
   5083               binop(Iop_Shr32,
   5084                     mkNarrowTo32(ty, getIReg(rS)),
   5085                     mkU8(toUChar(shift))))
   5086       );
   5087       shift -= 8;
   5088    }
   5089 }
   5090 
   5091 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   5092 {
   5093    /* X-Form */
   5094    UChar opc1     = ifieldOPC(theInstr);
   5095    UChar rD_addr  = ifieldRegDS(theInstr);
   5096    UChar rS_addr  = rD_addr;
   5097    UChar rA_addr  = ifieldRegA(theInstr);
   5098    UChar rB_addr  = ifieldRegB(theInstr);
   5099    UChar NumBytes = rB_addr;
   5100    UInt  opc2     = ifieldOPClo10(theInstr);
   5101    UChar b0       = ifieldBIT0(theInstr);
   5102 
   5103    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5104    IRTemp t_EA    = newTemp(ty);
   5105    IRTemp t_nbytes = IRTemp_INVALID;
   5106 
   5107    *stopHere = False;
   5108 
   5109    if (opc1 != 0x1F || b0 != 0) {
   5110       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   5111       return False;
   5112    }
   5113 
   5114    switch (opc2) {
   5115    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   5116       /* NB: does not reject the case where RA is in the range of
   5117          registers to be loaded.  It should. */
   5118       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   5119       assign( t_EA, ea_rAor0(rA_addr) );
   5120       if (NumBytes == 8 && !mode64) {
   5121          /* Special case hack */
   5122          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   5123          putIReg( rD_addr,
   5124                   loadBE(Ity_I32, mkexpr(t_EA)) );
   5125          putIReg( (rD_addr+1) % 32,
   5126                   loadBE(Ity_I32,
   5127                          binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   5128       } else {
   5129          t_nbytes = newTemp(Ity_I32);
   5130          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5131          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5132          *stopHere = True;
   5133       }
   5134       return True;
   5135 
   5136    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   5137       /* NB: does not reject the case where RA is in the range of
   5138          registers to be loaded.  It should.  Although considering
   5139          that that can only be detected at run time, it's not easy to
   5140          do so. */
   5141       if (rD_addr == rA_addr || rD_addr == rB_addr)
   5142          return False;
   5143       if (rD_addr == 0 && rA_addr == 0)
   5144          return False;
   5145       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5146       t_nbytes = newTemp(Ity_I32);
   5147       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5148       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5149       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   5150       *stopHere = True;
   5151       return True;
   5152 
   5153    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   5154       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   5155       assign( t_EA, ea_rAor0(rA_addr) );
   5156       if (NumBytes == 8 && !mode64) {
   5157          /* Special case hack */
   5158          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   5159          storeBE( mkexpr(t_EA),
   5160                   getIReg(rD_addr) );
   5161          storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   5162                   getIReg((rD_addr+1) % 32) );
   5163       } else {
   5164          t_nbytes = newTemp(Ity_I32);
   5165          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5166          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5167          *stopHere = True;
   5168       }
   5169       return True;
   5170 
   5171    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   5172       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5173       t_nbytes = newTemp(Ity_I32);
   5174       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5175       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5176       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   5177       *stopHere = True;
   5178       return True;
   5179 
   5180    default:
   5181       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   5182       return False;
   5183    }
   5184    return True;
   5185 }
   5186 
   5187 
   5188 /* ------------------------------------------------------------------
   5189    Integer Branch Instructions
   5190    ------------------------------------------------------------------ */
   5191 
   5192 /*
   5193   Branch helper function
   5194   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   5195   Returns an I32 which is 0x00000000 if the ctr condition failed
   5196   and 0xFFFFFFFF otherwise.
   5197 */
   5198 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   5199 {
   5200    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5201    IRTemp ok = newTemp(Ity_I32);
   5202 
   5203    if ((BO >> 2) & 1) {     // independent of ctr
   5204       assign( ok, mkU32(0xFFFFFFFF) );
   5205    } else {
   5206       if ((BO >> 1) & 1) {  // ctr == 0 ?
   5207          assign( ok, unop( Iop_1Sto32,
   5208                            binop( mkSzOp(ty, Iop_CmpEQ8),
   5209                                   getGST( PPC_GST_CTR ),
   5210                                   mkSzImm(ty,0))) );
   5211       } else {              // ctr != 0 ?
   5212          assign( ok, unop( Iop_1Sto32,
   5213                            binop( mkSzOp(ty, Iop_CmpNE8),
   5214                                   getGST( PPC_GST_CTR ),
   5215                                   mkSzImm(ty,0))) );
   5216       }
   5217    }
   5218    return mkexpr(ok);
   5219 }
   5220 
   5221 
   5222 /*
   5223   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   5224   Returns an I32 which is either 0 if the condition failed or
   5225   some arbitrary nonzero value otherwise. */
   5226 
   5227 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   5228 {
   5229    Int where;
   5230    IRTemp res   = newTemp(Ity_I32);
   5231    IRTemp cr_bi = newTemp(Ity_I32);
   5232 
   5233    if ((BO >> 4) & 1) {
   5234       assign( res, mkU32(1) );
   5235    } else {
   5236       // ok = (CR[BI] == BO[3]) Note, the following relies on
   5237       // getCRbit_anywhere returning a value which
   5238       // is either zero or has exactly 1 bit set.
   5239       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   5240 
   5241       if ((BO >> 3) & 1) {
   5242          /* We can use cr_bi as-is. */
   5243          assign( res, mkexpr(cr_bi) );
   5244       } else {
   5245          /* We have to invert the sense of the information held in
   5246             cr_bi.  For that we need to know which bit
   5247             getCRbit_anywhere regards as significant. */
   5248          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   5249                                        mkU32(1<<where)) );
   5250       }
   5251    }
   5252    return mkexpr(res);
   5253 }
   5254 
   5255 
   5256 /*
   5257   Integer Branch Instructions
   5258 */
   5259 static Bool dis_branch ( UInt theInstr,
   5260                          VexAbiInfo* vbi,
   5261                          /*OUT*/DisResult* dres,
   5262                          Bool (*resteerOkFn)(void*,Addr64),
   5263                          void* callback_opaque )
   5264 {
   5265    UChar opc1    = ifieldOPC(theInstr);
   5266    UChar BO      = ifieldRegDS(theInstr);
   5267    UChar BI      = ifieldRegA(theInstr);
   5268    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   5269    UChar b11to15 = ifieldRegB(theInstr);
   5270    UInt  opc2    = ifieldOPClo10(theInstr);
   5271    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   5272    UChar flag_AA = ifieldBIT1(theInstr);
   5273    UChar flag_LK = ifieldBIT0(theInstr);
   5274 
   5275    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   5276    Addr64   tgt       = 0;
   5277    Int      BD        = extend_s_16to32(BD_u16);
   5278    IRTemp   do_branch = newTemp(Ity_I32);
   5279    IRTemp   ctr_ok    = newTemp(Ity_I32);
   5280    IRTemp   cond_ok   = newTemp(Ity_I32);
   5281    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   5282    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   5283    IRTemp   lr_old    = newTemp(ty);
   5284 
   5285    /* Hack to pass through code that just wants to read the PC */
   5286    if (theInstr == 0x429F0005) {
   5287       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   5288       putGST( PPC_GST_LR, e_nia );
   5289       return True;
   5290    }
   5291 
   5292    /* The default what-next.  Individual cases can override it. */
   5293    dres->whatNext = Dis_StopHere;
   5294    vassert(dres->jk_StopHere == Ijk_INVALID);
   5295 
   5296    switch (opc1) {
   5297    case 0x12: // b     (Branch, PPC32 p360)
   5298       if (flag_AA) {
   5299          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   5300       } else {
   5301          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   5302                              (Long)extend_s_26to64(LI_u26) );
   5303       }
   5304       if (mode64) {
   5305          DIP("b%s%s 0x%llx\n",
   5306              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   5307       } else {
   5308          DIP("b%s%s 0x%x\n",
   5309              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   5310       }
   5311 
   5312       if (flag_LK) {
   5313          putGST( PPC_GST_LR, e_nia );
   5314          if (vbi->guest_ppc_zap_RZ_at_bl
   5315              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   5316             IRTemp t_tgt = newTemp(ty);
   5317             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   5318             make_redzone_AbiHint( vbi, t_tgt,
   5319                                   "branch-and-link (unconditional call)" );
   5320          }
   5321       }
   5322 
   5323       if (resteerOkFn( callback_opaque, tgt )) {
   5324          dres->whatNext   = Dis_ResteerU;
   5325          dres->continueAt = tgt;
   5326       } else {
   5327          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
   5328          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
   5329       }
   5330       break;
   5331 
   5332    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   5333       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   5334           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   5335 
   5336       if (!(BO & 0x4)) {
   5337          putGST( PPC_GST_CTR,
   5338                  binop(mkSzOp(ty, Iop_Sub8),
   5339                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5340       }
   5341 
   5342       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   5343          cond_ok is either zero or nonzero, since that's the cheapest
   5344          way to compute it.  Anding them together gives a value which
   5345          is either zero or non zero and so that's what we must test
   5346          for in the IRStmt_Exit. */
   5347       assign( ctr_ok,  branch_ctr_ok( BO ) );
   5348       assign( cond_ok, branch_cond_ok( BO, BI ) );
   5349       assign( do_branch,
   5350               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5351 
   5352       if (flag_AA) {
   5353          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   5354       } else {
   5355          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   5356                             (Long)extend_s_16to64(BD_u16));
   5357       }
   5358       if (flag_LK)
   5359          putGST( PPC_GST_LR, e_nia );
   5360 
   5361       stmt( IRStmt_Exit(
   5362                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   5363                flag_LK ? Ijk_Call : Ijk_Boring,
   5364                mkSzConst(ty, tgt), OFFB_CIA ) );
   5365 
   5366       dres->jk_StopHere = Ijk_Boring;
   5367       putGST( PPC_GST_CIA, e_nia );
   5368       break;
   5369 
   5370    case 0x13:
   5371       /* For bclr and bcctr, it appears that the lowest two bits of
   5372          b11to15 are a branch hint, and so we only need to ensure it's
   5373          of the form 000XX. */
   5374       if ((b11to15 & ~3) != 0) {
   5375          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
   5376          return False;
   5377       }
   5378 
   5379       switch (opc2) {
   5380       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   5381          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   5382             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   5383             return False;
   5384          }
   5385          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5386 
   5387          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5388 
   5389          /* FIXME: this is confusing.  lr_old holds the old value
   5390             of ctr, not lr :-) */
   5391          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   5392 
   5393          if (flag_LK)
   5394             putGST( PPC_GST_LR, e_nia );
   5395 
   5396          stmt( IRStmt_Exit(
   5397                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   5398                   Ijk_Boring,
   5399                   c_nia, OFFB_CIA ));
   5400 
   5401          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   5402             make_redzone_AbiHint( vbi, lr_old,
   5403                                   "b-ctr-l (indirect call)" );
   5404 	 }
   5405 
   5406          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
   5407          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5408          break;
   5409 
   5410       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   5411          Bool vanilla_return = False;
   5412          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   5413             DIP("blr\n");
   5414             vanilla_return = True;
   5415          } else {
   5416             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5417          }
   5418 
   5419          if (!(BO & 0x4)) {
   5420             putGST( PPC_GST_CTR,
   5421                     binop(mkSzOp(ty, Iop_Sub8),
   5422                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5423          }
   5424 
   5425          /* See comments above for 'bc' about this */
   5426          assign( ctr_ok,  branch_ctr_ok( BO ) );
   5427          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5428          assign( do_branch,
   5429                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5430 
   5431          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   5432 
   5433          if (flag_LK)
   5434             putGST( PPC_GST_LR,  e_nia );
   5435 
   5436          stmt( IRStmt_Exit(
   5437                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   5438                   Ijk_Boring,
   5439                   c_nia, OFFB_CIA ));
   5440 
   5441          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   5442             make_redzone_AbiHint( vbi, lr_old,
   5443                                   "branch-to-lr (unconditional return)" );
   5444          }
   5445 
   5446          /* blrl is pretty strange; it's like a return that sets the
   5447             return address of its caller to the insn following this
   5448             one.  Mark it as a return. */
   5449          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   5450          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5451          break;
   5452       }
   5453       default:
   5454          vex_printf("dis_int_branch(ppc)(opc2)\n");
   5455          return False;
   5456       }
   5457       break;
   5458 
   5459    default:
   5460       vex_printf("dis_int_branch(ppc)(opc1)\n");
   5461       return False;
   5462    }
   5463 
   5464    return True;
   5465 }
   5466 
   5467 
   5468 
   5469 /*
   5470   Condition Register Logical Instructions
   5471 */
   5472 static Bool dis_cond_logic ( UInt theInstr )
   5473 {
   5474    /* XL-Form */
   5475    UChar opc1      = ifieldOPC(theInstr);
   5476    UChar crbD_addr = ifieldRegDS(theInstr);
   5477    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   5478    UChar crbA_addr = ifieldRegA(theInstr);
   5479    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   5480    UChar crbB_addr = ifieldRegB(theInstr);
   5481    UInt  opc2      = ifieldOPClo10(theInstr);
   5482    UChar b0        = ifieldBIT0(theInstr);
   5483 
   5484    IRTemp crbD     = newTemp(Ity_I32);
   5485    IRTemp crbA     = newTemp(Ity_I32);
   5486    IRTemp crbB     = newTemp(Ity_I32);
   5487 
   5488    if (opc1 != 19 || b0 != 0) {
   5489       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   5490       return False;
   5491    }
   5492 
   5493    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   5494       if (((crbD_addr & 0x3) != 0) ||
   5495           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   5496          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   5497          return False;
   5498       }
   5499       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   5500       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   5501       putCR321( crfD_addr, getCR321(crfS_addr) );
   5502    } else {
   5503       assign( crbA, getCRbit(crbA_addr) );
   5504       if (crbA_addr == crbB_addr)
   5505          crbB = crbA;
   5506       else
   5507          assign( crbB, getCRbit(crbB_addr) );
   5508 
   5509       switch (opc2) {
   5510       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   5511          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5512          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   5513          break;
   5514       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   5515          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5516          assign( crbD, binop(Iop_And32,
   5517                              mkexpr(crbA),
   5518                              unop(Iop_Not32, mkexpr(crbB))) );
   5519          break;
   5520       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   5521          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5522          assign( crbD, unop(Iop_Not32,
   5523                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   5524          break;
   5525       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   5526          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5527          assign( crbD, unop(Iop_Not32,
   5528                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   5529          break;
   5530       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   5531          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5532          assign( crbD, unop(Iop_Not32,
   5533                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   5534          break;
   5535       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   5536          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5537          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   5538          break;
   5539       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   5540          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5541          assign( crbD, binop(Iop_Or32,
   5542                              mkexpr(crbA),
   5543                              unop(Iop_Not32, mkexpr(crbB))) );
   5544          break;
   5545       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   5546          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5547          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   5548          break;
   5549       default:
   5550          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   5551          return False;
   5552       }
   5553 
   5554       putCRbit( crbD_addr, mkexpr(crbD) );
   5555    }
   5556    return True;
   5557 }
   5558 
   5559 
   5560 /*
   5561   Trap instructions
   5562 */
   5563 
   5564 /* Do the code generation for a trap.  Returned Bool is true iff
   5565    this is an unconditional trap.  If the two arg IRExpr*s are
   5566    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   5567    then they are 64-bit, and we must be disassembling 64-bit
   5568    instructions. */
   5569 static Bool do_trap ( UChar TO,
   5570                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   5571 {
   5572    IRTemp argL, argR;
   5573    IRExpr *argLe, *argRe, *cond, *tmp;
   5574 
   5575    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   5576 
   5577    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   5578    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   5579    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   5580    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   5581    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   5582    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   5583    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   5584    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   5585    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   5586    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   5587 
   5588    const UChar b11100 = 0x1C;
   5589    const UChar b00111 = 0x07;
   5590 
   5591    if (is32bit) {
   5592       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   5593       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   5594    } else {
   5595       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   5596       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   5597       vassert( mode64 );
   5598    }
   5599 
   5600    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   5601       /* Unconditional trap.  Just do the exit without
   5602          testing the arguments. */
   5603       stmt( IRStmt_Exit(
   5604                binop(opCMPEQ, const0, const0),
   5605                Ijk_SigTRAP,
   5606                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   5607                OFFB_CIA
   5608       ));
   5609       return True; /* unconditional trap */
   5610    }
   5611 
   5612    if (is32bit) {
   5613       argL = newTemp(Ity_I32);
   5614       argR = newTemp(Ity_I32);
   5615    } else {
   5616       argL = newTemp(Ity_I64);
   5617       argR = newTemp(Ity_I64);
   5618    }
   5619 
   5620    assign( argL, argL0 );
   5621    assign( argR, argR0 );
   5622 
   5623    argLe = mkexpr(argL);
   5624    argRe = mkexpr(argR);
   5625 
   5626    cond = const0;
   5627    if (TO & 16) { // L <s R
   5628       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   5629       cond = binop(opOR, tmp, cond);
   5630    }
   5631    if (TO & 8) { // L >s R
   5632       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   5633       cond = binop(opOR, tmp, cond);
   5634    }
   5635    if (TO & 4) { // L == R
   5636       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   5637       cond = binop(opOR, tmp, cond);
   5638    }
   5639    if (TO & 2) { // L <u R
   5640       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   5641       cond = binop(opOR, tmp, cond);
   5642    }
   5643    if (TO & 1) { // L >u R
   5644       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   5645       cond = binop(opOR, tmp, cond);
   5646    }
   5647    stmt( IRStmt_Exit(
   5648             binop(opCMPNE, cond, const0),
   5649             Ijk_SigTRAP,
   5650             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   5651             OFFB_CIA
   5652    ));
   5653    return False; /* not an unconditional trap */
   5654 }
   5655 
   5656 static Bool dis_trapi ( UInt theInstr,
   5657                         /*OUT*/DisResult* dres )
   5658 {
   5659    /* D-Form */
   5660    UChar  opc1    = ifieldOPC(theInstr);
   5661    UChar  TO      = ifieldRegDS(theInstr);
   5662    UChar  rA_addr = ifieldRegA(theInstr);
   5663    UInt   uimm16  = ifieldUIMM16(theInstr);
   5664    ULong  simm16  = extend_s_16to64(uimm16);
   5665    Addr64 cia     = guest_CIA_curr_instr;
   5666    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5667    Bool   uncond  = False;
   5668 
   5669    switch (opc1) {
   5670    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   5671       uncond = do_trap( TO,
   5672                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   5673                                : getIReg(rA_addr),
   5674                         mkU32( (UInt)simm16 ),
   5675                         cia );
   5676       if (TO == 4) {
   5677          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5678       } else {
   5679          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5680       }
   5681       break;
   5682    case 0x02: // tdi
   5683       if (!mode64)
   5684          return False;
   5685       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   5686       if (TO == 4) {
   5687          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5688       } else {
   5689          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5690       }
   5691       break;
   5692    default:
   5693       return False;
   5694    }
   5695 
   5696    if (uncond) {
   5697       /* If the trap shows signs of being unconditional, don't
   5698          continue decoding past it. */
   5699       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   5700       dres->jk_StopHere = Ijk_Boring;
   5701       dres->whatNext    = Dis_StopHere;
   5702    }
   5703 
   5704    return True;
   5705 }
   5706 
   5707 static Bool dis_trap ( UInt theInstr,
   5708                         /*OUT*/DisResult* dres )
   5709 {
   5710    /* X-Form */
   5711    UInt   opc2    = ifieldOPClo10(theInstr);
   5712    UChar  TO      = ifieldRegDS(theInstr);
   5713    UChar  rA_addr = ifieldRegA(theInstr);
   5714    UChar  rB_addr = ifieldRegB(theInstr);
   5715    Addr64 cia     = guest_CIA_curr_instr;
   5716    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5717    Bool   uncond  = False;
   5718 
   5719    if (ifieldBIT0(theInstr) != 0)
   5720       return False;
   5721 
   5722    switch (opc2) {
   5723    case 0x004: // tw  (Trap Word, PPC64 p540)
   5724       uncond = do_trap( TO,
   5725                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   5726                                : getIReg(rA_addr),
   5727                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   5728                                : getIReg(rB_addr),
   5729                         cia );
   5730       if (TO == 4) {
   5731          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   5732       } else {
   5733          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   5734       }
   5735       break;
   5736    case 0x044: // td (Trap Doubleword, PPC64 p534)
   5737       if (!mode64)
   5738          return False;
   5739       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   5740       if (TO == 4) {
   5741          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   5742       } else {
   5743          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   5744       }
   5745       break;
   5746    default:
   5747       return False;
   5748    }
   5749 
   5750    if (uncond) {
   5751       /* If the trap shows signs of being unconditional, don't
   5752          continue decoding past it. */
   5753       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   5754       dres->jk_StopHere = Ijk_Boring;
   5755       dres->whatNext    = Dis_StopHere;
   5756    }
   5757 
   5758    return True;
   5759 }
   5760 
   5761 
   5762 /*
   5763   System Linkage Instructions
   5764 */
   5765 static Bool dis_syslink ( UInt theInstr,
   5766                           VexAbiInfo* abiinfo, DisResult* dres )
   5767 {
   5768    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5769 
   5770    if (theInstr != 0x44000002) {
   5771       vex_printf("dis_syslink(ppc)(theInstr)\n");
   5772       return False;
   5773    }
   5774 
   5775    // sc  (System Call, PPC32 p504)
   5776    DIP("sc\n");
   5777 
   5778    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
   5779       Valgrind can back the guest up to this instruction if it needs
   5780       to restart the syscall. */
   5781    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   5782 
   5783    /* It's important that all ArchRegs carry their up-to-date value
   5784       at this point.  So we declare an end-of-block here, which
   5785       forces any TempRegs caching ArchRegs to be flushed. */
   5786    putGST( PPC_GST_CIA, abiinfo->guest_ppc_sc_continues_at_LR
   5787                         ? getGST( PPC_GST_LR )
   5788                         : mkSzImm( ty, nextInsnAddr() ));
   5789 
   5790    dres->whatNext    = Dis_StopHere;
   5791    dres->jk_StopHere = Ijk_Sys_syscall;
   5792    return True;
   5793 }
   5794 
   5795 
   5796 /*
   5797   Memory Synchronization Instructions
   5798 
   5799   Note on Reservations:
   5800   We rely on the assumption that V will in fact only allow one thread at
   5801   once to run.  In effect, a thread can make a reservation, but we don't
   5802   check any stores it does.  Instead, the reservation is cancelled when
   5803   the scheduler switches to another thread (run_thread_for_a_while()).
   5804 */
   5805 static Bool dis_memsync ( UInt theInstr )
   5806 {
   5807    /* X-Form, XL-Form */
   5808    UChar opc1    = ifieldOPC(theInstr);
   5809    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   5810    UChar flag_L  = ifieldRegDS(theInstr);
   5811    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   5812    UChar rD_addr = ifieldRegDS(theInstr);
   5813    UChar rS_addr = rD_addr;
   5814    UChar rA_addr = ifieldRegA(theInstr);
   5815    UChar rB_addr = ifieldRegB(theInstr);
   5816    UInt  opc2    = ifieldOPClo10(theInstr);
   5817    UChar b0      = ifieldBIT0(theInstr);
   5818 
   5819    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5820    IRTemp EA     = newTemp(ty);
   5821 
   5822    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5823 
   5824    switch (opc1) {
   5825    /* XL-Form */
   5826    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   5827       if (opc2 != 0x096) {
   5828          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   5829          return False;
   5830       }
   5831       if (b11to25 != 0 || b0 != 0) {
   5832          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   5833          return False;
   5834       }
   5835       DIP("isync\n");
   5836       stmt( IRStmt_MBE(Imbe_Fence) );
   5837       break;
   5838 
   5839    /* X-Form */
   5840    case 0x1F:
   5841       switch (opc2) {
   5842       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
   5843          if (b11to25 != 0 || b0 != 0) {
   5844             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
   5845             return False;
   5846          }
   5847          DIP("eieio\n");
   5848          /* Insert a memory fence, just to be on the safe side. */
   5849          stmt( IRStmt_MBE(Imbe_Fence) );
   5850          break;
   5851 
   5852       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   5853          IRTemp res;
   5854          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5855             in the documentation) is merely a hint bit to the
   5856             hardware, I think as to whether or not contention is
   5857             likely.  So we can just ignore it. */
   5858          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5859 
   5860          // trap if misaligned
   5861          gen_SIGBUS_if_misaligned( EA, 4 );
   5862 
   5863          // and actually do the load
   5864          res = newTemp(Ity_I32);
   5865          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5866 
   5867          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   5868          break;
   5869       }
   5870 
   5871       case 0x096: {
   5872          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   5873          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   5874          // so isn't quite as straightforward as it might otherwise be.
   5875          IRTemp rS = newTemp(Ity_I32);
   5876          IRTemp resSC;
   5877          if (b0 != 1) {
   5878             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   5879             return False;
   5880          }
   5881          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5882 
   5883          // trap if misaligned
   5884          gen_SIGBUS_if_misaligned( EA, 4 );
   5885 
   5886          // Get the data to be stored, and narrow to 32 bits if necessary
   5887          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   5888 
   5889          // Do the store, and get success/failure bit into resSC
   5890          resSC = newTemp(Ity_I1);
   5891          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5892 
   5893          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5894          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5895          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5896          putCR0(0, getXER_SO());
   5897 
   5898          /* Note:
   5899             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5900             whether rS is stored is dependent on that value. */
   5901          /* So I guess we can just ignore this case? */
   5902          break;
   5903       }
   5904 
   5905       case 0x256: // sync (Synchronize, PPC32 p543),
   5906                   // also lwsync (L==1), ptesync (L==2)
   5907          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   5908 
   5909             The PowerPC architecture used in IBM chips has expanded
   5910             the sync instruction into two variants: lightweight sync
   5911             and heavyweight sync.  The original sync instruction is
   5912             the new heavyweight sync and lightweight sync is a strict
   5913             subset of the heavyweight sync functionality. This allows
   5914             the programmer to specify a less expensive operation on
   5915             high-end systems when the full sync functionality is not
   5916             necessary.
   5917 
   5918             The basic "sync" mnemonic now utilizes an operand. "sync"
   5919             without an operand now becomes a extended mnemonic for
   5920             heavyweight sync.  Processors without the lwsync
   5921             instruction will not decode the L field and will perform a
   5922             heavyweight sync.  Everything is backward compatible.
   5923 
   5924             sync    =       sync 0
   5925             lwsync  =       sync 1
   5926             ptesync =       sync 2    *** TODO - not implemented ***
   5927          */
   5928          if (b11to20 != 0 || b0 != 0) {
   5929             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   5930             return False;
   5931          }
   5932          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   5933             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   5934             return False;
   5935          }
   5936          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   5937          /* Insert a memory fence.  It's sometimes important that these
   5938             are carried through to the generated code. */
   5939          stmt( IRStmt_MBE(Imbe_Fence) );
   5940          break;
   5941 
   5942       /* 64bit Memsync */
   5943       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   5944          IRTemp res;
   5945          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5946             in the documentation) is merely a hint bit to the
   5947             hardware, I think as to whether or not contention is
   5948             likely.  So we can just ignore it. */
   5949          if (!mode64)
   5950             return False;
   5951          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5952 
   5953          // trap if misaligned
   5954          gen_SIGBUS_if_misaligned( EA, 8 );
   5955 
   5956          // and actually do the load
   5957          res = newTemp(Ity_I64);
   5958          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5959 
   5960          putIReg( rD_addr, mkexpr(res) );
   5961          break;
   5962       }
   5963 
   5964       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   5965          // A marginally simplified version of the stwcx. case
   5966          IRTemp rS = newTemp(Ity_I64);
   5967          IRTemp resSC;
   5968          if (b0 != 1) {
   5969             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   5970             return False;
   5971          }
   5972          if (!mode64)
   5973             return False;
   5974          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5975 
   5976          // trap if misaligned
   5977          gen_SIGBUS_if_misaligned( EA, 8 );
   5978 
   5979          // Get the data to be stored
   5980          assign( rS, getIReg(rS_addr) );
   5981 
   5982          // Do the store, and get success/failure bit into resSC
   5983          resSC = newTemp(Ity_I1);
   5984          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5985 
   5986          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5987          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5988          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5989          putCR0(0, getXER_SO());
   5990 
   5991          /* Note:
   5992             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5993             whether rS is stored is dependent on that value. */
   5994          /* So I guess we can just ignore this case? */
   5995          break;
   5996       }
   5997 
   5998       default:
   5999          vex_printf("dis_memsync(ppc)(opc2)\n");
   6000          return False;
   6001       }
   6002       break;
   6003 
   6004    default:
   6005       vex_printf("dis_memsync(ppc)(opc1)\n");
   6006       return False;
   6007    }
   6008    return True;
   6009 }
   6010 
   6011 
   6012 
   6013 /*
   6014   Integer Shift Instructions
   6015 */
   6016 static Bool dis_int_shift ( UInt theInstr )
   6017 {
   6018    /* X-Form, XS-Form */
   6019    UChar opc1    = ifieldOPC(theInstr);
   6020    UChar rS_addr = ifieldRegDS(theInstr);
   6021    UChar rA_addr = ifieldRegA(theInstr);
   6022    UChar rB_addr = ifieldRegB(theInstr);
   6023    UChar sh_imm  = rB_addr;
   6024    UInt  opc2    = ifieldOPClo10(theInstr);
   6025    UChar b1      = ifieldBIT1(theInstr);
   6026    UChar flag_rC = ifieldBIT0(theInstr);
   6027 
   6028    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   6029    IRTemp  rA         = newTemp(ty);
   6030    IRTemp  rS         = newTemp(ty);
   6031    IRTemp  rB         = newTemp(ty);
   6032    IRTemp  outofrange = newTemp(Ity_I8);
   6033    IRTemp  rS_lo32    = newTemp(Ity_I32);
   6034    IRTemp  rB_lo32    = newTemp(Ity_I32);
   6035    IRExpr* e_tmp;
   6036 
   6037    assign( rS, getIReg(rS_addr) );
   6038    assign( rB, getIReg(rB_addr) );
   6039    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   6040    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   6041 
   6042    if (opc1 == 0x1F) {
   6043       switch (opc2) {
   6044       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   6045          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6046              rA_addr, rS_addr, rB_addr);
   6047          /* rA = rS << rB */
   6048          /* ppc32 semantics are:
   6049             slw(x,y) = (x << (y & 31))         -- primary result
   6050                        & ~((y << 26) >>s 31)   -- make result 0
   6051                                                   for y in 32 .. 63
   6052          */
   6053          e_tmp =
   6054             binop( Iop_And32,
   6055                binop( Iop_Shl32,
   6056                       mkexpr(rS_lo32),
   6057                       unop( Iop_32to8,
   6058                             binop(Iop_And32,
   6059                                   mkexpr(rB_lo32), mkU32(31)))),
   6060                unop( Iop_Not32,
   6061                      binop( Iop_Sar32,
   6062                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   6063                             mkU8(31))) );
   6064          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6065          break;
   6066       }
   6067 
   6068       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   6069          IRTemp sh_amt = newTemp(Ity_I32);
   6070          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6071              rA_addr, rS_addr, rB_addr);
   6072          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   6073             amt = rB & 63
   6074             rA = Sar32( rS, amt > 31 ? 31 : amt )
   6075             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   6076          */
   6077          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   6078                                           mkexpr(rB_lo32)) );
   6079          assign( outofrange,
   6080                  unop( Iop_1Uto8,
   6081                        binop(Iop_CmpLT32U, mkU32(31),
   6082                                            mkexpr(sh_amt)) ));
   6083          e_tmp = binop( Iop_Sar32,
   6084                         mkexpr(rS_lo32),
   6085                         unop( Iop_32to8,
   6086                               IRExpr_Mux0X( mkexpr(outofrange),
   6087                                             mkexpr(sh_amt),
   6088                                             mkU32(31)) ) );
   6089          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   6090 
   6091          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   6092                      mkexpr(rA),
   6093                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   6094                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   6095                      mkWidenFrom32(ty, getXER_CA32(), True) );
   6096          break;
   6097       }
   6098 
   6099       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   6100          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   6101              rA_addr, rS_addr, sh_imm);
   6102          vassert(sh_imm < 32);
   6103          if (mode64) {
   6104             assign( rA, binop(Iop_Sar64,
   6105                               binop(Iop_Shl64, getIReg(rS_addr),
   6106                                                mkU8(32)),
   6107                               mkU8(32 + sh_imm)) );
   6108          } else {
   6109             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   6110                                          mkU8(sh_imm)) );
   6111          }
   6112 
   6113          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   6114                      mkexpr(rA),
   6115                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   6116                      mkSzImm(ty, sh_imm),
   6117                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6118          break;
   6119 
   6120       case 0x218: // srw (Shift Right Word, PPC32 p508)
   6121          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6122              rA_addr, rS_addr, rB_addr);
   6123          /* rA = rS >>u rB */
   6124          /* ppc32 semantics are:
   6125             srw(x,y) = (x >>u (y & 31))        -- primary result
   6126                        & ~((y << 26) >>s 31)   -- make result 0
   6127                                                   for y in 32 .. 63
   6128          */
   6129          e_tmp =
   6130             binop(
   6131                Iop_And32,
   6132                binop( Iop_Shr32,
   6133                       mkexpr(rS_lo32),
   6134                       unop( Iop_32to8,
   6135                             binop(Iop_And32, mkexpr(rB_lo32),
   6136                                              mkU32(31)))),
   6137                unop( Iop_Not32,
   6138                      binop( Iop_Sar32,
   6139                             binop(Iop_Shl32, mkexpr(rB_lo32),
   6140                                              mkU8(26)),
   6141                             mkU8(31))));
   6142          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6143          break;
   6144 
   6145 
   6146       /* 64bit Shifts */
   6147       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   6148          DIP("sld%s r%u,r%u,r%u\n",
   6149              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6150          /* rA = rS << rB */
   6151          /* ppc64 semantics are:
   6152             slw(x,y) = (x << (y & 63))         -- primary result
   6153                        & ~((y << 57) >>s 63)   -- make result 0
   6154                                                   for y in 64 ..
   6155          */
   6156          assign( rA,
   6157             binop(
   6158                Iop_And64,
   6159                binop( Iop_Shl64,
   6160                       mkexpr(rS),
   6161                       unop( Iop_64to8,
   6162                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6163                unop( Iop_Not64,
   6164                      binop( Iop_Sar64,
   6165                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6166                             mkU8(63)))) );
   6167          break;
   6168 
   6169       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   6170          IRTemp sh_amt = newTemp(Ity_I64);
   6171          DIP("srad%s r%u,r%u,r%u\n",
   6172              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6173          /* amt = rB & 127
   6174             rA = Sar64( rS, amt > 63 ? 63 : amt )
   6175             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   6176          */
   6177          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   6178          assign( outofrange,
   6179                  unop( Iop_1Uto8,
   6180                        binop(Iop_CmpLT64U, mkU64(63),
   6181                                            mkexpr(sh_amt)) ));
   6182          assign( rA,
   6183                  binop( Iop_Sar64,
   6184                         mkexpr(rS),
   6185                         unop( Iop_64to8,
   6186                               IRExpr_Mux0X( mkexpr(outofrange),
   6187                                             mkexpr(sh_amt),
   6188                                             mkU64(63)) ))
   6189                );
   6190          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   6191                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   6192                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6193          break;
   6194       }
   6195 
   6196       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   6197          sh_imm |= b1<<5;
   6198          vassert(sh_imm < 64);
   6199          DIP("sradi%s r%u,r%u,%u\n",
   6200              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   6201          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   6202 
   6203          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   6204                      mkexpr(rA),
   6205                      getIReg(rS_addr),
   6206                      mkU64(sh_imm),
   6207                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6208          break;
   6209 
   6210       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   6211          DIP("srd%s r%u,r%u,r%u\n",
   6212              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6213          /* rA = rS >>u rB */
   6214          /* ppc semantics are:
   6215             srw(x,y) = (x >>u (y & 63))        -- primary result
   6216                        & ~((y << 57) >>s 63)   -- make result 0
   6217                                                   for y in 64 .. 127
   6218          */
   6219          assign( rA,
   6220             binop(
   6221                Iop_And64,
   6222                binop( Iop_Shr64,
   6223                       mkexpr(rS),
   6224                       unop( Iop_64to8,
   6225                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6226                unop( Iop_Not64,
   6227                      binop( Iop_Sar64,
   6228                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6229                             mkU8(63)))) );
   6230          break;
   6231 
   6232       default:
   6233          vex_printf("dis_int_shift(ppc)(opc2)\n");
   6234          return False;
   6235       }
   6236    } else {
   6237       vex_printf("dis_int_shift(ppc)(opc1)\n");
   6238       return False;
   6239    }
   6240 
   6241    putIReg( rA_addr, mkexpr(rA) );
   6242 
   6243    if (flag_rC) {
   6244       set_CR0( mkexpr(rA) );
   6245    }
   6246    return True;
   6247 }
   6248 
   6249 
   6250 
   6251 /*
   6252   Integer Load/Store Reverse Instructions
   6253 */
   6254 /* Generates code to swap the byte order in an Ity_I32. */
   6255 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   6256 {
   6257    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6258    return
   6259       binop(Iop_Or32,
   6260          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   6261       binop(Iop_Or32,
   6262          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6263                           mkU32(0x00FF0000)),
   6264       binop(Iop_Or32,
   6265          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6266                           mkU32(0x0000FF00)),
   6267          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   6268                           mkU32(0x000000FF) )
   6269       )));
   6270 }
   6271 
   6272 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   6273    and zeroes the upper half. */
   6274 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   6275 {
   6276    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6277    return
   6278       binop(Iop_Or32,
   6279          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6280                           mkU32(0x0000FF00)),
   6281          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6282                           mkU32(0x000000FF))
   6283       );
   6284 }
   6285 
   6286 static Bool dis_int_ldst_rev ( UInt theInstr )
   6287 {
   6288    /* X-Form */
   6289    UChar opc1    = ifieldOPC(theInstr);
   6290    UChar rD_addr = ifieldRegDS(theInstr);
   6291    UChar rS_addr = rD_addr;
   6292    UChar rA_addr = ifieldRegA(theInstr);
   6293    UChar rB_addr = ifieldRegB(theInstr);
   6294    UInt  opc2    = ifieldOPClo10(theInstr);
   6295    UChar b0      = ifieldBIT0(theInstr);
   6296 
   6297    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6298    IRTemp EA = newTemp(ty);
   6299    IRTemp w1 = newTemp(Ity_I32);
   6300    IRTemp w2 = newTemp(Ity_I32);
   6301 
   6302    if (opc1 != 0x1F || b0 != 0) {
   6303       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   6304       return False;
   6305    }
   6306 
   6307    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6308 
   6309    switch (opc2) {
   6310 
   6311       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   6312          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6313          assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
   6314          assign( w2, gen_byterev16(w1) );
   6315          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6316                                          /* Signed */False) );
   6317          break;
   6318 
   6319       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   6320          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6321          assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
   6322          assign( w2, gen_byterev32(w1) );
   6323          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6324                                          /* Signed */False) );
   6325          break;
   6326 
   6327       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
   6328       {
   6329          IRExpr * nextAddr;
   6330          IRTemp w3 = newTemp( Ity_I32 );
   6331          IRTemp w4 = newTemp( Ity_I32 );
   6332          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6333          assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
   6334          assign( w2, gen_byterev32( w1 ) );
   6335          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   6336                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
   6337          assign( w3, loadBE( Ity_I32, nextAddr ) );
   6338          assign( w4, gen_byterev32( w3 ) );
   6339          putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
   6340          break;
   6341       }
   6342 
   6343       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   6344          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6345          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6346          storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   6347          break;
   6348 
   6349       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   6350          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6351          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6352          storeBE( mkexpr(EA), gen_byterev32(w1) );
   6353          break;
   6354 
   6355       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
   6356       {
   6357          IRTemp lo = newTemp(Ity_I32);
   6358          IRTemp hi = newTemp(Ity_I32);
   6359          IRTemp rS = newTemp(Ity_I64);
   6360          assign( rS, getIReg( rS_addr ) );
   6361          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6362          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
   6363          assign(hi, unop(Iop_64to32, mkexpr(rS)));
   6364          storeBE( mkexpr( EA ),
   6365                   binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
   6366          break;
   6367       }
   6368 
   6369       default:
   6370          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   6371          return False;
   6372    }
   6373    return True;
   6374 }
   6375 
   6376 
   6377 
   6378 /*
   6379   Processor Control Instructions
   6380 */
   6381 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
   6382 {
   6383    UChar opc1     = ifieldOPC(theInstr);
   6384 
   6385    /* X-Form */
   6386    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   6387    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   6388    UChar rD_addr  = ifieldRegDS(theInstr);
   6389    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   6390 
   6391    /* XFX-Form */
   6392    UChar rS_addr  = rD_addr;
   6393    UInt  SPR      = b11to20;
   6394    UInt  TBR      = b11to20;
   6395    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   6396    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   6397    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   6398 
   6399    UInt  opc2     = ifieldOPClo10(theInstr);
   6400    UChar b0       = ifieldBIT0(theInstr);
   6401 
   6402    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6403    IRTemp rS = newTemp(ty);
   6404    assign( rS, getIReg(rS_addr) );
   6405 
   6406    /* Reorder SPR field as per PPC32 p470 */
   6407    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   6408    /* Reorder TBR field as per PPC32 p475 */
   6409    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   6410 
   6411    if (opc1 != 0x1F || b0 != 0) {
   6412       vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
   6413       return False;
   6414    }
   6415 
   6416    switch (opc2) {
   6417    /* X-Form */
   6418    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   6419       if (b21to22 != 0 || b11to20 != 0) {
   6420          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   6421          return False;
   6422       }
   6423       DIP("mcrxr crf%d\n", crfD);
   6424       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   6425       putGST_field( PPC_GST_CR,
   6426                     getGST_field( PPC_GST_XER, 7 ),
   6427                     crfD );
   6428 
   6429       // Clear XER[0-3]
   6430       putXER_SO( mkU8(0) );
   6431       putXER_OV( mkU8(0) );
   6432       putXER_CA( mkU8(0) );
   6433       break;
   6434    }
   6435 
   6436    case 0x013:
   6437       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   6438       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   6439       // However it seems that the 'mfcr' behaviour is an acceptable
   6440       // implementation of mfocr (from the 2.02 arch spec)
   6441       if (b11to20 == 0) {
   6442          DIP("mfcr r%u\n", rD_addr);
   6443          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6444                                          /* Signed */False) );
   6445          break;
   6446       }
   6447       if (b20 == 1 && b11 == 0) {
   6448          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   6449          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6450                                          /* Signed */False) );
   6451          break;
   6452       }
   6453       /* not decodable */
   6454       return False;
   6455 
   6456    /* XFX-Form */
   6457    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   6458 
   6459       switch (SPR) {  // Choose a register...
   6460       case 0x1:
   6461          DIP("mfxer r%u\n", rD_addr);
   6462          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   6463                                          /* Signed */False) );
   6464          break;
   6465       case 0x8:
   6466          DIP("mflr r%u\n", rD_addr);
   6467          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   6468          break;
   6469       case 0x9:
   6470          DIP("mfctr r%u\n", rD_addr);
   6471          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   6472          break;
   6473       case 0x100:
   6474          DIP("mfvrsave r%u\n", rD_addr);
   6475          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   6476                                          /* Signed */False) );
   6477          break;
   6478 
   6479       case 0x103:
   6480          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   6481          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   6482          break;
   6483 
   6484       /* Even a lowly PPC7400 can run the associated helper, so no
   6485          obvious need for feature testing at this point. */
   6486       case 268 /* 0x10C */:
   6487       case 269 /* 0x10D */: {
   6488          UInt     arg  = SPR==268 ? 0 : 1;
   6489          IRTemp   val  = newTemp(Ity_I32);
   6490          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   6491          IRDirty* d    = unsafeIRDirty_1_N(
   6492                             val,
   6493                             0/*regparms*/,
   6494                             "ppc32g_dirtyhelper_MFSPR_268_269",
   6495                             fnptr_to_fnentry
   6496                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   6497                             args
   6498                          );
   6499          /* execute the dirty call, dumping the result in val. */
   6500          stmt( IRStmt_Dirty(d) );
   6501          putIReg( rD_addr,
   6502                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6503          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6504          break;
   6505       }
   6506 
   6507       /* Again, runs natively on PPC7400 (7447, really).  Not
   6508          bothering with a feature test. */
   6509       case 287: /* 0x11F */ {
   6510          IRTemp   val  = newTemp(Ity_I32);
   6511          IRExpr** args = mkIRExprVec_0();
   6512          IRDirty* d    = unsafeIRDirty_1_N(
   6513                             val,
   6514                             0/*regparms*/,
   6515                             "ppc32g_dirtyhelper_MFSPR_287",
   6516                             fnptr_to_fnentry
   6517                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   6518                             args
   6519                          );
   6520          /* execute the dirty call, dumping the result in val. */
   6521          stmt( IRStmt_Dirty(d) );
   6522          putIReg( rD_addr,
   6523                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6524          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6525          break;
   6526       }
   6527 
   6528       default:
   6529          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   6530          return False;
   6531       }
   6532       break;
   6533 
   6534    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   6535       IRTemp   val  = newTemp(Ity_I64);
   6536       IRExpr** args = mkIRExprVec_0();
   6537       IRDirty* d    = unsafeIRDirty_1_N(
   6538                               val,
   6539                               0/*regparms*/,
   6540                               "ppcg_dirtyhelper_MFTB",
   6541                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   6542                               args );
   6543       /* execute the dirty call, dumping the result in val. */
   6544       stmt( IRStmt_Dirty(d) );
   6545 
   6546       switch (TBR) {
   6547       case 269:
   6548          DIP("mftbu r%u", rD_addr);
   6549          putIReg( rD_addr,
   6550                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   6551                                 /* Signed */False) );
   6552          break;
   6553       case 268:
   6554          DIP("mftb r%u", rD_addr);
   6555          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   6556                                       unop(Iop_64to32, mkexpr(val)) );
   6557          break;
   6558       default:
   6559          return False; /* illegal instruction */
   6560       }
   6561       break;
   6562    }
   6563 
   6564    case 0x090: {
   6565       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   6566       // b20==1: mtocrf (Move to One Cond Reg Field)
   6567       Int   cr;
   6568       UChar shft;
   6569       if (b11 != 0)
   6570          return False;
   6571       if (b20 == 1) {
   6572          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   6573             1 field is written.  It seems more robust to decline to
   6574             decode the insn if so. */
   6575          switch (CRM) {
   6576             case 0x01: case 0x02: case 0x04: case 0x08:
   6577             case 0x10: case 0x20: case 0x40: case 0x80:
   6578                break;
   6579             default:
   6580                return False;
   6581          }
   6582       }
   6583       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   6584                            CRM, rS_addr);
   6585       /* Write to each field specified by CRM */
   6586       for (cr = 0; cr < 8; cr++) {
   6587          if ((CRM & (1 << (7-cr))) == 0)
   6588             continue;
   6589          shft = 4*(7-cr);
   6590          putGST_field( PPC_GST_CR,
   6591                        binop(Iop_Shr32,
   6592                              mkNarrowTo32(ty, mkexpr(rS)),
   6593                              mkU8(shft)), cr );
   6594       }
   6595       break;
   6596    }
   6597 
   6598    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   6599 
   6600       switch (SPR) {  // Choose a register...
   6601       case 0x1:
   6602          DIP("mtxer r%u\n", rS_addr);
   6603          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   6604          break;
   6605       case 0x8:
   6606          DIP("mtlr r%u\n", rS_addr);
   6607          putGST( PPC_GST_LR, mkexpr(rS) );
   6608          break;
   6609       case 0x9:
   6610          DIP("mtctr r%u\n", rS_addr);
   6611          putGST( PPC_GST_CTR, mkexpr(rS) );
   6612          break;
   6613       case 0x100:
   6614          DIP("mtvrsave r%u\n", rS_addr);
   6615          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   6616          break;
   6617 
   6618       default:
   6619          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   6620          return False;
   6621       }
   6622       break;
   6623 
   6624    default:
   6625       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   6626       return False;
   6627    }
   6628    return True;
   6629 }
   6630 
   6631 
   6632 /*
   6633   Cache Management Instructions
   6634 */
   6635 static Bool dis_cache_manage ( UInt         theInstr,
   6636                                DisResult*   dres,
   6637                                VexArchInfo* guest_archinfo )
   6638 {
   6639    /* X-Form */
   6640    UChar opc1    = ifieldOPC(theInstr);
   6641    UChar b21to25 = ifieldRegDS(theInstr);
   6642    UChar rA_addr = ifieldRegA(theInstr);
   6643    UChar rB_addr = ifieldRegB(theInstr);
   6644    UInt  opc2    = ifieldOPClo10(theInstr);
   6645    UChar b0      = ifieldBIT0(theInstr);
   6646    UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
   6647    Bool  is_dcbzl = False;
   6648 
   6649    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6650 
   6651    /* For dcbt, the lowest two bits of b21to25 encode an
   6652       access-direction hint (TH field) which we ignore.  Well, that's
   6653       what the PowerPC documentation says.  In fact xlc -O4 on POWER5
   6654       seems to generate values of 8 and 10 for b21to25. */
   6655    if (opc1 == 0x1F && opc2 == 0x116) {
   6656      /* b21to25 &= ~3; */ /* if the docs were true */
   6657      b21to25 = 0; /* blunt instrument */
   6658    }
   6659    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   6660       if (b21to25 == 1) {
   6661          is_dcbzl = True;
   6662          b21to25 = 0;
   6663          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   6664             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   6665             return False;
   6666          }
   6667       }
   6668    }
   6669 
   6670    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
   6671       if (0) vex_printf("dis_cache_manage %d %d %d\n",
   6672                         (Int)opc1, (Int)b21to25, (Int)b0);
   6673       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
   6674       return False;
   6675    }
   6676 
   6677    /* stay sane .. */
   6678    vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
   6679 
   6680    switch (opc2) {
   6681 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   6682 //zz       vassert(0); /* AWAITING TEST CASE */
   6683 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   6684 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   6685 //zz       break;
   6686 
   6687    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   6688       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   6689       /* nop as far as vex is concerned */
   6690       break;
   6691 
   6692    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   6693       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   6694       /* nop as far as vex is concerned */
   6695       break;
   6696 
   6697    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   6698       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   6699       /* nop as far as vex is concerned */
   6700       break;
   6701 
   6702    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   6703       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   6704       /* nop as far as vex is concerned */
   6705       break;
   6706 
   6707    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   6708                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   6709       /* Clear all bytes in cache block at (rA|0) + rB. */
   6710       IRTemp  EA   = newTemp(ty);
   6711       IRTemp  addr = newTemp(ty);
   6712       IRExpr* irx_addr;
   6713       UInt    i;
   6714       UInt clearszB;
   6715       if (is_dcbzl) {
   6716           clearszB = guest_archinfo->ppc_dcbzl_szB;
   6717           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   6718       }
   6719       else {
   6720           clearszB = guest_archinfo->ppc_dcbz_szB;
   6721           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   6722       }
   6723 
   6724       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6725 
   6726       if (mode64) {
   6727          /* Round EA down to the start of the containing block. */
   6728          assign( addr, binop( Iop_And64,
   6729                               mkexpr(EA),
   6730                               mkU64( ~((ULong)clearszB-1) )) );
   6731 
   6732          for (i = 0; i < clearszB / 8; i++) {
   6733             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   6734             storeBE( irx_addr, mkU64(0) );
   6735          }
   6736       } else {
   6737          /* Round EA down to the start of the containing block. */
   6738          assign( addr, binop( Iop_And32,
   6739                               mkexpr(EA),
   6740                               mkU32( ~(clearszB-1) )) );
   6741 
   6742          for (i = 0; i < clearszB / 4; i++) {
   6743             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   6744             storeBE( irx_addr, mkU32(0) );
   6745          }
   6746       }
   6747       break;
   6748    }
   6749 
   6750    case 0x3D6: {
   6751       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   6752       /* Invalidate all translations containing code from the cache
   6753          block at (rA|0) + rB. */
   6754       IRTemp EA   = newTemp(ty);
   6755       IRTemp addr = newTemp(ty);
   6756       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   6757       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6758 
   6759       /* Round EA down to the start of the containing block. */
   6760       assign( addr, binop( mkSzOp(ty, Iop_And8),
   6761                            mkexpr(EA),
   6762                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   6763       putGST( PPC_GST_TISTART, mkexpr(addr) );
   6764       putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
   6765 
   6766       /* be paranoid ... */
   6767       stmt( IRStmt_MBE(Imbe_Fence) );
   6768 
   6769       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
   6770       dres->jk_StopHere = Ijk_TInval;
   6771       dres->whatNext    = Dis_StopHere;
   6772       break;
   6773    }
   6774 
   6775    default:
   6776       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   6777       return False;
   6778    }
   6779    return True;
   6780 }
   6781 
   6782 
   6783 /*------------------------------------------------------------*/
   6784 /*--- Floating Point Helpers                               ---*/
   6785 /*------------------------------------------------------------*/
   6786 
   6787 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   6788 /* Produces a value in 0 .. 3, which is encoded as per the type
   6789    IRRoundingMode.  PPCRoundingMode encoding is different to
   6790    IRRoundingMode, so need to map it.
   6791 */
   6792 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   6793 {
   6794 /*
   6795    rounding mode | PPC | IR
   6796    ------------------------
   6797    to nearest    | 00  | 00
   6798    to zero       | 01  | 11
   6799    to +infinity  | 10  | 10
   6800    to -infinity  | 11  | 01
   6801 */
   6802    IRTemp rm_PPC32 = newTemp(Ity_I32);
   6803    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   6804 
   6805    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   6806    return binop( Iop_Xor32,
   6807                  mkexpr(rm_PPC32),
   6808                  binop( Iop_And32,
   6809                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   6810                         mkU32(2) ));
   6811 }
   6812 
   6813 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
   6814  * mapping would still work with the extended three bit DFP rounding
   6815  * mode designator.
   6816 
   6817  *  rounding mode                     | PPC  |  IR
   6818  *  -----------------------------------------------
   6819  *  to nearest, ties to even          | 000  | 000
   6820  *  to zero                           | 001  | 011
   6821  *  to +infinity                      | 010  | 010
   6822  *  to -infinity                      | 011  | 001
   6823  *  to nearest, ties away from 0      | 100  | 100
   6824  *  to nearest, ties toward 0         | 101  | 111
   6825  *  to away from 0                    | 110  | 110
   6826  *  to prepare for shorter precision  | 111  | 101
   6827  */
   6828 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
   6829 {
   6830    IRTemp rm_PPC32 = newTemp( Ity_I32 );
   6831    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
   6832 
   6833    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   6834    return binop( Iop_Xor32,
   6835                  mkexpr( rm_PPC32 ),
   6836                  binop( Iop_And32,
   6837                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
   6838                         mkU32( 2 ) ) );
   6839 }
   6840 
   6841 #define NANmaskSingle   0x7F800000
   6842 #define NANmaskDouble   0x7FF00000
   6843 
   6844 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
   6845 {
   6846    IRTemp exp_zero  = newTemp(Ity_I8);
   6847    IRTemp frac_mask = newTemp(Ity_I32);
   6848    IRTemp frac_not_zero = newTemp(Ity_I8);
   6849 
   6850    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
   6851     * The input value is always 64-bits, for single precision values, the
   6852     * lower 32 bits must be zero.
   6853     *
   6854     * Single Pricision
   6855     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
   6856     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
   6857     *  [31:0]  unused for single precision representation
   6858     *
   6859     * Double Pricision
   6860     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
   6861     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
   6862     *
   6863     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
   6864     */
   6865    assign( frac_mask, unop( Iop_Not32,
   6866                             binop( Iop_Or32,
   6867                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
   6868 
   6869    assign( exp_zero,
   6870            unop( Iop_1Sto8,
   6871                  binop( Iop_CmpEQ32,
   6872                         binop( Iop_And32,
   6873                                unop( Iop_64HIto32,
   6874                                      unop( Iop_ReinterpF64asI64,
   6875                                            value ) ),
   6876                                Hi32Mask ),
   6877                         Hi32Mask ) ) );
   6878    assign( frac_not_zero,
   6879            binop( Iop_Or8,
   6880                   unop( Iop_1Sto8,
   6881                         binop( Iop_CmpNE32,
   6882                                binop( Iop_And32,
   6883                                       unop( Iop_64HIto32,
   6884                                             unop( Iop_ReinterpF64asI64,
   6885                                                   value ) ),
   6886                                       mkexpr( frac_mask ) ),
   6887                                mkU32( 0x0 ) ) ),
   6888                   unop( Iop_1Sto8,
   6889                         binop( Iop_CmpNE32,
   6890                                binop( Iop_And32,
   6891                                       unop( Iop_64to32,
   6892                                             unop( Iop_ReinterpF64asI64,
   6893                                                   value ) ),
   6894                                       mkU32( 0xFFFFFFFF ) ),
   6895                                mkU32( 0x0 ) ) ) ) );
   6896    return unop( Iop_8Sto32,
   6897                 binop( Iop_And8,
   6898                        mkexpr( exp_zero ),
   6899                        mkexpr( frac_not_zero ) ) );
   6900 }
   6901 
   6902 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
   6903 {
   6904    /* This function will only complement the 64-bit floating point value if it
   6905     * is not Nan.  NaN is not a signed value.  Need to do computations using
   6906     * 32-bit operands to ensure it will run in 32-bit mode.
   6907     */
   6908    return  binop( Iop_32HLto64,
   6909                   binop( Iop_Or32,
   6910                          binop( Iop_And32,
   6911                                 nan_mask,
   6912                                 unop( Iop_64HIto32,
   6913                                       unop( Iop_ReinterpF64asI64,
   6914                                             value ) ) ),
   6915                          binop( Iop_And32,
   6916                                 unop( Iop_Not32,
   6917                                       nan_mask ),
   6918                                 unop( Iop_64HIto32,
   6919                                       unop( Iop_ReinterpF64asI64,
   6920                                             unop( Iop_NegF64,
   6921                                                   value ) ) ) ) ),
   6922                   unop( Iop_64to32,
   6923                         unop( Iop_ReinterpF64asI64, value ) ) );
   6924 }
   6925 
   6926 /*------------------------------------------------------------*/
   6927 /*--- Floating Point Instruction Translation               ---*/
   6928 /*------------------------------------------------------------*/
   6929 
   6930 /*
   6931   Floating Point Load Instructions
   6932 */
   6933 static Bool dis_fp_load ( UInt theInstr )
   6934 {
   6935    /* X-Form, D-Form */
   6936    UChar opc1      = ifieldOPC(theInstr);
   6937    UChar frD_addr  = ifieldRegDS(theInstr);
   6938    UChar rA_addr   = ifieldRegA(theInstr);
   6939    UChar rB_addr   = ifieldRegB(theInstr);
   6940    UInt  opc2      = ifieldOPClo10(theInstr);
   6941    UChar b0        = ifieldBIT0(theInstr);
   6942    UInt  uimm16    = ifieldUIMM16(theInstr);
   6943 
   6944    Int    simm16 = extend_s_16to32(uimm16);
   6945    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6946    IRTemp EA     = newTemp(ty);
   6947    IRTemp rA     = newTemp(ty);
   6948    IRTemp rB     = newTemp(ty);
   6949    IRTemp iHi    = newTemp(Ity_I32);
   6950    IRTemp iLo    = newTemp(Ity_I32);
   6951 
   6952    assign( rA, getIReg(rA_addr) );
   6953    assign( rB, getIReg(rB_addr) );
   6954 
   6955    /* These are completely straightforward from a rounding and status
   6956       bits perspective: no rounding involved and no funny status or CR
   6957       bits affected. */
   6958 
   6959    switch (opc1) {
   6960    case 0x30: // lfs (Load Float Single, PPC32 p441)
   6961       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6962       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6963       putFReg( frD_addr,
   6964                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6965       break;
   6966 
   6967    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   6968       if (rA_addr == 0)
   6969          return False;
   6970       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6971       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6972       putFReg( frD_addr,
   6973                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6974       putIReg( rA_addr, mkexpr(EA) );
   6975       break;
   6976 
   6977    case 0x32: // lfd (Load Float Double, PPC32 p437)
   6978       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6979       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6980       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6981       break;
   6982 
   6983    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   6984       if (rA_addr == 0)
   6985          return False;
   6986       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6987       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6988       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6989       putIReg( rA_addr, mkexpr(EA) );
   6990       break;
   6991 
   6992    case 0x1F:
   6993       if (b0 != 0) {
   6994          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   6995          return False;
   6996       }
   6997 
   6998       switch(opc2) {
   6999       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   7000          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7001          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7002          putFReg( frD_addr, unop( Iop_F32toF64,
   7003                                   loadBE(Ity_F32, mkexpr(EA))) );
   7004          break;
   7005 
   7006       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   7007          if (rA_addr == 0)
   7008             return False;
   7009          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7010          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7011          putFReg( frD_addr,
   7012                   unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   7013          putIReg( rA_addr, mkexpr(EA) );
   7014          break;
   7015 
   7016       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   7017          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7018          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7019          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7020          break;
   7021 
   7022       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   7023          if (rA_addr == 0)
   7024             return False;
   7025          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7026          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7027          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   7028          putIReg( rA_addr, mkexpr(EA) );
   7029          break;
   7030 
   7031       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   7032          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7033          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7034          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   7035          assign( iHi, binop(Iop_Sub32,
   7036                             mkU32(0),
   7037                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   7038          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   7039                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   7040          break;
   7041 
   7042       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
   7043       {
   7044          IRTemp dw = newTemp( Ity_I64 );
   7045          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7046          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7047          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   7048          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
   7049          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
   7050          break;
   7051       }
   7052 
   7053       default:
   7054          vex_printf("dis_fp_load(ppc)(opc2)\n");
   7055          return False;
   7056       }
   7057       break;
   7058 
   7059    default:
   7060       vex_printf("dis_fp_load(ppc)(opc1)\n");
   7061       return False;
   7062    }
   7063    return True;
   7064 }
   7065 
   7066 
   7067 
   7068 /*
   7069   Floating Point Store Instructions
   7070 */
   7071 static Bool dis_fp_store ( UInt theInstr )
   7072 {
   7073    /* X-Form, D-Form */
   7074    UChar opc1      = ifieldOPC(theInstr);
   7075    UChar frS_addr  = ifieldRegDS(theInstr);
   7076    UChar rA_addr   = ifieldRegA(theInstr);
   7077    UChar rB_addr   = ifieldRegB(theInstr);
   7078    UInt  opc2      = ifieldOPClo10(theInstr);
   7079    UChar b0        = ifieldBIT0(theInstr);
   7080    Int   uimm16    = ifieldUIMM16(theInstr);
   7081 
   7082    Int    simm16 = extend_s_16to32(uimm16);
   7083    IRTemp frS    = newTemp(Ity_F64);
   7084    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7085    IRTemp EA     = newTemp(ty);
   7086    IRTemp rA     = newTemp(ty);
   7087    IRTemp rB     = newTemp(ty);
   7088 
   7089    assign( frS, getFReg(frS_addr) );
   7090    assign( rA,  getIReg(rA_addr) );
   7091    assign( rB,  getIReg(rB_addr) );
   7092 
   7093    /* These are straightforward from a status bits perspective: no
   7094       funny status or CR bits affected.  For single precision stores,
   7095       the values are truncated and denormalised (not rounded) to turn
   7096       them into single precision values. */
   7097 
   7098    switch (opc1) {
   7099 
   7100    case 0x34: // stfs (Store Float Single, PPC32 p518)
   7101       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7102       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7103       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   7104          the value to be stored in the correct way, without any
   7105          rounding. */
   7106       storeBE( mkexpr(EA),
   7107                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7108       break;
   7109 
   7110    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   7111       if (rA_addr == 0)
   7112          return False;
   7113       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7114       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7115       /* See comment for stfs */
   7116       storeBE( mkexpr(EA),
   7117                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7118       putIReg( rA_addr, mkexpr(EA) );
   7119       break;
   7120 
   7121    case 0x36: // stfd (Store Float Double, PPC32 p513)
   7122       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7123       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7124       storeBE( mkexpr(EA), mkexpr(frS) );
   7125       break;
   7126 
   7127    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   7128       if (rA_addr == 0)
   7129          return False;
   7130       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   7131       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7132       storeBE( mkexpr(EA), mkexpr(frS) );
   7133       putIReg( rA_addr, mkexpr(EA) );
   7134       break;
   7135 
   7136    case 0x1F:
   7137       if (b0 != 0) {
   7138          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   7139          return False;
   7140       }
   7141       switch(opc2) {
   7142       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   7143          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7144          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7145          /* See note for stfs */
   7146          storeBE( mkexpr(EA),
   7147                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7148          break;
   7149 
   7150       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   7151          if (rA_addr == 0)
   7152             return False;
   7153          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7154          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7155          /* See note for stfs */
   7156          storeBE( mkexpr(EA),
   7157                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   7158          putIReg( rA_addr, mkexpr(EA) );
   7159          break;
   7160 
   7161       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   7162          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7163          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7164          storeBE( mkexpr(EA), mkexpr(frS) );
   7165          break;
   7166 
   7167       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   7168          if (rA_addr == 0)
   7169             return False;
   7170          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7171          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7172          storeBE( mkexpr(EA), mkexpr(frS) );
   7173          putIReg( rA_addr, mkexpr(EA) );
   7174          break;
   7175 
   7176       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   7177          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7178          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   7179          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7180          storeBE( mkexpr(EA),
   7181                   unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   7182          break;
   7183 
   7184       default:
   7185          vex_printf("dis_fp_store(ppc)(opc2)\n");
   7186          return False;
   7187       }
   7188       break;
   7189 
   7190    default:
   7191       vex_printf("dis_fp_store(ppc)(opc1)\n");
   7192       return False;
   7193    }
   7194    return True;
   7195 }
   7196 
   7197 
   7198 
   7199 /*
   7200   Floating Point Arith Instructions
   7201 */
   7202 static Bool dis_fp_arith ( UInt theInstr )
   7203 {
   7204    /* A-Form */
   7205    UChar opc1     = ifieldOPC(theInstr);
   7206    UChar frD_addr = ifieldRegDS(theInstr);
   7207    UChar frA_addr = ifieldRegA(theInstr);
   7208    UChar frB_addr = ifieldRegB(theInstr);
   7209    UChar frC_addr = ifieldRegC(theInstr);
   7210    UChar opc2     = ifieldOPClo5(theInstr);
   7211    UChar flag_rC  = ifieldBIT0(theInstr);
   7212 
   7213    IRTemp  frD = newTemp(Ity_F64);
   7214    IRTemp  frA = newTemp(Ity_F64);
   7215    IRTemp  frB = newTemp(Ity_F64);
   7216    IRTemp  frC = newTemp(Ity_F64);
   7217    IRExpr* rm  = get_IR_roundingmode();
   7218 
   7219    /* By default, we will examine the results of the operation and set
   7220       fpscr[FPRF] accordingly. */
   7221    Bool set_FPRF = True;
   7222 
   7223    /* By default, if flag_RC is set, we will clear cr1 after the
   7224       operation.  In reality we should set cr1 to indicate the
   7225       exception status of the operation, but since we're not
   7226       simulating exceptions, the exception status will appear to be
   7227       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7228    Bool clear_CR1 = True;
   7229 
   7230    assign( frA, getFReg(frA_addr));
   7231    assign( frB, getFReg(frB_addr));
   7232    assign( frC, getFReg(frC_addr));
   7233 
   7234    switch (opc1) {
   7235    case 0x3B:
   7236       switch (opc2) {
   7237       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   7238          if (frC_addr != 0)
   7239             return False;
   7240          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7241              frD_addr, frA_addr, frB_addr);
   7242          assign( frD, triop( Iop_DivF64r32,
   7243                              rm, mkexpr(frA), mkexpr(frB) ));
   7244          break;
   7245 
   7246       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   7247          if (frC_addr != 0)
   7248             return False;
   7249          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7250              frD_addr, frA_addr, frB_addr);
   7251          assign( frD, triop( Iop_SubF64r32,
   7252                              rm, mkexpr(frA), mkexpr(frB) ));
   7253          break;
   7254 
   7255       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   7256          if (frC_addr != 0)
   7257             return False;
   7258          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7259              frD_addr, frA_addr, frB_addr);
   7260          assign( frD, triop( Iop_AddF64r32,
   7261                              rm, mkexpr(frA), mkexpr(frB) ));
   7262          break;
   7263 
   7264       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   7265          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7266          if (frA_addr != 0 || frC_addr != 0)
   7267             return False;
   7268          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   7269              frD_addr, frB_addr);
   7270          // however illogically, on ppc970 this insn behaves identically
   7271          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   7272          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   7273          break;
   7274 
   7275       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   7276          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7277          if (frA_addr != 0 || frC_addr != 0)
   7278             return False;
   7279          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   7280              frD_addr, frB_addr);
   7281          { IRExpr* ieee_one
   7282               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7283            assign( frD, triop( Iop_DivF64r32,
   7284                                rm,
   7285                                ieee_one, mkexpr(frB) ));
   7286          }
   7287          break;
   7288 
   7289       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   7290          if (frB_addr != 0)
   7291             return False;
   7292          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7293              frD_addr, frA_addr, frC_addr);
   7294          assign( frD, triop( Iop_MulF64r32,
   7295                              rm, mkexpr(frA), mkexpr(frC) ));
   7296          break;
   7297 
   7298       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   7299          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7300          // Undocumented instruction?
   7301          if (frA_addr != 0 || frC_addr != 0)
   7302             return False;
   7303          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   7304              frD_addr, frB_addr);
   7305          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7306          break;
   7307 
   7308       default:
   7309          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   7310          return False;
   7311       }
   7312       break;
   7313 
   7314    case 0x3F:
   7315       switch (opc2) {
   7316       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   7317          if (frC_addr != 0)
   7318             return False;
   7319          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7320              frD_addr, frA_addr, frB_addr);
   7321          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   7322          break;
   7323 
   7324       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   7325          if (frC_addr != 0)
   7326             return False;
   7327          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7328              frD_addr, frA_addr, frB_addr);
   7329          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   7330          break;
   7331 
   7332       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   7333          if (frC_addr != 0)
   7334             return False;
   7335          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7336              frD_addr, frA_addr, frB_addr);
   7337          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   7338          break;
   7339 
   7340       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   7341          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7342          if (frA_addr != 0 || frC_addr != 0)
   7343             return False;
   7344          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   7345              frD_addr, frB_addr);
   7346          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   7347          break;
   7348 
   7349       case 0x17: { // fsel (Floating Select, PPC32 p426)
   7350          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7351          IRTemp cc    = newTemp(Ity_I32);
   7352          IRTemp cc_b0 = newTemp(Ity_I32);
   7353 
   7354          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7355              frD_addr, frA_addr, frC_addr, frB_addr);
   7356 
   7357          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   7358          // => GT|EQ == (cc & 0x1 == 0)
   7359          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   7360                                        IRExpr_Const(IRConst_F64(0))) );
   7361          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   7362 
   7363          // frD = (frA >= 0.0) ? frC : frB
   7364          //     = (cc_b0 == 0) ? frC : frB
   7365          assign( frD,
   7366                  IRExpr_Mux0X(
   7367                     unop(Iop_1Uto8,
   7368                          binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
   7369                     mkexpr(frB),
   7370                     mkexpr(frC) ));
   7371 
   7372          /* One of the rare ones which don't mess with FPRF */
   7373          set_FPRF = False;
   7374          break;
   7375       }
   7376 
   7377       case 0x18: // fre (Floating Reciprocal Estimate)
   7378          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7379          // Note: unclear whether this insn really exists or not
   7380          // ppc970 doesn't have it, but POWER5 does
   7381          if (frA_addr != 0 || frC_addr != 0)
   7382             return False;
   7383          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   7384              frD_addr, frB_addr);
   7385          { IRExpr* ieee_one
   7386               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7387            assign( frD, triop( Iop_DivF64,
   7388                                rm,
   7389                                ieee_one, mkexpr(frB) ));
   7390          }
   7391          break;
   7392 
   7393       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   7394          if (frB_addr != 0)
   7395             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   7396          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7397              frD_addr, frA_addr, frC_addr);
   7398          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   7399          break;
   7400 
   7401       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   7402          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7403          if (frA_addr != 0 || frC_addr != 0)
   7404             return False;
   7405          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   7406              frD_addr, frB_addr);
   7407          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7408          break;
   7409 
   7410       default:
   7411          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   7412          return False;
   7413       }
   7414       break;
   7415 
   7416    default:
   7417       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   7418       return False;
   7419    }
   7420 
   7421    putFReg( frD_addr, mkexpr(frD) );
   7422 
   7423    if (set_FPRF) {
   7424       // XXX XXX XXX FIXME
   7425       // set FPRF from frD
   7426    }
   7427 
   7428    if (flag_rC && clear_CR1) {
   7429       putCR321( 1, mkU8(0) );
   7430       putCR0( 1, mkU8(0) );
   7431    }
   7432 
   7433    return True;
   7434 }
   7435 
   7436 
   7437 
   7438 /*
   7439   Floating Point Mult-Add Instructions
   7440 */
   7441 static Bool dis_fp_multadd ( UInt theInstr )
   7442 {
   7443    /* A-Form */
   7444    UChar opc1     = ifieldOPC(theInstr);
   7445    UChar frD_addr = ifieldRegDS(theInstr);
   7446    UChar frA_addr = ifieldRegA(theInstr);
   7447    UChar frB_addr = ifieldRegB(theInstr);
   7448    UChar frC_addr = ifieldRegC(theInstr);
   7449    UChar opc2     = ifieldOPClo5(theInstr);
   7450    UChar flag_rC  = ifieldBIT0(theInstr);
   7451 
   7452    IRTemp  frD = newTemp(Ity_F64);
   7453    IRTemp  frA = newTemp(Ity_F64);
   7454    IRTemp  frB = newTemp(Ity_F64);
   7455    IRTemp  frC = newTemp(Ity_F64);
   7456    IRTemp  rmt = newTemp(Ity_I32);
   7457    IRTemp  tmp = newTemp(Ity_F64);
   7458    IRTemp  sign_tmp = newTemp(Ity_I64);
   7459    IRTemp  nan_mask = newTemp(Ity_I32);
   7460    IRExpr* rm;
   7461 
   7462    /* By default, we will examine the results of the operation and set
   7463       fpscr[FPRF] accordingly. */
   7464    Bool set_FPRF = True;
   7465 
   7466    /* By default, if flag_RC is set, we will clear cr1 after the
   7467       operation.  In reality we should set cr1 to indicate the
   7468       exception status of the operation, but since we're not
   7469       simulating exceptions, the exception status will appear to be
   7470       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7471    Bool clear_CR1 = True;
   7472 
   7473    /* Bind the rounding mode expression to a temp; there's no
   7474       point in creating gratuitous CSEs, as we know we'll need
   7475       to use it twice. */
   7476    assign( rmt, get_IR_roundingmode() );
   7477    rm = mkexpr(rmt);
   7478 
   7479    assign( frA, getFReg(frA_addr));
   7480    assign( frB, getFReg(frB_addr));
   7481    assign( frC, getFReg(frC_addr));
   7482 
   7483    /* The rounding in this is all a bit dodgy.  The idea is to only do
   7484       one rounding.  That clearly isn't achieveable without dedicated
   7485       four-input IR primops, although in the single precision case we
   7486       can sort-of simulate it by doing the inner multiply in double
   7487       precision.
   7488 
   7489       In the negated cases, the negation happens after rounding. */
   7490 
   7491    switch (opc1) {
   7492    case 0x3B:
   7493       switch (opc2) {
   7494       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   7495          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7496              frD_addr, frA_addr, frC_addr, frB_addr);
   7497          assign( frD, qop( Iop_MSubF64r32, rm,
   7498                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7499          break;
   7500 
   7501       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   7502          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7503              frD_addr, frA_addr, frC_addr, frB_addr);
   7504          assign( frD, qop( Iop_MAddF64r32, rm,
   7505                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7506          break;
   7507 
   7508       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   7509       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   7510 
   7511          if (opc2 == 0x1E) {
   7512             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7513                      frD_addr, frA_addr, frC_addr, frB_addr);
   7514             assign( tmp, qop( Iop_MSubF64r32, rm,
   7515                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   7516          } else {
   7517             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7518                      frD_addr, frA_addr, frC_addr, frB_addr);
   7519             assign( tmp, qop( Iop_MAddF64r32, rm,
   7520                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   7521          }
   7522 
   7523          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   7524                                       mkU32( NANmaskSingle ) ) );
   7525          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   7526                                                mkexpr( nan_mask ) ) );
   7527          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   7528          break;
   7529 
   7530       default:
   7531          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   7532          return False;
   7533       }
   7534       break;
   7535 
   7536    case 0x3F:
   7537       switch (opc2) {
   7538       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   7539          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7540              frD_addr, frA_addr, frC_addr, frB_addr);
   7541          assign( frD, qop( Iop_MSubF64, rm,
   7542                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7543          break;
   7544 
   7545       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   7546          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7547              frD_addr, frA_addr, frC_addr, frB_addr);
   7548          assign( frD, qop( Iop_MAddF64, rm,
   7549                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7550          break;
   7551 
   7552       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   7553       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   7554 
   7555          if (opc2 == 0x1E) {
   7556             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7557                      frD_addr, frA_addr, frC_addr, frB_addr);
   7558             assign( tmp, qop( Iop_MSubF64, rm,
   7559                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   7560          } else {
   7561             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7562                      frD_addr, frA_addr, frC_addr, frB_addr);
   7563             assign( tmp, qop( Iop_MAddF64, rm,
   7564                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7565          }
   7566 
   7567          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   7568                                       mkU32( NANmaskDouble ) ) );
   7569          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   7570                                                mkexpr( nan_mask ) ) );
   7571          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   7572          break;
   7573 
   7574       default:
   7575          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   7576          return False;
   7577       }
   7578       break;
   7579 
   7580    default:
   7581       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   7582       return False;
   7583    }
   7584 
   7585    putFReg( frD_addr, mkexpr(frD) );
   7586 
   7587    if (set_FPRF) {
   7588       // XXX XXX XXX FIXME
   7589       // set FPRF from frD
   7590    }
   7591 
   7592    if (flag_rC && clear_CR1) {
   7593       putCR321( 1, mkU8(0) );
   7594       putCR0( 1, mkU8(0) );
   7595    }
   7596 
   7597    return True;
   7598 }
   7599 
   7600 /*
   7601  * fe_flag is set to 1 if any of the following conditions occurs:
   7602  *  - The floating-point operand in register FRB is a Zero, a
   7603  *    NaN, an Infinity, or a negative value.
   7604  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
   7605  *  Otherwise fe_flag is set to 0.
   7606  *
   7607  * fg_flag is set to 1 if either of the following conditions occurs.
   7608  *   - The floating-point operand in register FRB is a Zero, an
   7609  *     Infinity, or a denormalized value.
   7610  *  Otherwise fg_flag is set to 0.
   7611  *
   7612  */
   7613 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   7614 {
   7615    // The following temps are for holding intermediate results
   7616    IRTemp e_b = newTemp(Ity_I32);
   7617    IRExpr * fe_flag,  * fg_flag;
   7618    IRTemp frB_exp_shR = newTemp(Ity_I32);
   7619    UInt bias = sp? 127 : 1023;
   7620    IRExpr * frbNaN, * frbDenorm, * frBNeg;
   7621    IRExpr * eb_LTE;
   7622    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   7623    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   7624    *fe_flag_tmp = newTemp(Ity_I32);
   7625    *fg_flag_tmp = newTemp(Ity_I32);
   7626    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
   7627    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   7628 
   7629    //////////////////  fe_flag tests BEGIN //////////////////////
   7630    /* We first do all tests that may result in setting fe_flag to '1'.
   7631     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
   7632     * for details.)
   7633     */
   7634    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
   7635    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
   7636    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
   7637    {
   7638       // Test_value = -970 for double precision
   7639       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
   7640       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
   7641    }
   7642    frBNeg = binop( Iop_CmpEQ32,
   7643                    binop( Iop_Shr32,
   7644                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
   7645                           mkU8( 31 ) ),
   7646                    mkU32( 1 ) );
   7647    //////////////////  fe_flag tests END //////////////////////
   7648 
   7649    //////////////////  fg_flag tests BEGIN //////////////////////
   7650    /*
   7651     * The following tests were already performed above in the fe_flag
   7652     * tests.  So these conditions will result in both fe_ and fg_ flags
   7653     * being set.
   7654     *   - Test if FRB is Zero
   7655     *   - Test if FRB is an Infinity
   7656     */
   7657 
   7658    /*
   7659     * Test if FRB holds a denormalized value.  A denormalized value is one where
   7660     * the exp is 0 and the fraction is non-zero.
   7661     */
   7662    if (sp) {
   7663       IRTemp frac_part = newTemp(Ity_I32);
   7664       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
   7665       frbDenorm
   7666                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   7667                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
   7668    } else {
   7669       IRExpr * hi32, * low32, * fraction_is_nonzero;
   7670       IRTemp frac_part = newTemp(Ity_I64);
   7671 
   7672       assign( frac_part, FP_FRAC_PART(frB_Int) );
   7673       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   7674       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   7675       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   7676                                                 mkU32( 0 ) );
   7677       frbDenorm
   7678                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   7679                          fraction_is_nonzero );
   7680    }
   7681    //////////////////  fg_flag tests END //////////////////////
   7682 
   7683    /////////////////////////
   7684    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
   7685                     mkOR1( frbNaN,
   7686                            mkOR1( mkexpr( frbInf_tmp ),
   7687                                   mkOR1( frBNeg, eb_LTE ) ) ) );
   7688 
   7689    fe_flag = unop(Iop_1Uto32, fe_flag);
   7690 
   7691    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
   7692                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
   7693    fg_flag = unop(Iop_1Uto32, fg_flag);
   7694    assign (*fg_flag_tmp, fg_flag);
   7695    assign (*fe_flag_tmp, fe_flag);
   7696 }
   7697 /*
   7698  * fe_flag is set to 1 if any of the following conditions occurs:
   7699  *  - The double-precision floating-point operand in register FRA is a NaN or an
   7700  *    Infinity.
   7701  *  - The double-precision floating-point operand in register FRB is a Zero, a
   7702  *    NaN, or an Infinity.
   7703  *  - e_b is less than or equal to -1022.
   7704  *  - e_b is greater than or equal to 1021.
   7705  *  - The double-precision floating-point operand in register FRA is not a zero
   7706  *    and the difference, e_a - e_b, is greater than or equal to 1023.
   7707  *  - The double-precision floating-point operand in register FRA is not a zero
   7708  *    and the difference, e_a - e_b, is less than or equal to -1021.
   7709  *  - The double-precision floating-point operand in register FRA is not a zero
   7710  *    and e_a is less than or equal to -970
   7711  *  Otherwise fe_flag is set to 0.
   7712  *
   7713  * fg_flag is set to 1 if either of the following conditions occurs.
   7714  *   - The double-precision floating-point operand in register FRA is an Infinity.
   7715  *   - The double-precision floating-point operand in register FRB is a Zero, an
   7716  *     Infinity, or a denormalized value.
   7717  *  Otherwise fg_flag is set to 0.
   7718  *
   7719  */
   7720 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   7721 {
   7722    // The following temps are for holding intermediate results
   7723    IRTemp e_a = newTemp(Ity_I32);
   7724    IRTemp e_b = newTemp(Ity_I32);
   7725    IRTemp frA_exp_shR = newTemp(Ity_I32);
   7726    IRTemp frB_exp_shR = newTemp(Ity_I32);
   7727 
   7728    UInt bias = sp? 127 : 1023;
   7729    *fe_flag_tmp = newTemp(Ity_I32);
   7730    *fg_flag_tmp = newTemp(Ity_I32);
   7731 
   7732    /* The following variables hold boolean results from tests
   7733     * that are OR'ed together for setting the fe_ and fg_ flags.
   7734     * For some cases, the booleans are used more than once, so
   7735     * I make those IRTemp's instead of IRExpr's.
   7736     */
   7737    IRExpr * fraNaN, * frbNaN, * frbDenorm;
   7738    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
   7739    IRTemp  fraInf_tmp = newTemp(Ity_I1);
   7740    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   7741    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   7742    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
   7743 
   7744 /* The following are the flags that are set by OR'ing the results of
   7745  * all the tests done for tdiv.  These flags are the input to the specified CR.
   7746  */
   7747    IRExpr * fe_flag, * fg_flag;
   7748 
   7749    // Create temps that will be used throughout the following tests.
   7750    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
   7751    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
   7752    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
   7753    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
   7754    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   7755 
   7756 
   7757    //////////////////  fe_flag tests BEGIN //////////////////////
   7758    /* We first do all tests that may result in setting fe_flag to '1'. */
   7759 
   7760    /*
   7761     * Test if the double-precision floating-point operand in register FRA is
   7762     * a NaN:
   7763     */
   7764    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
   7765    /*
   7766     * Test if the double-precision floating-point operand in register FRA is
   7767     * an Infinity.
   7768     */
   7769    assign(fraInf_tmp, is_Inf(frA_int, sp));
   7770 
   7771    /*
   7772     * Test if the double-precision floating-point operand in register FRB is
   7773     * a NaN:
   7774     */
   7775    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
   7776    /*
   7777     * Test if the double-precision floating-point operand in register FRB is
   7778     * an Infinity.
   7779     */
   7780    assign( frbInf_tmp, is_Inf(frB_int, sp) );
   7781    /*
   7782     * Test if the double-precision floating-point operand in register FRB is
   7783     * a Zero.
   7784     */
   7785    assign( frbZero_tmp, is_Zero(frB_int, sp) );
   7786 
   7787    /*
   7788     * Test if e_b <= -1022 for double precision;
   7789     * or e_b <= -126 for single precision
   7790     */
   7791    {
   7792       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
   7793       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
   7794    }
   7795 
   7796    /*
   7797     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
   7798     * or e_b >= -125 (125 < e_b) for single precision
   7799     */
   7800    {
   7801       Int test_value = sp ? 125 : 1021;
   7802       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
   7803    }
   7804 
   7805    /*
   7806     * Test if FRA != Zero and (e_a - e_b) >= bias
   7807     */
   7808    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
   7809    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
   7810                        binop( Iop_CmpLT32S, mkU32( bias ),
   7811                               binop( Iop_Sub32, mkexpr( e_a ),
   7812                                      mkexpr( e_b ) ) ) );
   7813 
   7814    /*
   7815     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
   7816     */
   7817    {
   7818       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
   7819 
   7820       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
   7821                           binop( Iop_CmpLE32S,
   7822                                  binop( Iop_Sub32,
   7823                                         mkexpr( e_a ),
   7824                                         mkexpr( e_b ) ),
   7825                                         mkU32( test_value ) ) );
   7826    }
   7827 
   7828    /*
   7829     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
   7830     */
   7831    {
   7832       UInt test_value = 0xfffffc36;  //Int test_value = -970;
   7833 
   7834       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
   7835                                                         mkexpr( e_a ),
   7836                                                         mkU32( test_value ) ) );
   7837    }
   7838    //////////////////  fe_flag tests END //////////////////////
   7839 
   7840    //////////////////  fg_flag tests BEGIN //////////////////////
   7841    /*
   7842     * The following tests were already performed above in the fe_flag
   7843     * tests.  So these conditions will result in both fe_ and fg_ flags
   7844     * being set.
   7845     *   - Test if FRA is an Infinity
   7846     *   - Test if FRB ix Zero
   7847     *   - Test if FRB is an Infinity
   7848     */
   7849 
   7850    /*
   7851     * Test if FRB holds a denormalized value.  A denormalized value is one where
   7852     * the exp is 0 and the fraction is non-zero.
   7853     */
   7854    {
   7855       IRExpr * fraction_is_nonzero;
   7856 
   7857       if (sp) {
   7858          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
   7859                                       mkU32( 0 ) );
   7860       } else {
   7861          IRExpr * hi32, * low32;
   7862          IRTemp frac_part = newTemp(Ity_I64);
   7863          assign( frac_part, FP_FRAC_PART(frB_int) );
   7864 
   7865          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   7866          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   7867          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   7868                                       mkU32( 0 ) );
   7869       }
   7870       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
   7871                                  mkU32( 0x0 ) ), fraction_is_nonzero );
   7872 
   7873    }
   7874    //////////////////  fg_flag tests END //////////////////////
   7875 
   7876    fe_flag
   7877    = mkOR1(
   7878             fraNaN,
   7879             mkOR1(
   7880                    mkexpr( fraInf_tmp ),
   7881                    mkOR1(
   7882                           mkexpr( frbZero_tmp ),
   7883                           mkOR1(
   7884                                  frbNaN,
   7885                                  mkOR1(
   7886                                         mkexpr( frbInf_tmp ),
   7887                                         mkOR1( eb_LTE,
   7888                                                mkOR1( eb_GTE,
   7889                                                       mkOR1( ea_eb_GTE,
   7890                                                              mkOR1( ea_eb_LTE,
   7891                                                                     ea_LTE ) ) ) ) ) ) ) ) );
   7892 
   7893    fe_flag = unop(Iop_1Uto32, fe_flag);
   7894 
   7895    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
   7896                                                  mkOR1( mkexpr( frbInf_tmp ),
   7897                                                         frbDenorm ) ) );
   7898    fg_flag = unop(Iop_1Uto32, fg_flag);
   7899    assign(*fe_flag_tmp, fe_flag);
   7900    assign(*fg_flag_tmp, fg_flag);
   7901 }
   7902 
   7903 /* See description for _do_fp_tdiv() above. */
   7904 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
   7905 {
   7906    IRTemp  fe_flag, fg_flag;
   7907    /////////////////////////
   7908    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   7909     * where fl_flag == 1 on ppc64.
   7910     */
   7911    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
   7912    fe_flag = fg_flag = IRTemp_INVALID;
   7913    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
   7914    return binop( Iop_Or32,
   7915                  binop( Iop_Or32,
   7916                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
   7917                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   7918                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
   7919 }
   7920 
   7921 static Bool dis_fp_tests ( UInt theInstr )
   7922 {
   7923    UChar opc1     = ifieldOPC(theInstr);
   7924    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7925    UChar frB_addr = ifieldRegB(theInstr);
   7926    UChar b0       = ifieldBIT0(theInstr);
   7927    UInt  opc2     = ifieldOPClo10(theInstr);
   7928    IRTemp frB_I64     = newTemp(Ity_I64);
   7929 
   7930    if (opc1 != 0x3F || b0 != 0 ){
   7931       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   7932       return False;
   7933    }
   7934    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
   7935 
   7936    switch (opc2) {
   7937       case 0x080: // ftdiv
   7938       {
   7939          UChar frA_addr = ifieldRegA(theInstr);
   7940          IRTemp frA_I64     = newTemp(Ity_I64);
   7941          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7942          if (b21to22 != 0 ) {
   7943             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   7944             return False;
   7945          }
   7946 
   7947          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
   7948          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   7949 
   7950          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   7951          break;
   7952       }
   7953       case 0x0A0: // ftsqrt
   7954       {
   7955          IRTemp flags = newTemp(Ity_I32);
   7956          IRTemp  fe_flag, fg_flag;
   7957          fe_flag = fg_flag = IRTemp_INVALID;
   7958          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
   7959          if ( b18to22 != 0) {
   7960             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
   7961             return False;
   7962          }
   7963          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
   7964          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
   7965          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   7966           * where fl_flag == 1 on ppc64.
   7967           */
   7968          assign( flags,
   7969                  binop( Iop_Or32,
   7970                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   7971                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   7972                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   7973          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   7974          break;
   7975       }
   7976 
   7977       default:
   7978          vex_printf("dis_fp_tests(ppc)(opc2)\n");
   7979          return False;
   7980 
   7981    }
   7982    return True;
   7983 }
   7984 
   7985 /*
   7986   Floating Point Compare Instructions
   7987 */
   7988 static Bool dis_fp_cmp ( UInt theInstr )
   7989 {
   7990    /* X-Form */
   7991    UChar opc1     = ifieldOPC(theInstr);
   7992    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7993    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7994    UChar frA_addr = ifieldRegA(theInstr);
   7995    UChar frB_addr = ifieldRegB(theInstr);
   7996    UInt  opc2     = ifieldOPClo10(theInstr);
   7997    UChar b0       = ifieldBIT0(theInstr);
   7998 
   7999    IRTemp ccIR    = newTemp(Ity_I32);
   8000    IRTemp ccPPC32 = newTemp(Ity_I32);
   8001 
   8002    IRTemp frA     = newTemp(Ity_F64);
   8003    IRTemp frB     = newTemp(Ity_F64);
   8004 
   8005    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   8006       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   8007       return False;
   8008    }
   8009 
   8010    assign( frA, getFReg(frA_addr));
   8011    assign( frB, getFReg(frB_addr));
   8012 
   8013    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   8014 
   8015    /* Map compare result from IR to PPC32 */
   8016    /*
   8017      FP cmp result | PPC | IR
   8018      --------------------------
   8019      UN            | 0x1 | 0x45
   8020      EQ            | 0x2 | 0x40
   8021      GT            | 0x4 | 0x00
   8022      LT            | 0x8 | 0x01
   8023    */
   8024 
   8025    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   8026    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   8027    assign(
   8028       ccPPC32,
   8029       binop(
   8030          Iop_Shl32,
   8031          mkU32(1),
   8032          unop(
   8033             Iop_32to8,
   8034             binop(
   8035                Iop_Or32,
   8036                binop(
   8037                   Iop_And32,
   8038                   unop(
   8039                      Iop_Not32,
   8040                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   8041                   ),
   8042                   mkU32(2)
   8043                ),
   8044                binop(
   8045                   Iop_And32,
   8046                   binop(
   8047                      Iop_Xor32,
   8048                      mkexpr(ccIR),
   8049                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   8050                   ),
   8051                   mkU32(1)
   8052                )
   8053             )
   8054          )
   8055       )
   8056    );
   8057 
   8058    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   8059 
   8060    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   8061       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   8062    */
   8063    // XXX XXX XXX FIXME
   8064    // Also write the result into FPRF (it's not entirely clear how)
   8065 
   8066    /* Note: Differences between fcmpu and fcmpo are only in exception
   8067       flag settings, which aren't supported anyway. */
   8068    switch (opc2) {
   8069    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   8070       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8071       break;
   8072    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   8073       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8074       break;
   8075    default:
   8076       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   8077       return False;
   8078    }
   8079    return True;
   8080 }
   8081 
   8082 
   8083 
   8084 /*
   8085   Floating Point Rounding/Conversion Instructions
   8086 */
   8087 static Bool dis_fp_round ( UInt theInstr )
   8088 {
   8089    /* X-Form */
   8090    UChar opc1     = ifieldOPC(theInstr);
   8091    UChar b16to20  = ifieldRegA(theInstr);
   8092    UChar frD_addr = ifieldRegDS(theInstr);
   8093    UChar frB_addr = ifieldRegB(theInstr);
   8094    UInt  opc2     = ifieldOPClo10(theInstr);
   8095    UChar flag_rC  = ifieldBIT0(theInstr);
   8096 
   8097    IRTemp  frD     = newTemp(Ity_F64);
   8098    IRTemp  frB     = newTemp(Ity_F64);
   8099    IRTemp  r_tmp32 = newTemp(Ity_I32);
   8100    IRTemp  r_tmp64 = newTemp(Ity_I64);
   8101    IRExpr* rm      = get_IR_roundingmode();
   8102 
   8103    /* By default, we will examine the results of the operation and set
   8104       fpscr[FPRF] accordingly. */
   8105    Bool set_FPRF = True;
   8106 
   8107    /* By default, if flag_RC is set, we will clear cr1 after the
   8108       operation.  In reality we should set cr1 to indicate the
   8109       exception status of the operation, but since we're not
   8110       simulating exceptions, the exception status will appear to be
   8111       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8112    Bool clear_CR1 = True;
   8113    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
   8114       vex_printf("dis_fp_round(ppc)(instr)\n");
   8115       return False;
   8116    }
   8117 
   8118    assign( frB, getFReg(frB_addr));
   8119    if (opc1 == 0x3B) {
   8120       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
   8121        * they're very similar to the other instructions handled here, but have
   8122        * a different primary opcode.
   8123        */
   8124       switch (opc2) {
   8125          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
   8126             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8127             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8128             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
   8129                                                               mkexpr( r_tmp64 ) ) ) );
   8130             goto putFR;
   8131 
   8132          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
   8133             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8134             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8135             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
   8136             goto putFR;
   8137       }
   8138    }
   8139 
   8140 
   8141    switch (opc2) {
   8142    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   8143       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8144       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   8145       break;
   8146 
   8147    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   8148       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8149       assign( r_tmp32,
   8150               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   8151       assign( frD, unop( Iop_ReinterpI64asF64,
   8152                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8153       /* FPRF is undefined after fctiw.  Leave unchanged. */
   8154       set_FPRF = False;
   8155       break;
   8156 
   8157    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   8158       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8159       assign( r_tmp32,
   8160               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   8161       assign( frD, unop( Iop_ReinterpI64asF64,
   8162                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8163       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8164       set_FPRF = False;
   8165       break;
   8166 
   8167    case 0x08F: case 0x08E: // fctiwu[z]
   8168       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
   8169                flag_rC ? ".":"", frD_addr, frB_addr);
   8170       assign( r_tmp32,
   8171               binop( Iop_F64toI32U,
   8172                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
   8173                      mkexpr( frB ) ) );
   8174       assign( frD, unop( Iop_ReinterpI64asF64,
   8175                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   8176       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   8177       set_FPRF = False;
   8178       break;
   8179 
   8180 
   8181    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   8182       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8183       assign( r_tmp64,
   8184               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   8185       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8186       /* FPRF is undefined after fctid.  Leave unchanged. */
   8187       set_FPRF = False;
   8188       break;
   8189 
   8190    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   8191       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8192       assign( r_tmp64,
   8193               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   8194       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8195       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8196       set_FPRF = False;
   8197       break;
   8198 
   8199    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
   8200    {
   8201       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
   8202                flag_rC ? ".":"", frD_addr, frB_addr);
   8203       assign( r_tmp64,
   8204               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
   8205       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   8206       /* FPRF is undefined after fctidz.  Leave unchanged. */
   8207       set_FPRF = False;
   8208       break;
   8209    }
   8210    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   8211       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8212       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8213       assign( frD,
   8214               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   8215       break;
   8216 
   8217    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
   8218       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8219       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   8220       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
   8221       break;
   8222 
   8223    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   8224       switch(opc2) {
   8225       case 0x188: // frin (Floating Round to Integer Nearest)
   8226          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8227          assign( r_tmp64,
   8228                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   8229          break;
   8230       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   8231          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8232          assign( r_tmp64,
   8233                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   8234          break;
   8235       case 0x1C8: // frip (Floating Round to Integer Plus)
   8236          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8237          assign( r_tmp64,
   8238                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   8239          break;
   8240       case 0x1E8: // frim (Floating Round to Integer Minus)
   8241          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8242          assign( r_tmp64,
   8243                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   8244          break;
   8245       }
   8246 
   8247       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   8248       /* F64 has only log10(2**52) significant digits anyway */
   8249       /* need to preserve sign of zero */
   8250       /*   frD = (fabs(frB) > 9e18) ? frB :
   8251                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   8252       assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
   8253                                      binop(Iop_CmpF64,
   8254                                            IRExpr_Const(IRConst_F64(9e18)),
   8255                                            unop(Iop_AbsF64, mkexpr(frB)))),
   8256                                 IRExpr_Mux0X(unop(Iop_32to8,
   8257                                                   binop(Iop_Shr32,
   8258                                                         unop(Iop_64HIto32,
   8259                                                              unop(Iop_ReinterpF64asI64,
   8260                                                                   mkexpr(frB))), mkU8(31))),
   8261                                              binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
   8262                                              unop(Iop_NegF64,
   8263                                                   unop( Iop_AbsF64,
   8264                                                         binop(Iop_I64StoF64, mkU32(0),
   8265                                                               mkexpr(r_tmp64)) )) ),
   8266                                 mkexpr(frB)));
   8267       break;
   8268 
   8269    default:
   8270       vex_printf("dis_fp_round(ppc)(opc2)\n");
   8271       return False;
   8272    }
   8273 putFR:
   8274    putFReg( frD_addr, mkexpr(frD) );
   8275 
   8276    if (set_FPRF) {
   8277       // XXX XXX XXX FIXME
   8278       // set FPRF from frD
   8279    }
   8280 
   8281    if (flag_rC && clear_CR1) {
   8282       putCR321( 1, mkU8(0) );
   8283       putCR0( 1, mkU8(0) );
   8284    }
   8285 
   8286    return True;
   8287 }
   8288 
   8289 /*
   8290   Floating Point Pair Instructions
   8291 */
   8292 static Bool dis_fp_pair ( UInt theInstr )
   8293 {
   8294    /* X-Form/DS-Form */
   8295    UChar  opc1         = ifieldOPC(theInstr);
   8296    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   8297    UChar  frT_lo_addr  = frT_hi_addr + 1;
   8298    UChar  rA_addr      = ifieldRegA(theInstr);
   8299    UChar  rB_addr      = ifieldRegB(theInstr);
   8300    UInt  uimm16        = ifieldUIMM16(theInstr);
   8301    Int    simm16       = extend_s_16to32(uimm16);
   8302    UInt   opc2         = ifieldOPClo10(theInstr);
   8303    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   8304    IRTemp EA_hi        = newTemp(ty);
   8305    IRTemp EA_lo        = newTemp(ty);
   8306    IRTemp frT_hi       = newTemp(Ity_F64);
   8307    IRTemp frT_lo       = newTemp(Ity_F64);
   8308    UChar b0            = ifieldBIT0(theInstr);
   8309    Bool is_load        = 0;
   8310 
   8311    if ((frT_hi_addr %2) != 0) {
   8312       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   8313       return False;
   8314    }
   8315 
   8316    switch (opc1) {
   8317    case 0x1F: // register offset
   8318       switch(opc2) {
   8319       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   8320          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8321          is_load = 1;
   8322          break;
   8323       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   8324          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8325          break;
   8326       default:
   8327          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   8328          return False;
   8329       }
   8330 
   8331       if (b0 != 0) {
   8332          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   8333          return False;
   8334       }
   8335       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   8336       break;
   8337    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   8338       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8339       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8340       is_load = 1;
   8341       break;
   8342    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   8343       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8344       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8345       break;
   8346    default:   // immediate offset
   8347       vex_printf("dis_fp_pair(ppc)(instr)\n");
   8348       return False;
   8349    }
   8350 
   8351    if (mode64)
   8352       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   8353    else
   8354       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   8355 
   8356    assign( frT_hi, getFReg(frT_hi_addr) );
   8357    assign( frT_lo, getFReg(frT_lo_addr) );
   8358 
   8359    if (is_load) {
   8360       putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
   8361       putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
   8362    } else {
   8363       storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
   8364       storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
   8365    }
   8366 
   8367    return True;
   8368 }
   8369 
   8370 
   8371 /*
   8372   Floating Point Move Instructions
   8373 */
   8374 static Bool dis_fp_move ( UInt theInstr )
   8375 {
   8376    /* X-Form */
   8377    UChar opc1     = ifieldOPC(theInstr);
   8378    UChar frD_addr = ifieldRegDS(theInstr);
   8379    UChar frA_addr = ifieldRegA(theInstr);
   8380    UChar frB_addr = ifieldRegB(theInstr);
   8381    UInt  opc2     = ifieldOPClo10(theInstr);
   8382    UChar flag_rC  = ifieldBIT0(theInstr);
   8383 
   8384    IRTemp frD = newTemp(Ity_F64);
   8385    IRTemp frB = newTemp(Ity_F64);
   8386    IRTemp itmpB = newTemp(Ity_F64);
   8387    IRTemp frA;
   8388    IRTemp signA;
   8389    IRTemp hiD;
   8390 
   8391    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   8392       vex_printf("dis_fp_move(ppc)(instr)\n");
   8393       return False;
   8394    }
   8395 
   8396    assign( frB, getFReg(frB_addr));
   8397 
   8398    switch (opc2) {
   8399    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   8400       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   8401           frB_addr);
   8402       signA = newTemp(Ity_I32);
   8403       hiD = newTemp(Ity_I32);
   8404       itmpB = newTemp(Ity_I64);
   8405       frA = newTemp(Ity_F64);
   8406       assign( frA, getFReg(frA_addr) );
   8407 
   8408       /* get A's sign bit */
   8409       assign(signA, binop(Iop_And32,
   8410                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   8411                                                   mkexpr(frA))),
   8412                           mkU32(0x80000000)) );
   8413 
   8414       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   8415 
   8416       /* mask off B's sign bit and or in A's sign bit */
   8417       assign(hiD, binop(Iop_Or32,
   8418                         binop(Iop_And32,
   8419                               unop(Iop_64HIto32,
   8420                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   8421                               mkU32(0x7fffffff)),
   8422                         mkexpr(signA)) );
   8423 
   8424       /* combine hiD/loB into frD */
   8425       assign( frD, unop(Iop_ReinterpI64asF64,
   8426                         binop(Iop_32HLto64,
   8427                               mkexpr(hiD),
   8428                               unop(Iop_64to32,
   8429                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   8430       break;
   8431 
   8432    case 0x028: // fneg (Floating Negate, PPC32 p416)
   8433       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8434       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   8435       break;
   8436 
   8437    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   8438       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8439       assign( frD, mkexpr(frB) );
   8440       break;
   8441 
   8442    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   8443       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8444       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   8445       break;
   8446 
   8447    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   8448       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8449       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   8450       break;
   8451 
   8452    default:
   8453       vex_printf("dis_fp_move(ppc)(opc2)\n");
   8454       return False;
   8455    }
   8456 
   8457    putFReg( frD_addr, mkexpr(frD) );
   8458 
   8459    /* None of these change FPRF.  cr1 is set in the usual way though,
   8460       if flag_rC is set. */
   8461 
   8462    if (flag_rC) {
   8463       putCR321( 1, mkU8(0) );
   8464       putCR0( 1, mkU8(0) );
   8465    }
   8466 
   8467    return True;
   8468 }
   8469 
   8470 
   8471 
   8472 /*
   8473   Floating Point Status/Control Register Instructions
   8474 */
   8475 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
   8476 {
   8477    /* Many forms - see each switch case */
   8478    UChar opc1    = ifieldOPC(theInstr);
   8479    UInt  opc2    = ifieldOPClo10(theInstr);
   8480    UChar flag_rC = ifieldBIT0(theInstr);
   8481 
   8482    if (opc1 != 0x3F) {
   8483       vex_printf("dis_fp_scr(ppc)(instr)\n");
   8484       return False;
   8485    }
   8486 
   8487    switch (opc2) {
   8488    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   8489       // Bit crbD of the FPSCR is set.
   8490       UChar crbD    = ifieldRegDS(theInstr);
   8491       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   8492 
   8493       if (b11to20 != 0) {
   8494          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   8495          return False;
   8496       }
   8497       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   8498       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
   8499 		     1ULL << ( 31 - crbD ) );
   8500       break;
   8501    }
   8502 
   8503    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   8504       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   8505       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   8506       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   8507       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   8508       IRTemp  tmp     = newTemp(Ity_I32);
   8509       IRExpr* fpscr_all;
   8510       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   8511          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   8512          return False;
   8513       }
   8514       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   8515       vassert(crfD < 8);
   8516       vassert(crfS < 8);
   8517       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   8518       assign( tmp, binop(Iop_And32,
   8519                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   8520                         mkU32(0xF)) );
   8521       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   8522       break;
   8523    }
   8524 
   8525    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   8526       // Bit crbD of the FPSCR is cleared.
   8527       UChar crbD    = ifieldRegDS(theInstr);
   8528       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   8529 
   8530       if (b11to20 != 0) {
   8531          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   8532          return False;
   8533       }
   8534       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   8535       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
   8536       break;
   8537    }
   8538 
   8539    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   8540       UInt crfD     = IFIELD( theInstr, 23, 3 );
   8541       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   8542       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   8543       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   8544       UChar Wbit;
   8545 
   8546       if (b16to22 != 0 || b11 != 0) {
   8547          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   8548          return False;
   8549       }
   8550       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
   8551       if (GX_level) {
   8552          /* This implies that Decimal Floating Point is supported, and the
   8553           * FPSCR must be managed as a 64-bit register.
   8554           */
   8555          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   8556       } else {
   8557          Wbit = 0;
   8558       }
   8559       crfD = crfD + (8 * (1 - Wbit) );
   8560       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
   8561       break;
   8562    }
   8563 
   8564    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   8565       UChar   frD_addr  = ifieldRegDS(theInstr);
   8566       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   8567       IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   8568       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
   8569                                                  MASK_FPSCR_DRN );
   8570 
   8571       if (b11to20 != 0) {
   8572          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   8573          return False;
   8574       }
   8575       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   8576       putFReg( frD_addr,
   8577           unop( Iop_ReinterpI64asF64,
   8578                 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
   8579       break;
   8580    }
   8581 
   8582    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   8583       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   8584       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   8585       UChar frB_addr = ifieldRegB(theInstr);
   8586       IRTemp frB   = newTemp(Ity_F64);
   8587       IRTemp rB_64 = newTemp( Ity_I64 );
   8588       Int i;
   8589       ULong mask;
   8590       UChar Wbit;
   8591 #define BFP_MASK_SEED 0x3000000000000000ULL
   8592 #define DFP_MASK_SEED 0x7000000000000000ULL
   8593 
   8594       if (GX_level) {
   8595          /* This implies that Decimal Floating Point is supported, and the
   8596           * FPSCR must be managed as a 64-bit register.
   8597           */
   8598          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   8599       } else {
   8600          Wbit = 0;
   8601       }
   8602 
   8603       if (b25 == 1) {
   8604          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   8605           * a one do a full 64 bit move.  Note, the FPSCR is not really
   8606           * properly modeled.  This instruciton only changes the value of
   8607           * the rounding mode.  The HW exception bits do not get set in
   8608           * the simulator.  1/12/09
   8609           */
   8610          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   8611          mask = 0xFF;
   8612 
   8613       } else {
   8614          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   8615          // Build 32bit mask from FM:
   8616          mask = 0;
   8617          for (i=0; i<8; i++) {
   8618             if ((FM & (1<<(7-i))) == 1) {
   8619                /* FPSCR field k is set to the contents of the corresponding
   8620                 * field of register FRB, where k = i+8x(1-W).  In the Power
   8621                 * ISA, register field numbering is from left to right, so field
   8622                 * 15 is the least significant field in a 64-bit register.  To
   8623                 * generate the mask, we set all the appropriate rounding mode
   8624                 * bits in the highest order nibble (field 0) and shift right
   8625                 * 'k x nibble length'.
   8626                 */
   8627                if (Wbit)
   8628                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   8629                else
   8630                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   8631             }
   8632          }
   8633       }
   8634       assign( frB, getFReg(frB_addr));
   8635       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   8636       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
   8637       break;
   8638    }
   8639 
   8640    default:
   8641       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   8642       return False;
   8643    }
   8644    return True;
   8645 }
   8646 
   8647 /*------------------------------------------------------------*/
   8648 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
   8649 /*------------------------------------------------------------*/
   8650 #define DFP_LONG  1
   8651 #define DFP_EXTND 2
   8652 #define DFP_LONG_BIAS   398
   8653 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
   8654 #define DFP_EXTND_BIAS  6176
   8655 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
   8656 #define DFP_LONG_EXP_MSK   0XFF
   8657 #define DFP_EXTND_EXP_MSK  0XFFF
   8658 
   8659 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
   8660 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
   8661 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
   8662 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
   8663 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
   8664 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
   8665 #define DFP_LONG_EXP_MAX          369      // biased max
   8666 #define DFP_LONG_EXP_MIN          0        // biased min
   8667 #define DFP_EXTND_EXP_MAX         6111     // biased max
   8668 #define DFP_EXTND_EXP_MIN         0        // biased min
   8669 #define DFP_LONG_MAX_SIG_DIGITS   16
   8670 #define DFP_EXTND_MAX_SIG_DIGITS  34
   8671 #define MAX_DIGITS_IN_STRING      8
   8672 
   8673 
   8674 #define  AND(x, y) binop( Iop_And32, x, y )
   8675 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
   8676 #define   OR(x, y) binop( Iop_Or32,  x, y )
   8677 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
   8678 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
   8679 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
   8680 
   8681 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
   8682 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
   8683 
   8684 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
   8685    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
   8686     ((_b1) << 1) | ((_b0) << 0))
   8687 
   8688 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
   8689 {
   8690    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   8691    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
   8692    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
   8693    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
   8694    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
   8695    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
   8696    IRTemp lmd_07_val    = newTemp( Ity_I32 );
   8697    IRTemp lmd_8_val     = newTemp( Ity_I32 );
   8698    IRTemp lmd_9_val     = newTemp( Ity_I32 );
   8699 
   8700    /* The encodig is as follows:
   8701     * lmd - left most digit
   8702     * lme - left most 2-bits of the exponent
   8703     *
   8704     *    lmd
   8705     *   0 - 7    (lmexp << 3) | lmd
   8706     *     8      0b11000 (24 decimal) if lme=0b00;
   8707     *            0b11010 (26 decimal) if lme=0b01;
   8708     *            0b11100 (28 decimal) if lme=0b10;
   8709     *     9      0b11001 (25 decimal) if lme=0b00;
   8710     *            0b11011 (27 decimal) if lme=0b01;
   8711     *            0b11101 (29 decimal) if lme=0b10;
   8712     */
   8713 
   8714    /* Generate the masks for each condition */
   8715    assign( lmd_07_mask,
   8716            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
   8717    assign( lmd_8_mask,
   8718            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
   8719    assign( lmd_9_mask,
   8720            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
   8721    assign( lmexp_00_mask,
   8722            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
   8723    assign( lmexp_01_mask,
   8724            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
   8725    assign( lmexp_10_mask,
   8726            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
   8727 
   8728    /* Generate the values for each LMD condition, assuming the condition
   8729     * is TRUE.
   8730     */
   8731    assign( lmd_07_val,
   8732            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
   8733    assign( lmd_8_val,
   8734            binop( Iop_Or32,
   8735                   binop( Iop_Or32,
   8736                          binop( Iop_And32,
   8737                                 mkexpr( lmexp_00_mask ),
   8738                                 mkU32( 24 ) ),
   8739                          binop( Iop_And32,
   8740                                 mkexpr( lmexp_01_mask ),
   8741                                 mkU32( 26 ) ) ),
   8742                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
   8743    assign( lmd_9_val,
   8744            binop( Iop_Or32,
   8745                   binop( Iop_Or32,
   8746                          binop( Iop_And32,
   8747                                 mkexpr( lmexp_00_mask ),
   8748                                 mkU32( 25 ) ),
   8749                          binop( Iop_And32,
   8750                                 mkexpr( lmexp_01_mask ),
   8751                                 mkU32( 27 ) ) ),
   8752                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
   8753 
   8754    /* generate the result from the possible LMD values */
   8755    return binop( Iop_Or32,
   8756                  binop( Iop_Or32,
   8757                         binop( Iop_And32,
   8758                                mkexpr( lmd_07_mask ),
   8759                                mkexpr( lmd_07_val ) ),
   8760                         binop( Iop_And32,
   8761                                mkexpr( lmd_8_mask ),
   8762                                mkexpr( lmd_8_val ) ) ),
   8763                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
   8764 }
   8765 
   8766 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
   8767 {
   8768    /* Extract the exponent and the left most digit of the mantissa
   8769     * from the G field bits [0:4].
   8770     */
   8771    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   8772    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
   8773    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
   8774    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
   8775    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
   8776    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
   8777    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
   8778 
   8779    IRTemp lmd_07_val = newTemp( Ity_I32 );
   8780    IRTemp lmd_8_val  = newTemp( Ity_I32 );
   8781    IRTemp lmd_9_val  = newTemp( Ity_I32 );
   8782 
   8783    /* The left most digit (LMD) encoding is as follows:
   8784     *    lmd
   8785     *   0 - 7    (lmexp << 3) | lmd
   8786     *     8      0b11000 (24 decimal) if lme=0b00;
   8787     *            0b11010 (26 decimal) if lme=0b01;
   8788     *            0b11100 (28 decimal) if lme=0b10
   8789     *     9      0b11001 (25 decimal) if lme=0b00;
   8790     *            0b11011 (27 decimal) if lme=0b01;
   8791     *            0b11101 (29 decimal) if lme=0b10;
   8792     */
   8793 
   8794    /* Generate the masks for each condition of LMD and exponent bits */
   8795    assign( lmd_07_mask,
   8796            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
   8797                                     gfield_0_4,
   8798                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
   8799    assign( lmd_8_00_mask,
   8800            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8801                                     gfield_0_4,
   8802                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
   8803    assign( lmd_8_01_mask,
   8804            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8805                                     gfield_0_4,
   8806                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
   8807    assign( lmd_8_10_mask,
   8808            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8809                                     gfield_0_4,
   8810                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
   8811    assign( lmd_9_00_mask,
   8812            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8813                                     gfield_0_4,
   8814                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
   8815    assign( lmd_9_01_mask,
   8816            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8817                                     gfield_0_4,
   8818                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
   8819    assign( lmd_9_10_mask,
   8820            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   8821                                     gfield_0_4,
   8822                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
   8823 
   8824    /* Generate the values for each LMD condition, assuming the condition
   8825     * is TRUE.
   8826     */
   8827    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
   8828    assign( lmd_8_val, mkU32( 0x8 ) );
   8829    assign( lmd_9_val, mkU32( 0x9 ) );
   8830 
   8831    assign( *lmd,
   8832            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
   8833                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
   8834                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
   8835                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
   8836                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
   8837                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
   8838                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
   8839                      ) ) );
   8840 }
   8841 
   8842 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
   8843 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
   8844 #define DIGIT3_SHR 12
   8845 #define DIGIT4_SHR 16
   8846 #define DIGIT5_SHR 20
   8847 #define DIGIT6_SHR 24
   8848 #define DIGIT7_SHR 28
   8849 
   8850 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
   8851 {
   8852    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
   8853     * digit is a valid BCD number, i.e. less then 9.
   8854     */
   8855    IRTemp valid = newTemp( Ity_I32 );
   8856 
   8857    assign( valid,
   8858            AND4( AND4 ( unop( Iop_1Sto32,
   8859                               binop( Iop_CmpLE32U,
   8860                                      binop( Iop_And32,
   8861                                             bcd_l,
   8862                                             mkU32 ( 0xF ) ),
   8863                                       mkU32( 0x9 ) ) ),
   8864                         unop( Iop_1Sto32,
   8865                               binop( Iop_CmpLE32U,
   8866                                      binop( Iop_And32,
   8867                                             binop( Iop_Shr32,
   8868                                                    bcd_l,
   8869                                                    mkU8 ( DIGIT1_SHR ) ),
   8870                                              mkU32 ( 0xF ) ),
   8871                                       mkU32( 0x9 ) ) ),
   8872                         unop( Iop_1Sto32,
   8873                               binop( Iop_CmpLE32U,
   8874                                      binop( Iop_And32,
   8875                                             binop( Iop_Shr32,
   8876                                                    bcd_l,
   8877                                                    mkU8 ( DIGIT2_SHR ) ),
   8878                                             mkU32 ( 0xF ) ),
   8879                                       mkU32( 0x9 ) ) ),
   8880                         unop( Iop_1Sto32,
   8881                               binop( Iop_CmpLE32U,
   8882                                      binop( Iop_And32,
   8883                                             binop( Iop_Shr32,
   8884                                                    bcd_l,
   8885                                                    mkU8 ( DIGIT3_SHR ) ),
   8886                                              mkU32 ( 0xF ) ),
   8887                                       mkU32( 0x9 ) ) ) ),
   8888                  AND4 ( unop( Iop_1Sto32,
   8889                               binop( Iop_CmpLE32U,
   8890                                      binop( Iop_And32,
   8891                                             binop( Iop_Shr32,
   8892                                                    bcd_l,
   8893                                                    mkU8 ( DIGIT4_SHR ) ),
   8894                                             mkU32 ( 0xF ) ),
   8895                                      mkU32( 0x9 ) ) ),
   8896                         unop( Iop_1Sto32,
   8897                               binop( Iop_CmpLE32U,
   8898                                      binop( Iop_And32,
   8899                                             binop( Iop_Shr32,
   8900                                                    bcd_l,
   8901                                                    mkU8 ( DIGIT5_SHR ) ),
   8902                                             mkU32 ( 0xF ) ),
   8903                                      mkU32( 0x9 ) ) ),
   8904                         unop( Iop_1Sto32,
   8905                               binop( Iop_CmpLE32U,
   8906                                      binop( Iop_And32,
   8907                                             binop( Iop_Shr32,
   8908                                                    bcd_l,
   8909                                                    mkU8 ( DIGIT6_SHR ) ),
   8910                                             mkU32 ( 0xF ) ),
   8911                                      mkU32( 0x9 ) ) ),
   8912                         unop( Iop_1Sto32,
   8913                               binop( Iop_CmpLE32U,
   8914                                      binop( Iop_And32,
   8915                                             binop( Iop_Shr32,
   8916                                                    bcd_l,
   8917                                                    mkU8 ( DIGIT7_SHR ) ),
   8918                                             mkU32 ( 0xF ) ),
   8919                                      mkU32( 0x9 ) ) ) ),
   8920                  AND4( unop( Iop_1Sto32,
   8921                              binop( Iop_CmpLE32U,
   8922                                     binop( Iop_And32,
   8923                                            bcd_u,
   8924                                            mkU32 ( 0xF ) ),
   8925                                     mkU32( 0x9 ) ) ),
   8926                        unop( Iop_1Sto32,
   8927                              binop( Iop_CmpLE32U,
   8928                                     binop( Iop_And32,
   8929                                            binop( Iop_Shr32,
   8930                                                   bcd_u,
   8931                                                   mkU8 ( DIGIT1_SHR ) ),
   8932                                            mkU32 ( 0xF ) ),
   8933                                     mkU32( 0x9 ) ) ),
   8934                        unop( Iop_1Sto32,
   8935                              binop( Iop_CmpLE32U,
   8936                                     binop( Iop_And32,
   8937                                            binop( Iop_Shr32,
   8938                                                   bcd_u,
   8939                                                   mkU8 ( DIGIT2_SHR ) ),
   8940                                            mkU32 ( 0xF ) ),
   8941                                     mkU32( 0x9 ) ) ),
   8942                        unop( Iop_1Sto32,
   8943                              binop( Iop_CmpLE32U,
   8944                                     binop( Iop_And32,
   8945                                            binop( Iop_Shr32,
   8946                                                   bcd_u,
   8947                                                   mkU8 ( DIGIT3_SHR ) ),
   8948                                            mkU32 ( 0xF ) ),
   8949                                     mkU32( 0x9 ) ) ) ),
   8950                  AND4( unop( Iop_1Sto32,
   8951                              binop( Iop_CmpLE32U,
   8952                                     binop( Iop_And32,
   8953                                            binop( Iop_Shr32,
   8954                                                   bcd_u,
   8955                                                   mkU8 ( DIGIT4_SHR ) ),
   8956                                            mkU32 ( 0xF ) ),
   8957                                     mkU32( 0x9 ) ) ),
   8958                        unop( Iop_1Sto32,
   8959                              binop( Iop_CmpLE32U,
   8960                                     binop( Iop_And32,
   8961                                            binop( Iop_Shr32,
   8962                                                   bcd_u,
   8963                                                   mkU8 ( DIGIT5_SHR ) ),
   8964                                            mkU32 ( 0xF ) ),
   8965                                     mkU32( 0x9 ) ) ),
   8966                        unop( Iop_1Sto32,
   8967                              binop( Iop_CmpLE32U,
   8968                                     binop( Iop_And32,
   8969                                            binop( Iop_Shr32,
   8970                                                   bcd_u,
   8971                                                   mkU8 ( DIGIT6_SHR ) ),
   8972                                            mkU32 ( 0xF ) ),
   8973                                     mkU32( 0x9 ) ) ),
   8974                        unop( Iop_1Sto32,
   8975                              binop( Iop_CmpLE32U,
   8976                                     binop( Iop_And32,
   8977                                            binop( Iop_Shr32,
   8978                                                   bcd_u,
   8979                                                   mkU8 ( DIGIT7_SHR ) ),
   8980                                            mkU32 ( 0xF ) ),
   8981                                     mkU32( 0x9 ) ) ) ) ) );
   8982 
   8983    return unop( Iop_Not32, mkexpr( valid ) );
   8984 }
   8985 #undef DIGIT1_SHR
   8986 #undef DIGIT2_SHR
   8987 #undef DIGIT3_SHR
   8988 #undef DIGIT4_SHR
   8989 #undef DIGIT5_SHR
   8990 #undef DIGIT6_SHR
   8991 #undef DIGIT7_SHR
   8992 
   8993 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
   8994 {
   8995    return binop( Iop_Or32,
   8996                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
   8997                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
   8998                );
   8999 }
   9000 
   9001 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
   9002 {
   9003    return binop( Iop_Or32,
   9004                  binop( Iop_Or32,
   9005                         unop( Iop_1Sto32,
   9006                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
   9007                         unop( Iop_1Sto32,
   9008                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
   9009                  binop( Iop_Or32,
   9010                         unop( Iop_1Sto32,
   9011                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
   9012                         unop( Iop_1Sto32,
   9013                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
   9014 }
   9015 
   9016 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
   9017                                    IRExpr * neg_sign_mask )
   9018 {
   9019    return binop( Iop_Or32,
   9020                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
   9021                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
   9022 }
   9023 
   9024 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
   9025                                    IRExpr * pos_sign_mask,
   9026                                    IRExpr * neg_sign_mask )
   9027 /* first argument is all 1's if the BCD string had an invalid digit in it. */
   9028 {
   9029    return binop( Iop_Or32,
   9030                  invalid_bcd_mask,
   9031                  unop( Iop_1Sto32,
   9032                        binop( Iop_CmpEQ32,
   9033                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
   9034                               mkU32( 0x0 ) ) ) );
   9035 }
   9036 
   9037 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
   9038                                          IRTemp * top_12_l, IRTemp * mid_60_u,
   9039                                          IRTemp * mid_60_l, IRTemp * low_60_u,
   9040                                          IRTemp * low_60_l)
   9041 {
   9042    IRTemp tmplow60 = newTemp( Ity_I64 );
   9043    IRTemp tmpmid60 = newTemp( Ity_I64 );
   9044    IRTemp tmptop12 = newTemp( Ity_I64 );
   9045    IRTemp low_50   = newTemp( Ity_I64 );
   9046    IRTemp mid_50   = newTemp( Ity_I64 );
   9047    IRTemp top_10   = newTemp( Ity_I64 );
   9048    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
   9049 
   9050    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
   9051 
   9052    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
   9053    assign( low_50,
   9054            binop( Iop_32HLto64,
   9055                   binop( Iop_And32,
   9056                          unop( Iop_64HIto32, frBI64_lo ),
   9057                          mkU32( 0x3FFFF ) ),
   9058                          unop( Iop_64to32, frBI64_lo ) ) );
   9059 
   9060    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9061     * BCD string.
   9062     */
   9063    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
   9064    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
   9065    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
   9066 
   9067    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
   9068     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
   9069     */
   9070    assign( mid_50,
   9071            binop( Iop_32HLto64,
   9072                   binop( Iop_Or32,
   9073                          binop( Iop_Shl32,
   9074                                 binop( Iop_And32,
   9075                                        unop( Iop_64HIto32, frBI64_hi ),
   9076                                        mkU32( 0xF ) ),
   9077                                 mkU8( 14 ) ),
   9078                          binop( Iop_Shr32,
   9079                                 unop( Iop_64to32, frBI64_hi ),
   9080                                 mkU8( 18 ) ) ),
   9081                   binop( Iop_Or32,
   9082                          binop( Iop_Shl32,
   9083                                 unop( Iop_64to32, frBI64_hi ),
   9084                                 mkU8( 14 ) ),
   9085                          binop( Iop_Shr32,
   9086                                 unop( Iop_64HIto32, frBI64_lo ),
   9087                                 mkU8( 18 ) ) ) ) );
   9088 
   9089    /* Convert the 50 bit densely packed BCD string to a 60 bit
   9090     * BCD string.
   9091     */
   9092    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
   9093    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
   9094    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
   9095 
   9096    /* top_10[49:0] = frBI64_hi[45:36]) |  */
   9097    assign( top_10,
   9098            binop( Iop_32HLto64,
   9099                   mkU32( 0 ),
   9100                   binop( Iop_And32,
   9101                          binop( Iop_Shr32,
   9102                                 unop( Iop_64HIto32, frBI64_hi ),
   9103                                 mkU8( 4 ) ),
   9104                          mkU32( 0x3FF ) ) ) );
   9105 
   9106    /* Convert the 10 bit densely packed BCD string to a 12 bit
   9107     * BCD string.
   9108     */
   9109    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
   9110    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
   9111    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
   9112 }
   9113 
   9114 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
   9115                          IRTemp * final_cnt, IRTemp * final_flag,
   9116                          IRExpr * string )
   9117 {
   9118    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
   9119    int digits = MAX_DIGITS_IN_STRING;
   9120    int i;
   9121 
   9122    cnt[start-1] = newTemp( Ity_I8 );
   9123    flag[start-1] = newTemp( Ity_I8 );
   9124    assign( cnt[start-1], init_cnt);
   9125    assign( flag[start-1], init_flag);
   9126 
   9127    for ( i = start; i <= digits; i++) {
   9128       cnt[i] = newTemp( Ity_I8 );
   9129       flag[i] = newTemp( Ity_I8 );
   9130       assign( cnt[i],
   9131               binop( Iop_Add8,
   9132                      mkexpr( cnt[i-1] ),
   9133                      binop(Iop_And8,
   9134                            unop( Iop_1Uto8,
   9135                                  binop(Iop_CmpEQ32,
   9136                                        binop(Iop_And32,
   9137                                              string,
   9138                                              mkU32( 0xF <<
   9139                                                     ( ( digits - i ) * 4) ) ),
   9140                                        mkU32( 0 ) ) ),
   9141                            binop( Iop_Xor8, /* complement flag */
   9142                                   mkexpr( flag[i - 1] ),
   9143                                   mkU8( 0xFF ) ) ) ) );
   9144 
   9145       /* set flag to 1 if digit was not a zero */
   9146       assign( flag[i],
   9147               binop(Iop_Or8,
   9148                     unop( Iop_1Sto8,
   9149                           binop(Iop_CmpNE32,
   9150                                 binop(Iop_And32,
   9151                                       string,
   9152                                       mkU32( 0xF <<
   9153                                              ( (digits - i) * 4) ) ),
   9154                                 mkU32( 0 ) ) ),
   9155                     mkexpr( flag[i - 1] ) ) );
   9156    }
   9157 
   9158    *final_cnt = cnt[digits];
   9159    *final_flag = flag[digits];
   9160 }
   9161 
   9162 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
   9163                                         IRExpr * low_32 )
   9164 {
   9165    IRTemp num_lmd    = newTemp( Ity_I8 );
   9166    IRTemp num_upper  = newTemp( Ity_I8 );
   9167    IRTemp num_low    = newTemp( Ity_I8 );
   9168    IRTemp lmd_flag   = newTemp( Ity_I8 );
   9169    IRTemp upper_flag = newTemp( Ity_I8 );
   9170    IRTemp low_flag   = newTemp( Ity_I8 );
   9171 
   9172    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   9173    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   9174 
   9175    Count_zeros( 2,
   9176                 mkexpr( num_lmd ),
   9177                 mkexpr( lmd_flag ),
   9178                 &num_upper,
   9179                 &upper_flag,
   9180                 upper_28 );
   9181 
   9182    Count_zeros( 1,
   9183                 mkexpr( num_upper ),
   9184                 mkexpr( upper_flag ),
   9185                 &num_low,
   9186                 &low_flag,
   9187                 low_32 );
   9188 
   9189    return mkexpr( num_low );
   9190 }
   9191 
   9192 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
   9193                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
   9194                                          IRExpr * low_60_u, IRExpr * low_60_l)
   9195 {
   9196    IRTemp num_lmd   = newTemp( Ity_I8 );
   9197    IRTemp num_top   = newTemp( Ity_I8 );
   9198    IRTemp num_mid_u = newTemp( Ity_I8 );
   9199    IRTemp num_mid_l = newTemp( Ity_I8 );
   9200    IRTemp num_low_u = newTemp( Ity_I8 );
   9201    IRTemp num_low_l = newTemp( Ity_I8 );
   9202 
   9203    IRTemp lmd_flag   = newTemp( Ity_I8 );
   9204    IRTemp top_flag   = newTemp( Ity_I8 );
   9205    IRTemp mid_u_flag = newTemp( Ity_I8 );
   9206    IRTemp mid_l_flag = newTemp( Ity_I8 );
   9207    IRTemp low_u_flag = newTemp( Ity_I8 );
   9208    IRTemp low_l_flag = newTemp( Ity_I8 );
   9209 
   9210    /* Check the LMD, digit 16, to see if it is zero. */
   9211    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   9212 
   9213    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   9214 
   9215    Count_zeros( 6,
   9216                 mkexpr( num_lmd ),
   9217                 mkexpr( lmd_flag ),
   9218                 &num_top,
   9219                 &top_flag,
   9220                 top_12_l );
   9221 
   9222    Count_zeros( 1,
   9223                 mkexpr( num_top ),
   9224                 mkexpr( top_flag ),
   9225                 &num_mid_u,
   9226                 &mid_u_flag,
   9227                 binop( Iop_Or32,
   9228                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
   9229                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
   9230 
   9231    Count_zeros( 2,
   9232                 mkexpr( num_mid_u ),
   9233                 mkexpr( mid_u_flag ),
   9234                 &num_mid_l,
   9235                 &mid_l_flag,
   9236                 mid_60_l );
   9237 
   9238    Count_zeros( 1,
   9239                 mkexpr( num_mid_l ),
   9240                 mkexpr( mid_l_flag ),
   9241                 &num_low_u,
   9242                 &low_u_flag,
   9243                 binop( Iop_Or32,
   9244                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
   9245                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
   9246 
   9247    Count_zeros( 2,
   9248                 mkexpr( num_low_u ),
   9249                 mkexpr( low_u_flag ),
   9250                 &num_low_l,
   9251                 &low_l_flag,
   9252                 low_60_l );
   9253 
   9254    return mkexpr( num_low_l );
   9255 }
   9256 
   9257 static IRExpr * Check_unordered(IRExpr * val)
   9258 {
   9259    IRTemp gfield0to5 = newTemp( Ity_I32 );
   9260 
   9261    /* Extract G[0:4] */
   9262    assign( gfield0to5,
   9263            binop( Iop_And32,
   9264                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
   9265                   mkU32( 0x1F ) ) );
   9266 
   9267    /* Check for unordered, return all 1'x if true */
   9268    return binop( Iop_Or32, /* QNaN check */
   9269                  unop( Iop_1Sto32,
   9270                        binop( Iop_CmpEQ32,
   9271                               mkexpr( gfield0to5 ),
   9272                               mkU32( 0x1E ) ) ),
   9273                               unop( Iop_1Sto32, /* SNaN check */
   9274                                     binop( Iop_CmpEQ32,
   9275                                            mkexpr( gfield0to5 ),
   9276                                            mkU32( 0x1F ) ) ) );
   9277 }
   9278 
   9279 #undef AND
   9280 #undef AND4
   9281 #undef OR
   9282 #undef OR3
   9283 #undef OR4
   9284 #undef NOT
   9285 #undef SHR
   9286 #undef SHL
   9287 #undef BITS5
   9288 
   9289 /*------------------------------------------------------------*/
   9290 /*--- Decimal Floating Point (DFP) instruction translation ---*/
   9291 /*------------------------------------------------------------*/
   9292 
   9293 /* DFP Arithmetic instructions */
   9294 static Bool dis_dfp_arith(UInt theInstr)
   9295 {
   9296    UInt opc2 = ifieldOPClo10( theInstr );
   9297    UChar frS_addr = ifieldRegDS( theInstr );
   9298    UChar frA_addr = ifieldRegA( theInstr );
   9299    UChar frB_addr = ifieldRegB( theInstr );
   9300    UChar flag_rC = ifieldBIT0( theInstr );
   9301 
   9302    IRTemp frA = newTemp( Ity_D64 );
   9303    IRTemp frB = newTemp( Ity_D64 );
   9304    IRTemp frS = newTemp( Ity_D64 );
   9305    IRExpr* round = get_IR_roundingmode_DFP();
   9306 
   9307    /* By default, if flag_RC is set, we will clear cr1 after the
   9308     * operation.  In reality we should set cr1 to indicate the
   9309     * exception status of the operation, but since we're not
   9310     * simulating exceptions, the exception status will appear to be
   9311     * zero.  Hence cr1 should be cleared if this is a . form insn.
   9312     */
   9313    Bool clear_CR1 = True;
   9314 
   9315    assign( frA, getDReg( frA_addr ) );
   9316    assign( frB, getDReg( frB_addr ) );
   9317 
   9318    switch (opc2) {
   9319    case 0x2: // dadd
   9320       DIP( "dadd%s fr%u,fr%u,fr%u\n",
   9321            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9322       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9323       break;
   9324    case 0x202: // dsub
   9325       DIP( "dsub%s fr%u,fr%u,fr%u\n",
   9326            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9327       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9328       break;
   9329    case 0x22: // dmul
   9330       DIP( "dmul%s fr%u,fr%u,fr%u\n",
   9331            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9332       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9333       break;
   9334    case 0x222: // ddiv
   9335       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
   9336            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9337       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   9338       break;
   9339    }
   9340 
   9341    putDReg( frS_addr, mkexpr( frS ) );
   9342 
   9343    if (flag_rC && clear_CR1) {
   9344       putCR321( 1, mkU8( 0 ) );
   9345       putCR0( 1, mkU8( 0 ) );
   9346    }
   9347 
   9348    return True;
   9349 }
   9350 
   9351 /* Quad DFP Arithmetic instructions */
   9352 static Bool dis_dfp_arithq(UInt theInstr)
   9353 {
   9354    UInt opc2 = ifieldOPClo10( theInstr );
   9355    UChar frS_addr = ifieldRegDS( theInstr );
   9356    UChar frA_addr = ifieldRegA( theInstr );
   9357    UChar frB_addr = ifieldRegB( theInstr );
   9358    UChar flag_rC = ifieldBIT0( theInstr );
   9359 
   9360    IRTemp frA = newTemp( Ity_D128 );
   9361    IRTemp frB = newTemp( Ity_D128 );
   9362    IRTemp frS = newTemp( Ity_D128 );
   9363    IRExpr* round = get_IR_roundingmode_DFP();
   9364 
   9365    /* By default, if flag_RC is set, we will clear cr1 after the
   9366     * operation.  In reality we should set cr1 to indicate the
   9367     * exception status of the operation, but since we're not
   9368     * simulating exceptions, the exception status will appear to be
   9369     * zero.  Hence cr1 should be cleared if this is a . form insn.
   9370     */
   9371    Bool clear_CR1 = True;
   9372 
   9373    assign( frA, getDReg_pair( frA_addr ) );
   9374    assign( frB, getDReg_pair( frB_addr ) );
   9375 
   9376    switch (opc2) {
   9377    case 0x2: // daddq
   9378       DIP( "daddq%s fr%u,fr%u,fr%u\n",
   9379            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9380       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9381       break;
   9382    case 0x202: // dsubq
   9383       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
   9384            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9385       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9386       break;
   9387    case 0x22: // dmulq
   9388       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
   9389            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9390       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9391       break;
   9392    case 0x222: // ddivq
   9393       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
   9394            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9395       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   9396       break;
   9397    }
   9398 
   9399    putDReg_pair( frS_addr, mkexpr( frS ) );
   9400 
   9401    if (flag_rC && clear_CR1) {
   9402       putCR321( 1, mkU8( 0 ) );
   9403       putCR0( 1, mkU8( 0 ) );
   9404    }
   9405 
   9406    return True;
   9407 }
   9408 
   9409 /* DFP 64-bit logical shift instructions  */
   9410 static Bool dis_dfp_shift(UInt theInstr) {
   9411    UInt opc2       = ifieldOPClo9( theInstr );
   9412    UChar frS_addr  = ifieldRegDS( theInstr );
   9413    UChar frA_addr  = ifieldRegA( theInstr );
   9414    UChar shift_val = IFIELD(theInstr, 10, 6);
   9415    UChar flag_rC   = ifieldBIT0( theInstr );
   9416 
   9417    IRTemp frA = newTemp( Ity_D64 );
   9418    IRTemp frS = newTemp( Ity_D64 );
   9419    Bool clear_CR1 = True;
   9420 
   9421    assign( frA, getDReg( frA_addr ) );
   9422 
   9423    switch (opc2) {
   9424    case 0x42: // dscli
   9425       DIP( "dscli%s fr%u,fr%u,%u\n",
   9426            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9427       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
   9428       break;
   9429    case 0x62: // dscri
   9430       DIP( "dscri%s fr%u,fr%u,%u\n",
   9431            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9432       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
   9433       break;
   9434    }
   9435 
   9436    putDReg( frS_addr, mkexpr( frS ) );
   9437 
   9438    if (flag_rC && clear_CR1) {
   9439       putCR321( 1, mkU8( 0 ) );
   9440       putCR0( 1, mkU8( 0 ) );
   9441    }
   9442 
   9443    return True;
   9444 }
   9445 
   9446 /* Quad DFP  logical shift instructions  */
   9447 static Bool dis_dfp_shiftq(UInt theInstr) {
   9448    UInt opc2       = ifieldOPClo9( theInstr );
   9449    UChar frS_addr  = ifieldRegDS( theInstr );
   9450    UChar frA_addr  = ifieldRegA( theInstr );
   9451    UChar shift_val = IFIELD(theInstr, 10, 6);
   9452    UChar flag_rC   = ifieldBIT0( theInstr );
   9453 
   9454    IRTemp frA = newTemp( Ity_D128 );
   9455    IRTemp frS = newTemp( Ity_D128 );
   9456    Bool clear_CR1 = True;
   9457 
   9458    assign( frA, getDReg_pair( frA_addr ) );
   9459 
   9460    switch (opc2) {
   9461    case 0x42: // dscliq
   9462       DIP( "dscliq%s fr%u,fr%u,%u\n",
   9463            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9464       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
   9465       break;
   9466    case 0x62: // dscriq
   9467       DIP( "dscriq%s fr%u,fr%u,%u\n",
   9468            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   9469       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
   9470       break;
   9471    }
   9472 
   9473    putDReg_pair( frS_addr, mkexpr( frS ) );
   9474 
   9475    if (flag_rC && clear_CR1) {
   9476       putCR321( 1, mkU8( 0 ) );
   9477       putCR0( 1, mkU8( 0 ) );
   9478    }
   9479 
   9480    return True;
   9481 }
   9482 
   9483 /* DFP 64-bit format conversion instructions */
   9484 static Bool dis_dfp_fmt_conv(UInt theInstr) {
   9485    UInt opc2      = ifieldOPClo10( theInstr );
   9486    UChar frS_addr = ifieldRegDS( theInstr );
   9487    UChar frB_addr = ifieldRegB( theInstr );
   9488    IRExpr* round  = get_IR_roundingmode_DFP();
   9489    UChar flag_rC  = ifieldBIT0( theInstr );
   9490    IRTemp frB;
   9491    IRTemp frS;
   9492    Bool clear_CR1 = True;
   9493 
   9494    switch (opc2) {
   9495    case 0x102: //dctdp
   9496       DIP( "dctdp%s fr%u,fr%u\n",
   9497            flag_rC ? ".":"", frS_addr, frB_addr );
   9498 
   9499       frB = newTemp( Ity_D64 );
   9500       frS = newTemp( Ity_D64 );
   9501       assign( frB, getDReg( frB_addr ) );
   9502       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
   9503       putDReg( frS_addr, mkexpr( frS ) );
   9504       break;
   9505    case 0x302: // drsp
   9506       DIP( "drsp%s fr%u,fr%u\n",
   9507            flag_rC ? ".":"", frS_addr, frB_addr );
   9508       frB = newTemp( Ity_D64 );
   9509       frS = newTemp( Ity_D64 );
   9510       assign( frB, getDReg( frB_addr ) );
   9511       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
   9512       putDReg( frS_addr, mkexpr( frS ) );
   9513       break;
   9514    case 0x122: // dctfix
   9515       DIP( "dctfix%s fr%u,fr%u\n",
   9516            flag_rC ? ".":"", frS_addr, frB_addr );
   9517       frB = newTemp( Ity_D64 );
   9518       frS = newTemp( Ity_D64 );
   9519       assign( frB, getDReg( frB_addr ) );
   9520       assign( frS, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
   9521       putDReg( frS_addr, mkexpr( frS ) );
   9522       break;
   9523    case 0x322: // dcffix
   9524       DIP( "dcffix%s fr%u,fr%u\n",
   9525            flag_rC ? ".":"", frS_addr, frB_addr );
   9526       frB = newTemp( Ity_D64 );
   9527       frS = newTemp( Ity_D64 );
   9528       assign( frB, getDReg( frB_addr ) );
   9529       assign( frS, binop( Iop_I64StoD64, round, mkexpr( frB ) ) );
   9530       putDReg( frS_addr, mkexpr( frS ) );
   9531       break;
   9532    }
   9533 
   9534    if (flag_rC && clear_CR1) {
   9535       putCR321( 1, mkU8( 0 ) );
   9536       putCR0( 1, mkU8( 0 ) );
   9537    }
   9538 
   9539    return True;
   9540 }
   9541 
   9542 /* Quad DFP format conversion instructions */
   9543 static Bool dis_dfp_fmt_convq(UInt theInstr) {
   9544    UInt opc2      = ifieldOPClo10( theInstr );
   9545    UChar frS_addr = ifieldRegDS( theInstr );
   9546    UChar frB_addr = ifieldRegB( theInstr );
   9547    IRExpr* round  = get_IR_roundingmode_DFP();
   9548    IRTemp frB64   = newTemp( Ity_D64 );
   9549    IRTemp frB128  = newTemp( Ity_D128 );
   9550    IRTemp frS64   = newTemp( Ity_D64 );
   9551    IRTemp frS128  = newTemp( Ity_D128 );
   9552    UChar flag_rC  = ifieldBIT0( theInstr );
   9553    Bool clear_CR1 = True;
   9554 
   9555    switch (opc2) {
   9556    case 0x102: // dctqpq
   9557       DIP( "dctqpq%s fr%u,fr%u\n",
   9558            flag_rC ? ".":"", frS_addr, frB_addr );
   9559       assign( frB64, getDReg( frB_addr ) );
   9560       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
   9561       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   9562       break;
   9563    case 0x122: // dctfixq
   9564       DIP( "dctfixq%s fr%u,fr%u\n",
   9565            flag_rC ? ".":"", frS_addr, frB_addr );
   9566       assign( frB128, getDReg_pair( frB_addr ) );
   9567       assign( frS64, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
   9568       putDReg( frS_addr, mkexpr( frS64 ) );
   9569       break;
   9570    case 0x302: //drdpq
   9571       DIP( "drdpq%s fr%u,fr%u\n",
   9572            flag_rC ? ".":"", frS_addr, frB_addr );
   9573       assign( frB128, getDReg_pair( frB_addr ) );
   9574       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
   9575       putDReg( frS_addr, mkexpr( frS64 ) );
   9576       break;
   9577    case 0x322: // dcffixq
   9578       /* Have to introduce an IOP for this instruction so it will work
   9579        * on POWER 6 because emulating the instruction requires a POWER 7
   9580        * DFP instruction in the emulation code.
   9581        */
   9582       DIP( "dcffixq%s fr%u,fr%u\n",
   9583            flag_rC ? ".":"", frS_addr, frB_addr );
   9584       assign( frB64, getDReg( frB_addr ) );
   9585       assign( frS128, unop( Iop_I64StoD128, mkexpr( frB64 ) ) );
   9586       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   9587       break;
   9588    }
   9589 
   9590    if (flag_rC && clear_CR1) {
   9591       putCR321( 1, mkU8( 0 ) );
   9592       putCR0( 1, mkU8( 0 ) );
   9593    }
   9594 
   9595    return True;
   9596 }
   9597 
   9598 static Bool dis_dfp_round( UInt theInstr ) {
   9599    UChar frS_addr = ifieldRegDS(theInstr);
   9600    UChar R        = IFIELD(theInstr, 16, 1);
   9601    UChar RMC      = IFIELD(theInstr, 9, 2);
   9602    UChar frB_addr = ifieldRegB( theInstr );
   9603    UChar flag_rC  = ifieldBIT0( theInstr );
   9604    IRTemp frB     = newTemp( Ity_D64 );
   9605    IRTemp frS     = newTemp( Ity_D64 );
   9606    UInt opc2      = ifieldOPClo8( theInstr );
   9607    Bool clear_CR1 = True;
   9608 
   9609    switch (opc2) {
   9610    /* drintn, is the same as drintx.  The only difference is this
   9611     * instruction does not generate an exception for an inexact operation.
   9612     * Currently not supporting inexact exceptions.
   9613     */
   9614    case 0x63: // drintx
   9615    case 0xE3: // drintn
   9616       DIP( "drintx/drintn%s fr%u,fr%u\n",
   9617            flag_rC ? ".":"", frS_addr, frB_addr );
   9618 
   9619       /* pass the value of R and RMC in the same field */
   9620       assign( frB, getDReg( frB_addr ) );
   9621       assign( frS, binop( Iop_RoundD64toInt,
   9622                           mkU32( ( R << 3 ) | RMC ),
   9623                           mkexpr( frB ) ) );
   9624       putDReg( frS_addr, mkexpr( frS ) );
   9625       break;
   9626    default:
   9627       vex_printf("dis_dfp_round(ppc)(opc2)\n");
   9628       return False;
   9629    }
   9630 
   9631    if (flag_rC && clear_CR1) {
   9632       putCR321( 1, mkU8( 0 ) );
   9633       putCR0( 1, mkU8( 0 ) );
   9634    }
   9635 
   9636    return True;
   9637 }
   9638 
   9639 static Bool dis_dfp_roundq(UInt theInstr) {
   9640    UChar frS_addr = ifieldRegDS( theInstr );
   9641    UChar frB_addr = ifieldRegB( theInstr );
   9642    UChar R = IFIELD(theInstr, 16, 1);
   9643    UChar RMC = IFIELD(theInstr, 9, 2);
   9644    UChar flag_rC = ifieldBIT0( theInstr );
   9645    IRTemp frB = newTemp( Ity_D128 );
   9646    IRTemp frS = newTemp( Ity_D128 );
   9647    Bool clear_CR1 = True;
   9648    UInt opc2 = ifieldOPClo8( theInstr );
   9649 
   9650    switch (opc2) {
   9651    /* drintnq, is the same as drintxq.  The only difference is this
   9652     * instruction does not generate an exception for an inexact operation.
   9653     * Currently not supporting inexact exceptions.
   9654     */
   9655    case 0x63: // drintxq
   9656    case 0xE3: // drintnq
   9657       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
   9658            flag_rC ? ".":"", frS_addr, frB_addr );
   9659 
   9660       /* pass the value of R and RMC in the same field */
   9661       assign( frB, getDReg_pair( frB_addr ) );
   9662       assign( frS, binop( Iop_RoundD128toInt,
   9663                           mkU32( ( R << 3 ) | RMC ),
   9664                           mkexpr( frB ) ) );
   9665       putDReg_pair( frS_addr, mkexpr( frS ) );
   9666       break;
   9667    default:
   9668       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
   9669       return False;
   9670    }
   9671 
   9672    if (flag_rC && clear_CR1) {
   9673       putCR321( 1, mkU8( 0 ) );
   9674       putCR0( 1, mkU8( 0 ) );
   9675    }
   9676 
   9677    return True;
   9678 }
   9679 
   9680 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
   9681    UInt opc2 = ifieldOPClo8( theInstr );
   9682    UChar frS_addr = ifieldRegDS( theInstr );
   9683    UChar frA_addr = ifieldRegA( theInstr );
   9684    UChar frB_addr = ifieldRegB( theInstr );
   9685    UChar flag_rC = ifieldBIT0( theInstr );
   9686    UInt TE_value = IFIELD(theInstr, 16, 4);
   9687    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   9688    UInt RMC = IFIELD(theInstr, 9, 2);
   9689    IRTemp frA = newTemp( Ity_D64 );
   9690    IRTemp frB = newTemp( Ity_D64 );
   9691    IRTemp frS = newTemp( Ity_D64 );
   9692    Bool clear_CR1 = True;
   9693 
   9694    assign( frB, getDReg( frB_addr ) );
   9695 
   9696    switch (opc2) {
   9697    case 0x43: // dquai
   9698       DIP( "dquai%s fr%u,fr%u,fr%u\n",
   9699            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9700       IRTemp TE_D64 = newTemp( Ity_D64 );
   9701 
   9702       /* Generate a reference DFP value frA with the desired exponent
   9703        * given by TE using significand from frB.  Need to add the bias
   9704        * 398 to TE.  TE is stored as a 2's complement number.
   9705        */
   9706       if (TE_sign == 1) {
   9707          /* Take 2's complement of the 5-bit value and subtract from bias.
   9708           *  Bias is adjusted for the +1 required when taking 2's complement.
   9709           */
   9710          assign( TE_D64,
   9711                  unop( Iop_ReinterpI64asD64,
   9712                        binop( Iop_Sub64, mkU64( 397 ),
   9713                               binop( Iop_And64, mkU64( 0xF ),
   9714                                      unop( Iop_Not64, mkU64( TE_value ) )
   9715                                            ) ) ) );
   9716 
   9717       } else {
   9718          assign( TE_D64,
   9719                  unop( Iop_ReinterpI64asD64,
   9720                        binop( Iop_Add64, mkU64( 398 ), mkU64( TE_value ) ) ) );
   9721       }
   9722 
   9723       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_D64 ),
   9724                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
   9725 
   9726       assign( frS, triop( Iop_QuantizeD64,
   9727                           mkU32( RMC ),
   9728                           mkexpr( frA ),
   9729                           mkexpr( frB ) ) );
   9730       break;
   9731 
   9732    case 0x3: // dqua
   9733       DIP( "dqua%s fr%u,fr%u,fr%u\n",
   9734            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9735       assign( frA, getDReg( frA_addr ) );
   9736       assign( frS, triop( Iop_QuantizeD64,
   9737                           mkU32( RMC ),
   9738                           mkexpr( frA ),
   9739                           mkexpr( frB ) ) );
   9740       break;
   9741    case 0x23: // drrnd
   9742       DIP( "drrnd%s fr%u,fr%u,fr%u\n",
   9743            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9744       assign( frA, getDReg( frA_addr ) );
   9745       assign( frS, triop( Iop_SignificanceRoundD64,
   9746                           mkU32( RMC ),
   9747                           mkexpr( frA ),
   9748                           mkexpr( frB ) ) );
   9749       break;
   9750    default:
   9751       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
   9752       return False;
   9753    }
   9754    putDReg( frS_addr, mkexpr( frS ) );
   9755 
   9756    if (flag_rC && clear_CR1) {
   9757       putCR321( 1, mkU8( 0 ) );
   9758       putCR0( 1, mkU8( 0 ) );
   9759    }
   9760 
   9761    return True;
   9762 }
   9763 
   9764 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
   9765    UInt opc2 = ifieldOPClo8( theInstr );
   9766    UChar frS_addr = ifieldRegDS( theInstr );
   9767    UChar frA_addr = ifieldRegA( theInstr );
   9768    UChar frB_addr = ifieldRegB( theInstr );
   9769    UChar flag_rC = ifieldBIT0( theInstr );
   9770    UInt TE_value = IFIELD(theInstr, 16, 4);
   9771    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   9772    UInt RMC = IFIELD(theInstr, 9, 2);
   9773    IRTemp frA = newTemp( Ity_D128 );
   9774    IRTemp frB = newTemp( Ity_D128 );
   9775    IRTemp frS = newTemp( Ity_D128 );
   9776    Bool clear_CR1 = True;
   9777 
   9778    assign( frB, getDReg_pair( frB_addr ) );
   9779 
   9780    switch (opc2) {
   9781    case 0x43: // dquaiq
   9782       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   9783            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9784       IRTemp TE_D64 = newTemp( Ity_D64 );
   9785 
   9786       /* Generate a reference DFP value frA with the desired exponent
   9787        * given by TE using significand of 1.  Need to add the bias
   9788        * 6176 to TE.
   9789        */
   9790       if (TE_sign == 1) {
   9791          /* Take 2's complement of the 5-bit value and subtract from bias.
   9792           *  Bias adjusted for the +1 required when taking 2's complement.
   9793           */
   9794          assign( TE_D64,
   9795                  unop( Iop_ReinterpI64asD64,
   9796                        binop( Iop_Sub64, mkU64( 6175 ),
   9797                               binop( Iop_And64, mkU64( 0xF ),
   9798                                      unop( Iop_Not64, mkU64( TE_value ) )
   9799                                            ) ) ) );
   9800 
   9801       } else {
   9802          assign( TE_D64,
   9803                  unop( Iop_ReinterpI64asD64,
   9804                        binop( Iop_Add64, mkU64( 6176 ), mkU64( TE_value ) )
   9805                             ) );
   9806       }
   9807 
   9808       assign( frA,
   9809               binop( Iop_InsertExpD128, mkexpr( TE_D64 ),
   9810                      unop( Iop_D64toD128,
   9811                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
   9812       assign( frS, triop( Iop_QuantizeD128,
   9813                           mkU32( RMC ),
   9814                           mkexpr( frA ),
   9815                           mkexpr( frB ) ) );
   9816       break;
   9817    case 0x3: // dquaq
   9818       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   9819            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9820       assign( frA, getDReg_pair( frA_addr ) );
   9821       assign( frS, triop( Iop_QuantizeD128,
   9822                           mkU32( RMC ),
   9823                           mkexpr( frA ),
   9824                           mkexpr( frB ) ) );
   9825       break;
   9826    case 0x23: // drrndq
   9827       DIP( "drrndq%s fr%u,fr%u,fr%u\n",
   9828            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9829       assign( frA, getDReg_pair( frA_addr ) );
   9830       assign( frS, triop( Iop_SignificanceRoundD128,
   9831                           mkU32( RMC ),
   9832                           mkexpr( frA ),
   9833                           mkexpr( frB ) ) );
   9834       break;
   9835    default:
   9836       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
   9837       return False;
   9838    }
   9839    putDReg_pair( frS_addr, mkexpr( frS ) );
   9840 
   9841    if (flag_rC && clear_CR1) {
   9842       putCR321( 1, mkU8( 0 ) );
   9843       putCR0( 1, mkU8( 0 ) );
   9844    }
   9845 
   9846    return True;
   9847 }
   9848 
   9849 static Bool dis_dfp_extract_insert(UInt theInstr) {
   9850    UInt opc2 = ifieldOPClo10( theInstr );
   9851    UChar frS_addr = ifieldRegDS( theInstr );
   9852    UChar frA_addr = ifieldRegA( theInstr );
   9853    UChar frB_addr = ifieldRegB( theInstr );
   9854    UChar flag_rC = ifieldBIT0( theInstr );
   9855    Bool clear_CR1 = True;
   9856 
   9857    IRTemp frA = newTemp( Ity_D64 );
   9858    IRTemp frB = newTemp( Ity_D64 );
   9859    IRTemp frS = newTemp( Ity_D64 );
   9860 
   9861    assign( frA, getDReg( frA_addr ) );
   9862    assign( frB, getDReg( frB_addr ) );
   9863 
   9864    switch (opc2) {
   9865    case 0x162: // dxex
   9866       DIP( "dxex%s fr%u,fr%u,fr%u\n",
   9867            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9868       assign( frS, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
   9869       break;
   9870    case 0x362: // diex
   9871       DIP( "diex%s fr%u,fr%u,fr%u\n",
   9872            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9873       assign( frS, binop( Iop_InsertExpD64, mkexpr( frA ), mkexpr( frB ) ) );
   9874       break;
   9875    default:
   9876       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
   9877       return False;
   9878    }
   9879 
   9880    putDReg( frS_addr, mkexpr( frS ) );
   9881 
   9882    if (flag_rC && clear_CR1) {
   9883       putCR321( 1, mkU8( 0 ) );
   9884       putCR0( 1, mkU8( 0 ) );
   9885    }
   9886 
   9887    return True;
   9888 }
   9889 
   9890 static Bool dis_dfp_extract_insertq(UInt theInstr) {
   9891    UInt opc2 = ifieldOPClo10( theInstr );
   9892    UChar frS_addr = ifieldRegDS( theInstr );
   9893    UChar frA_addr = ifieldRegA( theInstr );
   9894    UChar frB_addr = ifieldRegB( theInstr );
   9895    UChar flag_rC = ifieldBIT0( theInstr );
   9896 
   9897    IRTemp frA   = newTemp( Ity_D64 );
   9898    IRTemp frB   = newTemp( Ity_D128 );
   9899    IRTemp frS64 = newTemp( Ity_D64 );
   9900    IRTemp frS   = newTemp( Ity_D128 );
   9901    Bool clear_CR1 = True;
   9902 
   9903    assign( frB, getDReg_pair( frB_addr ) );
   9904 
   9905    switch (opc2) {
   9906    case 0x162:  // dxexq
   9907       DIP( "dxexq%s fr%u,fr%u\n",
   9908            flag_rC ? ".":"", frS_addr,  frB_addr );
   9909       /* Instruction actually returns a 64-bit result.  So as to be
   9910        * consistent and not have to add a new struct, the emulation returns
   9911        * the 64-bit result in the upper and lower register.
   9912        */
   9913       assign( frS64, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
   9914       putDReg( frS_addr, mkexpr( frS64 ) );
   9915       break;
   9916    case 0x362:  // diexq
   9917       DIP( "diexq%s fr%u,fr%u,fr%u\n",
   9918            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   9919       assign( frA, getDReg( frA_addr ) );
   9920       assign( frS, binop( Iop_InsertExpD128, mkexpr( frA ), mkexpr( frB ) ) );
   9921       putDReg_pair( frS_addr, mkexpr( frS ) );
   9922       break;
   9923    default:
   9924       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
   9925       return False;
   9926    }
   9927 
   9928    if (flag_rC && clear_CR1) {
   9929       putCR321( 1, mkU8( 0 ) );
   9930       putCR0( 1, mkU8( 0 ) );
   9931    }
   9932 
   9933    return True;
   9934 }
   9935 
   9936 /* DFP 64-bit comparison instructions */
   9937 static Bool dis_dfp_compare(UInt theInstr) {
   9938    /* X-Form */
   9939    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   9940    UChar frA_addr = ifieldRegA( theInstr );
   9941    UChar frB_addr = ifieldRegB( theInstr );
   9942    UInt opc1 = ifieldOPC( theInstr );
   9943    IRTemp frA;
   9944    IRTemp frB;
   9945 
   9946    IRTemp ccIR = newTemp( Ity_I32 );
   9947    IRTemp ccPPC32 = newTemp( Ity_I32 );
   9948 
   9949 
   9950    /* Note: Differences between dcmpu and dcmpo are only in exception
   9951     flag settings, which aren't supported anyway. */
   9952    switch (opc1) {
   9953    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
   9954       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   9955       frA = newTemp( Ity_D64 );
   9956       frB = newTemp( Ity_D64 );
   9957 
   9958       assign( frA, getDReg( frA_addr ) );
   9959       assign( frB, getDReg( frB_addr ) );
   9960 
   9961       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
   9962       break;
   9963    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
   9964       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   9965       frA = newTemp( Ity_D128 );
   9966       frB = newTemp( Ity_D128 );
   9967 
   9968       assign( frA, getDReg_pair( frA_addr ) );
   9969       assign( frB, getDReg_pair( frB_addr ) );
   9970       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
   9971       break;
   9972    default:
   9973       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
   9974       return False;
   9975    }
   9976 
   9977    /* Map compare result from IR to PPC32 */
   9978    /*
   9979     FP cmp result | PPC | IR
   9980     --------------------------
   9981     UN            | 0x1 | 0x45
   9982     EQ            | 0x2 | 0x40
   9983     GT            | 0x4 | 0x00
   9984     LT            | 0x8 | 0x01
   9985     */
   9986 
   9987    assign( ccPPC32,
   9988            binop( Iop_Shl32,
   9989                   mkU32( 1 ),
   9990                   unop( Iop_32to8,
   9991                         binop( Iop_Or32,
   9992                                binop( Iop_And32,
   9993                                       unop( Iop_Not32,
   9994                                             binop( Iop_Shr32,
   9995                                                    mkexpr( ccIR ),
   9996                                                    mkU8( 5 ) ) ),
   9997                                       mkU32( 2 ) ),
   9998                                binop( Iop_And32,
   9999                                       binop( Iop_Xor32,
   10000                                              mkexpr( ccIR ),
   10001                                              binop( Iop_Shr32,
   10002                                                     mkexpr( ccIR ),
   10003                                                     mkU8( 6 ) ) ),
   10004                                       mkU32( 1 ) ) ) ) ) );
   10005 
   10006    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
   10007    return True;
   10008 }
   10009 
   10010 /* Test class/group/exponent/significance instructions. */
   10011 static Bool dis_dfp_exponent_test ( UInt theInstr )
   10012 {
   10013    UChar frA_addr   = ifieldRegA( theInstr );
   10014    UChar frB_addr   = ifieldRegB( theInstr );
   10015    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
   10016    IRTemp frA       = newTemp( Ity_D64 );
   10017    IRTemp frB       = newTemp( Ity_D64 );
   10018    IRTemp frA128    = newTemp( Ity_D128 );
   10019    IRTemp frB128    = newTemp( Ity_D128 );
   10020    UInt opc1        = ifieldOPC( theInstr );
   10021    IRTemp gfield_A  = newTemp( Ity_I32 );
   10022    IRTemp gfield_B  = newTemp( Ity_I32 );
   10023    IRTemp gfield_mask   = newTemp( Ity_I32 );
   10024    IRTemp exponent_A    = newTemp( Ity_I32 );
   10025    IRTemp exponent_B    = newTemp( Ity_I32 );
   10026    IRTemp A_NaN_true    = newTemp( Ity_I32 );
   10027    IRTemp B_NaN_true    = newTemp( Ity_I32 );
   10028    IRTemp A_inf_true    = newTemp( Ity_I32 );
   10029    IRTemp B_inf_true    = newTemp( Ity_I32 );
   10030    IRTemp A_equals_B    = newTemp( Ity_I32 );
   10031    IRTemp finite_number = newTemp( Ity_I32 );
   10032    IRTemp cc0 = newTemp( Ity_I32 );
   10033    IRTemp cc1 = newTemp( Ity_I32 );
   10034    IRTemp cc2 = newTemp( Ity_I32 );
   10035    IRTemp cc3 = newTemp( Ity_I32 );
   10036 
   10037    /* The dtstex and dtstexg instructions only differ in the size of the
   10038     * exponent field.  The following switch statement takes care of the size
   10039     * specific setup.  Once the value of the exponents, the G-field shift
   10040     * and mask is setup the remaining code is identical.
   10041     */
   10042    switch (opc1) {
   10043    case 0x3b: // dtstex       Extended instruction setup
   10044       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10045       assign( frA, getDReg( frA_addr ) );
   10046       assign( frB, getDReg( frB_addr ) );
   10047       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   10048       assign(exponent_A, unop( Iop_64to32,
   10049                                unop( Iop_ReinterpD64asI64,
   10050                                      unop( Iop_ExtractExpD64,
   10051                                            mkexpr( frA ) ) ) ) );
   10052       assign(exponent_B, unop( Iop_64to32,
   10053                                unop( Iop_ReinterpD64asI64,
   10054                                      unop( Iop_ExtractExpD64,
   10055                                            mkexpr( frB ) ) ) ) );
   10056       break;
   10057 
   10058    case 0x3F: //  dtstexq      Quad instruction setup
   10059       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   10060       assign( frA128, getDReg_pair( frA_addr ) );
   10061       assign( frB128, getDReg_pair( frB_addr ) );
   10062       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
   10063       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
   10064       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   10065       assign( exponent_A, unop( Iop_64to32,
   10066                                 unop( Iop_ReinterpD64asI64,
   10067                                       unop( Iop_ExtractExpD128,
   10068                                             mkexpr( frA128 ) ) ) ) );
   10069       assign( exponent_B, unop( Iop_64to32,
   10070                                 unop( Iop_ReinterpD64asI64,
   10071                                       unop( Iop_ExtractExpD128,
   10072                                             mkexpr( frB128 ) ) ) ) );
   10073       break;
   10074    default:
   10075       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
   10076       return False;
   10077    }
   10078 
   10079    /* Extract the Gfield */
   10080    assign( gfield_A, binop( Iop_And32,
   10081                             mkexpr( gfield_mask ),
   10082                             unop( Iop_64HIto32,
   10083                                   unop( Iop_ReinterpD64asI64,
   10084                                         mkexpr(frA) ) ) ) );
   10085 
   10086    assign( gfield_B, binop( Iop_And32,
   10087                             mkexpr( gfield_mask ),
   10088                             unop( Iop_64HIto32,
   10089                                   unop( Iop_ReinterpD64asI64,
   10090                                         mkexpr(frB) ) ) ) );
   10091 
   10092    /* check for NAN */
   10093    assign( A_NaN_true, binop(Iop_Or32,
   10094                              unop( Iop_1Sto32,
   10095                                    binop( Iop_CmpEQ32,
   10096                                           mkexpr( gfield_A ),
   10097                                           mkU32( 0x7C000000 ) ) ),
   10098                              unop( Iop_1Sto32,
   10099                                    binop( Iop_CmpEQ32,
   10100                                           mkexpr( gfield_A ),
   10101                                           mkU32( 0x7E000000 ) )
   10102                                    ) ) );
   10103    assign( B_NaN_true, binop(Iop_Or32,
   10104                              unop( Iop_1Sto32,
   10105                                    binop( Iop_CmpEQ32,
   10106                                           mkexpr( gfield_B ),
   10107                                           mkU32( 0x7C000000 ) ) ),
   10108                              unop( Iop_1Sto32,
   10109                                    binop( Iop_CmpEQ32,
   10110                                           mkexpr( gfield_B ),
   10111                                           mkU32( 0x7E000000 ) )
   10112                              ) ) );
   10113 
   10114    /* check for infinity */
   10115    assign( A_inf_true,
   10116            unop( Iop_1Sto32,
   10117                  binop( Iop_CmpEQ32,
   10118                         mkexpr( gfield_A ),
   10119                         mkU32( 0x78000000 ) ) ) );
   10120 
   10121    assign( B_inf_true,
   10122            unop( Iop_1Sto32,
   10123                  binop( Iop_CmpEQ32,
   10124                         mkexpr( gfield_B ),
   10125                         mkU32( 0x78000000 ) ) ) );
   10126 
   10127    assign( finite_number,
   10128            unop( Iop_Not32,
   10129                  binop( Iop_Or32,
   10130                         binop( Iop_Or32,
   10131                                mkexpr( A_NaN_true ),
   10132                                mkexpr( B_NaN_true ) ),
   10133                         binop( Iop_Or32,
   10134                                mkexpr( A_inf_true ),
   10135                                mkexpr( B_inf_true ) ) ) ) );
   10136 
   10137    /* Calculate the condition code bits
   10138     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
   10139     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
   10140     * cc0, cc1 and cc0 reflect the results of the comparisons.
   10141     */
   10142    assign( A_equals_B,
   10143            binop( Iop_Or32,
   10144                   unop( Iop_1Uto32,
   10145                   binop( Iop_CmpEQ32,
   10146                          mkexpr( exponent_A ),
   10147                          mkexpr( exponent_B ) ) ),
   10148                   binop( Iop_Or32,
   10149                          binop( Iop_And32,
   10150                                 mkexpr( A_inf_true ),
   10151                                 mkexpr( B_inf_true ) ),
   10152                          binop( Iop_And32,
   10153                                 mkexpr( A_NaN_true ),
   10154                                 mkexpr( B_NaN_true ) ) ) ) );
   10155 
   10156    assign( cc0, binop( Iop_And32,
   10157                        mkexpr( finite_number ),
   10158                        binop( Iop_Shl32,
   10159                               unop( Iop_1Uto32,
   10160                                     binop( Iop_CmpLT32U,
   10161                                            mkexpr( exponent_A ),
   10162                                            mkexpr( exponent_B ) ) ),
   10163                                            mkU8( 3 ) ) ) );
   10164 
   10165    assign( cc1, binop( Iop_And32,
   10166                        mkexpr( finite_number ),
   10167                        binop( Iop_Shl32,
   10168                               unop( Iop_1Uto32,
   10169                                     binop( Iop_CmpLT32U,
   10170                                            mkexpr( exponent_B ),
   10171                                            mkexpr( exponent_A ) ) ),
   10172                                            mkU8( 2 ) ) ) );
   10173 
   10174    assign( cc2, binop( Iop_Shl32,
   10175                        binop( Iop_And32,
   10176                               mkexpr( A_equals_B ),
   10177                               mkU32( 1 ) ),
   10178                               mkU8( 1 ) ) );
   10179 
   10180    assign( cc3, binop( Iop_And32,
   10181                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
   10182                        binop( Iop_And32,
   10183                               mkU32( 0x1 ),
   10184                               binop( Iop_Or32,
   10185                                      binop( Iop_Or32,
   10186                                             mkexpr ( A_inf_true ),
   10187                                             mkexpr ( B_inf_true ) ),
   10188                                             binop( Iop_Or32,
   10189                                                    mkexpr ( A_NaN_true ),
   10190                                                    mkexpr ( B_NaN_true ) ) )
   10191                               ) ) );
   10192 
   10193    /* store the condition code */
   10194    putGST_field( PPC_GST_CR,
   10195                  binop( Iop_Or32,
   10196                         mkexpr( cc0 ),
   10197                         binop( Iop_Or32,
   10198                                mkexpr( cc1 ),
   10199                                binop( Iop_Or32,
   10200                                       mkexpr( cc2 ),
   10201                                       mkexpr( cc3 ) ) ) ),
   10202                  crfD );
   10203    return True;
   10204 }
   10205 
   10206 /* Test class/group/exponent/significance instructions. */
   10207 static Bool dis_dfp_class_test ( UInt theInstr )
   10208 {
   10209    UChar frA_addr   = ifieldRegA( theInstr );
   10210    IRTemp frA       = newTemp( Ity_D64 );
   10211    IRTemp abs_frA   = newTemp( Ity_D64 );
   10212    IRTemp frAI64_hi = newTemp( Ity_I64 );
   10213    IRTemp frAI64_lo = newTemp( Ity_I64 );
   10214    UInt opc1        = ifieldOPC( theInstr );
   10215    UInt opc2        = ifieldOPClo9( theInstr );
   10216    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
   10217    UInt DCM         = IFIELD( theInstr, 10, 6 );
   10218    IRTemp DCM_calc  = newTemp( Ity_I32 );
   10219    UInt max_exp     = 0;
   10220    UInt min_exp     = 0;
   10221    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
   10222    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
   10223    IRTemp significand64  = newTemp( Ity_D64 );
   10224    IRTemp significand128 = newTemp( Ity_D128 );
   10225    IRTemp exp_min_normal = newTemp( Ity_D64 );
   10226    IRTemp exponent       = newTemp( Ity_I32 );
   10227 
   10228    IRTemp infinity_true  = newTemp( Ity_I32 );
   10229    IRTemp SNaN_true      = newTemp( Ity_I32 );
   10230    IRTemp QNaN_true      = newTemp( Ity_I32 );
   10231    IRTemp subnormal_true = newTemp( Ity_I32 );
   10232    IRTemp normal_true    = newTemp( Ity_I32 );
   10233    IRTemp extreme_true   = newTemp( Ity_I32 );
   10234    IRTemp lmd            = newTemp( Ity_I32 );
   10235    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
   10236    IRTemp zero_true      = newTemp( Ity_I32 );
   10237    IRTemp sign           = newTemp( Ity_I32 );
   10238    IRTemp field          = newTemp( Ity_I32 );
   10239    IRTemp ccIR_zero      = newTemp( Ity_I32 );
   10240    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
   10241 
   10242    /* UInt size     = DFP_LONG;  JRS:unused */
   10243    IRTemp gfield = newTemp( Ity_I32 );
   10244    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
   10245    IRTemp gfield_mask       = newTemp( Ity_I32 );
   10246    IRTemp dcm0 = newTemp( Ity_I32 );
   10247    IRTemp dcm1 = newTemp( Ity_I32 );
   10248    IRTemp dcm2 = newTemp( Ity_I32 );
   10249    IRTemp dcm3 = newTemp( Ity_I32 );
   10250    IRTemp dcm4 = newTemp( Ity_I32 );
   10251    IRTemp dcm5 = newTemp( Ity_I32 );
   10252 
   10253    /* The only difference between the dtstdc and dtstdcq instructions is
   10254     * size of the T and G fields.  The calculation of the 4 bit field
   10255     * is the same.  Setup the parameters and values that are DFP size
   10256     * specific.  The rest of the code is independent of the DFP size.
   10257     *
   10258     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
   10259     * The interpretation of the ccIR values is as follows:
   10260     *
   10261     *    DFP cmp result | IR
   10262     * --------------------------
   10263     *	 UN             | 0x45
   10264     *	 EQ             | 0x40
   10265     *	 GT             | 0x00
   10266     *	 LT             | 0x01
   10267     */
   10268 
   10269    assign( frA, getDReg( frA_addr ) );
   10270    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
   10271 
   10272    assign( abs_frA, unop( Iop_ReinterpI64asD64,
   10273                           binop( Iop_And64,
   10274                                  unop( Iop_ReinterpD64asI64,
   10275                                        mkexpr( frA ) ),
   10276                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
   10277    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
   10278    switch (opc1) {
   10279    case 0x3b: // dtstdc, dtstdg
   10280       DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   10281                crfD, frA_addr, DCM);
   10282       /* setup the parameters for the long format of the two instructions */
   10283       assign( frAI64_lo, mkU64( 0 ) );
   10284       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   10285       max_exp = DFP_LONG_EXP_MAX;
   10286       min_exp = DFP_LONG_EXP_MIN;
   10287 
   10288       assign( exponent, unop( Iop_64to32,
   10289                               unop( Iop_ReinterpD64asI64,
   10290                                     unop( Iop_ExtractExpD64,
   10291                                           mkexpr( frA ) ) ) ) );
   10292       assign( significand64,
   10293               unop( Iop_ReinterpI64asD64,
   10294                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
   10295       assign( exp_min_normal,
   10296               unop( Iop_ReinterpI64asD64, mkU64( 398 - 383 ) ) );
   10297       assign( min_subnormalD64,
   10298               binop( Iop_InsertExpD64,
   10299                      mkexpr( exp_min_normal ),
   10300                      mkexpr( significand64 ) ) );
   10301 
   10302       assign( ccIR_subnormal,
   10303               binop( Iop_CmpD64,
   10304                      mkexpr( abs_frA ),
   10305                      mkexpr( min_subnormalD64 ) ) );
   10306 
   10307       /* compare absolute value of frA with zero */
   10308       assign( ccIR_zero,
   10309               binop( Iop_CmpD64,
   10310                      mkexpr( abs_frA ),
   10311                      unop( Iop_ReinterpI64asD64,
   10312                            mkU64( 0x2238000000000000ULL ) ) ) );
   10313 
   10314       /* size = DFP_LONG; JRS: unused */
   10315       break;
   10316 
   10317    case 0x3F:   // dtstdcq, dtstdgq
   10318       DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
   10319                crfD, frA_addr, DCM);
   10320       /* setup the parameters for the extended format of the
   10321        * two instructions
   10322        */
   10323       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
   10324                                getDReg( frA_addr+1 ) ) );
   10325 
   10326       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   10327       max_exp = DFP_EXTND_EXP_MAX;
   10328       min_exp = DFP_EXTND_EXP_MIN;
   10329       assign( exponent, unop( Iop_64to32,
   10330                               unop( Iop_ReinterpD64asI64,
   10331                                     unop( Iop_ExtractExpD128,
   10332                                           getDReg_pair( frA_addr) ) ) ) );
   10333 
   10334       /* create quand exponent for minimum normal number */
   10335       assign( exp_min_normal,
   10336               unop( Iop_ReinterpI64asD64, mkU64( 6176 - 6143 ) ) );
   10337       assign( significand128,
   10338               unop( Iop_D64toD128,
   10339                     unop( Iop_ReinterpI64asD64,
   10340                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
   10341 
   10342       assign( min_subnormalD128,
   10343               binop( Iop_InsertExpD128,
   10344                      mkexpr( exp_min_normal ),
   10345                      mkexpr( significand128 ) ) );
   10346 
   10347       assign( ccIR_subnormal,
   10348               binop( Iop_CmpD128,
   10349                      binop( Iop_D64HLtoD128,
   10350                             unop( Iop_ReinterpI64asD64,
   10351                                   binop( Iop_And64,
   10352                                          unop( Iop_ReinterpD64asI64,
   10353                                                mkexpr( frA ) ),
   10354                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
   10355                             getDReg( frA_addr+1 ) ),
   10356                      mkexpr( min_subnormalD128 ) ) );
   10357       assign( ccIR_zero,
   10358               binop( Iop_CmpD128,
   10359                      binop( Iop_D64HLtoD128,
   10360                             mkexpr( abs_frA ),
   10361                             getDReg( frA_addr+1 ) ),
   10362                      unop( Iop_D64toD128,
   10363                            unop( Iop_ReinterpI64asD64,
   10364                                  mkU64( 0x0ULL ) ) ) ) );
   10365 
   10366       /* size = DFP_EXTND; JRS:unused */
   10367       break;
   10368    default:
   10369       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
   10370       return False;
   10371    }
   10372 
   10373    /* The G-field is in the upper 32-bits.  The I64 logical operations
   10374     * do not seem to be supported in 32-bit mode so keep things as 32-bit
   10375     * operations.
   10376     */
   10377    assign( gfield, binop( Iop_And32,
   10378                           mkexpr( gfield_mask ),
   10379                           unop( Iop_64HIto32,
   10380                                 mkexpr(frAI64_hi) ) ) );
   10381 
   10382    /* There is a lot of code that is the same to do the class and group
   10383     * instructions.  Later there is an if statement to handle the specific
   10384     * instruction.
   10385     *
   10386     * Will be using I32 values, compares, shifts and logical operations for
   10387     * this code as the 64-bit compare, shifts, logical operations are not
   10388     * supported in 32-bit mode.
   10389     */
   10390 
   10391    /* Check the bits for Infinity, QNaN or Signaling NaN */
   10392    assign( infinity_true,
   10393            unop( Iop_1Sto32,
   10394                  binop( Iop_CmpEQ32,
   10395                         binop( Iop_And32,
   10396                                mkU32( 0x7C000000 ),
   10397                                mkexpr( gfield ) ),
   10398                         mkU32( 0x78000000 ) ) ) );
   10399 
   10400    assign( SNaN_true,
   10401            unop( Iop_1Sto32,
   10402                  binop( Iop_CmpEQ32,
   10403                         binop( Iop_And32,
   10404                                mkU32( 0x7E000000 ),
   10405                                mkexpr( gfield ) ),
   10406                         mkU32( 0x7E000000 ) ) ) );
   10407 
   10408    assign( QNaN_true,
   10409            binop( Iop_And32,
   10410                   unop( Iop_1Sto32,
   10411                        binop( Iop_CmpEQ32,
   10412                               binop( Iop_And32,
   10413                                      mkU32( 0x7E000000 ),
   10414                                      mkexpr( gfield ) ),
   10415                               mkU32( 0x7C000000 ) ) ),
   10416                   unop( Iop_Not32,
   10417                         mkexpr( SNaN_true ) ) ) );
   10418 
   10419    assign( zero_true,
   10420            binop( Iop_And32,
   10421                   unop(Iop_1Sto32,
   10422                        binop( Iop_CmpEQ32,
   10423                               mkexpr( ccIR_zero ),
   10424                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
   10425                   unop( Iop_Not32,
   10426                         binop( Iop_Or32,
   10427                                mkexpr( infinity_true ),
   10428                                binop( Iop_Or32,
   10429                                       mkexpr( QNaN_true ),
   10430                                       mkexpr( SNaN_true ) ) ) ) ) );
   10431 
   10432    /* Do compare of frA the minimum normal value.  Comparison is size
   10433     * depenent and was done above to get the ccIR value.
   10434     */
   10435    assign( subnormal_true,
   10436            binop( Iop_And32,
   10437                   binop( Iop_Or32,
   10438                          unop( Iop_1Sto32,
   10439                                binop( Iop_CmpEQ32,
   10440                                       mkexpr( ccIR_subnormal ),
   10441                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
   10442                          unop( Iop_1Sto32,
   10443                                binop( Iop_CmpEQ32,
   10444                                       mkexpr( ccIR_subnormal ),
   10445                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
   10446            unop( Iop_Not32,
   10447                  binop( Iop_Or32,
   10448                         binop( Iop_Or32,
   10449                                mkexpr( infinity_true ),
   10450                                mkexpr( zero_true) ),
   10451                         binop( Iop_Or32,
   10452                                mkexpr( QNaN_true ),
   10453                                mkexpr( SNaN_true ) ) ) ) ) );
   10454 
   10455    /* Normal number is not subnormal, infinity, NaN or Zero */
   10456    assign( normal_true,
   10457            unop( Iop_Not32,
   10458                  binop( Iop_Or32,
   10459                         binop( Iop_Or32,
   10460                                mkexpr( infinity_true ),
   10461                                mkexpr( zero_true ) ),
   10462                         binop( Iop_Or32,
   10463                                mkexpr( subnormal_true ),
   10464                                binop( Iop_Or32,
   10465                                       mkexpr( QNaN_true ),
   10466                                       mkexpr( SNaN_true ) ) ) ) ) );
   10467 
   10468    /* Calculate the DCM bit field based on the tests for the specific
   10469     * instruction
   10470     */
   10471    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
   10472       /* DCM[0:5] Bit   Data Class definition
   10473        *   0   Zero
   10474        *   1   Subnormal
   10475        *   2   Normal
   10476        *   3   Infinity
   10477        *   4   Quiet NaN
   10478        *   5   Signaling NaN
   10479        */
   10480 
   10481       assign( dcm0, binop( Iop_Shl32,
   10482                            mkexpr( zero_true ),
   10483                            mkU8( 5 ) ) );
   10484       assign( dcm1, binop( Iop_Shl32,
   10485                            binop( Iop_And32,
   10486                                   mkexpr( subnormal_true ),
   10487                                   mkU32( 1 ) ),
   10488                            mkU8( 4 ) ) );
   10489       assign( dcm2, binop( Iop_Shl32,
   10490                            binop( Iop_And32,
   10491                                   mkexpr( normal_true ),
   10492                                   mkU32( 1 ) ),
   10493                            mkU8( 3 ) ) );
   10494       assign( dcm3, binop( Iop_Shl32,
   10495                            binop( Iop_And32,
   10496                                   mkexpr( infinity_true),
   10497                                   mkU32( 1 ) ),
   10498                            mkU8( 2 ) ) );
   10499       assign( dcm4, binop( Iop_Shl32,
   10500                            binop( Iop_And32,
   10501                                   mkexpr( QNaN_true ),
   10502                                   mkU32( 1 ) ),
   10503                            mkU8( 1 ) ) );
   10504       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
   10505 
   10506    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
   10507       /* check if the exponent is extreme */
   10508       assign( extreme_true, binop( Iop_Or32,
   10509                                    unop( Iop_1Sto32,
   10510                                          binop( Iop_CmpEQ32,
   10511                                                 mkexpr( exponent ),
   10512                                                 mkU32( max_exp ) ) ),
   10513                                    unop( Iop_1Sto32,
   10514                                          binop( Iop_CmpEQ32,
   10515                                                 mkexpr( exponent ),
   10516                                                 mkU32( min_exp ) ) ) ) );
   10517 
   10518       /* Check if LMD is zero */
   10519       Get_lmd( &lmd, binop( Iop_Shr32,
   10520                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
   10521 
   10522       assign( lmd_zero_true, unop( Iop_1Sto32,
   10523                                    binop( Iop_CmpEQ32,
   10524                                           mkexpr( lmd ),
   10525                                           mkU32( 0 ) ) ) );
   10526 
   10527       /* DCM[0:5] Bit   Data Class definition
   10528        *  0   Zero with non-extreme exponent
   10529        *  1   Zero with extreme exponent
   10530        *  2   Subnormal or (Normal with extreme exponent)
   10531        *  3   Normal with non-extreme exponent and
   10532        *      leftmost zero digit in significand
   10533        *  4   Normal with non-extreme exponent and
   10534        *      leftmost nonzero digit in significand
   10535        *  5   Special symbol (Infinity, QNaN, or SNaN)
   10536        */
   10537       assign( dcm0, binop( Iop_Shl32,
   10538                            binop( Iop_And32,
   10539                                   binop( Iop_And32,
   10540                                          unop( Iop_Not32,
   10541                                                mkexpr( extreme_true ) ),
   10542                                          mkexpr( zero_true ) ),
   10543                                   mkU32( 0x1 ) ),
   10544                            mkU8( 5 ) ) );
   10545 
   10546       assign( dcm1, binop( Iop_Shl32,
   10547                            binop( Iop_And32,
   10548                                   binop( Iop_And32,
   10549                                          mkexpr( extreme_true ),
   10550                                          mkexpr( zero_true ) ),
   10551                                   mkU32( 0x1 ) ),
   10552                            mkU8( 4 ) ) );
   10553 
   10554       assign( dcm2, binop( Iop_Shl32,
   10555                            binop( Iop_And32,
   10556                                   binop( Iop_Or32,
   10557                                          binop( Iop_And32,
   10558                                                 mkexpr( extreme_true ),
   10559                                                 mkexpr( normal_true ) ),
   10560                                          mkexpr( subnormal_true ) ),
   10561                                   mkU32( 0x1 ) ),
   10562                            mkU8( 3 ) ) );
   10563 
   10564       assign( dcm3, binop( Iop_Shl32,
   10565                            binop( Iop_And32,
   10566                                   binop( Iop_And32,
   10567                                          binop( Iop_And32,
   10568                                                 unop( Iop_Not32,
   10569                                                       mkexpr( extreme_true ) ),
   10570                                                       mkexpr( normal_true ) ),
   10571                                          unop( Iop_1Sto32,
   10572                                                binop( Iop_CmpEQ32,
   10573                                                       mkexpr( lmd ),
   10574                                                       mkU32( 0 ) ) ) ),
   10575                                   mkU32( 0x1 ) ),
   10576                            mkU8( 2 ) ) );
   10577 
   10578       assign( dcm4, binop( Iop_Shl32,
   10579                            binop( Iop_And32,
   10580                                   binop( Iop_And32,
   10581                                          binop( Iop_And32,
   10582                                                 unop( Iop_Not32,
   10583                                                       mkexpr( extreme_true ) ),
   10584                                                 mkexpr( normal_true ) ),
   10585                                           unop( Iop_1Sto32,
   10586                                                 binop( Iop_CmpNE32,
   10587                                                        mkexpr( lmd ),
   10588                                                        mkU32( 0 ) ) ) ),
   10589                                   mkU32( 0x1 ) ),
   10590                            mkU8( 1 ) ) );
   10591 
   10592       assign( dcm5, binop( Iop_And32,
   10593                            binop( Iop_Or32,
   10594                                   mkexpr( SNaN_true),
   10595                                   binop( Iop_Or32,
   10596                                          mkexpr( QNaN_true),
   10597                                          mkexpr( infinity_true) ) ),
   10598                            mkU32( 0x1 ) ) );
   10599    }
   10600 
   10601    /* create DCM field */
   10602    assign( DCM_calc,
   10603            binop( Iop_Or32,
   10604                   mkexpr( dcm0 ),
   10605                   binop( Iop_Or32,
   10606                          mkexpr( dcm1 ),
   10607                          binop( Iop_Or32,
   10608                                 mkexpr( dcm2 ),
   10609                                 binop( Iop_Or32,
   10610                                        mkexpr( dcm3 ),
   10611                                        binop( Iop_Or32,
   10612                                               mkexpr( dcm4 ),
   10613                                               mkexpr( dcm5 ) ) ) ) ) ) );
   10614 
   10615    /* Get the sign of the DFP number, ignore sign for QNaN */
   10616    assign( sign,
   10617            unop( Iop_1Uto32,
   10618                  binop( Iop_CmpEQ32,
   10619                         binop( Iop_Shr32,
   10620                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
   10621                                mkU8( 63 - 32 ) ),
   10622                         mkU32( 1 ) ) ) );
   10623 
   10624    /* This instruction generates a four bit field to be stored in the
   10625     * condition code register.  The condition code register consists of 7
   10626     * fields.  The field to be written to is specified by the BF (AKA crfD)
   10627     * field.
   10628     *
   10629     * The field layout is as follows:
   10630     *
   10631     *      Field          Meaning
   10632     *      0000           Operand positive with no match
   10633     *      0100           Operand positive with at least one match
   10634     *      0001           Operand negative with no match
   10635     *      0101           Operand negative with at least one match
   10636     */
   10637    assign( field, binop( Iop_Or32,
   10638                          binop( Iop_Shl32,
   10639                                 mkexpr( sign ),
   10640                                 mkU8( 3 ) ),
   10641                                 binop( Iop_Shl32,
   10642                                        unop( Iop_1Uto32,
   10643                                              binop( Iop_CmpNE32,
   10644                                                     binop( Iop_And32,
   10645                                                            mkU32( DCM ),
   10646                                                            mkexpr( DCM_calc ) ),
   10647                                                      mkU32( 0 ) ) ),
   10648                                        mkU8( 1 ) ) ) );
   10649 
   10650    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
   10651    return True;
   10652 }
   10653 
   10654 static Bool dis_dfp_bcd(UInt theInstr) {
   10655    UInt opc2        = ifieldOPClo10( theInstr );
   10656    ULong sp         = IFIELD(theInstr, 19, 2);
   10657    ULong s          = IFIELD(theInstr, 20, 1);
   10658    UChar frT_addr   = ifieldRegDS( theInstr );
   10659    UChar frB_addr   = ifieldRegB( theInstr );
   10660    IRTemp frB       = newTemp( Ity_D64 );
   10661    IRTemp frBI64    = newTemp( Ity_I64 );
   10662    IRTemp result    = newTemp( Ity_I64 );
   10663    IRTemp resultD64 = newTemp( Ity_D64 );
   10664    IRTemp bcd64     = newTemp( Ity_I64 );
   10665    IRTemp bcd_u     = newTemp( Ity_I32 );
   10666    IRTemp bcd_l     = newTemp( Ity_I32 );
   10667    IRTemp dbcd_u    = newTemp( Ity_I32 );
   10668    IRTemp dbcd_l    = newTemp( Ity_I32 );
   10669    IRTemp lmd       = newTemp( Ity_I32 );
   10670 
   10671    assign( frB, getDReg( frB_addr ) );
   10672    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   10673 
   10674    switch ( opc2 ) {
   10675    case 0x142: // ddedpd   DFP Decode DPD to BCD
   10676       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   10677 
   10678          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   10679          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
   10680          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
   10681 
   10682       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   10683          /* Unsigned BCD string */
   10684          Get_lmd( &lmd,
   10685                   binop( Iop_Shr32,
   10686                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   10687                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
   10688 
   10689          assign( result,
   10690                  binop( Iop_32HLto64,
   10691                         binop( Iop_Or32,
   10692                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
   10693                                mkexpr( bcd_u ) ),
   10694                         mkexpr( bcd_l ) ) );
   10695 
   10696       } else {
   10697          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   10698           * the positive and negative values are encoded in the least
   10699           * significant bits.
   10700           */
   10701          IRTemp sign = newTemp( Ity_I32 );
   10702 
   10703          if (sp == 2) {
   10704             /* Positive sign = 0xC, negative sign = 0xD */
   10705 
   10706             assign( sign,
   10707                     binop( Iop_Or32,
   10708                            binop( Iop_Shr32,
   10709                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   10710                                   mkU8( 31 ) ),
   10711                            mkU32( 0xC ) ) );
   10712 
   10713          } else if ( sp == 3 ) {
   10714             /* Positive sign = 0xF, negative sign = 0xD */
   10715             IRTemp tmp32 = newTemp( Ity_I32 );
   10716 
   10717             /* Complement sign bit then OR into bit position 1 */
   10718             assign( tmp32,
   10719                     binop( Iop_Xor32,
   10720                            binop( Iop_Shr32,
   10721                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   10722                                   mkU8( 30 ) ),
   10723                            mkU32( 0x2 ) ) );
   10724 
   10725             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   10726 
   10727          } else {
   10728             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   10729          }
   10730 
   10731          /* Put sign in bottom 4 bits, move most significant 4-bits from
   10732           * bcd_l to bcd_u.
   10733           */
   10734          assign( result,
   10735                  binop( Iop_32HLto64,
   10736                         binop( Iop_Or32,
   10737                                binop( Iop_Shr32,
   10738                                       mkexpr( bcd_l ),
   10739                                       mkU8( 28 ) ),
   10740                                binop( Iop_Shl32,
   10741                                       mkexpr( bcd_u ),
   10742                                       mkU8( 4 ) ) ),
   10743                         binop( Iop_Or32,
   10744                                       mkexpr( sign ),
   10745                                binop( Iop_Shl32,
   10746                                       mkexpr( bcd_l ),
   10747                                       mkU8( 4 ) ) ) ) );
   10748       }
   10749 
   10750       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
   10751       break;
   10752 
   10753    case 0x342: // denbcd   DFP Encode BCD to DPD
   10754    {
   10755       IRTemp valid_mask   = newTemp( Ity_I32 );
   10756       IRTemp invalid_mask = newTemp( Ity_I32 );
   10757       IRTemp without_lmd  = newTemp( Ity_I64 );
   10758       IRTemp tmp64        = newTemp( Ity_I64 );
   10759       IRTemp dbcd64       = newTemp( Ity_I64 );
   10760       IRTemp left_exp     = newTemp( Ity_I32 );
   10761       IRTemp g0_4         = newTemp( Ity_I32 );
   10762 
   10763       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   10764 
   10765       if ( s == 0 ) {
   10766          /* Unsigned BCD string */
   10767          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
   10768          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
   10769          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
   10770 
   10771          assign( lmd,
   10772                  binop( Iop_Shr32,
   10773                         binop( Iop_And32,
   10774                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   10775                                mkU32( 0xF0000000 ) ),
   10776                         mkU8( 28 ) ) );
   10777 
   10778          assign( invalid_mask,
   10779                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   10780                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
   10781          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   10782 
   10783          assign( without_lmd,
   10784                  unop( Iop_ReinterpD64asI64,
   10785                        binop( Iop_InsertExpD64,
   10786                               unop( Iop_ReinterpI64asD64,
   10787                                     mkU64( DFP_LONG_BIAS ) ),
   10788                               unop( Iop_ReinterpI64asD64,
   10789                                     binop( Iop_32HLto64,
   10790                                            mkexpr( dbcd_u ),
   10791                                            mkexpr( dbcd_l ) ) ) ) ) );
   10792          assign( left_exp,
   10793                  binop( Iop_Shr32,
   10794                         binop( Iop_And32,
   10795                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
   10796                                mkU32( 0x60000000 ) ),
   10797                         mkU8( 29 ) ) );
   10798 
   10799          assign( g0_4,
   10800                  binop( Iop_Shl32,
   10801                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
   10802                         mkU8( 26 ) ) );
   10803 
   10804          assign( tmp64,
   10805                  binop( Iop_32HLto64,
   10806                         binop( Iop_Or32,
   10807                                binop( Iop_And32,
   10808                                       unop( Iop_64HIto32,
   10809                                             mkexpr( without_lmd ) ),
   10810                                       mkU32( 0x83FFFFFF ) ),
   10811                                mkexpr( g0_4 ) ),
   10812                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
   10813 
   10814       } else if ( s == 1 ) {
   10815          IRTemp sign = newTemp( Ity_I32 );
   10816          IRTemp sign_bit = newTemp( Ity_I32 );
   10817          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   10818          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   10819          IRTemp tmp = newTemp( Ity_I64 );
   10820 
   10821          /* Signed BCD string, least significant 4 bits are sign bits
   10822           * positive sign = 0xC, negative sign = 0xD
   10823           */
   10824          assign( tmp, unop( Iop_BCDtoDPB,
   10825                             binop( Iop_32HLto64,
   10826                                    binop( Iop_Shr32,
   10827                                           unop( Iop_64HIto32,
   10828                                                 mkexpr( frBI64 ) ),
   10829                                                 mkU8( 4 ) ),
   10830                                    binop( Iop_Or32,
   10831                                           binop( Iop_Shr32,
   10832                                                  unop( Iop_64to32,
   10833                                                        mkexpr( frBI64 ) ),
   10834                                                   mkU8( 4 ) ),
   10835                                           binop( Iop_Shl32,
   10836                                                  unop( Iop_64HIto32,
   10837                                                        mkexpr( frBI64 ) ),
   10838                                                        mkU8( 28 ) ) ) ) ) );
   10839 
   10840          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
   10841          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
   10842 
   10843          /* Get the sign of the BCD string. */
   10844          assign( sign,
   10845                  binop( Iop_And32,
   10846                         unop( Iop_64to32, mkexpr( frBI64 ) ),
   10847                         mkU32( 0xF ) ) );
   10848 
   10849          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   10850          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   10851          assign( sign_bit,
   10852                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   10853                                     mkexpr( neg_sign_mask ) ) );
   10854 
   10855          /* Check for invalid sign and BCD digit.  Don't check the bottom
   10856           * four bits of bcd_l as that is the sign value.
   10857           */
   10858          assign( invalid_mask,
   10859                  Generate_inv_mask(
   10860                                    bcd_digit_inval( unop( Iop_64HIto32,
   10861                                                           mkexpr( frBI64 ) ),
   10862                                                     binop( Iop_Shr32,
   10863                                                            unop( Iop_64to32,
   10864                                                                  mkexpr( frBI64 ) ),
   10865                                                            mkU8( 4 ) ) ),
   10866                                    mkexpr( pos_sign_mask ),
   10867                                    mkexpr( neg_sign_mask ) ) );
   10868 
   10869          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   10870 
   10871          /* Generate the result assuming the sign value was valid. */
   10872          assign( tmp64,
   10873                  unop( Iop_ReinterpD64asI64,
   10874                        binop( Iop_InsertExpD64,
   10875                               unop( Iop_ReinterpI64asD64,
   10876                                     mkU64( DFP_LONG_BIAS ) ),
   10877                               unop( Iop_ReinterpI64asD64,
   10878                                     binop( Iop_32HLto64,
   10879                                            binop( Iop_Or32,
   10880                                                   mkexpr( dbcd_u ),
   10881                                                   mkexpr( sign_bit ) ),
   10882                                            mkexpr( dbcd_l ) ) ) ) ) );
   10883       }
   10884 
   10885       /* Generate the value to store depending on the validity of the
   10886        * sign value and the validity of the BCD digits.
   10887        */
   10888       assign( resultD64,
   10889               unop( Iop_ReinterpI64asD64,
   10890                     binop( Iop_32HLto64,
   10891                            binop( Iop_Or32,
   10892                                   binop( Iop_And32,
   10893                                          mkexpr( valid_mask ),
   10894                                          unop( Iop_64HIto32,
   10895                                                mkexpr( tmp64 ) ) ),
   10896                                   binop( Iop_And32,
   10897                                          mkU32( 0x7C000000 ),
   10898                                          mkexpr( invalid_mask ) ) ),
   10899                            binop( Iop_Or32,
   10900                                   binop( Iop_And32,
   10901                                          mkexpr( valid_mask ),
   10902                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
   10903                                   binop( Iop_And32,
   10904                                          mkU32( 0x0 ),
   10905                                          mkexpr( invalid_mask ) ) ) ) ) );
   10906       putDReg( frT_addr, mkexpr( resultD64 ) );
   10907    }
   10908    break;
   10909    default:
   10910       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
   10911       return False;
   10912    }
   10913    return True;
   10914 }
   10915 
   10916 static Bool dis_dfp_bcdq( UInt theInstr )
   10917 {
   10918    UInt opc2        = ifieldOPClo10( theInstr );
   10919    ULong sp         = IFIELD(theInstr, 19, 2);
   10920    ULong s          = IFIELD(theInstr, 20, 1);
   10921    IRTemp frB_hi    = newTemp( Ity_D64 );
   10922    IRTemp frB_lo    = newTemp( Ity_D64 );
   10923    IRTemp frBI64_hi = newTemp( Ity_I64 );
   10924    IRTemp frBI64_lo = newTemp( Ity_I64 );
   10925    UChar frT_addr   = ifieldRegDS( theInstr );
   10926    UChar frB_addr   = ifieldRegB( theInstr );
   10927 
   10928    IRTemp lmd       = newTemp( Ity_I32 );
   10929    IRTemp result_hi = newTemp( Ity_I64 );
   10930    IRTemp result_lo = newTemp( Ity_I64 );
   10931 
   10932    assign( frB_hi, getDReg( frB_addr ) );
   10933    assign( frB_lo, getDReg( frB_addr + 1 ) );
   10934    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   10935    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   10936 
   10937    switch ( opc2 ) {
   10938    case 0x142: // ddedpdq   DFP Decode DPD to BCD
   10939    {
   10940       IRTemp low_60_u = newTemp( Ity_I32 );
   10941       IRTemp low_60_l = newTemp( Ity_I32 );
   10942       IRTemp mid_60_u = newTemp( Ity_I32 );
   10943       IRTemp mid_60_l = newTemp( Ity_I32 );
   10944       IRTemp top_12_l = newTemp( Ity_I32 );
   10945 
   10946       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   10947 
   10948       /* Note, instruction only stores the lower 32 BCD digits in
   10949        * the result
   10950        */
   10951       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   10952                                    mkexpr( frBI64_lo ),
   10953                                    &top_12_l,
   10954                                    &mid_60_u,
   10955                                    &mid_60_l,
   10956                                    &low_60_u,
   10957                                    &low_60_l );
   10958 
   10959       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   10960          /* Unsigned BCD string */
   10961          assign( result_hi,
   10962                  binop( Iop_32HLto64,
   10963                         binop( Iop_Or32,
   10964                                binop( Iop_Shl32,
   10965                                       mkexpr( top_12_l ),
   10966                                       mkU8( 24 ) ),
   10967                                binop( Iop_Shr32,
   10968                                       mkexpr( mid_60_u ),
   10969                                       mkU8( 4 ) ) ),
   10970                         binop( Iop_Or32,
   10971                                binop( Iop_Shl32,
   10972                                       mkexpr( mid_60_u ),
   10973                                       mkU8( 28 ) ),
   10974                                binop( Iop_Shr32,
   10975                                       mkexpr( mid_60_l ),
   10976                                       mkU8( 4 ) ) ) ) );
   10977 
   10978          assign( result_lo,
   10979                  binop( Iop_32HLto64,
   10980                         binop( Iop_Or32,
   10981                                binop( Iop_Shl32,
   10982                                       mkexpr( mid_60_l ),
   10983                                       mkU8( 28 ) ),
   10984                                mkexpr( low_60_u ) ),
   10985                         mkexpr( low_60_l ) ) );
   10986 
   10987       } else {
   10988          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   10989           * the positive and negative values are encoded in the least
   10990           * significant bits.
   10991           */
   10992          IRTemp sign = newTemp( Ity_I32 );
   10993 
   10994          if ( sp == 2 ) {
   10995             /* Positive sign = 0xC, negative sign = 0xD */
   10996             assign( sign,
   10997                     binop( Iop_Or32,
   10998                            binop( Iop_Shr32,
   10999                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11000                                   mkU8( 31 ) ),
   11001                            mkU32( 0xC ) ) );
   11002 
   11003          } else if ( sp == 3 ) {
   11004             IRTemp tmp32 = newTemp( Ity_I32 );
   11005 
   11006             /* Positive sign = 0xF, negative sign = 0xD.
   11007              * Need to complement sign bit then OR into bit position 1.
   11008              */
   11009             assign( tmp32,
   11010                     binop( Iop_Xor32,
   11011                            binop( Iop_Shr32,
   11012                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11013                                   mkU8( 30 ) ),
   11014                            mkU32( 0x2 ) ) );
   11015 
   11016             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11017 
   11018          } else {
   11019             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11020          }
   11021 
   11022          assign( result_hi,
   11023                  binop( Iop_32HLto64,
   11024                         binop( Iop_Or32,
   11025                                binop( Iop_Shl32,
   11026                                       mkexpr( top_12_l ),
   11027                                       mkU8( 28 ) ),
   11028                                mkexpr( mid_60_u ) ),
   11029                         mkexpr( mid_60_l ) ) );
   11030 
   11031          assign( result_lo,
   11032                  binop( Iop_32HLto64,
   11033                         binop( Iop_Or32,
   11034                                binop( Iop_Shl32,
   11035                                       mkexpr( low_60_u ),
   11036                                       mkU8( 4 ) ),
   11037                                binop( Iop_Shr32,
   11038                                       mkexpr( low_60_l ),
   11039                                       mkU8( 28 ) ) ),
   11040                         binop( Iop_Or32,
   11041                                binop( Iop_Shl32,
   11042                                       mkexpr( low_60_l ),
   11043                                       mkU8( 4 ) ),
   11044                                mkexpr( sign ) ) ) );
   11045       }
   11046 
   11047       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   11048       putDReg( frT_addr + 1,
   11049                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   11050    }
   11051    break;
   11052    case 0x342: // denbcdq   DFP Encode BCD to DPD
   11053    {
   11054       IRTemp valid_mask      = newTemp( Ity_I32 );
   11055       IRTemp invalid_mask    = newTemp( Ity_I32 );
   11056       IRTemp result128       = newTemp( Ity_D128 );
   11057       IRTemp dfp_significand = newTemp( Ity_D128 );
   11058       IRTemp tmp_hi          = newTemp( Ity_I64 );
   11059       IRTemp tmp_lo          = newTemp( Ity_I64 );
   11060       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
   11061       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
   11062       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
   11063       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
   11064       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
   11065       IRTemp bcd_top_8       = newTemp( Ity_I64 );
   11066       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
   11067       IRTemp bcd_low_60      = newTemp( Ity_I64 );
   11068       IRTemp sign_bit        = newTemp( Ity_I32 );
   11069       IRTemp tmptop10        = newTemp( Ity_I64 );
   11070       IRTemp tmpmid50        = newTemp( Ity_I64 );
   11071       IRTemp tmplow50        = newTemp( Ity_I64 );
   11072       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
   11073 
   11074       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11075 
   11076       if ( s == 0 ) {
   11077          /* Unsigned BCD string */
   11078          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
   11079 
   11080          assign( bcd_top_8,
   11081                  binop( Iop_32HLto64,
   11082                         mkU32( 0 ),
   11083                         binop( Iop_And32,
   11084                                binop( Iop_Shr32,
   11085                                       unop( Iop_64HIto32,
   11086                                             mkexpr( frBI64_hi ) ),
   11087                                       mkU8( 24 ) ),
   11088                                mkU32( 0xFF ) ) ) );
   11089          assign( bcd_mid_60,
   11090                  binop( Iop_32HLto64,
   11091                         binop( Iop_Or32,
   11092                                binop( Iop_Shr32,
   11093                                       unop( Iop_64to32,
   11094                                             mkexpr( frBI64_hi ) ),
   11095                                       mkU8( 28 ) ),
   11096                                binop( Iop_Shl32,
   11097                                       unop( Iop_64HIto32,
   11098                                             mkexpr( frBI64_hi ) ),
   11099                                       mkU8( 4 ) ) ),
   11100                         binop( Iop_Or32,
   11101                                binop( Iop_Shl32,
   11102                                       unop( Iop_64to32,
   11103                                             mkexpr( frBI64_hi ) ),
   11104                                       mkU8( 4 ) ),
   11105                                binop( Iop_Shr32,
   11106                                       unop( Iop_64HIto32,
   11107                                             mkexpr( frBI64_lo ) ),
   11108                                       mkU8( 28 ) ) ) ) );
   11109 
   11110          /* Note, the various helper functions ignores top 4-bits */
   11111          assign( bcd_low_60, mkexpr( frBI64_lo ) );
   11112 
   11113          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
   11114          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   11115 
   11116          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
   11117          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   11118          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   11119 
   11120          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   11121          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   11122          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   11123 
   11124          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
   11125           * value is not part of the final result. Only the right most
   11126           * BCD digits are stored.
   11127           */
   11128          assign( lmd, mkU32( 0 ) );
   11129 
   11130          assign( invalid_mask,
   11131                  binop( Iop_Or32,
   11132                         bcd_digit_inval( mkU32( 0 ),
   11133                                          unop( Iop_64to32,
   11134                                                mkexpr( bcd_top_8 ) ) ),
   11135                         binop( Iop_Or32,
   11136                                bcd_digit_inval( unop( Iop_64HIto32,
   11137                                                       mkexpr( bcd_mid_60 ) ),
   11138                                                 unop( Iop_64to32,
   11139                                                       mkexpr( bcd_mid_60 ) ) ),
   11140                                bcd_digit_inval( unop( Iop_64HIto32,
   11141                                                       mkexpr( bcd_low_60 ) ),
   11142                                                 unop( Iop_64to32,
   11143                                                       mkexpr( bcd_low_60 ) )
   11144                                                 ) ) ) );
   11145 
   11146       } else if ( s == 1 ) {
   11147          IRTemp sign          = newTemp( Ity_I32 );
   11148          IRTemp zero          = newTemp( Ity_I32 );
   11149          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   11150          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   11151 
   11152          /* The sign of the BCD string is stored in lower 4 bits */
   11153          assign( sign,
   11154                  binop( Iop_And32,
   11155                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
   11156                         mkU32( 0xF ) ) );
   11157          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   11158          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   11159          assign( sign_bit,
   11160                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   11161                                     mkexpr( neg_sign_mask ) ) );
   11162 
   11163          /* Generate the value assuminig the sign and BCD digits are vaild */
   11164          assign( bcd_top_8,
   11165                  binop( Iop_32HLto64,
   11166                         mkU32( 0x0 ),
   11167                         binop( Iop_Shr32,
   11168                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11169                                mkU8( 28 ) ) ) );
   11170 
   11171          /* The various helper routines ignore the upper 4-bits */
   11172          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
   11173 
   11174          /* Remove bottom four sign bits */
   11175          assign( bcd_low_60,
   11176                  binop( Iop_32HLto64,
   11177                         binop( Iop_Shr32,
   11178                                unop( Iop_64HIto32,
   11179                                      mkexpr( frBI64_lo ) ),
   11180                                mkU8( 4 ) ),
   11181                                binop( Iop_Or32,
   11182                                       binop( Iop_Shl32,
   11183                                              unop( Iop_64HIto32,
   11184                                                    mkexpr( frBI64_lo ) ),
   11185                                              mkU8( 28 ) ),
   11186                                       binop( Iop_Shr32,
   11187                                              unop( Iop_64to32,
   11188                                                    mkexpr( frBI64_lo ) ),
   11189                                              mkU8( 4 ) ) ) ) );
   11190          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
   11191          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   11192 
   11193          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
   11194          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   11195          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   11196 
   11197          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   11198          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   11199          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   11200 
   11201          /* The entire BCD string fits in lower 110-bits.  The LMD value
   11202           * is not stored in the final result for the DFP Long instruction.
   11203           */
   11204          assign( lmd, mkU32( 0 ) );
   11205 
   11206          /* Check for invalid sign and invalid BCD digit.  Don't check the
   11207           *  bottom four bits of frBI64_lo as that is the sign value.
   11208           */
   11209          assign( zero, mkU32( 0 ) );
   11210          assign( inval_bcd_digit_mask,
   11211                  binop( Iop_Or32,
   11212                         bcd_digit_inval( mkexpr( zero ),
   11213                                          unop( Iop_64to32,
   11214                                                mkexpr( bcd_top_8 ) ) ),
   11215                         binop( Iop_Or32,
   11216                                bcd_digit_inval( unop( Iop_64HIto32,
   11217                                                      mkexpr( bcd_mid_60 ) ),
   11218                                                unop( Iop_64to32,
   11219                                                      mkexpr( bcd_mid_60 ) ) ),
   11220                                bcd_digit_inval( unop( Iop_64HIto32,
   11221                                                      mkexpr( frBI64_lo ) ),
   11222                                                binop( Iop_Shr32,
   11223                                                       unop( Iop_64to32,
   11224                                                             mkexpr( frBI64_lo ) ),
   11225                                                         mkU8( 4 ) ) ) ) ) );
   11226          assign( invalid_mask,
   11227                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
   11228                                     mkexpr( pos_sign_mask ),
   11229                                     mkexpr( neg_sign_mask ) ) );
   11230 
   11231       }
   11232 
   11233       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11234 
   11235       /* Calculate the value of the result assuming sign and BCD digits
   11236        * are all valid.
   11237        */
   11238       assign( dfp_significand,
   11239               binop( Iop_D64HLtoD128,
   11240                      unop( Iop_ReinterpI64asD64,
   11241                            binop( Iop_32HLto64,
   11242                                   binop( Iop_Or32,
   11243                                          mkexpr( sign_bit ),
   11244                                          mkexpr( dbcd_top_l ) ),
   11245                                   binop( Iop_Or32,
   11246                                          binop( Iop_Shl32,
   11247                                                 mkexpr( dbcd_mid_u ),
   11248                                                 mkU8( 18 ) ),
   11249                                          binop( Iop_Shr32,
   11250                                                 mkexpr( dbcd_mid_l ),
   11251                                                 mkU8( 14 ) ) ) ) ),
   11252                      unop( Iop_ReinterpI64asD64,
   11253                            binop( Iop_32HLto64,
   11254                                   binop( Iop_Or32,
   11255                                          mkexpr( dbcd_low_u ),
   11256                                          binop( Iop_Shl32,
   11257                                                 mkexpr( dbcd_mid_l ),
   11258                                                 mkU8( 18 ) ) ),
   11259                                   mkexpr( dbcd_low_l ) ) ) ) );
   11260 
   11261       /* Break the result back down to 32-bit chunks and replace chunks.
   11262        * If there was an invalid BCD digit or invalid sign value, replace
   11263        * the calculated result with the invalid bit string.
   11264        */
   11265       assign( result128,
   11266               binop( Iop_InsertExpD128,
   11267                      unop( Iop_ReinterpI64asD64, mkU64( DFP_EXTND_BIAS ) ),
   11268                      mkexpr( dfp_significand ) ) );
   11269 
   11270       assign( tmp_hi,
   11271               unop( Iop_ReinterpD64asI64,
   11272                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
   11273 
   11274       assign( tmp_lo,
   11275               unop( Iop_ReinterpD64asI64,
   11276                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
   11277 
   11278       assign( result_hi,
   11279               binop( Iop_32HLto64,
   11280                      binop( Iop_Or32,
   11281                             binop( Iop_And32,
   11282                                    mkexpr( valid_mask ),
   11283                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
   11284                             binop( Iop_And32,
   11285                                    mkU32( 0x7C000000 ),
   11286                                    mkexpr( invalid_mask ) ) ),
   11287                      binop( Iop_Or32,
   11288                             binop( Iop_And32,
   11289                                    mkexpr( valid_mask ),
   11290                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
   11291                             binop( Iop_And32,
   11292                                    mkU32( 0x0 ),
   11293                                    mkexpr( invalid_mask ) ) ) ) );
   11294 
   11295       assign( result_lo,
   11296               binop( Iop_32HLto64,
   11297                      binop( Iop_Or32,
   11298                             binop( Iop_And32,
   11299                                    mkexpr( valid_mask ),
   11300                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
   11301                             binop( Iop_And32,
   11302                                    mkU32( 0x0 ),
   11303                                    mkexpr( invalid_mask ) ) ),
   11304                      binop( Iop_Or32,
   11305                             binop( Iop_And32,
   11306                                    mkexpr( valid_mask ),
   11307                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
   11308                             binop( Iop_And32,
   11309                                    mkU32( 0x0 ),
   11310                                    mkexpr( invalid_mask ) ) ) ) );
   11311 
   11312       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   11313       putDReg( frT_addr + 1,
   11314                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   11315 
   11316    }
   11317    break;
   11318    default:
   11319       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
   11320       break;
   11321    }
   11322    return True;
   11323 }
   11324 
   11325 static Bool dis_dfp_significant_digits( UInt theInstr )
   11326 {
   11327    UChar frA_addr = ifieldRegA( theInstr );
   11328    UChar frB_addr = ifieldRegB( theInstr );
   11329    IRTemp frA     = newTemp( Ity_D64 );
   11330    UInt opc1      = ifieldOPC( theInstr );
   11331    IRTemp B_sig   = newTemp( Ity_I8 );
   11332    IRTemp K       = newTemp( Ity_I8 );
   11333    IRTemp lmd_B   = newTemp( Ity_I32 );
   11334    IRTemp field   = newTemp( Ity_I32 );
   11335    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   11336    IRTemp Unordered_true     = newTemp( Ity_I32 );
   11337    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
   11338    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
   11339    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
   11340    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
   11341    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
   11342 
   11343    /* Get the reference singificance stored in frA */
   11344    assign( frA, getDReg( frA_addr ) );
   11345 
   11346    /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
   11347     * supported in 32-bit mode.
   11348     */
   11349    assign( K, unop( Iop_32to8,
   11350                     binop( Iop_And32,
   11351                            unop( Iop_64to32,
   11352                                  unop( Iop_ReinterpD64asI64,
   11353                                        mkexpr( frA ) ) ),
   11354                            mkU32( 0x3F ) ) ) );
   11355 
   11356    switch ( opc1 ) {
   11357    case 0x3b: // dtstsf   DFP Test Significance
   11358    {
   11359       IRTemp frB     = newTemp( Ity_D64 );
   11360       IRTemp frBI64  = newTemp( Ity_I64 );
   11361       IRTemp B_bcd_u = newTemp( Ity_I32 );
   11362       IRTemp B_bcd_l = newTemp( Ity_I32 );
   11363       IRTemp tmp64   = newTemp( Ity_I64 );
   11364 
   11365       DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   11366 
   11367       assign( frB, getDReg( frB_addr ) );
   11368       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   11369 
   11370       /* Get the BCD string for the value stored in a series of I32 values.
   11371        * Count the number of leading zeros.  Subtract the number of leading
   11372        * zeros from 16 (maximum number of significant digits in DFP
   11373        * Long).
   11374        */
   11375       Get_lmd( &lmd_B,
   11376                binop( Iop_Shr32,
   11377                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11378                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11379 
   11380       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   11381       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
   11382       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
   11383 
   11384       assign( B_sig,
   11385               binop( Iop_Sub8,
   11386                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
   11387                      Count_leading_zeros_60( mkexpr( lmd_B ),
   11388                                              mkexpr( B_bcd_u ),
   11389                                              mkexpr( B_bcd_l ) ) ) );
   11390       assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
   11391    }
   11392    break;
   11393    case 0x3F: // dtstsfq     DFP Test Significance
   11394    {
   11395       IRTemp frB_hi     = newTemp( Ity_D64 );
   11396       IRTemp frB_lo     = newTemp( Ity_D64 );
   11397       IRTemp frBI64_hi  = newTemp( Ity_I64 );
   11398       IRTemp frBI64_lo  = newTemp( Ity_I64 );
   11399       IRTemp B_low_60_u = newTemp( Ity_I32 );
   11400       IRTemp B_low_60_l = newTemp( Ity_I32 );
   11401       IRTemp B_mid_60_u = newTemp( Ity_I32 );
   11402       IRTemp B_mid_60_l = newTemp( Ity_I32 );
   11403       IRTemp B_top_12_l = newTemp( Ity_I32 );
   11404 
   11405       DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   11406 
   11407       assign( frB_hi, getDReg( frB_addr ) );
   11408       assign( frB_lo, getDReg( frB_addr + 1 ) );
   11409 
   11410       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   11411       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   11412 
   11413       /* Get the BCD string for the value stored in a series of I32 values.
   11414        * Count the number of leading zeros.  Subtract the number of leading
   11415        * zeros from 32 (maximum number of significant digits in DFP
   11416        * extended).
   11417        */
   11418       Get_lmd( &lmd_B,
   11419                binop( Iop_Shr32,
   11420                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   11421                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11422 
   11423       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   11424                                    mkexpr( frBI64_lo ),
   11425                                    &B_top_12_l,
   11426                                    &B_mid_60_u,
   11427                                    &B_mid_60_l,
   11428                                    &B_low_60_u,
   11429                                    &B_low_60_l );
   11430 
   11431       assign( B_sig,
   11432               binop( Iop_Sub8,
   11433                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
   11434                      Count_leading_zeros_128( mkexpr( lmd_B ),
   11435                                               mkexpr( B_top_12_l ),
   11436                                               mkexpr( B_mid_60_u ),
   11437                                               mkexpr( B_mid_60_l ),
   11438                                               mkexpr( B_low_60_u ),
   11439                                               mkexpr( B_low_60_l ) ) ) );
   11440 
   11441       assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
   11442    }
   11443    break;
   11444    }
   11445 
   11446    /* Compare (16 - cnt[0]) against K and set the condition code field
   11447     * accordingly.
   11448     *
   11449     * The field layout is as follows:
   11450     *
   11451     * bit[3:0]    Description
   11452     *    3     K != 0 and K < Number of significant digits if FRB
   11453     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
   11454     *    1     K != 0 and K = Number of significant digits if FRB
   11455     *    0     K ? Number of significant digits if FRB
   11456     */
   11457    assign( Eq_true_mask,
   11458            unop( Iop_1Sto32,
   11459                  binop( Iop_CmpEQ32,
   11460                         unop( Iop_8Uto32, mkexpr( K ) ),
   11461                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   11462    assign( Lt_true_mask,
   11463            unop( Iop_1Sto32,
   11464                  binop( Iop_CmpLT32U,
   11465                         unop( Iop_8Uto32, mkexpr( K ) ),
   11466                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   11467    assign( Gt_true_mask,
   11468            unop( Iop_1Sto32,
   11469                  binop( Iop_CmpLT32U,
   11470                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
   11471                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
   11472 
   11473    assign( KisZero_true_mask,
   11474            unop( Iop_1Sto32,
   11475                  binop( Iop_CmpEQ32,
   11476                         unop( Iop_8Uto32, mkexpr( K ) ),
   11477                         mkU32( 0 ) ) ) );
   11478    assign( KisZero_false_mask,
   11479            unop( Iop_1Sto32,
   11480                  binop( Iop_CmpNE32,
   11481                         unop( Iop_8Uto32, mkexpr( K ) ),
   11482                         mkU32( 0 ) ) ) );
   11483 
   11484    assign( field,
   11485            binop( Iop_Or32,
   11486                   binop( Iop_And32,
   11487                          mkexpr( KisZero_false_mask ),
   11488                          binop( Iop_Or32,
   11489                                 binop( Iop_And32,
   11490                                        mkexpr( Lt_true_mask ),
   11491                                        mkU32( 0x8 ) ),
   11492                                 binop( Iop_Or32,
   11493                                        binop( Iop_And32,
   11494                                               mkexpr( Gt_true_mask ),
   11495                                               mkU32( 0x4 ) ),
   11496                                        binop( Iop_And32,
   11497                                               mkexpr( Eq_true_mask ),
   11498                                               mkU32( 0x2 ) ) ) ) ),
   11499                   binop( Iop_And32,
   11500                          mkexpr( KisZero_true_mask ),
   11501                          mkU32( 0x4 ) ) ) );
   11502 
   11503    putGST_field( PPC_GST_CR,
   11504                  binop( Iop_Or32,
   11505                         binop( Iop_And32,
   11506                                mkexpr( Unordered_true ),
   11507                                mkU32( 0x1 ) ),
   11508                         binop( Iop_And32,
   11509                                unop( Iop_Not32, mkexpr( Unordered_true ) ),
   11510                                mkexpr( field ) ) ),
   11511                  crfD );
   11512 
   11513    return True;
   11514 }
   11515 
   11516 /*------------------------------------------------------------*/
   11517 /*--- AltiVec Instruction Translation                      ---*/
   11518 /*------------------------------------------------------------*/
   11519 
   11520 /*
   11521   Altivec Cache Control Instructions (Data Streams)
   11522 */
   11523 static Bool dis_av_datastream ( UInt theInstr )
   11524 {
   11525    /* X-Form */
   11526    UChar opc1     = ifieldOPC(theInstr);
   11527    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   11528    UChar flag_A   = flag_T;
   11529    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   11530    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   11531    UChar rA_addr  = ifieldRegA(theInstr);
   11532    UChar rB_addr  = ifieldRegB(theInstr);
   11533    UInt  opc2     = ifieldOPClo10(theInstr);
   11534    UChar b0       = ifieldBIT0(theInstr);
   11535 
   11536    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   11537       vex_printf("dis_av_datastream(ppc)(instr)\n");
   11538       return False;
   11539    }
   11540 
   11541    switch (opc2) {
   11542    case 0x156: // dst (Data Stream Touch, AV p115)
   11543       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   11544                                 rA_addr, rB_addr, STRM);
   11545       break;
   11546 
   11547    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   11548       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   11549                                   rA_addr, rB_addr, STRM);
   11550       break;
   11551 
   11552    case 0x336: // dss (Data Stream Stop, AV p114)
   11553       if (rA_addr != 0 || rB_addr != 0) {
   11554          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   11555          return False;
   11556       }
   11557       if (flag_A == 0) {
   11558          DIP("dss %d\n", STRM);
   11559       } else {
   11560          DIP("dssall\n");
   11561       }
   11562       break;
   11563 
   11564    default:
   11565       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   11566       return False;
   11567    }
   11568    return True;
   11569 }
   11570 
   11571 /*
   11572   AltiVec Processor Control Instructions
   11573 */
   11574 static Bool dis_av_procctl ( UInt theInstr )
   11575 {
   11576    /* VX-Form */
   11577    UChar opc1    = ifieldOPC(theInstr);
   11578    UChar vD_addr = ifieldRegDS(theInstr);
   11579    UChar vA_addr = ifieldRegA(theInstr);
   11580    UChar vB_addr = ifieldRegB(theInstr);
   11581    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   11582 
   11583    if (opc1 != 0x4) {
   11584       vex_printf("dis_av_procctl(ppc)(instr)\n");
   11585       return False;
   11586    }
   11587 
   11588    switch (opc2) {
   11589    case 0x604: // mfvscr (Move from VSCR, AV p129)
   11590       if (vA_addr != 0 || vB_addr != 0) {
   11591          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   11592          return False;
   11593       }
   11594       DIP("mfvscr v%d\n", vD_addr);
   11595       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   11596       break;
   11597 
   11598    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   11599       IRTemp vB = newTemp(Ity_V128);
   11600       if (vD_addr != 0 || vA_addr != 0) {
   11601          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   11602          return False;
   11603       }
   11604       DIP("mtvscr v%d\n", vB_addr);
   11605       assign( vB, getVReg(vB_addr));
   11606       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   11607       break;
   11608    }
   11609    default:
   11610       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   11611       return False;
   11612    }
   11613    return True;
   11614 }
   11615 
   11616 /*
   11617  * VSX scalar and vector convert instructions
   11618  */
   11619 static Bool
   11620 dis_vx_conv ( UInt theInstr, UInt opc2 )
   11621 {
   11622    /* XX2-Form */
   11623    UChar opc1 = ifieldOPC( theInstr );
   11624    UChar XT = ifieldRegXT( theInstr );
   11625    UChar XB = ifieldRegXB( theInstr );
   11626    IRTemp xB, xB2;
   11627    IRTemp b3, b2, b1, b0;
   11628    xB = xB2 = IRTemp_INVALID;
   11629 
   11630    if (opc1 != 0x3C) {
   11631       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   11632       return False;
   11633    }
   11634 
   11635    /* Create and assign temps only as needed for the given instruction. */
   11636    switch (opc2) {
   11637       // scalar double-precision floating point argument
   11638       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090:
   11639          xB = newTemp(Ity_F64);
   11640          assign( xB,
   11641                  unop( Iop_ReinterpI64asF64,
   11642                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   11643          break;
   11644       // vector double-precision floating point arguments
   11645       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   11646 
   11647          xB = newTemp(Ity_F64);
   11648          xB2 = newTemp(Ity_F64);
   11649          assign( xB,
   11650                  unop( Iop_ReinterpI64asF64,
   11651                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   11652          assign( xB2,
   11653                  unop( Iop_ReinterpI64asF64,
   11654                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   11655          break;
   11656       // vector single precision or [un]signed integer word arguments
   11657       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   11658       case 0x1f0: case 0x1d0:
   11659          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   11660          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   11661          break;
   11662          // vector [un]signed integer doubleword argument
   11663       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   11664          xB = newTemp(Ity_I64);
   11665          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   11666          xB2 = newTemp(Ity_I64);
   11667          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   11668          break;
   11669       // scalar [un]signed integer doubleword argument
   11670       case 0x2F0: case 0x2D0:
   11671          xB = newTemp(Ity_I64);
   11672          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   11673          break;
   11674       // scalar single precision argument
   11675       case 0x292: // xscvspdp
   11676          xB = newTemp(Ity_I32);
   11677          assign( xB,
   11678                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   11679          break;
   11680 
   11681       /* Certain instructions have their complete implementation in the main switch statement
   11682        * that follows this one; thus we have a "do nothing" case for those instructions here.
   11683        */
   11684       case 0x170: case 0x150:
   11685          break; // do nothing
   11686 
   11687       default:
   11688          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   11689          return False;
   11690    }
   11691 
   11692 
   11693    switch (opc2) {
   11694       case 0x2B0:
   11695          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   11696          //             to Signed Integer Doubleword format with Saturate)
   11697          DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11698          putVSReg( XT,
   11699                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   11700                                                  mkU32( Irrm_ZERO ),
   11701                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   11702          break;
   11703       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   11704                   //             Convert to Signed Integer Word format with Saturate)
   11705          DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11706          putVSReg( XT,
   11707                    binop( Iop_64HLtoV128,
   11708                           unop( Iop_32Sto64,
   11709                                 binop( Iop_F64toI32S,
   11710                                        mkU32( Irrm_ZERO ),
   11711                                        mkexpr( xB ) ) ),
   11712                                        mkU64( 0ULL ) ) );
   11713          break;
   11714       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   11715                   //             to Unsigned Integer Doubleword format with Saturate)
   11716          DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11717          putVSReg( XT,
   11718                    binop( Iop_64HLtoV128,
   11719                           binop( Iop_F64toI64U,
   11720                                  mkU32( Irrm_ZERO ),
   11721                                  mkexpr( xB ) ),
   11722                                  mkU64( 0ULL ) ) );
   11723          break;
   11724       case 0x2F0:
   11725          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   11726          //            Double-Precision format)
   11727          DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11728          putVSReg( XT,
   11729                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   11730                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   11731                                                        mkexpr( xB ) ) ),
   11732                                                        mkU64( 0 ) ) );
   11733          break;
   11734       case 0x2D0:
   11735          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   11736          //            Double-Precision format)
   11737          DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11738          putVSReg( XT,
   11739                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   11740                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   11741                                                        mkexpr( xB ) ) ),
   11742                                                        mkU64( 0 ) ) );
   11743          break;
   11744       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   11745                   //             to Signed Integer Word format with Saturate)
   11746       {
   11747          IRTemp hiResult_32 = newTemp(Ity_I32);
   11748          IRTemp loResult_32 = newTemp(Ity_I32);
   11749          IRExpr* rmZero = mkU32(Irrm_ZERO);
   11750 
   11751          DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11752          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   11753          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   11754          putVSReg( XT,
   11755                    binop( Iop_64HLtoV128,
   11756                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   11757                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   11758          break;
   11759       }
   11760       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   11761          //  (VSX Vector truncate Single-Precision to integer and
   11762          //   Convert to [Un]signed Integer Word format with Saturate)
   11763       {
   11764          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   11765          IRTemp tempResult = newTemp(Ity_V128);
   11766          IRTemp res0 = newTemp(Ity_I32);
   11767          IRTemp res1 = newTemp(Ity_I32);
   11768          IRTemp res2 = newTemp(Ity_I32);
   11769          IRTemp res3 = newTemp(Ity_I32);
   11770          IRTemp hi64 = newTemp(Ity_I64);
   11771          IRTemp lo64 = newTemp(Ity_I64);
   11772          Bool un_signed = (opc2 == 0x110);
   11773          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   11774 
   11775          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
   11776          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   11777           * then result is set to 0x80000000.  */
   11778          assign(tempResult, unop(op, getVSReg(XB)));
   11779          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   11780          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   11781          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   11782          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   11783          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   11784          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   11785 
   11786          b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)),
   11787                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   11788                                   mkexpr(res3),
   11789                                   // then: result is 0x{8|0}80000000
   11790                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   11791          b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)),
   11792                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   11793                                   mkexpr(res2),
   11794                                   // then: result is 0x{8|0}80000000
   11795                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   11796          b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)),
   11797                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   11798                                   mkexpr(res1),
   11799                                   // then: result is 0x{8|0}80000000
   11800                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   11801          b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)),
   11802                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   11803                                   mkexpr(res0),
   11804                                   // then: result is 0x{8|0}80000000
   11805                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   11806 
   11807          putVSReg( XT,
   11808                    binop( Iop_64HLtoV128,
   11809                           binop( Iop_32HLto64, b3_result, b2_result ),
   11810                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   11811          break;
   11812       }
   11813       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   11814                   //           Convert to Single-Precision format
   11815          DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11816          putVSReg( XT,
   11817                    binop( Iop_64HLtoV128,
   11818                           binop( Iop_32HLto64,
   11819                                  unop( Iop_ReinterpF32asI32,
   11820                                        unop( Iop_TruncF64asF32,
   11821                                              binop( Iop_RoundF64toF32,
   11822                                                     get_IR_roundingmode(),
   11823                                                     mkexpr( xB ) ) ) ),
   11824                                  mkU32( 0 ) ),
   11825                           mkU64( 0ULL ) ) );
   11826          break;
   11827       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   11828                   //             and Convert to Unsigned Integer Word format with Saturate)
   11829          DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11830          putVSReg( XT,
   11831                    binop( Iop_64HLtoV128,
   11832                           binop( Iop_32HLto64,
   11833                                  mkU32( 0 ),
   11834                                  binop( Iop_F64toI32U,
   11835                                         mkU32( Irrm_ZERO ),
   11836                                         mkexpr( xB ) ) ),
   11837                           mkU64( 0ULL ) ) );
   11838          break;
   11839       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format)
   11840          DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11841          putVSReg( XT,
   11842                    binop( Iop_64HLtoV128,
   11843                           unop( Iop_ReinterpF64asI64,
   11844                                 unop( Iop_F32toF64,
   11845                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   11846                           mkU64( 0ULL ) ) );
   11847          break;
   11848       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   11849                   //           and Convert to Single-Precision format)
   11850          DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11851          putVSReg( XT,
   11852                    binop( Iop_64HLtoV128,
   11853                           binop( Iop_32HLto64,
   11854                                  unop( Iop_ReinterpF32asI32,
   11855                                        unop( Iop_TruncF64asF32,
   11856                                              binop( Iop_RoundF64toF32,
   11857                                                     get_IR_roundingmode(),
   11858                                                     mkexpr( xB ) ) ) ),
   11859                                  mkU32( 0 ) ),
   11860                           binop( Iop_32HLto64,
   11861                                  unop( Iop_ReinterpF32asI32,
   11862                                        unop( Iop_TruncF64asF32,
   11863                                              binop( Iop_RoundF64toF32,
   11864                                                     get_IR_roundingmode(),
   11865                                                     mkexpr( xB2 ) ) ) ),
   11866                                  mkU32( 0 ) ) ) );
   11867          break;
   11868       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   11869                   //             and Convert to Unsigned Integer Doubleword format
   11870                   //             with Saturate)
   11871          DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11872          putVSReg( XT,
   11873                    binop( Iop_64HLtoV128,
   11874                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   11875                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   11876          break;
   11877       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   11878                   //             Convert to Unsigned Integer Word format with Saturate)
   11879          DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11880          putVSReg( XT,
   11881                    binop( Iop_64HLtoV128,
   11882                           binop( Iop_32HLto64,
   11883                                  binop( Iop_F64toI32U,
   11884                                         mkU32( Irrm_ZERO ),
   11885                                         mkexpr( xB ) ),
   11886                                  mkU32( 0 ) ),
   11887                           binop( Iop_32HLto64,
   11888                                  binop( Iop_F64toI32U,
   11889                                         mkU32( Irrm_ZERO ),
   11890                                         mkexpr( xB2 ) ),
   11891                                  mkU32( 0 ) ) ) );
   11892          break;
   11893       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   11894          DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11895          putVSReg( XT,
   11896                    binop( Iop_64HLtoV128,
   11897                           unop( Iop_ReinterpF64asI64,
   11898                                 unop( Iop_F32toF64,
   11899                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   11900                           unop( Iop_ReinterpF64asI64,
   11901                                 unop( Iop_F32toF64,
   11902                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   11903          break;
   11904       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   11905                   //           Convert to Signed Integer Doubleword format with Saturate)
   11906          DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11907          putVSReg( XT,
   11908                    binop( Iop_64HLtoV128,
   11909                           binop( Iop_F64toI64S,
   11910                                  mkU32( Irrm_ZERO ),
   11911                                  unop( Iop_F32toF64,
   11912                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   11913                           binop( Iop_F64toI64S,
   11914                                  mkU32( Irrm_ZERO ),
   11915                                  unop( Iop_F32toF64,
   11916                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   11917          break;
   11918       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   11919                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   11920          DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11921          putVSReg( XT,
   11922                    binop( Iop_64HLtoV128,
   11923                           binop( Iop_F64toI64U,
   11924                                  mkU32( Irrm_ZERO ),
   11925                                  unop( Iop_F32toF64,
   11926                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   11927                           binop( Iop_F64toI64U,
   11928                                  mkU32( Irrm_ZERO ),
   11929                                  unop( Iop_F32toF64,
   11930                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   11931          break;
   11932       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   11933                   //             Convert to Signed Integer Doubleword format with Saturate)
   11934          DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11935          putVSReg( XT,
   11936                    binop( Iop_64HLtoV128,
   11937                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   11938                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   11939          break;
   11940       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   11941                   //            to Double-Precision format)
   11942          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11943          putVSReg( XT,
   11944                    binop( Iop_64HLtoV128,
   11945                           unop( Iop_ReinterpF64asI64,
   11946                                 binop( Iop_I64StoF64,
   11947                                        get_IR_roundingmode(),
   11948                                        mkexpr( xB ) ) ),
   11949                           unop( Iop_ReinterpF64asI64,
   11950                                 binop( Iop_I64StoF64,
   11951                                        get_IR_roundingmode(),
   11952                                        mkexpr( xB2 ) ) ) ) );
   11953          break;
   11954       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   11955                   //            to Double-Precision format)
   11956          DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11957          putVSReg( XT,
   11958                    binop( Iop_64HLtoV128,
   11959                           unop( Iop_ReinterpF64asI64,
   11960                                 binop( Iop_I64UtoF64,
   11961                                        get_IR_roundingmode(),
   11962                                        mkexpr( xB ) ) ),
   11963                           unop( Iop_ReinterpF64asI64,
   11964                                 binop( Iop_I64UtoF64,
   11965                                        get_IR_roundingmode(),
   11966                                        mkexpr( xB2 ) ) ) ) );
   11967 
   11968          break;
   11969       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   11970                   //            to Single-Precision format)
   11971          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   11972          putVSReg( XT,
   11973                    binop( Iop_64HLtoV128,
   11974                           binop( Iop_32HLto64,
   11975                                  unop( Iop_ReinterpF32asI32,
   11976                                        unop( Iop_TruncF64asF32,
   11977                                              binop( Iop_RoundF64toF32,
   11978                                                     get_IR_roundingmode(),
   11979                                                     binop( Iop_I64StoF64,
   11980                                                            get_IR_roundingmode(),
   11981                                                            mkexpr( xB ) ) ) ) ),
   11982                                  mkU32( 0 ) ),
   11983                           binop( Iop_32HLto64,
   11984                                  unop( Iop_ReinterpF32asI32,
   11985                                        unop( Iop_TruncF64asF32,
   11986                                              binop( Iop_RoundF64toF32,
   11987                                                     get_IR_roundingmode(),
   11988                                                     binop( Iop_I64StoF64,
   11989                                                            get_IR_roundingmode(),
   11990                                                            mkexpr( xB2 ) ) ) ) ),
   11991                                  mkU32( 0 ) ) ) );
   11992          break;
   11993       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   11994                   //            to Single-Precision format)
   11995          DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
   11996          putVSReg( XT,
   11997                    binop( Iop_64HLtoV128,
   11998                           binop( Iop_32HLto64,
   11999                                  unop( Iop_ReinterpF32asI32,
   12000                                        unop( Iop_TruncF64asF32,
   12001                                              binop( Iop_RoundF64toF32,
   12002                                                     get_IR_roundingmode(),
   12003                                                     binop( Iop_I64UtoF64,
   12004                                                            get_IR_roundingmode(),
   12005                                                            mkexpr( xB ) ) ) ) ),
   12006                                  mkU32( 0 ) ),
   12007                           binop( Iop_32HLto64,
   12008                                  unop( Iop_ReinterpF32asI32,
   12009                                        unop( Iop_TruncF64asF32,
   12010                                              binop( Iop_RoundF64toF32,
   12011                                                     get_IR_roundingmode(),
   12012                                                     binop( Iop_I64UtoF64,
   12013                                                            get_IR_roundingmode(),
   12014                                                            mkexpr( xB2 ) ) ) ) ),
   12015                                  mkU32( 0 ) ) ) );
   12016          break;
   12017 
   12018       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   12019          DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12020          putVSReg( XT,
   12021                    binop( Iop_64HLtoV128,
   12022                           unop( Iop_ReinterpF64asI64,
   12023                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12024                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   12025                           unop( Iop_ReinterpF64asI64,
   12026                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12027                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   12028          break;
   12029       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   12030          DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12031          putVSReg( XT,
   12032                    binop( Iop_64HLtoV128,
   12033                           unop( Iop_ReinterpF64asI64,
   12034                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12035                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   12036                           unop( Iop_ReinterpF64asI64,
   12037                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12038                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   12039          break;
   12040       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   12041          DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12042          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   12043          break;
   12044       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   12045          DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   12046          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   12047          break;
   12048 
   12049       default:
   12050          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   12051          return False;
   12052    }
   12053    return True;
   12054 }
   12055 
   12056 /*
   12057  * VSX vector Double Precision Floating Point Arithmetic Instructions
   12058  */
   12059 static Bool
   12060 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   12061 {
   12062    /* XX3-Form */
   12063    UChar opc1 = ifieldOPC( theInstr );
   12064    UChar XT = ifieldRegXT( theInstr );
   12065    UChar XA = ifieldRegXA( theInstr );
   12066    UChar XB = ifieldRegXB( theInstr );
   12067    IRExpr* rm = get_IR_roundingmode();
   12068    IRTemp frA = newTemp(Ity_F64);
   12069    IRTemp frB = newTemp(Ity_F64);
   12070    IRTemp frA2 = newTemp(Ity_F64);
   12071    IRTemp frB2 = newTemp(Ity_F64);
   12072 
   12073    if (opc1 != 0x3C) {
   12074       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   12075       return False;
   12076    }
   12077 
   12078    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   12079    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   12080    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   12081    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   12082 
   12083    switch (opc2) {
   12084       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   12085       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   12086       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   12087       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   12088       {
   12089          IROp mOp;
   12090          Char * oper_name;
   12091          switch (opc2) {
   12092             case 0x1E0:
   12093                mOp = Iop_DivF64;
   12094                oper_name = "div";
   12095                break;
   12096             case 0x1C0:
   12097                mOp = Iop_MulF64;
   12098                oper_name = "mul";
   12099                break;
   12100             case 0x180:
   12101                mOp = Iop_AddF64;
   12102                oper_name = "add";
   12103                break;
   12104             case 0x1A0:
   12105                mOp = Iop_SubF64;
   12106                oper_name = "sub";
   12107                break;
   12108 
   12109             default:
   12110                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   12111          }
   12112          IRTemp hiResult = newTemp(Ity_I64);
   12113          IRTemp loResult = newTemp(Ity_I64);
   12114          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
   12115 
   12116          assign( hiResult,
   12117                  unop( Iop_ReinterpF64asI64,
   12118                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   12119          assign( loResult,
   12120                  unop( Iop_ReinterpF64asI64,
   12121                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   12122          putVSReg( XT,
   12123                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   12124          break;
   12125       }
   12126       case 0x196: // xvsqrtdp
   12127       {
   12128          IRTemp hiResult = newTemp(Ity_I64);
   12129          IRTemp loResult = newTemp(Ity_I64);
   12130          DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   12131 
   12132          assign( hiResult,
   12133                  unop( Iop_ReinterpF64asI64,
   12134                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   12135          assign( loResult,
   12136                  unop( Iop_ReinterpF64asI64,
   12137                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   12138          putVSReg( XT,
   12139                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   12140          break;
   12141       }
   12142       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   12143       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   12144       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   12145       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   12146       {
   12147          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   12148           *    XT == FRC
   12149           *    XA == FRA
   12150           *    XB == FRB
   12151           *
   12152           * and for xvm{add|sub}adp . . .
   12153           *    XT == FRB
   12154           *    XA == FRA
   12155           *    XB == FRC
   12156           */
   12157          Bool negate;
   12158          IROp mOp = Iop_INVALID;
   12159          Char * oper_name = NULL;
   12160          Bool mdp = False;
   12161 
   12162          switch (opc2) {
   12163             case 0x184: case 0x1A4:
   12164             case 0x384: case 0x3A4:
   12165                mOp = Iop_MAddF64;
   12166                oper_name = "add";
   12167                mdp = (opc2 & 0x0FF) == 0x0A4;
   12168                break;
   12169 
   12170             case 0x1C4: case 0x1E4:
   12171             case 0x3C4: case 0x3E4:
   12172                mOp = Iop_MSubF64;
   12173                oper_name = "sub";
   12174                mdp = (opc2 & 0x0FF) == 0x0E4;
   12175                break;
   12176 
   12177             default:
   12178                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   12179          }
   12180 
   12181          switch (opc2) {
   12182             case 0x384: case 0x3A4:
   12183             case 0x3C4: case 0x3E4:
   12184                negate = True;
   12185                break;
   12186             default:
   12187                negate = False;
   12188          }
   12189          IRTemp hiResult = newTemp(Ity_I64);
   12190          IRTemp loResult = newTemp(Ity_I64);
   12191          IRTemp frT = newTemp(Ity_F64);
   12192          IRTemp frT2 = newTemp(Ity_F64);
   12193          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   12194              (UInt)XT, (UInt)XA, (UInt)XB);
   12195          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   12196          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   12197 
   12198          assign( hiResult,
   12199                  unop( Iop_ReinterpF64asI64,
   12200                        qop( mOp,
   12201                             rm,
   12202                             mkexpr( frA ),
   12203                             mkexpr( mdp ? frT : frB ),
   12204                             mkexpr( mdp ? frB : frT ) ) ) );
   12205          assign( loResult,
   12206                  unop( Iop_ReinterpF64asI64,
   12207                        qop( mOp,
   12208                             rm,
   12209                             mkexpr( frA2 ),
   12210                             mkexpr( mdp ? frT2 : frB2 ),
   12211                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   12212          putVSReg( XT,
   12213                    binop( Iop_64HLtoV128,
   12214                           mkexpr( negate ? getNegatedResult( hiResult )
   12215                                          : hiResult ),
   12216                           mkexpr( negate ? getNegatedResult( loResult )
   12217                                          : loResult ) ) );
   12218          break;
   12219       }
   12220       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   12221       {
   12222          IRTemp frBHi_I64 = newTemp(Ity_I64);
   12223          IRTemp frBLo_I64 = newTemp(Ity_I64);
   12224          IRTemp flagsHi = newTemp(Ity_I32);
   12225          IRTemp flagsLo = newTemp(Ity_I32);
   12226          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12227          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   12228          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   12229 
   12230          DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   12231          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   12232          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   12233          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   12234          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   12235          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12236           * where fl_flag == 1 on ppc64.
   12237           */
   12238          assign( flagsHi,
   12239                  binop( Iop_Or32,
   12240                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12241                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   12242                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   12243          assign( flagsLo,
   12244                  binop( Iop_Or32,
   12245                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12246                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   12247                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   12248          putGST_field( PPC_GST_CR,
   12249                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   12250                        crfD );
   12251          break;
   12252       }
   12253       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   12254       {
   12255          IRTemp frBHi_I64 = newTemp(Ity_I64);
   12256          IRTemp frBLo_I64 = newTemp(Ity_I64);
   12257          IRTemp frAHi_I64 = newTemp(Ity_I64);
   12258          IRTemp frALo_I64 = newTemp(Ity_I64);
   12259          IRTemp flagsHi = newTemp(Ity_I32);
   12260          IRTemp flagsLo = newTemp(Ity_I32);
   12261          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12262          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   12263          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   12264 
   12265          DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   12266          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   12267          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   12268          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   12269          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   12270 
   12271          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   12272          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   12273          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12274           * where fl_flag == 1 on ppc64.
   12275           */
   12276          assign( flagsHi,
   12277                  binop( Iop_Or32,
   12278                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12279                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   12280                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   12281          assign( flagsLo,
   12282                  binop( Iop_Or32,
   12283                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12284                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   12285                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   12286          putGST_field( PPC_GST_CR,
   12287                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   12288                        crfD );
   12289          break;
   12290       }
   12291 
   12292       default:
   12293          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   12294          return False;
   12295    }
   12296    return True;
   12297 }
   12298 
   12299 /*
   12300  * VSX vector Single Precision Floating Point Arithmetic Instructions
   12301  */
   12302 static Bool
   12303 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   12304 {
   12305    /* XX3-Form */
   12306    UChar opc1 = ifieldOPC( theInstr );
   12307    UChar XT = ifieldRegXT( theInstr );
   12308    UChar XA = ifieldRegXA( theInstr );
   12309    UChar XB = ifieldRegXB( theInstr );
   12310    IRExpr* rm = get_IR_roundingmode();
   12311    IRTemp a3, a2, a1, a0;
   12312    IRTemp b3, b2, b1, b0;
   12313    IRTemp res0 = newTemp(Ity_I32);
   12314    IRTemp res1 = newTemp(Ity_I32);
   12315    IRTemp res2 = newTemp(Ity_I32);
   12316    IRTemp res3 = newTemp(Ity_I32);
   12317 
   12318    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   12319    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12320 
   12321    if (opc1 != 0x3C) {
   12322       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   12323       return False;
   12324    }
   12325 
   12326    switch (opc2) {
   12327       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   12328          DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12329          putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) );
   12330          break;
   12331 
   12332       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   12333          DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12334          putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) );
   12335          break;
   12336 
   12337       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   12338          DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12339          putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) );
   12340          break;
   12341 
   12342       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   12343       {
   12344          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   12345           * So there are two choices:
   12346           *   1. Implement the xvdivsp with a native insn; or
   12347           *   2. Extract the 4 single precision floats from each vector
   12348           *      register inputs and perform fdivs on each pair
   12349           * I will do the latter, due to the general philosophy of
   12350           * reusing existing implementations when practical.
   12351           */
   12352          DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   12353          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   12354          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12355 
   12356          assign( res0,
   12357               unop( Iop_ReinterpF32asI32,
   12358                     unop( Iop_TruncF64asF32,
   12359                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   12360          assign( res1,
   12361                  unop( Iop_ReinterpF32asI32,
   12362                        unop( Iop_TruncF64asF32,
   12363                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   12364          assign( res2,
   12365                  unop( Iop_ReinterpF32asI32,
   12366                        unop( Iop_TruncF64asF32,
   12367                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   12368          assign( res3,
   12369                  unop( Iop_ReinterpF32asI32,
   12370                        unop( Iop_TruncF64asF32,
   12371                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   12372 
   12373          putVSReg( XT,
   12374                    binop( Iop_64HLtoV128,
   12375                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   12376                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   12377          break;
   12378       }
   12379       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   12380       {
   12381          DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   12382          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12383          /* Note: The native xvsqrtsp insruction does not always give the same precision
   12384           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   12385           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   12386           * to the actual instruction.
   12387           */
   12388 
   12389          assign( res0,
   12390                  unop( Iop_ReinterpF32asI32,
   12391                        unop( Iop_TruncF64asF32,
   12392                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   12393          assign( res1,
   12394                  unop( Iop_ReinterpF32asI32,
   12395                        unop( Iop_TruncF64asF32,
   12396                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   12397          assign( res2,
   12398                  unop( Iop_ReinterpF32asI32,
   12399                        unop( Iop_TruncF64asF32,
   12400                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   12401          assign( res3,
   12402                  unop( Iop_ReinterpF32asI32,
   12403                        unop( Iop_TruncF64asF32,
   12404                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   12405 
   12406          putVSReg( XT,
   12407                    binop( Iop_64HLtoV128,
   12408                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   12409                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   12410          break;
   12411       }
   12412 
   12413       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   12414       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   12415       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   12416       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   12417       {
   12418          IRTemp t3, t2, t1, t0;
   12419          Bool msp = False;
   12420          Bool negate;
   12421          Char * oper_name = NULL;
   12422          IROp mOp = Iop_INVALID;
   12423          switch (opc2) {
   12424             case 0x104: case 0x124:
   12425             case 0x304: case 0x324:
   12426                msp = (opc2 & 0x0FF) == 0x024;
   12427                mOp = Iop_MAddF64r32;
   12428                oper_name = "madd";
   12429                break;
   12430 
   12431             case 0x144: case 0x164:
   12432             case 0x344: case 0x364:
   12433                msp = (opc2 & 0x0FF) == 0x064;
   12434                mOp = Iop_MSubF64r32;
   12435                oper_name = "sub";
   12436                break;
   12437 
   12438             default:
   12439                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   12440          }
   12441 
   12442          switch (opc2) {
   12443             case 0x304: case 0x324:
   12444             case 0x344: case 0x364:
   12445                negate = True;
   12446                break;
   12447 
   12448             default:
   12449                negate = False;
   12450          }
   12451 
   12452          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
   12453              (UInt)XT, (UInt)XA, (UInt)XB);
   12454 
   12455          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   12456          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   12457          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12458          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   12459 
   12460          assign( res0,
   12461                  unop( Iop_ReinterpF32asI32,
   12462                        unop( Iop_TruncF64asF32,
   12463                              qop( mOp,
   12464                                   rm,
   12465                                   mkexpr( a0 ),
   12466                                   mkexpr( msp ? t0 : b0 ),
   12467                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   12468          assign( res1,
   12469                  unop( Iop_ReinterpF32asI32,
   12470                        unop( Iop_TruncF64asF32,
   12471                              qop( mOp,
   12472                                   rm,
   12473                                   mkexpr( a1 ),
   12474                                   mkexpr( msp ? t1 : b1 ),
   12475                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   12476          assign( res2,
   12477                  unop( Iop_ReinterpF32asI32,
   12478                        unop( Iop_TruncF64asF32,
   12479                              qop( mOp,
   12480                                   rm,
   12481                                   mkexpr( a2 ),
   12482                                   mkexpr( msp ? t2 : b2 ),
   12483                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   12484          assign( res3,
   12485                  unop( Iop_ReinterpF32asI32,
   12486                        unop( Iop_TruncF64asF32,
   12487                              qop( mOp,
   12488                                   rm,
   12489                                   mkexpr( a3 ),
   12490                                   mkexpr( msp ? t3 : b3 ),
   12491                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   12492 
   12493          putVSReg( XT,
   12494                    binop( Iop_64HLtoV128,
   12495                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   12496                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   12497                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   12498                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   12499 
   12500          break;
   12501       }
   12502       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   12503       {
   12504          IRTemp flags0 = newTemp(Ity_I32);
   12505          IRTemp flags1 = newTemp(Ity_I32);
   12506          IRTemp flags2 = newTemp(Ity_I32);
   12507          IRTemp flags3 = newTemp(Ity_I32);
   12508          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12509          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   12510          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   12511          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   12512          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   12513          DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   12514 
   12515          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12516          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   12517          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   12518          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   12519          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   12520 
   12521          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12522           * where fl_flag == 1 on ppc64.
   12523           */
   12524          assign( flags0,
   12525                  binop( Iop_Or32,
   12526                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12527                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   12528                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   12529          assign( flags1,
   12530                  binop( Iop_Or32,
   12531                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12532                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   12533                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   12534          assign( flags2,
   12535                  binop( Iop_Or32,
   12536                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12537                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   12538                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   12539          assign( flags3,
   12540                  binop( Iop_Or32,
   12541                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12542                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   12543                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   12544          putGST_field( PPC_GST_CR,
   12545                        binop( Iop_Or32,
   12546                               mkexpr( flags0 ),
   12547                               binop( Iop_Or32,
   12548                                      mkexpr( flags1 ),
   12549                                      binop( Iop_Or32,
   12550                                             mkexpr( flags2 ),
   12551                                             mkexpr( flags3 ) ) ) ),
   12552                        crfD );
   12553 
   12554          break;
   12555       }
   12556       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   12557       {
   12558          IRTemp flags0 = newTemp(Ity_I32);
   12559          IRTemp flags1 = newTemp(Ity_I32);
   12560          IRTemp flags2 = newTemp(Ity_I32);
   12561          IRTemp flags3 = newTemp(Ity_I32);
   12562          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   12563          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   12564          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   12565          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   12566          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   12567          DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   12568 
   12569          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   12570          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12571          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   12572          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   12573          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   12574          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   12575 
   12576          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   12577           * where fl_flag == 1 on ppc64.
   12578           */
   12579          assign( flags0,
   12580                  binop( Iop_Or32,
   12581                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12582                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   12583                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   12584          assign( flags1,
   12585                  binop( Iop_Or32,
   12586                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12587                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   12588                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   12589          assign( flags2,
   12590                  binop( Iop_Or32,
   12591                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12592                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   12593                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   12594          assign( flags3,
   12595                  binop( Iop_Or32,
   12596                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   12597                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   12598                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   12599          putGST_field( PPC_GST_CR,
   12600                        binop( Iop_Or32,
   12601                               mkexpr( flags0 ),
   12602                               binop( Iop_Or32,
   12603                                      mkexpr( flags1 ),
   12604                                      binop( Iop_Or32,
   12605                                             mkexpr( flags2 ),
   12606                                             mkexpr( flags3 ) ) ) ),
   12607                        crfD );
   12608 
   12609          break;
   12610       }
   12611 
   12612       default:
   12613          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   12614          return False;
   12615    }
   12616    return True;
   12617 }
   12618 
   12619 typedef enum {
   12620    PPC_CMP_EQ = 2,
   12621    PPC_CMP_GT = 4,
   12622    PPC_CMP_GE = 6,
   12623    PPC_CMP_LT = 8
   12624 } ppc_cmp_t;
   12625 
   12626 
   12627 /*
   12628   This helper function takes as input the IRExpr returned
   12629   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   12630   in IR form.  This helper function converts it to PPC form.
   12631 
   12632   Map compare result from IR to PPC
   12633 
   12634   FP cmp result | PPC | IR
   12635   --------------------------
   12636   UN            | 0x1 | 0x45
   12637   EQ            | 0x2 | 0x40
   12638   GT            | 0x4 | 0x00
   12639   LT            | 0x8 | 0x01
   12640 
   12641  condcode = Shl(1, (~(ccIR>>5) & 2)
   12642                     | ((ccIR ^ (ccIR>>6)) & 1)
   12643 */
   12644 static IRTemp
   12645 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   12646 {
   12647    IRTemp condcode = newTemp( Ity_I32 );
   12648    IRTemp ccIR = newTemp( Ity_I32 );
   12649 
   12650    assign(ccIR, ccIR_expr);
   12651    assign( condcode,
   12652            binop( Iop_Shl32,
   12653                   mkU32( 1 ),
   12654                   unop( Iop_32to8,
   12655                         binop( Iop_Or32,
   12656                                binop( Iop_And32,
   12657                                       unop( Iop_Not32,
   12658                                             binop( Iop_Shr32,
   12659                                                    mkexpr( ccIR ),
   12660                                                    mkU8( 5 ) ) ),
   12661                                       mkU32( 2 ) ),
   12662                                binop( Iop_And32,
   12663                                       binop( Iop_Xor32,
   12664                                              mkexpr( ccIR ),
   12665                                              binop( Iop_Shr32,
   12666                                                     mkexpr( ccIR ),
   12667                                                     mkU8( 6 ) ) ),
   12668                                       mkU32( 1 ) ) ) ) ) );
   12669    return condcode;
   12670 }
   12671 
   12672 /*
   12673  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   12674  * following these special rules:
   12675  *   - The max/min of a QNaN and any value is that value
   12676  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   12677  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   12678  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   12679  */
   12680 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   12681 {
   12682    IRTemp frA_isNaN = newTemp(Ity_I1);
   12683    IRTemp frB_isNaN = newTemp(Ity_I1);
   12684    IRTemp frA_isSNaN = newTemp(Ity_I1);
   12685    IRTemp frB_isSNaN = newTemp(Ity_I1);
   12686    IRTemp frA_isQNaN = newTemp(Ity_I1);
   12687    IRTemp frB_isQNaN = newTemp(Ity_I1);
   12688 
   12689    assign( frA_isNaN, is_NaN( frA_I64 ) );
   12690    assign( frB_isNaN, is_NaN( frB_I64 ) );
   12691    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   12692    assign( frA_isSNaN,
   12693            mkAND1( mkexpr(frA_isNaN),
   12694                    binop( Iop_CmpEQ32,
   12695                           binop( Iop_And32,
   12696                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   12697                                  mkU32( 0x00080000 ) ),
   12698                           mkU32( 0 ) ) ) );
   12699    assign( frB_isSNaN,
   12700            mkAND1( mkexpr(frB_isNaN),
   12701                    binop( Iop_CmpEQ32,
   12702                           binop( Iop_And32,
   12703                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   12704                                  mkU32( 0x00080000 ) ),
   12705                           mkU32( 0 ) ) ) );
   12706    assign( frA_isQNaN,
   12707            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   12708    assign( frB_isQNaN,
   12709            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   12710 
   12711    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   12712     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   12713     *   if frA is a SNaN
   12714     *     result = frA converted to QNaN
   12715     *   else if frB is a SNaN
   12716     *     result = frB converted to QNaN
   12717     *   else if frB is a QNaN
   12718     *     result = frA
   12719     *   // One of frA or frB was a NaN in order for this function to be called, so
   12720     *   // if we get to this point, we KNOW that frA must be a QNaN.
   12721     *   else // frA is a QNaN
   12722     *     result = frB
   12723     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   12724     */
   12725 
   12726 #define SNAN_MASK 0x0008000000000000ULL
   12727    return
   12728    IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)),
   12729                 /* else:  if frB is a SNaN */
   12730                 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)),
   12731                              /* else:  if frB is a QNaN */
   12732                              IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)),
   12733                                           /* else:  frA is a QNaN, so result = frB */
   12734                                           mkexpr(frB_I64),
   12735                                           /* then: result = frA */
   12736                                           mkexpr(frA_I64)),
   12737                              /* then: result = frB converted to QNaN */
   12738                              binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))),
   12739                 /* then: result = frA converted to QNaN */
   12740                 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)));
   12741 }
   12742 
   12743 /*
   12744  * Helper function for get_max_min_fp.
   12745  */
   12746 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   12747 {
   12748    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   12749                                                   unop( Iop_ReinterpI64asF64,
   12750                                                         mkexpr( src1 ) ),
   12751                                                   unop( Iop_ReinterpI64asF64,
   12752                                                         mkexpr( src2 ) ) ) );
   12753 
   12754    return IRExpr_Mux0X( unop( Iop_1Uto8,
   12755                               binop( Iop_CmpEQ32,
   12756                                      mkexpr( src1cmpsrc2 ),
   12757                                      mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ),
   12758                         /* else: use src2 */
   12759                         mkexpr( src2 ),
   12760                         /* then: use src1 */
   12761                         mkexpr( src1 ) );
   12762 }
   12763 
   12764 /*
   12765  * Helper function for "Maximum/Minimum Double Precision" operations.
   12766  * Arguments: frA and frb are Ity_I64
   12767  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   12768  */
   12769 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   12770 {
   12771    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   12772     * for ascertaining the maximum between two doubles:
   12773     *   1. The max/min of +0 and -0 is +0.
   12774     *   2. The max/min of a QNaN and any value is that value.
   12775     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   12776     * We perform the check for [+/-]0 here in this function and use the
   12777     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   12778     * to do the standard comparison function.
   12779     */
   12780    IRTemp anyNaN = newTemp(Ity_I1);
   12781    IRTemp frA_isZero = newTemp(Ity_I1);
   12782    IRTemp frB_isZero = newTemp(Ity_I1);
   12783    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
   12784    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
   12785    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
   12786 #define MINUS_ZERO 0x8000000000000000ULL
   12787 
   12788    return IRExpr_Mux0X( unop( Iop_1Uto8,
   12789                               /* If both arguments are zero . . . */
   12790                               mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ),
   12791                         /* else: check if either input is a NaN*/
   12792                         IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ),
   12793                                       /* else: use "comparison helper" */
   12794                                       _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ),
   12795                                       /* then: use "NaN helper" */
   12796                                       _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ),
   12797                         /* then: if frA is -0 and isMin==True, return -0;
   12798                          *     else if frA is +0 and isMin==False; return +0;
   12799                          *     otherwise, simply return frB. */
   12800                         IRExpr_Mux0X( unop( Iop_1Uto8,
   12801                                             binop( Iop_CmpEQ32,
   12802                                                    unop( Iop_64HIto32,
   12803                                                          mkexpr( frA_I64 ) ),
   12804                                                    mkU32( isMin ? 0x80000000 : 0 ) ) ),
   12805                                       mkexpr( frB_I64 ),
   12806                                       mkU64( isMin ? MINUS_ZERO : 0ULL ) ) );
   12807 }
   12808 
   12809 /*
   12810  * Helper function for vector/scalar double precision fp round to integer instructions.
   12811  */
   12812 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix)
   12813 {
   12814 
   12815    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   12816    IRTemp frB = newTemp(Ity_F64);
   12817    IRTemp frD = newTemp(Ity_F64);
   12818    IRTemp intermediateResult = newTemp(Ity_I64);
   12819    IRTemp is_SNAN = newTemp(Ity_I1);
   12820    IRExpr * hi32;
   12821    IRExpr * rxpi_rm;
   12822    switch (opc2 & 0x7F) {
   12823       case 0x72:
   12824          insn_suffix = "m";
   12825          rxpi_rm = mkU32(Irrm_NegINF);
   12826          break;
   12827       case 0x52:
   12828          insn_suffix = "p";
   12829          rxpi_rm = mkU32(Irrm_PosINF);
   12830          break;
   12831       case 0x56:
   12832          insn_suffix = "c";
   12833          rxpi_rm = get_IR_roundingmode();
   12834          break;
   12835       case 0x32:
   12836          insn_suffix = "z";
   12837          rxpi_rm = mkU32(Irrm_ZERO);
   12838          break;
   12839       case 0x12:
   12840          insn_suffix = "";
   12841          rxpi_rm = mkU32(Irrm_NEAREST);
   12842          break;
   12843 
   12844       default: // Impossible to get here
   12845          vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" );
   12846          return NULL;
   12847    }
   12848    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   12849    assign( intermediateResult,
   12850            binop( Iop_F64toI64S, rxpi_rm,
   12851                   mkexpr( frB ) ) );
   12852 
   12853    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   12854    /* F64 has only log10(2**52) significant digits anyway */
   12855    /* need to preserve sign of zero */
   12856    /*   frD = (fabs(frB) > 9e18) ? frB :
   12857             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   12858    assign( frD,
   12859            IRExpr_Mux0X( unop( Iop_32to8,
   12860                                binop( Iop_CmpF64,
   12861                                       IRExpr_Const( IRConst_F64( 9e18 ) ),
   12862                                       unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   12863                          IRExpr_Mux0X( unop( Iop_32to8,
   12864                                              binop( Iop_Shr32,
   12865                                                     unop( Iop_64HIto32,
   12866                                                           mkexpr( frB_I64 ) ),
   12867                                                     mkU8( 31 ) ) ),
   12868                                        binop( Iop_I64StoF64,
   12869                                               mkU32( 0 ),
   12870                                               mkexpr( intermediateResult ) ),
   12871                                        unop( Iop_NegF64,
   12872                                              unop( Iop_AbsF64,
   12873                                                    binop( Iop_I64StoF64,
   12874                                                           mkU32( 0 ),
   12875                                                           mkexpr( intermediateResult ) ) ) ) ),
   12876                          mkexpr( frB ) ) );
   12877 
   12878    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   12879     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   12880     */
   12881 #define SNAN_MASK 0x0008000000000000ULL
   12882    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   12883    assign( is_SNAN,
   12884            mkAND1( is_NaN( frB_I64 ),
   12885                    binop( Iop_CmpEQ32,
   12886                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   12887                           mkU32( 0 ) ) ) );
   12888 
   12889    return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ),
   12890                         mkexpr( frD ),
   12891                         unop( Iop_ReinterpI64asF64,
   12892                               binop( Iop_Xor64,
   12893                                      mkU64( SNAN_MASK ),
   12894                                      mkexpr( frB_I64 ) ) ) );
   12895 }
   12896 
   12897 /*
   12898  * Miscellaneous VSX vector instructions
   12899  */
   12900 static Bool
   12901 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   12902 {
   12903    /* XX3-Form */
   12904    UChar opc1 = ifieldOPC( theInstr );
   12905    UChar XT = ifieldRegXT( theInstr );
   12906    UChar XB = ifieldRegXB( theInstr );
   12907 
   12908    if (opc1 != 0x3C) {
   12909       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   12910       return False;
   12911    }
   12912 
   12913    switch (opc2) {
   12914       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   12915       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   12916                    //             Double-Precision)
   12917       {
   12918          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   12919          IRExpr* rm  = get_IR_roundingmode();
   12920          IRTemp frB = newTemp(Ity_I64);
   12921          IRTemp frB2 = newTemp(Ity_I64);
   12922          Bool redp = opc2 == 0x1B4;
   12923          IRTemp sqrtHi = newTemp(Ity_F64);
   12924          IRTemp sqrtLo = newTemp(Ity_F64);
   12925          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   12926          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   12927 
   12928          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
   12929          if (!redp) {
   12930             assign( sqrtHi,
   12931                     binop( Iop_SqrtF64,
   12932                            rm,
   12933                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   12934             assign( sqrtLo,
   12935                     binop( Iop_SqrtF64,
   12936                            rm,
   12937                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   12938          }
   12939          putVSReg( XT,
   12940                    binop( Iop_64HLtoV128,
   12941                           unop( Iop_ReinterpF64asI64,
   12942                                 triop( Iop_DivF64,
   12943                                        rm,
   12944                                        ieee_one,
   12945                                        redp ? unop( Iop_ReinterpI64asF64,
   12946                                                     mkexpr( frB ) )
   12947                                             : mkexpr( sqrtHi ) ) ),
   12948                           unop( Iop_ReinterpF64asI64,
   12949                                 triop( Iop_DivF64,
   12950                                        rm,
   12951                                        ieee_one,
   12952                                        redp ? unop( Iop_ReinterpI64asF64,
   12953                                                     mkexpr( frB2 ) )
   12954                                             : mkexpr( sqrtLo ) ) ) ) );
   12955          break;
   12956 
   12957       }
   12958       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   12959       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   12960       {
   12961          IRTemp b3, b2, b1, b0;
   12962          IRTemp res0 = newTemp(Ity_I32);
   12963          IRTemp res1 = newTemp(Ity_I32);
   12964          IRTemp res2 = newTemp(Ity_I32);
   12965          IRTemp res3 = newTemp(Ity_I32);
   12966          IRTemp sqrt3 = newTemp(Ity_F64);
   12967          IRTemp sqrt2 = newTemp(Ity_F64);
   12968          IRTemp sqrt1 = newTemp(Ity_F64);
   12969          IRTemp sqrt0 = newTemp(Ity_F64);
   12970          IRExpr* rm  = get_IR_roundingmode();
   12971          Bool resp = opc2 == 0x134;
   12972 
   12973          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   12974 
   12975          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12976          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
   12977          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   12978 
   12979          if (!resp) {
   12980             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   12981             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   12982             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   12983             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   12984          }
   12985 
   12986          assign( res0,
   12987                  unop( Iop_ReinterpF32asI32,
   12988                        unop( Iop_TruncF64asF32,
   12989                              triop( Iop_DivF64r32,
   12990                                     rm,
   12991                                     ieee_one,
   12992                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   12993          assign( res1,
   12994                  unop( Iop_ReinterpF32asI32,
   12995                        unop( Iop_TruncF64asF32,
   12996                              triop( Iop_DivF64r32,
   12997                                     rm,
   12998                                     ieee_one,
   12999                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   13000          assign( res2,
   13001                  unop( Iop_ReinterpF32asI32,
   13002                        unop( Iop_TruncF64asF32,
   13003                              triop( Iop_DivF64r32,
   13004                                     rm,
   13005                                     ieee_one,
   13006                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   13007          assign( res3,
   13008                  unop( Iop_ReinterpF32asI32,
   13009                        unop( Iop_TruncF64asF32,
   13010                              triop( Iop_DivF64r32,
   13011                                     rm,
   13012                                     ieee_one,
   13013                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   13014          putVSReg( XT,
   13015                    binop( Iop_64HLtoV128,
   13016                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13017                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13018          break;
   13019       }
   13020       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   13021       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   13022       {
   13023          UChar XA = ifieldRegXA( theInstr );
   13024          IRTemp a3, a2, a1, a0;
   13025          IRTemp b3, b2, b1, b0;
   13026          IRTemp res0 = newTemp( Ity_I32 );
   13027          IRTemp res1 = newTemp( Ity_I32 );
   13028          IRTemp res2 = newTemp( Ity_I32 );
   13029          IRTemp res3 = newTemp( Ity_I32 );
   13030          IRTemp a0_I64 = newTemp( Ity_I64 );
   13031          IRTemp a1_I64 = newTemp( Ity_I64 );
   13032          IRTemp a2_I64 = newTemp( Ity_I64 );
   13033          IRTemp a3_I64 = newTemp( Ity_I64 );
   13034          IRTemp b0_I64 = newTemp( Ity_I64 );
   13035          IRTemp b1_I64 = newTemp( Ity_I64 );
   13036          IRTemp b2_I64 = newTemp( Ity_I64 );
   13037          IRTemp b3_I64 = newTemp( Ity_I64 );
   13038 
   13039          Bool isMin = opc2 == 0x320 ? True : False;
   13040 
   13041          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   13042          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   13043          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
   13044          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13045          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13046          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   13047          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   13048          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   13049          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   13050          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   13051          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   13052          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   13053          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   13054          assign( res0,
   13055                  unop( Iop_ReinterpF32asI32,
   13056                        unop( Iop_TruncF64asF32,
   13057                              unop( Iop_ReinterpI64asF64,
   13058                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   13059          assign( res1,
   13060                  unop( Iop_ReinterpF32asI32,
   13061                        unop( Iop_TruncF64asF32,
   13062                              unop( Iop_ReinterpI64asF64,
   13063                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   13064          assign( res2,
   13065                  unop( Iop_ReinterpF32asI32,
   13066                        unop( Iop_TruncF64asF32,
   13067                              unop( Iop_ReinterpI64asF64,
   13068                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   13069          assign( res3,
   13070                  unop( Iop_ReinterpF32asI32,
   13071                        unop( Iop_TruncF64asF32,
   13072                              unop( Iop_ReinterpI64asF64,
   13073                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   13074          putVSReg( XT,
   13075                    binop( Iop_64HLtoV128,
   13076                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13077                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13078          break;
   13079       }
   13080       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   13081       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   13082       {
   13083          UChar XA = ifieldRegXA( theInstr );
   13084          IRTemp frA = newTemp(Ity_I64);
   13085          IRTemp frB = newTemp(Ity_I64);
   13086          IRTemp frA2 = newTemp(Ity_I64);
   13087          IRTemp frB2 = newTemp(Ity_I64);
   13088          Bool isMin = opc2 == 0x3A0 ? True : False;
   13089 
   13090          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   13091          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   13092          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   13093          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   13094          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
   13095          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   13096 
   13097          break;
   13098       }
   13099       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   13100       {
   13101          UChar XA = ifieldRegXA( theInstr );
   13102          IRTemp frA = newTemp(Ity_I64);
   13103          IRTemp frB = newTemp(Ity_I64);
   13104          IRTemp frA2 = newTemp(Ity_I64);
   13105          IRTemp frB2 = newTemp(Ity_I64);
   13106          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   13107          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   13108          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   13109          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   13110 
   13111          DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13112          putVSReg( XT,
   13113                    binop( Iop_64HLtoV128,
   13114                           binop( Iop_Or64,
   13115                                  binop( Iop_And64,
   13116                                         mkexpr( frA ),
   13117                                         mkU64( SIGN_BIT ) ),
   13118                                  binop( Iop_And64,
   13119                                         mkexpr( frB ),
   13120                                         mkU64( SIGN_MASK ) ) ),
   13121                           binop( Iop_Or64,
   13122                                  binop( Iop_And64,
   13123                                         mkexpr( frA2 ),
   13124                                         mkU64( SIGN_BIT ) ),
   13125                                  binop( Iop_And64,
   13126                                         mkexpr( frB2 ),
   13127                                         mkU64( SIGN_MASK ) ) ) ) );
   13128          break;
   13129       }
   13130       case 0x340: // xvcpsgnsp
   13131       {
   13132          UChar XA = ifieldRegXA( theInstr );
   13133          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   13134          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   13135          IRTemp resHi = newTemp(Ity_I64);
   13136          IRTemp resLo = newTemp(Ity_I64);
   13137 
   13138          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   13139          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   13140          DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
   13141          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   13142          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   13143 
   13144          assign( resHi,
   13145                  binop( Iop_32HLto64,
   13146                         binop( Iop_Or32,
   13147                                binop( Iop_And32,
   13148                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   13149                                       mkU32( SIGN_BIT32 ) ),
   13150                                binop( Iop_And32,
   13151                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   13152                                       mkU32( SIGN_MASK32) ) ),
   13153 
   13154                         binop( Iop_Or32,
   13155                                binop( Iop_And32,
   13156                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   13157                                       mkU32( SIGN_BIT32 ) ),
   13158                                binop( Iop_And32,
   13159                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   13160                                       mkU32( SIGN_MASK32 ) ) ) ) );
   13161          assign( resLo,
   13162                  binop( Iop_32HLto64,
   13163                         binop( Iop_Or32,
   13164                                binop( Iop_And32,
   13165                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   13166                                       mkU32( SIGN_BIT32 ) ),
   13167                                binop( Iop_And32,
   13168                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   13169                                       mkU32( SIGN_MASK32 ) ) ),
   13170 
   13171                         binop( Iop_Or32,
   13172                                binop( Iop_And32,
   13173                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   13174                                       mkU32( SIGN_BIT32 ) ),
   13175                                binop( Iop_And32,
   13176                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   13177                                       mkU32( SIGN_MASK32 ) ) ) ) );
   13178          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   13179          break;
   13180       }
   13181       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   13182       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   13183       {
   13184          IRTemp frB = newTemp(Ity_F64);
   13185          IRTemp frB2 = newTemp(Ity_F64);
   13186          IRTemp abs_resultHi = newTemp(Ity_F64);
   13187          IRTemp abs_resultLo = newTemp(Ity_F64);
   13188          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   13189          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13190          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   13191 
   13192          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
   13193          if (make_negative) {
   13194             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   13195             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   13196 
   13197          } else {
   13198             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   13199             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   13200          }
   13201          putVSReg( XT, binop( Iop_64HLtoV128,
   13202                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   13203                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   13204          break;
   13205       }
   13206       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   13207       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   13208       {
   13209          /*
   13210           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   13211           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   13212           * of this function is so easy using shifts, I choose to emulate this instruction that
   13213           * way versus a native instruction method of implementation.
   13214           */
   13215          Bool make_negative = (opc2 == 0x352) ? True : False;
   13216          IRTemp shiftVector = newTemp(Ity_V128);
   13217          IRTemp absVal_vector = newTemp(Ity_V128);
   13218          assign( shiftVector,
   13219                  binop( Iop_64HLtoV128,
   13220                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   13221                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   13222          assign( absVal_vector,
   13223                    binop( Iop_Shr32x4,
   13224                           binop( Iop_Shl32x4,
   13225                                  getVSReg( XB ),
   13226                                  mkexpr( shiftVector ) ),
   13227                           mkexpr( shiftVector ) ) );
   13228          if (make_negative) {
   13229             IRTemp signBit_vector = newTemp(Ity_V128);
   13230             assign( signBit_vector,
   13231                     binop( Iop_64HLtoV128,
   13232                            binop( Iop_32HLto64,
   13233                                   mkU32( 0x80000000 ),
   13234                                   mkU32( 0x80000000 ) ),
   13235                            binop( Iop_32HLto64,
   13236                                   mkU32( 0x80000000 ),
   13237                                   mkU32( 0x80000000 ) ) ) );
   13238             putVSReg( XT,
   13239                       binop( Iop_OrV128,
   13240                              mkexpr( absVal_vector ),
   13241                              mkexpr( signBit_vector ) ) );
   13242          } else {
   13243             putVSReg( XT, mkexpr( absVal_vector ) );
   13244          }
   13245          break;
   13246       }
   13247       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   13248       {
   13249          IRTemp frB = newTemp(Ity_F64);
   13250          IRTemp frB2 = newTemp(Ity_F64);
   13251          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13252          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   13253          DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
   13254          putVSReg( XT,
   13255                    binop( Iop_64HLtoV128,
   13256                           unop( Iop_ReinterpF64asI64,
   13257                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   13258                           unop( Iop_ReinterpF64asI64,
   13259                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   13260          break;
   13261       }
   13262       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   13263       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   13264       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   13265       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   13266       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   13267       {
   13268          IRTemp frBHi_I64 = newTemp(Ity_I64);
   13269          IRTemp frBLo_I64 = newTemp(Ity_I64);
   13270          IRExpr * frD_fp_roundHi = NULL;
   13271          IRExpr * frD_fp_roundLo = NULL;
   13272          UChar * insn_suffix = NULL;
   13273 
   13274          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   13275          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix);
   13276          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   13277          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix);
   13278 
   13279          DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   13280          putVSReg( XT,
   13281                    binop( Iop_64HLtoV128,
   13282                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   13283                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   13284          break;
   13285       }
   13286       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   13287       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   13288       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   13289       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   13290       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   13291       {
   13292          UChar * insn_suffix = NULL;
   13293          IROp op;
   13294          if (opc2 != 0x156) {
   13295             // Use pre-defined IRop's for vrfi{m|n|p|z}
   13296             switch (opc2) {
   13297                case 0x112:
   13298                   insn_suffix = "";
   13299                   op = Iop_RoundF32x4_RN;
   13300                   break;
   13301                case 0x172:
   13302                   insn_suffix = "m";
   13303                   op = Iop_RoundF32x4_RM;
   13304                   break;
   13305                case 0x152:
   13306                   insn_suffix = "p";
   13307                   op = Iop_RoundF32x4_RP;
   13308                   break;
   13309                case 0x132:
   13310                   insn_suffix = "z";
   13311                   op = Iop_RoundF32x4_RZ;
   13312                   break;
   13313 
   13314                default:
   13315                   vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" );
   13316                   return False;
   13317             }
   13318             DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   13319             putVSReg( XT, unop( op, getVSReg(XB) ) );
   13320          } else {
   13321             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   13322             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   13323             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   13324             IRTemp b3_I64 = newTemp(Ity_I64);
   13325             IRTemp b2_I64 = newTemp(Ity_I64);
   13326             IRTemp b1_I64 = newTemp(Ity_I64);
   13327             IRTemp b0_I64 = newTemp(Ity_I64);
   13328 
   13329             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   13330             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   13331             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   13332             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   13333             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   13334             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   13335             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   13336             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   13337                                   _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix));
   13338             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   13339                                   _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix));
   13340             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   13341                                   _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix));
   13342             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   13343                                   _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix));
   13344             DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
   13345             putVSReg( XT,
   13346                       binop( Iop_64HLtoV128,
   13347                              binop( Iop_32HLto64,
   13348                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   13349                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   13350                              binop( Iop_32HLto64,
   13351                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   13352                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   13353          }
   13354          break;
   13355       }
   13356 
   13357       default:
   13358          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   13359          return False;
   13360    }
   13361    return True;
   13362 }
   13363 
   13364 
   13365 /*
   13366  * VSX Scalar Floating Point Arithmetic Instructions
   13367  */
   13368 static Bool
   13369 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   13370 {
   13371    /* XX3-Form */
   13372    UChar opc1 = ifieldOPC( theInstr );
   13373    UChar XT = ifieldRegXT( theInstr );
   13374    UChar XA = ifieldRegXA( theInstr );
   13375    UChar XB = ifieldRegXB( theInstr );
   13376    IRExpr* rm = get_IR_roundingmode();
   13377    IRTemp frA = newTemp(Ity_F64);
   13378    IRTemp frB = newTemp(Ity_F64);
   13379 
   13380    if (opc1 != 0x3C) {
   13381       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   13382       return False;
   13383    }
   13384 
   13385    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   13386    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13387 
   13388    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   13389     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   13390     * element to zero where it makes sense to do so.
   13391     */
   13392    switch (opc2) {
   13393       case 0x080: // xsadddp (VSX scalar add double-precision)
   13394          DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13395          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13396                                                     triop( Iop_AddF64, rm,
   13397                                                            mkexpr( frA ),
   13398                                                            mkexpr( frB ) ) ),
   13399                               mkU64( 0 ) ) );
   13400          break;
   13401       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   13402          DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13403          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13404                                                     triop( Iop_DivF64, rm,
   13405                                                            mkexpr( frA ),
   13406                                                            mkexpr( frB ) ) ),
   13407                               mkU64( 0 ) ) );
   13408          break;
   13409       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   13410       {
   13411          IRTemp frT = newTemp(Ity_F64);
   13412          Bool mdp = opc2 == 0x0A4;
   13413          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   13414          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   13415                                                         getVSReg( XT ) ) ) );
   13416          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13417                                                     qop( Iop_MAddF64, rm,
   13418                                                          mkexpr( frA ),
   13419                                                          mkexpr( mdp ? frT : frB ),
   13420                                                          mkexpr( mdp ? frB : frT ) ) ),
   13421                               mkU64( 0 ) ) );
   13422          break;
   13423       }
   13424       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   13425       {
   13426          IRTemp frT = newTemp(Ity_F64);
   13427          Bool mdp = opc2 == 0x0E4;
   13428          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   13429          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   13430                                                         getVSReg( XT ) ) ) );
   13431          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13432                                                     qop( Iop_MSubF64, rm,
   13433                                                          mkexpr( frA ),
   13434                                                          mkexpr( mdp ? frT : frB ),
   13435                                                          mkexpr( mdp ? frB : frT ) ) ),
   13436                               mkU64( 0 ) ) );
   13437          break;
   13438       }
   13439       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   13440       {
   13441          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   13442           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   13443           * way it blindly negates the signbit, even if the floating point result is a NaN.
   13444           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   13445           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
   13446           * bit for NaN result.
   13447           */
   13448          Bool mdp = opc2 == 0x2A4;
   13449          IRTemp frT = newTemp(Ity_F64);
   13450          IRTemp maddResult = newTemp(Ity_I64);
   13451 
   13452          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   13453          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   13454                                                         getVSReg( XT ) ) ) );
   13455          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   13456                                                               mkexpr( frA ),
   13457                                                               mkexpr( mdp ? frT : frB ),
   13458                                                               mkexpr( mdp ? frB : frT ) ) ) );
   13459 
   13460          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   13461                               mkU64( 0 ) ) );
   13462          break;
   13463       }
   13464       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   13465       {
   13466          IRTemp frT = newTemp(Ity_F64);
   13467          Bool mdp = opc2 == 0x2E4;
   13468          IRTemp msubResult = newTemp(Ity_I64);
   13469 
   13470          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   13471          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   13472                                                         getVSReg( XT ) ) ) );
   13473          assign(msubResult, unop( Iop_ReinterpF64asI64,
   13474                                       qop( Iop_MSubF64,
   13475                                            rm,
   13476                                            mkexpr( frA ),
   13477                                            mkexpr( mdp ? frT : frB ),
   13478                                            mkexpr( mdp ? frB : frT ) ) ));
   13479 
   13480          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   13481 
   13482          break;
   13483       }
   13484 
   13485       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   13486          DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13487          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13488                                                     triop( Iop_MulF64, rm,
   13489                                                            mkexpr( frA ),
   13490                                                            mkexpr( frB ) ) ),
   13491                               mkU64( 0 ) ) );
   13492          break;
   13493       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   13494          DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13495          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13496                                                     triop( Iop_SubF64, rm,
   13497                                                            mkexpr( frA ),
   13498                                                            mkexpr( frB ) ) ),
   13499                               mkU64( 0 ) ) );
   13500          break;
   13501 
   13502       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   13503          DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13504          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   13505                                                      binop( Iop_SqrtF64, rm,
   13506                                                             mkexpr( frB ) ) ),
   13507                                mkU64( 0 ) ) );
   13508          break;
   13509 
   13510       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   13511       {
   13512          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13513          IRTemp frA_I64 = newTemp(Ity_I64);
   13514          IRTemp frB_I64 = newTemp(Ity_I64);
   13515          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
   13516          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   13517          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   13518          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   13519          break;
   13520       }
   13521       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   13522       {
   13523          IRTemp frB_I64 = newTemp(Ity_I64);
   13524          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13525          IRTemp flags = newTemp(Ity_I32);
   13526          IRTemp  fe_flag, fg_flag;
   13527          fe_flag = fg_flag = IRTemp_INVALID;
   13528          DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13529          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   13530          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   13531          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13532           * where fl_flag == 1 on ppc64.
   13533           */
   13534          assign( flags,
   13535                  binop( Iop_Or32,
   13536                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13537                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   13538                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   13539          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   13540          break;
   13541       }
   13542 
   13543       default:
   13544          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   13545          return False;
   13546    }
   13547 
   13548    return True;
   13549 }
   13550 
   13551 
   13552 /*
   13553  * VSX Floating Point Compare Instructions
   13554  */
   13555 static Bool
   13556 dis_vx_cmp( UInt theInstr, UInt opc2 )
   13557 {
   13558    /* XX3-Form and XX2-Form */
   13559    UChar opc1 = ifieldOPC( theInstr );
   13560    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13561    IRTemp ccPPC32;
   13562    UChar XA       = ifieldRegXA ( theInstr );
   13563    UChar XB       = ifieldRegXB ( theInstr );
   13564    IRTemp frA     = newTemp(Ity_F64);
   13565    IRTemp frB     = newTemp(Ity_F64);
   13566 
   13567    if (opc1 != 0x3C) {
   13568       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   13569       return False;
   13570    }
   13571 
   13572    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   13573    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13574    switch (opc2) {
   13575       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   13576          /* Note: Differences between xscmpudp and xscmpodp are only in
   13577           * exception flag settings, which aren't supported anyway. */
   13578          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   13579                                            crfD, (UInt)XA, (UInt)XB);
   13580          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   13581          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   13582          break;
   13583 
   13584       default:
   13585          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   13586          return False;
   13587    }
   13588    return True;
   13589 }
   13590 
   13591 static void
   13592 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   13593                  ppc_cmp_t cmp_type )
   13594 {
   13595    IRTemp frA_hi     = newTemp(Ity_F64);
   13596    IRTemp frB_hi     = newTemp(Ity_F64);
   13597    IRTemp frA_lo     = newTemp(Ity_F64);
   13598    IRTemp frB_lo     = newTemp(Ity_F64);
   13599    IRTemp ccPPC32    = newTemp(Ity_I32);
   13600    IRTemp ccIR_hi;
   13601    IRTemp ccIR_lo;
   13602 
   13603    IRTemp hiResult = newTemp(Ity_I64);
   13604    IRTemp loResult = newTemp(Ity_I64);
   13605    IRTemp hiEQlo = newTemp(Ity_I1);
   13606    IRTemp all_elem_true = newTemp(Ity_I32);
   13607    IRTemp all_elem_false = newTemp(Ity_I32);
   13608 
   13609    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   13610    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   13611    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   13612    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   13613 
   13614    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   13615                                        mkexpr( frA_hi ),
   13616                                        mkexpr( frB_hi ) ) );
   13617    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   13618                                        mkexpr( frA_lo ),
   13619                                        mkexpr( frB_lo ) ) );
   13620 
   13621    if (cmp_type != PPC_CMP_GE) {
   13622       assign( hiResult,
   13623               unop( Iop_1Sto64,
   13624                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   13625       assign( loResult,
   13626               unop( Iop_1Sto64,
   13627                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   13628    } else {
   13629       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   13630       // the other element compare may return "2" (for "equal to").
   13631       IRTemp lo_GE = newTemp(Ity_I1);
   13632       IRTemp hi_GE = newTemp(Ity_I1);
   13633 
   13634       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   13635                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   13636       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   13637 
   13638       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   13639                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   13640       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   13641    }
   13642 
   13643    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   13644    assign( hiEQlo,
   13645            binop( Iop_CmpEQ32,
   13646                   unop( Iop_64to32, mkexpr( hiResult ) ),
   13647                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   13648    putVSReg( XT,
   13649              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   13650 
   13651    assign( all_elem_true,
   13652            unop( Iop_1Uto32,
   13653                  mkAND1( mkexpr( hiEQlo ),
   13654                          binop( Iop_CmpEQ32,
   13655                                 mkU32( 0xffffffff ),
   13656                                 unop( Iop_64to32,
   13657                                 mkexpr( hiResult ) ) ) ) ) );
   13658 
   13659    assign( all_elem_false,
   13660            unop( Iop_1Uto32,
   13661                  mkAND1( mkexpr( hiEQlo ),
   13662                          binop( Iop_CmpEQ32,
   13663                                 mkU32( 0 ),
   13664                                 unop( Iop_64to32,
   13665                                 mkexpr( hiResult ) ) ) ) ) );
   13666    assign( ccPPC32,
   13667            binop( Iop_Or32,
   13668                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   13669                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   13670 
   13671    if (flag_rC) {
   13672       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   13673    }
   13674 }
   13675 
   13676 /*
   13677  * VSX Vector Compare Instructions
   13678  */
   13679 static Bool
   13680 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   13681 {
   13682    /* XX3-Form */
   13683    UChar opc1 = ifieldOPC( theInstr );
   13684    UChar XT = ifieldRegXT ( theInstr );
   13685    UChar XA = ifieldRegXA ( theInstr );
   13686    UChar XB = ifieldRegXB ( theInstr );
   13687    UChar flag_rC  = ifieldBIT10(theInstr);
   13688    IRTemp vA = newTemp( Ity_V128 );
   13689    IRTemp vB = newTemp( Ity_V128 );
   13690 
   13691    if (opc1 != 0x3C) {
   13692       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   13693       return False;
   13694    }
   13695 
   13696    assign( vA, getVSReg( XA ) );
   13697    assign( vB, getVSReg( XB ) );
   13698 
   13699    switch (opc2) {
   13700       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   13701       {
   13702          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13703              (UInt)XT, (UInt)XA, (UInt)XB);
   13704          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   13705          break;
   13706       }
   13707 
   13708       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   13709       {
   13710          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13711              (UInt)XT, (UInt)XA, (UInt)XB);
   13712          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   13713          break;
   13714       }
   13715 
   13716       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   13717       {
   13718          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13719              (UInt)XT, (UInt)XA, (UInt)XB);
   13720          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   13721          break;
   13722       }
   13723 
   13724       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   13725       {
   13726          IRTemp vD = newTemp(Ity_V128);
   13727 
   13728          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13729              (UInt)XT, (UInt)XA, (UInt)XB);
   13730          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   13731          putVSReg( XT, mkexpr(vD) );
   13732          if (flag_rC) {
   13733             set_AV_CR6( mkexpr(vD), True );
   13734          }
   13735          break;
   13736       }
   13737 
   13738       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   13739       {
   13740          IRTemp vD = newTemp(Ity_V128);
   13741 
   13742          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13743              (UInt)XT, (UInt)XA, (UInt)XB);
   13744          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   13745          putVSReg( XT, mkexpr(vD) );
   13746          if (flag_rC) {
   13747             set_AV_CR6( mkexpr(vD), True );
   13748          }
   13749          break;
   13750       }
   13751 
   13752       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   13753       {
   13754          IRTemp vD = newTemp(Ity_V128);
   13755 
   13756          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   13757              (UInt)XT, (UInt)XA, (UInt)XB);
   13758          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   13759          putVSReg( XT, mkexpr(vD) );
   13760          if (flag_rC) {
   13761             set_AV_CR6( mkexpr(vD), True );
   13762          }
   13763          break;
   13764       }
   13765 
   13766       default:
   13767          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   13768          return False;
   13769    }
   13770    return True;
   13771 }
   13772 /*
   13773  * Miscellaneous VSX Scalar Instructions
   13774  */
   13775 static Bool
   13776 dis_vxs_misc( UInt theInstr, UInt opc2 )
   13777 {
   13778    /* XX3-Form and XX2-Form */
   13779    UChar opc1 = ifieldOPC( theInstr );
   13780    UChar XT = ifieldRegXT ( theInstr );
   13781    UChar XA = ifieldRegXA ( theInstr );
   13782    UChar XB = ifieldRegXB ( theInstr );
   13783    IRTemp vA = newTemp( Ity_V128 );
   13784    IRTemp vB = newTemp( Ity_V128 );
   13785 
   13786    if (opc1 != 0x3C) {
   13787       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   13788       return False;
   13789    }
   13790 
   13791    assign( vA, getVSReg( XA ) );
   13792    assign( vB, getVSReg( XB ) );
   13793 
   13794    /* For all the VSX move instructions, the contents of doubleword element 1
   13795     * of VSX[XT] are undefined after the operation; therefore, we can simply
   13796     * move the entire array element where it makes sense to do so.
   13797     */
   13798 
   13799    switch (opc2) {
   13800       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   13801       {
   13802          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   13803          IRTemp absVal = newTemp(Ity_V128);
   13804          assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
   13805          DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13806          putVSReg(XT, mkexpr(absVal));
   13807          break;
   13808       }
   13809       case 0x2C0: // xscpsgndp
   13810       {
   13811          /* Scalar copy sign double-precision */
   13812          IRTemp vecA_signbit = newTemp(Ity_V128);
   13813          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   13814          IRTemp vec_result = newTemp(Ity_V128);
   13815          DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13816          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   13817                                                              mkexpr( vB ),
   13818                                                              mkU8( 1 ) ),
   13819                                          mkU8( 1 ) ) );
   13820          assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
   13821                                                           mkexpr( vA ),
   13822                                                           mkU8( 127 ) ),
   13823                                       mkU8( 127 ) ) );
   13824          assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
   13825          putVSReg(XT, mkexpr(vec_result));
   13826          break;
   13827       }
   13828       case 0x2D2: // xsnabsdp
   13829       {
   13830          /* Scalar negative absolute value double-precision */
   13831          IRTemp vec_neg_signbit = newTemp(Ity_V128);
   13832          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13833          assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
   13834                                                             mkV128( 0xffff ),
   13835                                                             mkU8( 1 ) ) ) );
   13836          putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
   13837          break;
   13838       }
   13839       case 0x2F2: // xsnegdp
   13840       {
   13841          /* Scalar negate double-precision */
   13842          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   13843          IRTemp vecB_signbit_comp = newTemp(Ity_V128);
   13844          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   13845          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   13846                                                              mkexpr( vB ),
   13847                                                              mkU8( 1 ) ),
   13848                                          mkU8( 1 ) ) );
   13849          assign( vecB_signbit_comp, binop( Iop_ShlV128,
   13850                                            unop( Iop_NotV128,
   13851                                                  binop( Iop_ShrV128,
   13852                                                         mkexpr( vB ),
   13853                                                         mkU8( 127 ) ) ),
   13854                                            mkU8( 127 ) ) );
   13855          putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
   13856                               mkexpr( vecB_signbit_comp ) ) );
   13857          break;
   13858       }
   13859       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   13860       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   13861       {
   13862          IRTemp frA     = newTemp(Ity_I64);
   13863          IRTemp frB     = newTemp(Ity_I64);
   13864          Bool isMin = opc2 == 0x2A0 ? True : False;
   13865          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
   13866 
   13867          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   13868          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   13869          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   13870 
   13871          break;
   13872       }
   13873       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   13874       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   13875       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   13876       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   13877       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   13878       {
   13879          IRTemp frB_I64 = newTemp(Ity_I64);
   13880          IRExpr * frD_fp_round = NULL;
   13881          UChar * insn_suffix = NULL;
   13882 
   13883          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   13884          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix);
   13885 
   13886          DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   13887          putVSReg( XT,
   13888                    binop( Iop_64HLtoV128,
   13889                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   13890                           mkU64( 0 ) ) );
   13891          break;
   13892       }
   13893       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   13894       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   13895 
   13896       {
   13897          IRTemp frB = newTemp(Ity_F64);
   13898          IRTemp sqrt = newTemp(Ity_F64);
   13899          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   13900          IRExpr* rm  = get_IR_roundingmode();
   13901          Bool redp = opc2 == 0x0B4;
   13902          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
   13903          assign( frB,
   13904                  unop( Iop_ReinterpI64asF64,
   13905                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   13906 
   13907          if (!redp)
   13908             assign( sqrt,
   13909                     binop( Iop_SqrtF64,
   13910                            rm,
   13911                            mkexpr(frB) ) );
   13912          putVSReg( XT,
   13913                       binop( Iop_64HLtoV128,
   13914                              unop( Iop_ReinterpF64asI64,
   13915                                    triop( Iop_DivF64,
   13916                                           rm,
   13917                                           ieee_one,
   13918                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   13919                              mkU64( 0 ) ) );
   13920          break;
   13921       }
   13922 
   13923       default:
   13924          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   13925          return False;
   13926    }
   13927    return True;
   13928 }
   13929 
   13930 /*
   13931  * VSX Logical Instructions
   13932  */
   13933 static Bool
   13934 dis_vx_logic ( UInt theInstr, UInt opc2 )
   13935 {
   13936    /* XX3-Form */
   13937    UChar opc1 = ifieldOPC( theInstr );
   13938    UChar XT = ifieldRegXT ( theInstr );
   13939    UChar XA = ifieldRegXA ( theInstr );
   13940    UChar XB = ifieldRegXB ( theInstr );
   13941    IRTemp vA = newTemp( Ity_V128 );
   13942    IRTemp vB = newTemp( Ity_V128 );
   13943 
   13944    if (opc1 != 0x3C) {
   13945       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   13946       return False;
   13947    }
   13948 
   13949    assign( vA, getVSReg( XA ) );
   13950    assign( vB, getVSReg( XB ) );
   13951 
   13952    switch (opc2) {
   13953       case 0x268: // xxlxor
   13954          DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13955          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   13956          break;
   13957       case 0x248: // xxlor
   13958          DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13959          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   13960          break;
   13961       case 0x288: // xxlnor
   13962          DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13963          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   13964                                                  mkexpr( vB ) ) ) );
   13965          break;
   13966       case 0x208: // xxland
   13967          DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13968          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   13969          break;
   13970       case 0x228: //xxlandc
   13971          DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   13972          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   13973                                                                mkexpr( vB ) ) ) );
   13974          break;
   13975       default:
   13976          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   13977          return False;
   13978    }
   13979    return True;
   13980 }
   13981 
   13982 /*
   13983  * VSX Load Instructions
   13984  * NOTE: VSX supports word-aligned storage access.
   13985  */
   13986 static Bool
   13987 dis_vx_load ( UInt theInstr )
   13988 {
   13989    /* XX1-Form */
   13990    UChar opc1 = ifieldOPC( theInstr );
   13991    UChar XT = ifieldRegXT ( theInstr );
   13992    UChar rA_addr = ifieldRegA( theInstr );
   13993    UChar rB_addr = ifieldRegB( theInstr );
   13994    UInt opc2 = ifieldOPClo10( theInstr );
   13995 
   13996    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   13997    IRTemp EA = newTemp( ty );
   13998 
   13999    if (opc1 != 0x1F) {
   14000       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   14001       return False;
   14002    }
   14003 
   14004    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   14005 
   14006    switch (opc2) {
   14007    case 0x24C: // lxsdx
   14008    {
   14009       IRExpr * exp;
   14010       DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   14011       exp = loadBE( Ity_I64, mkexpr( EA ) );
   14012       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   14013       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   14014       // are undefined after this operation, we can just do a splat op.
   14015       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   14016       break;
   14017    }
   14018    case 0x34C: // lxvd2x
   14019    {
   14020       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   14021       IRExpr * high, *low;
   14022       ULong ea_off = 8;
   14023       IRExpr* high_addr;
   14024       DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   14025       high = loadBE( Ity_I64, mkexpr( EA ) );
   14026       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   14027             : mkU32( ea_off ) );
   14028       low = loadBE( Ity_I64, high_addr );
   14029       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   14030       break;
   14031    }
   14032    case 0x14C: // lxvdsx
   14033    {
   14034       IRTemp data = newTemp(Ity_I64);
   14035       DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   14036       assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
   14037       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   14038       break;
   14039    }
   14040    case 0x30C:
   14041    {
   14042       IRExpr * t3, *t2, *t1, *t0;
   14043       UInt ea_off = 0;
   14044       IRExpr* irx_addr;
   14045 
   14046       DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   14047       t3 = loadBE( Ity_I32,  mkexpr( EA ) );
   14048       ea_off += 4;
   14049       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14050                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14051       t2 = loadBE( Ity_I32, irx_addr );
   14052       ea_off += 4;
   14053       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14054                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14055       t1 = loadBE( Ity_I32, irx_addr );
   14056       ea_off += 4;
   14057       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14058                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14059       t0 = loadBE( Ity_I32, irx_addr );
   14060       putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
   14061                            binop( Iop_32HLto64, t1, t0 ) ) );
   14062       break;
   14063    }
   14064    default:
   14065       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   14066       return False;
   14067    }
   14068    return True;
   14069 }
   14070 
   14071 /*
   14072  * VSX Store Instructions
   14073  * NOTE: VSX supports word-aligned storage access.
   14074  */
   14075 static Bool
   14076 dis_vx_store ( UInt theInstr )
   14077 {
   14078    /* XX1-Form */
   14079    UChar opc1 = ifieldOPC( theInstr );
   14080    UChar XS = ifieldRegXS( theInstr );
   14081    UChar rA_addr = ifieldRegA( theInstr );
   14082    UChar rB_addr = ifieldRegB( theInstr );
   14083    IRTemp vS = newTemp( Ity_V128 );
   14084    UInt opc2 = ifieldOPClo10( theInstr );
   14085 
   14086    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   14087    IRTemp EA = newTemp( ty );
   14088 
   14089    if (opc1 != 0x1F) {
   14090       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   14091       return False;
   14092    }
   14093 
   14094    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   14095    assign( vS, getVSReg( XS ) );
   14096 
   14097    switch (opc2) {
   14098    case 0x2CC:
   14099    {
   14100       IRExpr * high64;
   14101       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   14102       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   14103       storeBE( mkexpr( EA ), high64 );
   14104       break;
   14105    }
   14106    case 0x3CC:
   14107    {
   14108       IRExpr * high64, *low64;
   14109       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   14110       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   14111       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   14112       storeBE( mkexpr( EA ), high64 );
   14113       storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
   14114             : mkU32( 8 ) ), low64 );
   14115       break;
   14116    }
   14117    case 0x38C:
   14118    {
   14119       UInt ea_off = 0;
   14120       IRExpr* irx_addr;
   14121       IRTemp hi64 = newTemp( Ity_I64 );
   14122       IRTemp lo64 = newTemp( Ity_I64 );
   14123 
   14124       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   14125 
   14126       // This instruction supports word-aligned stores, so EA may not be
   14127       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   14128       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   14129       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   14130 
   14131       storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   14132       ea_off += 4;
   14133       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14134                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14135       storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   14136       ea_off += 4;
   14137       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14138                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14139       storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   14140       ea_off += 4;
   14141       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   14142                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   14143       storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   14144 
   14145       break;
   14146    }
   14147    default:
   14148       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   14149       return False;
   14150    }
   14151    return True;
   14152 }
   14153 
   14154 /*
   14155  * VSX permute and other miscealleous instructions
   14156  */
   14157 static Bool
   14158 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   14159 {
   14160    /* XX3-Form */
   14161    UChar opc1 = ifieldOPC( theInstr );
   14162    UChar XT = ifieldRegXT ( theInstr );
   14163    UChar XA = ifieldRegXA ( theInstr );
   14164    UChar XB = ifieldRegXB ( theInstr );
   14165    IRTemp vT = newTemp( Ity_V128 );
   14166    IRTemp vA = newTemp( Ity_V128 );
   14167    IRTemp vB = newTemp( Ity_V128 );
   14168 
   14169    if (opc1 != 0x3C) {
   14170       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   14171       return False;
   14172    }
   14173 
   14174    assign( vA, getVSReg( XA ) );
   14175    assign( vB, getVSReg( XB ) );
   14176 
   14177    switch (opc2) {
   14178       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   14179       {
   14180          UChar SHW = ifieldSHW ( theInstr );
   14181          IRTemp result = newTemp(Ity_V128);
   14182          if ( SHW != 0 ) {
   14183              IRTemp hi = newTemp(Ity_V128);
   14184              IRTemp lo = newTemp(Ity_V128);
   14185              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   14186              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   14187              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   14188          } else
   14189              assign ( result, mkexpr(vA) );
   14190          DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
   14191          putVSReg( XT, mkexpr(result) );
   14192          break;
   14193       }
   14194       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   14195       {
   14196          UChar DM = ifieldDM ( theInstr );
   14197          IRTemp hi = newTemp(Ity_I64);
   14198          IRTemp lo = newTemp(Ity_I64);
   14199 
   14200          if (DM & 0x2)
   14201            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   14202          else
   14203            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   14204 
   14205          if (DM & 0x1)
   14206            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   14207          else
   14208            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   14209 
   14210          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   14211 
   14212          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
   14213          putVSReg( XT, mkexpr( vT ) );
   14214          break;
   14215       }
   14216       case 0x48: // xxmrghw (VSX Merge High Word)
   14217       case 0xc8: // xxmrglw (VSX Merge Low Word)
   14218       {
   14219          char type = (opc2 == 0x48) ? 'h' : 'l';
   14220          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   14221          IRTemp a64 = newTemp(Ity_I64);
   14222          IRTemp ahi32 = newTemp(Ity_I32);
   14223          IRTemp alo32 = newTemp(Ity_I32);
   14224          IRTemp b64 = newTemp(Ity_I64);
   14225          IRTemp bhi32 = newTemp(Ity_I32);
   14226          IRTemp blo32 = newTemp(Ity_I32);
   14227 
   14228          assign( a64, unop(word_op, mkexpr(vA)) );
   14229          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   14230          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   14231 
   14232          assign( b64, unop(word_op, mkexpr(vB)) );
   14233          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   14234          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   14235 
   14236          assign( vT, binop(Iop_64HLtoV128,
   14237                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   14238                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   14239 
   14240          DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
   14241          putVSReg( XT, mkexpr( vT ) );
   14242          break;
   14243       }
   14244       case 0x018: // xxsel (VSX Select)
   14245       {
   14246          UChar XC = ifieldRegXC(theInstr);
   14247          IRTemp vC = newTemp( Ity_V128 );
   14248          assign( vC, getVSReg( XC ) );
   14249          DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
   14250          /* vD = (vA & ~vC) | (vB & vC) */
   14251          putVSReg( XT, binop(Iop_OrV128,
   14252             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   14253             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   14254          break;
   14255       }
   14256       case 0x148: // xxspltw (VSX Splat Word)
   14257       {
   14258          UChar UIM   = ifieldRegA(theInstr) & 3;
   14259          UChar sh_uim = (3 - (UIM)) * 32;
   14260          DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
   14261          putVSReg( XT,
   14262                    unop( Iop_Dup32x4,
   14263                          unop( Iop_V128to32,
   14264                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   14265          break;
   14266       }
   14267 
   14268       default:
   14269          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   14270          return False;
   14271    }
   14272    return True;
   14273 }
   14274 
   14275 /*
   14276   AltiVec Load Instructions
   14277 */
   14278 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
   14279 {
   14280    /* X-Form */
   14281    UChar opc1     = ifieldOPC(theInstr);
   14282    UChar vD_addr  = ifieldRegDS(theInstr);
   14283    UChar rA_addr  = ifieldRegA(theInstr);
   14284    UChar rB_addr  = ifieldRegB(theInstr);
   14285    UInt  opc2     = ifieldOPClo10(theInstr);
   14286    UChar b0       = ifieldBIT0(theInstr);
   14287 
   14288    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   14289    IRTemp EA         = newTemp(ty);
   14290    IRTemp EA_align16 = newTemp(ty);
   14291 
   14292    if (opc1 != 0x1F || b0 != 0) {
   14293       vex_printf("dis_av_load(ppc)(instr)\n");
   14294       return False;
   14295    }
   14296 
   14297    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   14298    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   14299 
   14300    switch (opc2) {
   14301 
   14302    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   14303       IRDirty* d;
   14304       UInt vD_off = vectorGuestRegOffset(vD_addr);
   14305       IRExpr** args = mkIRExprVec_3(
   14306                          mkU32(vD_off),
   14307                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   14308                                           mkU32(0xF)),
   14309                          mkU32(0)/*left*/ );
   14310       if (!mode64) {
   14311          d = unsafeIRDirty_0_N (
   14312                         0/*regparms*/,
   14313                         "ppc32g_dirtyhelper_LVS",
   14314                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   14315                         args );
   14316       } else {
   14317          d = unsafeIRDirty_0_N (
   14318                         0/*regparms*/,
   14319                         "ppc64g_dirtyhelper_LVS",
   14320                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   14321                         args );
   14322       }
   14323       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14324       /* declare guest state effects */
   14325       d->needsBBP = True;
   14326       d->nFxState = 1;
   14327       vex_bzero(&d->fxState, sizeof(d->fxState));
   14328       d->fxState[0].fx     = Ifx_Write;
   14329       d->fxState[0].offset = vD_off;
   14330       d->fxState[0].size   = sizeof(U128);
   14331 
   14332       /* execute the dirty call, side-effecting guest state */
   14333       stmt( IRStmt_Dirty(d) );
   14334       break;
   14335    }
   14336    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   14337       IRDirty* d;
   14338       UInt vD_off = vectorGuestRegOffset(vD_addr);
   14339       IRExpr** args = mkIRExprVec_3(
   14340                          mkU32(vD_off),
   14341                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   14342                                           mkU32(0xF)),
   14343                          mkU32(1)/*right*/ );
   14344       if (!mode64) {
   14345          d = unsafeIRDirty_0_N (
   14346                         0/*regparms*/,
   14347                         "ppc32g_dirtyhelper_LVS",
   14348                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   14349                         args );
   14350       } else {
   14351          d = unsafeIRDirty_0_N (
   14352                         0/*regparms*/,
   14353                         "ppc64g_dirtyhelper_LVS",
   14354                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   14355                         args );
   14356       }
   14357       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14358       /* declare guest state effects */
   14359       d->needsBBP = True;
   14360       d->nFxState = 1;
   14361       vex_bzero(&d->fxState, sizeof(d->fxState));
   14362       d->fxState[0].fx     = Ifx_Write;
   14363       d->fxState[0].offset = vD_off;
   14364       d->fxState[0].size   = sizeof(U128);
   14365 
   14366       /* execute the dirty call, side-effecting guest state */
   14367       stmt( IRStmt_Dirty(d) );
   14368       break;
   14369    }
   14370    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   14371       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14372       /* loads addressed byte into vector[EA[0:3]
   14373          since all other destination bytes are undefined,
   14374          can simply load entire vector from 16-aligned EA */
   14375       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   14376       break;
   14377 
   14378    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   14379       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14380       /* see note for lvebx */
   14381       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   14382       break;
   14383 
   14384    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   14385       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14386       /* see note for lvebx */
   14387       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   14388       break;
   14389 
   14390    case 0x067: // lvx (Load Vector Indexed, AV p127)
   14391       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14392       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   14393       break;
   14394 
   14395    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   14396       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   14397       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   14398       break;
   14399 
   14400    default:
   14401       vex_printf("dis_av_load(ppc)(opc2)\n");
   14402       return False;
   14403    }
   14404    return True;
   14405 }
   14406 
   14407 /*
   14408   AltiVec Store Instructions
   14409 */
   14410 static Bool dis_av_store ( UInt theInstr )
   14411 {
   14412    /* X-Form */
   14413    UChar opc1     = ifieldOPC(theInstr);
   14414    UChar vS_addr  = ifieldRegDS(theInstr);
   14415    UChar rA_addr  = ifieldRegA(theInstr);
   14416    UChar rB_addr  = ifieldRegB(theInstr);
   14417    UInt  opc2     = ifieldOPClo10(theInstr);
   14418    UChar b0       = ifieldBIT0(theInstr);
   14419 
   14420    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   14421    IRTemp EA           = newTemp(ty);
   14422    IRTemp addr_aligned = newTemp(ty);
   14423    IRTemp vS           = newTemp(Ity_V128);
   14424    IRTemp eb           = newTemp(Ity_I8);
   14425    IRTemp idx          = newTemp(Ity_I8);
   14426 
   14427    if (opc1 != 0x1F || b0 != 0) {
   14428       vex_printf("dis_av_store(ppc)(instr)\n");
   14429       return False;
   14430    }
   14431 
   14432    assign( vS, getVReg(vS_addr));
   14433    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   14434 
   14435    switch (opc2) {
   14436    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   14437       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   14438       assign( eb, binop(Iop_And8, mkU8(0xF),
   14439                         unop(Iop_32to8,
   14440                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   14441       assign( idx, binop(Iop_Shl8,
   14442                          binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   14443                          mkU8(3)) );
   14444       storeBE( mkexpr(EA),
   14445                unop(Iop_32to8, unop(Iop_V128to32,
   14446                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   14447       break;
   14448    }
   14449    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   14450       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   14451       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   14452       assign( eb, binop(Iop_And8, mkU8(0xF),
   14453                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   14454       assign( idx, binop(Iop_Shl8,
   14455                          binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   14456                          mkU8(3)) );
   14457       storeBE( mkexpr(addr_aligned),
   14458                unop(Iop_32to16, unop(Iop_V128to32,
   14459                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   14460       break;
   14461    }
   14462    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   14463       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   14464       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   14465       assign( eb, binop(Iop_And8, mkU8(0xF),
   14466                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   14467       assign( idx, binop(Iop_Shl8,
   14468                          binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   14469                          mkU8(3)) );
   14470       storeBE( mkexpr(addr_aligned),
   14471                unop(Iop_V128to32,
   14472                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   14473       break;
   14474    }
   14475 
   14476    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   14477       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   14478       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   14479       break;
   14480 
   14481    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   14482       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   14483       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   14484       break;
   14485 
   14486    default:
   14487       vex_printf("dis_av_store(ppc)(opc2)\n");
   14488       return False;
   14489    }
   14490    return True;
   14491 }
   14492 
   14493 /*
   14494   AltiVec Arithmetic Instructions
   14495 */
   14496 static Bool dis_av_arith ( UInt theInstr )
   14497 {
   14498    /* VX-Form */
   14499    UChar opc1     = ifieldOPC(theInstr);
   14500    UChar vD_addr  = ifieldRegDS(theInstr);
   14501    UChar vA_addr  = ifieldRegA(theInstr);
   14502    UChar vB_addr  = ifieldRegB(theInstr);
   14503    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   14504 
   14505    IRTemp vA = newTemp(Ity_V128);
   14506    IRTemp vB = newTemp(Ity_V128);
   14507    IRTemp z3 = newTemp(Ity_I64);
   14508    IRTemp z2 = newTemp(Ity_I64);
   14509    IRTemp z1 = newTemp(Ity_I64);
   14510    IRTemp z0 = newTemp(Ity_I64);
   14511    IRTemp aEvn, aOdd;
   14512    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   14513    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   14514    IRTemp b3, b2, b1, b0;
   14515 
   14516    aEvn = aOdd = IRTemp_INVALID;
   14517    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   14518    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   14519    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   14520 
   14521    assign( vA, getVReg(vA_addr));
   14522    assign( vB, getVReg(vB_addr));
   14523 
   14524    if (opc1 != 0x4) {
   14525       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   14526       return False;
   14527    }
   14528 
   14529    switch (opc2) {
   14530    /* Add */
   14531    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   14532       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14533       /* unsigned_ov(x+y) = (y >u not(x)) */
   14534       putVReg( vD_addr, binop(Iop_ShrN32x4,
   14535                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   14536                                     unop(Iop_NotV128, mkexpr(vA))),
   14537                               mkU8(31)) );
   14538       break;
   14539    }
   14540    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   14541       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14542       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   14543       break;
   14544 
   14545    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   14546       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14547       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   14548       break;
   14549 
   14550    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   14551       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14552       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   14553       break;
   14554 
   14555    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   14556       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14557       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   14558       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   14559       break;
   14560 
   14561    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   14562       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14563       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   14564       // TODO: set VSCR[SAT]
   14565       break;
   14566 
   14567    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   14568       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14569       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   14570       // TODO: set VSCR[SAT]
   14571       break;
   14572 
   14573    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   14574       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14575       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   14576       // TODO: set VSCR[SAT]
   14577       break;
   14578 
   14579    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   14580       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14581       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   14582       // TODO: set VSCR[SAT]
   14583       break;
   14584 
   14585    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   14586       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14587       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   14588       // TODO: set VSCR[SAT]
   14589       break;
   14590 
   14591 
   14592    /* Subtract */
   14593    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   14594       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14595       /* unsigned_ov(x-y) = (y >u x) */
   14596       putVReg( vD_addr, binop(Iop_ShrN32x4,
   14597                               unop(Iop_NotV128,
   14598                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   14599                                          mkexpr(vA))),
   14600                               mkU8(31)) );
   14601       break;
   14602    }
   14603    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   14604       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14605       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   14606       break;
   14607 
   14608    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   14609       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14610       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   14611       break;
   14612 
   14613    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   14614       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14615       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   14616       break;
   14617 
   14618    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   14619       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14620       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   14621       // TODO: set VSCR[SAT]
   14622       break;
   14623 
   14624    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   14625       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14626       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   14627       // TODO: set VSCR[SAT]
   14628       break;
   14629 
   14630    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   14631       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14632       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   14633       // TODO: set VSCR[SAT]
   14634       break;
   14635 
   14636    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   14637       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14638       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   14639       // TODO: set VSCR[SAT]
   14640       break;
   14641 
   14642    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   14643       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14644       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   14645       // TODO: set VSCR[SAT]
   14646       break;
   14647 
   14648    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   14649       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14650       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   14651       // TODO: set VSCR[SAT]
   14652       break;
   14653 
   14654 
   14655    /* Maximum */
   14656    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   14657       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14658       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   14659       break;
   14660 
   14661    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   14662       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14663       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   14664       break;
   14665 
   14666    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   14667       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14668       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   14669       break;
   14670 
   14671    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   14672       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14673       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   14674       break;
   14675 
   14676    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   14677       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14678       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   14679       break;
   14680 
   14681    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   14682       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14683       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   14684       break;
   14685 
   14686 
   14687    /* Minimum */
   14688    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   14689       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14690       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   14691       break;
   14692 
   14693    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   14694       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14695       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   14696       break;
   14697 
   14698    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   14699       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14700       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   14701       break;
   14702 
   14703    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   14704       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14705       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   14706       break;
   14707 
   14708    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   14709       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14710       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   14711       break;
   14712 
   14713    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   14714       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14715       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   14716       break;
   14717 
   14718 
   14719    /* Average */
   14720    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   14721       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14722       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   14723       break;
   14724 
   14725    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   14726       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14727       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   14728       break;
   14729 
   14730    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   14731       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14732       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   14733       break;
   14734 
   14735    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   14736       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14737       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   14738       break;
   14739 
   14740    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   14741       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14742       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   14743       break;
   14744 
   14745    case 0x582: // vavgsw (Average Signed Word, AV p151)
   14746       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14747       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   14748       break;
   14749 
   14750 
   14751    /* Multiply */
   14752    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   14753       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14754       putVReg( vD_addr,
   14755                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   14756       break;
   14757 
   14758    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   14759       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14760       putVReg( vD_addr,
   14761                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   14762       break;
   14763 
   14764    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   14765       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14766       putVReg( vD_addr,
   14767                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   14768       break;
   14769 
   14770    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   14771       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14772       putVReg( vD_addr,
   14773                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   14774       break;
   14775 
   14776    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   14777       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14778       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   14779       break;
   14780 
   14781    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   14782       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14783       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   14784       break;
   14785 
   14786    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   14787       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14788       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   14789       break;
   14790 
   14791    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   14792       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14793       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   14794       break;
   14795 
   14796 
   14797    /* Sum Across Partial */
   14798    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   14799       IRTemp aEE, aEO, aOE, aOO;
   14800       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   14801       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14802 
   14803       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   14804       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   14805       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   14806       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   14807 
   14808       /* break V128 to 4xI32's, zero-extending to I64's */
   14809       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   14810       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   14811       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   14812       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   14813       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   14814 
   14815       /* add lanes */
   14816       assign( z3, binop(Iop_Add64, mkexpr(b3),
   14817                      binop(Iop_Add64,
   14818                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   14819                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   14820       assign( z2, binop(Iop_Add64, mkexpr(b2),
   14821                      binop(Iop_Add64,
   14822                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   14823                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   14824       assign( z1, binop(Iop_Add64, mkexpr(b1),
   14825                      binop(Iop_Add64,
   14826                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   14827                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   14828       assign( z0, binop(Iop_Add64, mkexpr(b0),
   14829                      binop(Iop_Add64,
   14830                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   14831                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   14832 
   14833       /* saturate-narrow to 32bit, and combine to V128 */
   14834       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   14835                                          mkexpr(z1), mkexpr(z0)) );
   14836       break;
   14837    }
   14838    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   14839       IRTemp aEE, aEO, aOE, aOO;
   14840       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   14841       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14842 
   14843       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   14844       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   14845       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   14846       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   14847 
   14848       /* break V128 to 4xI32's, sign-extending to I64's */
   14849       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   14850       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   14851       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   14852       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   14853       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   14854 
   14855       /* add lanes */
   14856       assign( z3, binop(Iop_Add64, mkexpr(b3),
   14857                      binop(Iop_Add64,
   14858                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   14859                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   14860       assign( z2, binop(Iop_Add64, mkexpr(b2),
   14861                      binop(Iop_Add64,
   14862                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   14863                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   14864       assign( z1, binop(Iop_Add64, mkexpr(b1),
   14865                      binop(Iop_Add64,
   14866                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   14867                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   14868       assign( z0, binop(Iop_Add64, mkexpr(b0),
   14869                      binop(Iop_Add64,
   14870                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   14871                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   14872 
   14873       /* saturate-narrow to 32bit, and combine to V128 */
   14874       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   14875                                          mkexpr(z1), mkexpr(z0)) );
   14876       break;
   14877    }
   14878    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   14879       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14880 
   14881       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   14882       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   14883 
   14884       /* break V128 to 4xI32's, sign-extending to I64's */
   14885       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   14886       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   14887       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   14888 
   14889       /* add lanes */
   14890       assign( z3, binop(Iop_Add64, mkexpr(b3),
   14891                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   14892       assign( z2, binop(Iop_Add64, mkexpr(b2),
   14893                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   14894       assign( z1, binop(Iop_Add64, mkexpr(b1),
   14895                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   14896       assign( z0, binop(Iop_Add64, mkexpr(b0),
   14897                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   14898 
   14899       /* saturate-narrow to 32bit, and combine to V128 */
   14900       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   14901                                          mkexpr(z1), mkexpr(z0)) );
   14902       break;
   14903    }
   14904    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   14905       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14906 
   14907       /* break V128 to 4xI32's, sign-extending to I64's */
   14908       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   14909       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   14910 
   14911       /* add lanes */
   14912       assign( z2, binop(Iop_Add64, mkexpr(b2),
   14913                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   14914       assign( z0, binop(Iop_Add64, mkexpr(b0),
   14915                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   14916 
   14917       /* saturate-narrow to 32bit, and combine to V128 */
   14918       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   14919                                          mkU64(0), mkexpr(z0)) );
   14920       break;
   14921    }
   14922    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   14923       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14924 
   14925       /* break V128 to 4xI32's, sign-extending to I64's */
   14926       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   14927       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   14928 
   14929       /* add lanes */
   14930       assign( z0, binop(Iop_Add64, mkexpr(b0),
   14931                      binop(Iop_Add64,
   14932                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   14933                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   14934 
   14935       /* saturate-narrow to 32bit, and combine to V128 */
   14936       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   14937                                          mkU64(0), mkexpr(z0)) );
   14938       break;
   14939    }
   14940    default:
   14941       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   14942       return False;
   14943    }
   14944    return True;
   14945 }
   14946 
   14947 /*
   14948   AltiVec Logic Instructions
   14949 */
   14950 static Bool dis_av_logic ( UInt theInstr )
   14951 {
   14952    /* VX-Form */
   14953    UChar opc1    = ifieldOPC(theInstr);
   14954    UChar vD_addr = ifieldRegDS(theInstr);
   14955    UChar vA_addr = ifieldRegA(theInstr);
   14956    UChar vB_addr = ifieldRegB(theInstr);
   14957    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   14958 
   14959    IRTemp vA = newTemp(Ity_V128);
   14960    IRTemp vB = newTemp(Ity_V128);
   14961    assign( vA, getVReg(vA_addr));
   14962    assign( vB, getVReg(vB_addr));
   14963 
   14964    if (opc1 != 0x4) {
   14965       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   14966       return False;
   14967    }
   14968 
   14969    switch (opc2) {
   14970    case 0x404: // vand (And, AV p147)
   14971       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14972       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   14973       break;
   14974 
   14975    case 0x444: // vandc (And, AV p148)
   14976       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14977       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   14978                               unop(Iop_NotV128, mkexpr(vB))) );
   14979       break;
   14980 
   14981    case 0x484: // vor (Or, AV p217)
   14982       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14983       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   14984       break;
   14985 
   14986    case 0x4C4: // vxor (Xor, AV p282)
   14987       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14988       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   14989       break;
   14990 
   14991    case 0x504: // vnor (Nor, AV p216)
   14992       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   14993       putVReg( vD_addr,
   14994          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   14995       break;
   14996 
   14997    default:
   14998       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   14999       return False;
   15000    }
   15001    return True;
   15002 }
   15003 
   15004 /*
   15005   AltiVec Compare Instructions
   15006 */
   15007 static Bool dis_av_cmp ( UInt theInstr )
   15008 {
   15009    /* VXR-Form */
   15010    UChar opc1     = ifieldOPC(theInstr);
   15011    UChar vD_addr  = ifieldRegDS(theInstr);
   15012    UChar vA_addr  = ifieldRegA(theInstr);
   15013    UChar vB_addr  = ifieldRegB(theInstr);
   15014    UChar flag_rC  = ifieldBIT10(theInstr);
   15015    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   15016 
   15017    IRTemp vA = newTemp(Ity_V128);
   15018    IRTemp vB = newTemp(Ity_V128);
   15019    IRTemp vD = newTemp(Ity_V128);
   15020    assign( vA, getVReg(vA_addr));
   15021    assign( vB, getVReg(vB_addr));
   15022 
   15023    if (opc1 != 0x4) {
   15024       vex_printf("dis_av_cmp(ppc)(instr)\n");
   15025       return False;
   15026    }
   15027 
   15028    switch (opc2) {
   15029    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   15030       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15031                                       vD_addr, vA_addr, vB_addr);
   15032       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   15033       break;
   15034 
   15035    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   15036       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15037                                       vD_addr, vA_addr, vB_addr);
   15038       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   15039       break;
   15040 
   15041    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   15042       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15043                                       vD_addr, vA_addr, vB_addr);
   15044       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   15045       break;
   15046 
   15047    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   15048       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15049                                       vD_addr, vA_addr, vB_addr);
   15050       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   15051       break;
   15052 
   15053    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   15054       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15055                                       vD_addr, vA_addr, vB_addr);
   15056       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   15057       break;
   15058 
   15059    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   15060       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15061                                        vD_addr, vA_addr, vB_addr);
   15062       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   15063       break;
   15064 
   15065    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   15066       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15067                                        vD_addr, vA_addr, vB_addr);
   15068       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   15069       break;
   15070 
   15071    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   15072       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15073                                       vD_addr, vA_addr, vB_addr);
   15074       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   15075       break;
   15076 
   15077    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   15078       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   15079                                       vD_addr, vA_addr, vB_addr);
   15080       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   15081       break;
   15082 
   15083    default:
   15084       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   15085       return False;
   15086    }
   15087 
   15088    putVReg( vD_addr, mkexpr(vD) );
   15089 
   15090    if (flag_rC) {
   15091       set_AV_CR6( mkexpr(vD), True );
   15092    }
   15093    return True;
   15094 }
   15095 
   15096 /*
   15097   AltiVec Multiply-Sum Instructions
   15098 */
   15099 static Bool dis_av_multarith ( UInt theInstr )
   15100 {
   15101    /* VA-Form */
   15102    UChar opc1     = ifieldOPC(theInstr);
   15103    UChar vD_addr  = ifieldRegDS(theInstr);
   15104    UChar vA_addr  = ifieldRegA(theInstr);
   15105    UChar vB_addr  = ifieldRegB(theInstr);
   15106    UChar vC_addr  = ifieldRegC(theInstr);
   15107    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   15108 
   15109    IRTemp vA    = newTemp(Ity_V128);
   15110    IRTemp vB    = newTemp(Ity_V128);
   15111    IRTemp vC    = newTemp(Ity_V128);
   15112    IRTemp zeros = newTemp(Ity_V128);
   15113    IRTemp aLo   = newTemp(Ity_V128);
   15114    IRTemp bLo   = newTemp(Ity_V128);
   15115    IRTemp cLo   = newTemp(Ity_V128);
   15116    IRTemp zLo   = newTemp(Ity_V128);
   15117    IRTemp aHi   = newTemp(Ity_V128);
   15118    IRTemp bHi   = newTemp(Ity_V128);
   15119    IRTemp cHi   = newTemp(Ity_V128);
   15120    IRTemp zHi   = newTemp(Ity_V128);
   15121    IRTemp abEvn = newTemp(Ity_V128);
   15122    IRTemp abOdd = newTemp(Ity_V128);
   15123    IRTemp z3    = newTemp(Ity_I64);
   15124    IRTemp z2    = newTemp(Ity_I64);
   15125    IRTemp z1    = newTemp(Ity_I64);
   15126    IRTemp z0    = newTemp(Ity_I64);
   15127    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   15128    IRTemp c3, c2, c1, c0;
   15129 
   15130    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   15131    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   15132 
   15133    assign( vA, getVReg(vA_addr));
   15134    assign( vB, getVReg(vB_addr));
   15135    assign( vC, getVReg(vC_addr));
   15136    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   15137 
   15138    if (opc1 != 0x4) {
   15139       vex_printf("dis_av_multarith(ppc)(instr)\n");
   15140       return False;
   15141    }
   15142 
   15143    switch (opc2) {
   15144    /* Multiply-Add */
   15145    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   15146       IRTemp cSigns = newTemp(Ity_V128);
   15147       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   15148           vD_addr, vA_addr, vB_addr, vC_addr);
   15149       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   15150       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   15151       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   15152       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   15153       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   15154       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   15155       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   15156 
   15157       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   15158                          binop(Iop_SarN32x4,
   15159                                binop(Iop_MullEven16Sx8,
   15160                                      mkexpr(aLo), mkexpr(bLo)),
   15161                                mkU8(15))) );
   15162 
   15163       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   15164                          binop(Iop_SarN32x4,
   15165                                binop(Iop_MullEven16Sx8,
   15166                                      mkexpr(aHi), mkexpr(bHi)),
   15167                                mkU8(15))) );
   15168 
   15169       putVReg( vD_addr,
   15170                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   15171       break;
   15172    }
   15173    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   15174       IRTemp zKonst = newTemp(Ity_V128);
   15175       IRTemp cSigns = newTemp(Ity_V128);
   15176       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   15177           vD_addr, vA_addr, vB_addr, vC_addr);
   15178       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   15179       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   15180       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   15181       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   15182       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   15183       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   15184       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   15185 
   15186       /* shifting our const avoids store/load version of Dup */
   15187       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   15188                             mkU8(14)) );
   15189 
   15190       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   15191                          binop(Iop_SarN32x4,
   15192                                binop(Iop_Add32x4, mkexpr(zKonst),
   15193                                      binop(Iop_MullEven16Sx8,
   15194                                            mkexpr(aLo), mkexpr(bLo))),
   15195                                mkU8(15))) );
   15196 
   15197       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   15198                          binop(Iop_SarN32x4,
   15199                                binop(Iop_Add32x4, mkexpr(zKonst),
   15200                                      binop(Iop_MullEven16Sx8,
   15201                                            mkexpr(aHi), mkexpr(bHi))),
   15202                                mkU8(15))) );
   15203 
   15204       putVReg( vD_addr,
   15205                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   15206       break;
   15207    }
   15208    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   15209       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   15210           vD_addr, vA_addr, vB_addr, vC_addr);
   15211       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   15212       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   15213       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   15214       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   15215       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   15216       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   15217       assign(zLo, binop(Iop_Add32x4,
   15218                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   15219                      mkexpr(cLo)) );
   15220       assign(zHi, binop(Iop_Add32x4,
   15221                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   15222                      mkexpr(cHi)));
   15223       putVReg( vD_addr,
   15224                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   15225       break;
   15226    }
   15227 
   15228 
   15229    /* Multiply-Sum */
   15230    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   15231       IRTemp abEE, abEO, abOE, abOO;
   15232       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   15233       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   15234           vD_addr, vA_addr, vB_addr, vC_addr);
   15235 
   15236       /* multiply vA,vB (unsigned, widening) */
   15237       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   15238       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   15239 
   15240       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   15241       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   15242       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   15243 
   15244       putVReg( vD_addr,
   15245          binop(Iop_Add32x4, mkexpr(vC),
   15246                binop(Iop_Add32x4,
   15247                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   15248                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   15249       break;
   15250    }
   15251    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   15252       IRTemp aEvn, aOdd, bEvn, bOdd;
   15253       IRTemp abEE = newTemp(Ity_V128);
   15254       IRTemp abEO = newTemp(Ity_V128);
   15255       IRTemp abOE = newTemp(Ity_V128);
   15256       IRTemp abOO = newTemp(Ity_V128);
   15257       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   15258       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   15259           vD_addr, vA_addr, vB_addr, vC_addr);
   15260 
   15261       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   15262          (separating out adjacent lanes to different vectors) */
   15263       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   15264       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   15265 
   15266       /* multiply vA, vB, again separating adjacent lanes */
   15267       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   15268       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   15269       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   15270       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   15271 
   15272       /* add results together, + vC */
   15273       putVReg( vD_addr,
   15274          binop(Iop_QAdd32Sx4, mkexpr(vC),
   15275                binop(Iop_QAdd32Sx4,
   15276                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   15277                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   15278       break;
   15279    }
   15280    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   15281       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   15282           vD_addr, vA_addr, vB_addr, vC_addr);
   15283       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   15284       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   15285       putVReg( vD_addr,
   15286          binop(Iop_Add32x4, mkexpr(vC),
   15287                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   15288       break;
   15289    }
   15290    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   15291       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   15292           vD_addr, vA_addr, vB_addr, vC_addr);
   15293       /* widening multiply, separating lanes */
   15294       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   15295       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   15296 
   15297       /* break V128 to 4xI32's, zero-extending to I64's */
   15298       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   15299       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   15300       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   15301 
   15302       /* add lanes */
   15303       assign( z3, binop(Iop_Add64, mkexpr(c3),
   15304                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   15305       assign( z2, binop(Iop_Add64, mkexpr(c2),
   15306                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   15307       assign( z1, binop(Iop_Add64, mkexpr(c1),
   15308                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   15309       assign( z0, binop(Iop_Add64, mkexpr(c0),
   15310                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   15311 
   15312       /* saturate-narrow to 32bit, and combine to V128 */
   15313       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   15314                                          mkexpr(z1), mkexpr(z0)) );
   15315 
   15316       break;
   15317    }
   15318    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   15319       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   15320           vD_addr, vA_addr, vB_addr, vC_addr);
   15321       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   15322       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   15323       putVReg( vD_addr,
   15324          binop(Iop_Add32x4, mkexpr(vC),
   15325                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   15326       break;
   15327    }
   15328    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   15329       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   15330           vD_addr, vA_addr, vB_addr, vC_addr);
   15331       /* widening multiply, separating lanes */
   15332       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   15333       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   15334 
   15335       /* break V128 to 4xI32's, sign-extending to I64's */
   15336       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   15337       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   15338       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   15339 
   15340       /* add lanes */
   15341       assign( z3, binop(Iop_Add64, mkexpr(c3),
   15342                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   15343       assign( z2, binop(Iop_Add64, mkexpr(c2),
   15344                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   15345       assign( z1, binop(Iop_Add64, mkexpr(c1),
   15346                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   15347       assign( z0, binop(Iop_Add64, mkexpr(c0),
   15348                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   15349 
   15350       /* saturate-narrow to 32bit, and combine to V128 */
   15351       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   15352                                          mkexpr(z1), mkexpr(z0)) );
   15353       break;
   15354    }
   15355    default:
   15356       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   15357       return False;
   15358    }
   15359    return True;
   15360 }
   15361 
   15362 /*
   15363   AltiVec Shift/Rotate Instructions
   15364 */
   15365 static Bool dis_av_shift ( UInt theInstr )
   15366 {
   15367    /* VX-Form */
   15368    UChar opc1    = ifieldOPC(theInstr);
   15369    UChar vD_addr = ifieldRegDS(theInstr);
   15370    UChar vA_addr = ifieldRegA(theInstr);
   15371    UChar vB_addr = ifieldRegB(theInstr);
   15372    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   15373 
   15374    IRTemp vA = newTemp(Ity_V128);
   15375    IRTemp vB = newTemp(Ity_V128);
   15376    assign( vA, getVReg(vA_addr));
   15377    assign( vB, getVReg(vB_addr));
   15378 
   15379    if (opc1 != 0x4){
   15380       vex_printf("dis_av_shift(ppc)(instr)\n");
   15381       return False;
   15382    }
   15383 
   15384    switch (opc2) {
   15385    /* Rotate */
   15386    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   15387       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15388       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   15389       break;
   15390 
   15391    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   15392       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15393       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   15394       break;
   15395 
   15396    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   15397       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15398       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   15399       break;
   15400 
   15401 
   15402    /* Shift Left */
   15403    case 0x104: // vslb (Shift Left Integer B, AV p240)
   15404       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15405       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   15406       break;
   15407 
   15408    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   15409       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15410       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   15411       break;
   15412 
   15413    case 0x184: // vslw (Shift Left Integer W, AV p244)
   15414       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15415       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   15416       break;
   15417 
   15418    case 0x1C4: { // vsl (Shift Left, AV p239)
   15419       IRTemp sh = newTemp(Ity_I8);
   15420       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15421       assign( sh, binop(Iop_And8, mkU8(0x7),
   15422                         unop(Iop_32to8,
   15423                              unop(Iop_V128to32, mkexpr(vB)))) );
   15424       putVReg( vD_addr,
   15425                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   15426       break;
   15427    }
   15428    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   15429       IRTemp sh = newTemp(Ity_I8);
   15430       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15431       assign( sh, binop(Iop_And8, mkU8(0x78),
   15432                         unop(Iop_32to8,
   15433                              unop(Iop_V128to32, mkexpr(vB)))) );
   15434       putVReg( vD_addr,
   15435                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   15436       break;
   15437    }
   15438 
   15439 
   15440    /* Shift Right */
   15441    case 0x204: // vsrb (Shift Right B, AV p256)
   15442       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15443       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   15444       break;
   15445 
   15446    case 0x244: // vsrh (Shift Right HW, AV p257)
   15447       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15448       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   15449       break;
   15450 
   15451    case 0x284: // vsrw (Shift Right W, AV p259)
   15452       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15453       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   15454       break;
   15455 
   15456    case 0x2C4: { // vsr (Shift Right, AV p251)
   15457       IRTemp sh = newTemp(Ity_I8);
   15458       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15459       assign( sh, binop(Iop_And8, mkU8(0x7),
   15460                         unop(Iop_32to8,
   15461                              unop(Iop_V128to32, mkexpr(vB)))) );
   15462       putVReg( vD_addr,
   15463                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   15464       break;
   15465    }
   15466    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   15467       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15468       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   15469       break;
   15470 
   15471    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   15472       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15473       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   15474       break;
   15475 
   15476    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   15477       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15478       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   15479       break;
   15480 
   15481    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   15482       IRTemp sh = newTemp(Ity_I8);
   15483       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15484       assign( sh, binop(Iop_And8, mkU8(0x78),
   15485                         unop(Iop_32to8,
   15486                              unop(Iop_V128to32, mkexpr(vB)))) );
   15487       putVReg( vD_addr,
   15488                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   15489       break;
   15490    }
   15491 
   15492    default:
   15493       vex_printf("dis_av_shift(ppc)(opc2)\n");
   15494       return False;
   15495    }
   15496    return True;
   15497 }
   15498 
   15499 /*
   15500   AltiVec Permute Instructions
   15501 */
   15502 static Bool dis_av_permute ( UInt theInstr )
   15503 {
   15504    /* VA-Form, VX-Form */
   15505    UChar opc1      = ifieldOPC(theInstr);
   15506    UChar vD_addr   = ifieldRegDS(theInstr);
   15507    UChar vA_addr   = ifieldRegA(theInstr);
   15508    UChar UIMM_5    = vA_addr;
   15509    UChar vB_addr   = ifieldRegB(theInstr);
   15510    UChar vC_addr   = ifieldRegC(theInstr);
   15511    UChar b10       = ifieldBIT10(theInstr);
   15512    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   15513    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   15514 
   15515    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   15516 
   15517    IRTemp vA = newTemp(Ity_V128);
   15518    IRTemp vB = newTemp(Ity_V128);
   15519    IRTemp vC = newTemp(Ity_V128);
   15520    assign( vA, getVReg(vA_addr));
   15521    assign( vB, getVReg(vB_addr));
   15522    assign( vC, getVReg(vC_addr));
   15523 
   15524    if (opc1 != 0x4) {
   15525       vex_printf("dis_av_permute(ppc)(instr)\n");
   15526       return False;
   15527    }
   15528 
   15529    switch (opc2) {
   15530    case 0x2A: // vsel (Conditional Select, AV p238)
   15531       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   15532       /* vD = (vA & ~vC) | (vB & vC) */
   15533       putVReg( vD_addr, binop(Iop_OrV128,
   15534          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   15535          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   15536       return True;
   15537 
   15538    case 0x2B: { // vperm (Permute, AV p218)
   15539       /* limited to two args for IR, so have to play games... */
   15540       IRTemp a_perm  = newTemp(Ity_V128);
   15541       IRTemp b_perm  = newTemp(Ity_V128);
   15542       IRTemp mask    = newTemp(Ity_V128);
   15543       IRTemp vC_andF = newTemp(Ity_V128);
   15544       DIP("vperm v%d,v%d,v%d,v%d\n",
   15545           vD_addr, vA_addr, vB_addr, vC_addr);
   15546       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   15547          IR specifies, and also to hide irrelevant bits from
   15548          memcheck */
   15549       assign( vC_andF,
   15550               binop(Iop_AndV128, mkexpr(vC),
   15551                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   15552       assign( a_perm,
   15553               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   15554       assign( b_perm,
   15555               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   15556       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   15557       assign( mask, binop(Iop_SarN8x16,
   15558                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   15559                           mkU8(7)) );
   15560       // dst = (a & ~mask) | (b & mask)
   15561       putVReg( vD_addr, binop(Iop_OrV128,
   15562                               binop(Iop_AndV128, mkexpr(a_perm),
   15563                                     unop(Iop_NotV128, mkexpr(mask))),
   15564                               binop(Iop_AndV128, mkexpr(b_perm),
   15565                                     mkexpr(mask))) );
   15566       return True;
   15567    }
   15568    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   15569       if (b10 != 0) {
   15570          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   15571          return False;
   15572       }
   15573       DIP("vsldoi v%d,v%d,v%d,%d\n",
   15574           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   15575       if (SHB_uimm4 == 0)
   15576          putVReg( vD_addr, mkexpr(vA) );
   15577       else
   15578          putVReg( vD_addr,
   15579             binop(Iop_OrV128,
   15580                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   15581                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   15582       return True;
   15583 
   15584    default:
   15585      break; // Fall through...
   15586    }
   15587 
   15588    opc2 = IFIELD( theInstr, 0, 11 );
   15589    switch (opc2) {
   15590 
   15591    /* Merge */
   15592    case 0x00C: // vmrghb (Merge High B, AV p195)
   15593       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15594       putVReg( vD_addr,
   15595                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   15596       break;
   15597 
   15598    case 0x04C: // vmrghh (Merge High HW, AV p196)
   15599       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15600       putVReg( vD_addr,
   15601                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   15602       break;
   15603 
   15604    case 0x08C: // vmrghw (Merge High W, AV p197)
   15605       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15606       putVReg( vD_addr,
   15607                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   15608       break;
   15609 
   15610    case 0x10C: // vmrglb (Merge Low B, AV p198)
   15611       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15612       putVReg( vD_addr,
   15613                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   15614       break;
   15615 
   15616    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   15617       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15618       putVReg( vD_addr,
   15619                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   15620       break;
   15621 
   15622    case 0x18C: // vmrglw (Merge Low W, AV p200)
   15623       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15624       putVReg( vD_addr,
   15625                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   15626       break;
   15627 
   15628 
   15629    /* Splat */
   15630    case 0x20C: { // vspltb (Splat Byte, AV p245)
   15631       /* vD = Dup8x16( vB[UIMM_5] ) */
   15632       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   15633       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   15634       putVReg( vD_addr, unop(Iop_Dup8x16,
   15635            unop(Iop_32to8, unop(Iop_V128to32,
   15636                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   15637       break;
   15638    }
   15639    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   15640       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   15641       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   15642       putVReg( vD_addr, unop(Iop_Dup16x8,
   15643            unop(Iop_32to16, unop(Iop_V128to32,
   15644                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   15645       break;
   15646    }
   15647    case 0x28C: { // vspltw (Splat Word, AV p250)
   15648       /* vD = Dup32x4( vB[UIMM_5] ) */
   15649       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   15650       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   15651       putVReg( vD_addr, unop(Iop_Dup32x4,
   15652          unop(Iop_V128to32,
   15653               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   15654       break;
   15655    }
   15656    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   15657       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   15658       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   15659       break;
   15660 
   15661    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   15662       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   15663       putVReg( vD_addr,
   15664                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   15665       break;
   15666 
   15667    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   15668       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   15669       putVReg( vD_addr,
   15670                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   15671       break;
   15672 
   15673    default:
   15674       vex_printf("dis_av_permute(ppc)(opc2)\n");
   15675       return False;
   15676    }
   15677    return True;
   15678 }
   15679 
   15680 /*
   15681   AltiVec Pack/Unpack Instructions
   15682 */
   15683 static Bool dis_av_pack ( UInt theInstr )
   15684 {
   15685    /* VX-Form */
   15686    UChar opc1     = ifieldOPC(theInstr);
   15687    UChar vD_addr  = ifieldRegDS(theInstr);
   15688    UChar vA_addr  = ifieldRegA(theInstr);
   15689    UChar vB_addr  = ifieldRegB(theInstr);
   15690    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   15691 
   15692    IRTemp signs = IRTemp_INVALID;
   15693    IRTemp zeros = IRTemp_INVALID;
   15694    IRTemp vA    = newTemp(Ity_V128);
   15695    IRTemp vB    = newTemp(Ity_V128);
   15696    assign( vA, getVReg(vA_addr));
   15697    assign( vB, getVReg(vB_addr));
   15698 
   15699    if (opc1 != 0x4) {
   15700       vex_printf("dis_av_pack(ppc)(instr)\n");
   15701       return False;
   15702    }
   15703 
   15704    switch (opc2) {
   15705    /* Packing */
   15706    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   15707       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15708       putVReg( vD_addr,
   15709                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   15710       return True;
   15711 
   15712    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   15713       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15714       putVReg( vD_addr,
   15715                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   15716       return True;
   15717 
   15718    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   15719       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15720       putVReg( vD_addr,
   15721                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   15722       // TODO: set VSCR[SAT]
   15723       return True;
   15724 
   15725    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   15726       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15727       putVReg( vD_addr,
   15728                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   15729       // TODO: set VSCR[SAT]
   15730       return True;
   15731 
   15732    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   15733       // This insn does a signed->unsigned saturating conversion.
   15734       // Conversion done here, then uses unsigned->unsigned vpk insn:
   15735       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   15736       IRTemp vA_tmp = newTemp(Ity_V128);
   15737       IRTemp vB_tmp = newTemp(Ity_V128);
   15738       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15739       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   15740                             unop(Iop_NotV128,
   15741                                  binop(Iop_SarN16x8,
   15742                                        mkexpr(vA), mkU8(15)))) );
   15743       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   15744                             unop(Iop_NotV128,
   15745                                  binop(Iop_SarN16x8,
   15746                                        mkexpr(vB), mkU8(15)))) );
   15747       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   15748                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   15749       // TODO: set VSCR[SAT]
   15750       return True;
   15751    }
   15752    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   15753       // This insn does a signed->unsigned saturating conversion.
   15754       // Conversion done here, then uses unsigned->unsigned vpk insn:
   15755       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   15756       IRTemp vA_tmp = newTemp(Ity_V128);
   15757       IRTemp vB_tmp = newTemp(Ity_V128);
   15758       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15759       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   15760                             unop(Iop_NotV128,
   15761                                  binop(Iop_SarN32x4,
   15762                                        mkexpr(vA), mkU8(31)))) );
   15763       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   15764                             unop(Iop_NotV128,
   15765                                  binop(Iop_SarN32x4,
   15766                                        mkexpr(vB), mkU8(31)))) );
   15767       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   15768                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   15769       // TODO: set VSCR[SAT]
   15770       return True;
   15771    }
   15772    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   15773       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15774       putVReg( vD_addr,
   15775                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   15776       // TODO: set VSCR[SAT]
   15777       return True;
   15778 
   15779    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   15780       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15781       putVReg( vD_addr,
   15782                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   15783       // TODO: set VSCR[SAT]
   15784       return True;
   15785 
   15786    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   15787       /* CAB: Worth a new primop? */
   15788       /* Using shifts to compact pixel elements, then packing them */
   15789       IRTemp a1 = newTemp(Ity_V128);
   15790       IRTemp a2 = newTemp(Ity_V128);
   15791       IRTemp a3 = newTemp(Ity_V128);
   15792       IRTemp a_tmp = newTemp(Ity_V128);
   15793       IRTemp b1 = newTemp(Ity_V128);
   15794       IRTemp b2 = newTemp(Ity_V128);
   15795       IRTemp b3 = newTemp(Ity_V128);
   15796       IRTemp b_tmp = newTemp(Ity_V128);
   15797       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15798       assign( a1, binop(Iop_ShlN16x8,
   15799                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   15800                         mkU8(10)) );
   15801       assign( a2, binop(Iop_ShlN16x8,
   15802                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   15803                         mkU8(5)) );
   15804       assign( a3,  binop(Iop_ShrN16x8,
   15805                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   15806                          mkU8(11)) );
   15807       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   15808                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   15809 
   15810       assign( b1, binop(Iop_ShlN16x8,
   15811                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   15812                         mkU8(10)) );
   15813       assign( b2, binop(Iop_ShlN16x8,
   15814                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   15815                         mkU8(5)) );
   15816       assign( b3,  binop(Iop_ShrN16x8,
   15817                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   15818                          mkU8(11)) );
   15819       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   15820                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   15821 
   15822       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   15823                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   15824       return True;
   15825    }
   15826 
   15827    default:
   15828       break; // Fall through...
   15829    }
   15830 
   15831 
   15832    if (vA_addr != 0) {
   15833       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   15834       return False;
   15835    }
   15836 
   15837    signs = newTemp(Ity_V128);
   15838    zeros = newTemp(Ity_V128);
   15839    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   15840 
   15841    switch (opc2) {
   15842    /* Unpacking */
   15843    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   15844       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   15845       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   15846       putVReg( vD_addr,
   15847                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   15848       break;
   15849    }
   15850    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   15851       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   15852       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   15853       putVReg( vD_addr,
   15854                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   15855       break;
   15856    }
   15857    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   15858       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   15859       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   15860       putVReg( vD_addr,
   15861                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   15862       break;
   15863    }
   15864    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   15865       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   15866       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   15867       putVReg( vD_addr,
   15868                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   15869       break;
   15870    }
   15871    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   15872       /* CAB: Worth a new primop? */
   15873       /* Using shifts to isolate pixel elements, then expanding them */
   15874       IRTemp z0  = newTemp(Ity_V128);
   15875       IRTemp z1  = newTemp(Ity_V128);
   15876       IRTemp z01 = newTemp(Ity_V128);
   15877       IRTemp z2  = newTemp(Ity_V128);
   15878       IRTemp z3  = newTemp(Ity_V128);
   15879       IRTemp z23 = newTemp(Ity_V128);
   15880       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   15881       assign( z0,  binop(Iop_ShlN16x8,
   15882                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   15883                          mkU8(8)) );
   15884       assign( z1,  binop(Iop_ShrN16x8,
   15885                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   15886                          mkU8(11)) );
   15887       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   15888                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   15889       assign( z2,  binop(Iop_ShrN16x8,
   15890                          binop(Iop_ShlN16x8,
   15891                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   15892                                mkU8(11)),
   15893                          mkU8(3)) );
   15894       assign( z3,  binop(Iop_ShrN16x8,
   15895                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   15896                          mkU8(11)) );
   15897       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   15898                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   15899       putVReg( vD_addr,
   15900                binop(Iop_OrV128,
   15901                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   15902                      mkexpr(z23)) );
   15903       break;
   15904    }
   15905    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   15906       /* identical to vupkhpx, except interleaving LO */
   15907       IRTemp z0  = newTemp(Ity_V128);
   15908       IRTemp z1  = newTemp(Ity_V128);
   15909       IRTemp z01 = newTemp(Ity_V128);
   15910       IRTemp z2  = newTemp(Ity_V128);
   15911       IRTemp z3  = newTemp(Ity_V128);
   15912       IRTemp z23 = newTemp(Ity_V128);
   15913       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   15914       assign( z0,  binop(Iop_ShlN16x8,
   15915                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   15916                          mkU8(8)) );
   15917       assign( z1,  binop(Iop_ShrN16x8,
   15918                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   15919                          mkU8(11)) );
   15920       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   15921                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   15922       assign( z2,  binop(Iop_ShrN16x8,
   15923                          binop(Iop_ShlN16x8,
   15924                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   15925                                mkU8(11)),
   15926                          mkU8(3)) );
   15927       assign( z3,  binop(Iop_ShrN16x8,
   15928                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   15929                          mkU8(11)) );
   15930       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   15931                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   15932       putVReg( vD_addr,
   15933                binop(Iop_OrV128,
   15934                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   15935                      mkexpr(z23)) );
   15936       break;
   15937    }
   15938    default:
   15939       vex_printf("dis_av_pack(ppc)(opc2)\n");
   15940       return False;
   15941    }
   15942    return True;
   15943 }
   15944 
   15945 
   15946 /*
   15947   AltiVec Floating Point Arithmetic Instructions
   15948 */
   15949 static Bool dis_av_fp_arith ( UInt theInstr )
   15950 {
   15951    /* VA-Form */
   15952    UChar opc1     = ifieldOPC(theInstr);
   15953    UChar vD_addr  = ifieldRegDS(theInstr);
   15954    UChar vA_addr  = ifieldRegA(theInstr);
   15955    UChar vB_addr  = ifieldRegB(theInstr);
   15956    UChar vC_addr  = ifieldRegC(theInstr);
   15957    UInt  opc2=0;
   15958 
   15959    IRTemp vA = newTemp(Ity_V128);
   15960    IRTemp vB = newTemp(Ity_V128);
   15961    IRTemp vC = newTemp(Ity_V128);
   15962    assign( vA, getVReg(vA_addr));
   15963    assign( vB, getVReg(vB_addr));
   15964    assign( vC, getVReg(vC_addr));
   15965 
   15966    if (opc1 != 0x4) {
   15967       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   15968       return False;
   15969    }
   15970 
   15971    opc2 = IFIELD( theInstr, 0, 6 );
   15972    switch (opc2) {
   15973    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   15974       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   15975           vD_addr, vA_addr, vC_addr, vB_addr);
   15976       putVReg( vD_addr,
   15977                binop(Iop_Add32Fx4, mkexpr(vB),
   15978                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   15979       return True;
   15980 
   15981    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   15982       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   15983           vD_addr, vA_addr, vC_addr, vB_addr);
   15984       putVReg( vD_addr,
   15985                binop(Iop_Sub32Fx4,
   15986                      mkexpr(vB),
   15987                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   15988       return True;
   15989    }
   15990 
   15991    default:
   15992      break; // Fall through...
   15993    }
   15994 
   15995    opc2 = IFIELD( theInstr, 0, 11 );
   15996    switch (opc2) {
   15997    case 0x00A: // vaddfp (Add FP, AV p137)
   15998       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   15999       putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
   16000       return True;
   16001 
   16002   case 0x04A: // vsubfp (Subtract FP, AV p261)
   16003       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16004       putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
   16005       return True;
   16006 
   16007    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   16008       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16009       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   16010       return True;
   16011 
   16012    case 0x44A: // vminfp (Minimum FP, AV p187)
   16013       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16014       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   16015       return True;
   16016 
   16017    default:
   16018       break; // Fall through...
   16019    }
   16020 
   16021 
   16022    if (vA_addr != 0) {
   16023       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   16024       return False;
   16025    }
   16026 
   16027    switch (opc2) {
   16028    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   16029       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   16030       putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
   16031       return True;
   16032 
   16033    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   16034       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   16035       putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
   16036       return True;
   16037 
   16038    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   16039       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   16040       DIP(" => not implemented\n");
   16041       return False;
   16042 
   16043    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   16044       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   16045       DIP(" => not implemented\n");
   16046       return False;
   16047 
   16048    default:
   16049       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   16050       return False;
   16051    }
   16052    return True;
   16053 }
   16054 
   16055 /*
   16056   AltiVec Floating Point Compare Instructions
   16057 */
   16058 static Bool dis_av_fp_cmp ( UInt theInstr )
   16059 {
   16060    /* VXR-Form */
   16061    UChar opc1     = ifieldOPC(theInstr);
   16062    UChar vD_addr  = ifieldRegDS(theInstr);
   16063    UChar vA_addr  = ifieldRegA(theInstr);
   16064    UChar vB_addr  = ifieldRegB(theInstr);
   16065    UChar flag_rC  = ifieldBIT10(theInstr);
   16066    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   16067 
   16068    Bool cmp_bounds = False;
   16069 
   16070    IRTemp vA = newTemp(Ity_V128);
   16071    IRTemp vB = newTemp(Ity_V128);
   16072    IRTemp vD = newTemp(Ity_V128);
   16073    assign( vA, getVReg(vA_addr));
   16074    assign( vB, getVReg(vB_addr));
   16075 
   16076    if (opc1 != 0x4) {
   16077       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   16078       return False;
   16079    }
   16080 
   16081    switch (opc2) {
   16082    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   16083       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16084                                       vD_addr, vA_addr, vB_addr);
   16085       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   16086       break;
   16087 
   16088    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   16089       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16090                                       vD_addr, vA_addr, vB_addr);
   16091       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   16092       break;
   16093 
   16094    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   16095       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16096                                       vD_addr, vA_addr, vB_addr);
   16097       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   16098       break;
   16099 
   16100    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   16101       IRTemp gt      = newTemp(Ity_V128);
   16102       IRTemp lt      = newTemp(Ity_V128);
   16103       IRTemp zeros   = newTemp(Ity_V128);
   16104       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16105                                      vD_addr, vA_addr, vB_addr);
   16106       cmp_bounds = True;
   16107       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   16108 
   16109       /* Note: making use of fact that the ppc backend for compare insns
   16110          return zero'd lanes if either of the corresponding arg lanes is
   16111          a nan.
   16112 
   16113          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   16114          need this for the other compares too (vcmpeqfp etc)...
   16115          Better still, tighten down the spec for compare irops.
   16116        */
   16117       assign( gt, unop(Iop_NotV128,
   16118                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   16119       assign( lt, unop(Iop_NotV128,
   16120                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   16121                              binop(Iop_Sub32Fx4, mkexpr(zeros),
   16122                                                  mkexpr(vB)))) );
   16123 
   16124       // finally, just shift gt,lt to correct position
   16125       assign( vD, binop(Iop_ShlN32x4,
   16126                         binop(Iop_OrV128,
   16127                               binop(Iop_AndV128, mkexpr(gt),
   16128                                     unop(Iop_Dup32x4, mkU32(0x2))),
   16129                               binop(Iop_AndV128, mkexpr(lt),
   16130                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   16131                         mkU8(30)) );
   16132       break;
   16133    }
   16134 
   16135    default:
   16136       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   16137       return False;
   16138    }
   16139 
   16140    putVReg( vD_addr, mkexpr(vD) );
   16141 
   16142    if (flag_rC) {
   16143       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   16144    }
   16145    return True;
   16146 }
   16147 
   16148 /*
   16149   AltiVec Floating Point Convert/Round Instructions
   16150 */
   16151 static Bool dis_av_fp_convert ( UInt theInstr )
   16152 {
   16153    /* VX-Form */
   16154    UChar opc1     = ifieldOPC(theInstr);
   16155    UChar vD_addr  = ifieldRegDS(theInstr);
   16156    UChar UIMM_5   = ifieldRegA(theInstr);
   16157    UChar vB_addr  = ifieldRegB(theInstr);
   16158    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   16159 
   16160    IRTemp vB        = newTemp(Ity_V128);
   16161    IRTemp vScale    = newTemp(Ity_V128);
   16162    IRTemp vInvScale = newTemp(Ity_V128);
   16163 
   16164    float scale, inv_scale;
   16165 
   16166    assign( vB, getVReg(vB_addr));
   16167 
   16168    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   16169    scale = (float)( (unsigned int) 1<<UIMM_5 );
   16170    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   16171    inv_scale = 1/scale;
   16172    assign( vInvScale,
   16173            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   16174 
   16175    if (opc1 != 0x4) {
   16176       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   16177       return False;
   16178    }
   16179 
   16180    switch (opc2) {
   16181    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   16182       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16183       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   16184                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   16185                               mkexpr(vInvScale)) );
   16186       return True;
   16187 
   16188    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   16189       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16190 
   16191       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   16192                               unop(Iop_I32StoFx4, mkexpr(vB)),
   16193                               mkexpr(vInvScale)) );
   16194       return True;
   16195 
   16196    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   16197       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16198       putVReg( vD_addr,
   16199                unop(Iop_QFtoI32Ux4_RZ,
   16200                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   16201       return True;
   16202 
   16203    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   16204       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   16205       putVReg( vD_addr,
   16206                unop(Iop_QFtoI32Sx4_RZ,
   16207                      binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   16208       return True;
   16209 
   16210    default:
   16211      break;    // Fall through...
   16212    }
   16213 
   16214    if (UIMM_5 != 0) {
   16215       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   16216       return False;
   16217    }
   16218 
   16219    switch (opc2) {
   16220    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   16221       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   16222       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   16223       break;
   16224 
   16225    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   16226       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   16227       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   16228       break;
   16229 
   16230    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   16231       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   16232       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   16233       break;
   16234 
   16235    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   16236       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   16237       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   16238       break;
   16239 
   16240    default:
   16241       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   16242       return False;
   16243    }
   16244    return True;
   16245 }
   16246 
   16247 
   16248 /* The 0x3C primary opcode (VSX category) uses several different forms of
   16249  * extended opcodes:
   16250  *   o XX2-form:
   16251  *      - [10:2] (IBM notation [21:29])
   16252  *   o XX3-form variants:
   16253  *       - variant 1: [10:3] (IBM notation [21:28])
   16254  *       - variant 2: [9:3] (IBM notation [22:28])
   16255  *       - variant 3: [7:3] (IBM notation [24:28])
   16256  *   o XX-4 form:
   16257  *      - [10:6] (IBM notation [21:25])
   16258  *
   16259  * The XX2-form needs bit 0 masked from the standard extended opcode
   16260  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   16261  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   16262  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   16263  * front end since their encoding does not begin at bit 21 like the standard
   16264  * format.
   16265  *
   16266  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   16267  * secondary opcode for such VSX instructions.
   16268  *
   16269 */
   16270 
   16271 
   16272 struct vsx_insn {
   16273    UInt opcode;
   16274    Char * name;
   16275 };
   16276 
   16277 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   16278 static struct vsx_insn vsx_all[] = {
   16279       { 0x8, "xxsldwi" },
   16280       { 0x18, "xxsel" },
   16281       { 0x28, "xxpermdi" },
   16282       { 0x48, "xxmrghw" },
   16283       { 0x80, "xsadddp" },
   16284       { 0x84, "xsmaddadp" },
   16285       { 0x8c, "xscmpudp" },
   16286       { 0x90, "xscvdpuxws" },
   16287       { 0x92, "xsrdpi" },
   16288       { 0x94, "xsrsqrtedp" },
   16289       { 0x96, "xssqrtdp" },
   16290       { 0xa0, "xssubdp" },
   16291       { 0xa4, "xsmaddmdp" },
   16292       { 0xac, "xscmpodp" },
   16293       { 0xb0, "xscvdpsxws" },
   16294       { 0xb2, "xsrdpiz" },
   16295       { 0xb4, "xsredp" },
   16296       { 0xc0, "xsmuldp" },
   16297       { 0xc4, "xsmsubadp" },
   16298       { 0xc8, "xxmrglw" },
   16299       { 0xd2, "xsrdpip" },
   16300       { 0xd4, "xstsqrtdp" },
   16301       { 0xd6, "xsrdpic" },
   16302       { 0xe0, "xsdivdp" },
   16303       { 0xe4, "xsmsubmdp" },
   16304       { 0xf2, "xsrdpim" },
   16305       { 0xf4, "xstdivdp" },
   16306       { 0x100, "xvaddsp" },
   16307       { 0x104, "xvmaddasp" },
   16308       { 0x10c, "xvcmpeqsp" },
   16309       { 0x110, "xvcvspuxws" },
   16310       { 0x112, "xvrspi" },
   16311       { 0x114, "xvrsqrtesp" },
   16312       { 0x116, "xvsqrtsp" },
   16313       { 0x120, "xvsubsp" },
   16314       { 0x124, "xvmaddmsp" },
   16315       { 0x12c, "xvcmpgtsp" },
   16316       { 0x130, "xvcvspsxws" },
   16317       { 0x132, "xvrspiz" },
   16318       { 0x134, "xvresp" },
   16319       { 0x140, "xvmulsp" },
   16320       { 0x144, "xvmsubasp" },
   16321       { 0x148, "xxspltw" },
   16322       { 0x14c, "xvcmpgesp" },
   16323       { 0x150, "xvcvuxwsp" },
   16324       { 0x152, "xvrspip" },
   16325       { 0x154, "xvtsqrtsp" },
   16326       { 0x156, "xvrspic" },
   16327       { 0x160, "xvdivsp" },
   16328       { 0x164, "xvmsubmsp" },
   16329       { 0x170, "xvcvsxwsp" },
   16330       { 0x172, "xvrspim" },
   16331       { 0x174, "xvtdivsp" },
   16332       { 0x180, "xvadddp" },
   16333       { 0x184, "xvmaddadp" },
   16334       { 0x18c, "xvcmpeqdp" },
   16335       { 0x190, "xvcvdpuxws" },
   16336       { 0x192, "xvrdpi" },
   16337       { 0x194, "xvrsqrtedp" },
   16338       { 0x196, "xvsqrtdp" },
   16339       { 0x1a0, "xvsubdp" },
   16340       { 0x1a4, "xvmaddmdp" },
   16341       { 0x1ac, "xvcmpgtdp" },
   16342       { 0x1b0, "xvcvdpsxws" },
   16343       { 0x1b2, "xvrdpiz" },
   16344       { 0x1b4, "xvredp" },
   16345       { 0x1c0, "xvmuldp" },
   16346       { 0x1c4, "xvmsubadp" },
   16347       { 0x1cc, "xvcmpgedp" },
   16348       { 0x1d0, "xvcvuxwdp" },
   16349       { 0x1d2, "xvrdpip" },
   16350       { 0x1d4, "xvtsqrtdp" },
   16351       { 0x1d6, "xvrdpic" },
   16352       { 0x1e0, "xvdivdp" },
   16353       { 0x1e4, "xvmsubmdp" },
   16354       { 0x1f0, "xvcvsxwdp" },
   16355       { 0x1f2, "xvrdpim" },
   16356       { 0x1f4, "xvtdivdp" },
   16357       { 0x208, "xxland" },
   16358       { 0x212, "xscvdpsp" },
   16359       { 0x228, "xxlandc" },
   16360       { 0x248 , "xxlor" },
   16361       { 0x268, "xxlxor" },
   16362       { 0x280, "xsmaxdp" },
   16363       { 0x284, "xsnmaddadp" },
   16364       { 0x288, "xxlnor" },
   16365       { 0x290, "xscvdpuxds" },
   16366       { 0x292, "xscvspdp" },
   16367       { 0x2a0, "xsmindp" },
   16368       { 0x2a4, "xsnmaddmdp" },
   16369       { 0x2b0, "xscvdpsxds" },
   16370       { 0x2b2, "xsabsdp" },
   16371       { 0x2c0, "xscpsgndp" },
   16372       { 0x2c4, "xsnmsubadp" },
   16373       { 0x2d0, "xscvuxddp" },
   16374       { 0x2d2, "xsnabsdp" },
   16375       { 0x2e4, "xsnmsubmdp" },
   16376       { 0x2f0, "xscvsxddp" },
   16377       { 0x2f2, "xsnegdp" },
   16378       { 0x300, "xvmaxsp" },
   16379       { 0x304, "xvnmaddasp" },
   16380       { 0x30c, "xvcmpeqsp." },
   16381       { 0x310, "xvcvspuxds" },
   16382       { 0x312, "xvcvdpsp" },
   16383       { 0x320, "xvminsp" },
   16384       { 0x324, "xvnmaddmsp" },
   16385       { 0x32c, "xvcmpgtsp." },
   16386       { 0x330, "xvcvspsxds" },
   16387       { 0x332, "xvabssp" },
   16388       { 0x340, "xvcpsgnsp" },
   16389       { 0x344, "xvnmsubasp" },
   16390       { 0x34c, "xvcmpgesp." },
   16391       { 0x350, "xvcvuxdsp" },
   16392       { 0x352, "xvnabssp" },
   16393       { 0x364, "xvnmsubmsp" },
   16394       { 0x370, "xvcvsxdsp" },
   16395       { 0x372, "xvnegsp" },
   16396       { 0x380, "xvmaxdp" },
   16397       { 0x384, "xvnmaddadp" },
   16398       { 0x38c, "xvcmpeqdp." },
   16399       { 0x390, "xvcvdpuxds" },
   16400       { 0x392, "xvcvspdp" },
   16401       { 0x3a0, "xvmindp" },
   16402       { 0x3a4, "xvnmaddmdp" },
   16403       { 0x3ac, "xvcmpgtdp." },
   16404       { 0x3b0, "xvcvdpsxds" },
   16405       { 0x3b2, "xvabsdp" },
   16406       { 0x3c0, "xvcpsgndp" },
   16407       { 0x3c4, "xvnmsubadp" },
   16408       { 0x3cc, "xvcmpgedp." },
   16409       { 0x3d0, "xvcvuxddp" },
   16410       { 0x3d2, "xvnabsdp" },
   16411       { 0x3e4, "xvnmsubmdp" },
   16412       { 0x3f0, "xvcvsxddp" },
   16413       { 0x3f2, "xvnegdp" }
   16414 };
   16415 #define VSX_ALL_LEN 135
   16416 
   16417 // ATTENTION: This search function assumes vsx_all array is sorted.
   16418 static Int findVSXextOpCode(UInt opcode)
   16419 {
   16420    Int low, mid, high;
   16421    low = 0;
   16422    high = VSX_ALL_LEN - 1;
   16423    while (low <= high) {
   16424       mid = (low + high)/2;
   16425       if (opcode < vsx_all[mid].opcode)
   16426          high = mid - 1;
   16427       else if (opcode > vsx_all[mid].opcode)
   16428          low = mid + 1;
   16429       else
   16430          return mid;
   16431    }
   16432    return -1;
   16433 }
   16434 
   16435 
   16436 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   16437  * passed, and we then try to match it up with one of the VSX forms
   16438  * below.
   16439  */
   16440 static UInt get_VSX60_opc2(UInt opc2_full)
   16441 {
   16442 #define XX2_MASK 0x000003FE
   16443 #define XX3_1_MASK 0x000003FC
   16444 #define XX3_2_MASK 0x000001FC
   16445 #define XX3_3_MASK 0x0000007C
   16446 #define XX4_MASK 0x00000018
   16447    Int ret;
   16448    UInt vsxExtOpcode = 0;
   16449 
   16450    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
   16451       vsxExtOpcode = vsx_all[ret].opcode;
   16452    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
   16453       vsxExtOpcode = vsx_all[ret].opcode;
   16454    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
   16455       vsxExtOpcode = vsx_all[ret].opcode;
   16456    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
   16457       vsxExtOpcode = vsx_all[ret].opcode;
   16458    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
   16459       vsxExtOpcode = vsx_all[ret].opcode;
   16460 
   16461    return vsxExtOpcode;
   16462 }
   16463 
   16464 /*------------------------------------------------------------*/
   16465 /*--- Disassemble a single instruction                     ---*/
   16466 /*------------------------------------------------------------*/
   16467 
   16468 /* Disassemble a single instruction into IR.  The instruction
   16469    is located in host memory at &guest_code[delta]. */
   16470 
   16471 static
   16472 DisResult disInstr_PPC_WRK (
   16473              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   16474              Bool         resteerCisOk,
   16475              void*        callback_opaque,
   16476              Long         delta64,
   16477              VexArchInfo* archinfo,
   16478              VexAbiInfo*  abiinfo
   16479           )
   16480 {
   16481    UChar     opc1;
   16482    UInt      opc2;
   16483    DisResult dres;
   16484    UInt      theInstr;
   16485    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   16486    Bool      allow_F  = False;
   16487    Bool      allow_V  = False;
   16488    Bool      allow_FX = False;
   16489    Bool      allow_GX = False;
   16490    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   16491    Bool      allow_DFP = False;
   16492    UInt      hwcaps = archinfo->hwcaps;
   16493    Long      delta;
   16494 
   16495    /* What insn variants are we supporting today? */
   16496    if (mode64) {
   16497       allow_F  = True;
   16498       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   16499       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   16500       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   16501       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   16502       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
   16503    } else {
   16504       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   16505       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   16506       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   16507       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   16508       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   16509       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
   16510    }
   16511 
   16512    /* The running delta */
   16513    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   16514 
   16515    /* Set result defaults. */
   16516    dres.whatNext    = Dis_Continue;
   16517    dres.len         = 0;
   16518    dres.continueAt  = 0;
   16519    dres.jk_StopHere = Ijk_INVALID;
   16520 
   16521    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   16522       4-aligned.  So just fish the whole thing out of memory right now
   16523       and have done. */
   16524    theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
   16525 
   16526    if (0) vex_printf("insn: 0x%x\n", theInstr);
   16527 
   16528    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   16529 
   16530    /* Spot "Special" instructions (see comment at top of file). */
   16531    {
   16532       UChar* code = (UChar*)(guest_code + delta);
   16533       /* Spot the 16-byte preamble:
   16534          32-bit mode:
   16535             54001800  rlwinm 0,0,3,0,0
   16536             54006800  rlwinm 0,0,13,0,0
   16537             5400E800  rlwinm 0,0,29,0,0
   16538             54009800  rlwinm 0,0,19,0,0
   16539          64-bit mode:
   16540             78001800  rotldi 0,0,3
   16541             78006800  rotldi 0,0,13
   16542             7800E802  rotldi 0,0,61
   16543             78009802  rotldi 0,0,51
   16544       */
   16545       UInt word1 = mode64 ? 0x78001800 : 0x54001800;
   16546       UInt word2 = mode64 ? 0x78006800 : 0x54006800;
   16547       UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
   16548       UInt word4 = mode64 ? 0x78009802 : 0x54009800;
   16549       if (getUIntBigendianly(code+ 0) == word1 &&
   16550           getUIntBigendianly(code+ 4) == word2 &&
   16551           getUIntBigendianly(code+ 8) == word3 &&
   16552           getUIntBigendianly(code+12) == word4) {
   16553          /* Got a "Special" instruction preamble.  Which one is it? */
   16554          if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   16555             /* %R3 = client_request ( %R4 ) */
   16556             DIP("r3 = client_request ( %%r4 )\n");
   16557             delta += 20;
   16558             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   16559             dres.jk_StopHere = Ijk_ClientReq;
   16560             dres.whatNext    = Dis_StopHere;
   16561             goto decode_success;
   16562          }
   16563          else
   16564          if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   16565             /* %R3 = guest_NRADDR */
   16566             DIP("r3 = guest_NRADDR\n");
   16567             delta += 20;
   16568             dres.len = 20;
   16569             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   16570             goto decode_success;
   16571          }
   16572          else
   16573          if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   16574             /*  branch-and-link-to-noredir %R11 */
   16575             DIP("branch-and-link-to-noredir r11\n");
   16576             delta += 20;
   16577             putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   16578             putGST( PPC_GST_CIA, getIReg(11));
   16579             dres.jk_StopHere = Ijk_NoRedir;
   16580             dres.whatNext    = Dis_StopHere;
   16581             goto decode_success;
   16582          }
   16583          else
   16584          if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   16585             /* %R3 = guest_NRADDR_GPR2 */
   16586             DIP("r3 = guest_NRADDR_GPR2\n");
   16587             delta += 20;
   16588             dres.len = 20;
   16589             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   16590             goto decode_success;
   16591          }
   16592          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   16593             can print the insn following the Special-insn preamble. */
   16594          theInstr = getUIntBigendianly(code+16);
   16595          opc1     = ifieldOPC(theInstr);
   16596          opc2     = ifieldOPClo10(theInstr);
   16597          goto decode_failure;
   16598          /*NOTREACHED*/
   16599       }
   16600    }
   16601 
   16602    opc1 = ifieldOPC(theInstr);
   16603    opc2 = ifieldOPClo10(theInstr);
   16604 
   16605    // Note: all 'reserved' bits must be cleared, else invalid
   16606    switch (opc1) {
   16607 
   16608    /* Integer Arithmetic Instructions */
   16609    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   16610    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   16611       if (dis_int_arith( theInstr )) goto decode_success;
   16612       goto decode_failure;
   16613 
   16614    /* Integer Compare Instructions */
   16615    case 0x0B: case 0x0A: // cmpi, cmpli
   16616       if (dis_int_cmp( theInstr )) goto decode_success;
   16617       goto decode_failure;
   16618 
   16619    /* Integer Logical Instructions */
   16620    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   16621    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   16622       if (dis_int_logic( theInstr )) goto decode_success;
   16623       goto decode_failure;
   16624 
   16625    /* Integer Rotate Instructions */
   16626    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   16627       if (dis_int_rot( theInstr )) goto decode_success;
   16628       goto decode_failure;
   16629 
   16630    /* 64bit Integer Rotate Instructions */
   16631    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   16632       if (dis_int_rot( theInstr )) goto decode_success;
   16633       goto decode_failure;
   16634 
   16635    /* Integer Load Instructions */
   16636    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   16637    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   16638    case 0x20: case 0x21:            // lwz,  lwzu
   16639       if (dis_int_load( theInstr )) goto decode_success;
   16640       goto decode_failure;
   16641 
   16642    /* Integer Store Instructions */
   16643    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   16644    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   16645       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   16646       goto decode_failure;
   16647 
   16648    /* Integer Load and Store Multiple Instructions */
   16649    case 0x2E: case 0x2F: // lmw, stmw
   16650       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   16651       goto decode_failure;
   16652 
   16653    /* Branch Instructions */
   16654    case 0x12: case 0x10: // b, bc
   16655       if (dis_branch(theInstr, abiinfo, &dres,
   16656                                resteerOkFn, callback_opaque))
   16657          goto decode_success;
   16658       goto decode_failure;
   16659 
   16660    /* System Linkage Instructions */
   16661    case 0x11: // sc
   16662       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   16663       goto decode_failure;
   16664 
   16665    /* Trap Instructions */
   16666    case 0x02: case 0x03: // tdi, twi
   16667       if (dis_trapi(theInstr, &dres)) goto decode_success;
   16668       goto decode_failure;
   16669 
   16670    /* Floating Point Load Instructions */
   16671    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   16672    case 0x33:                       // lfdu
   16673       if (!allow_F) goto decode_noF;
   16674       if (dis_fp_load( theInstr )) goto decode_success;
   16675       goto decode_failure;
   16676 
   16677    /* Floating Point Store Instructions */
   16678    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   16679    case 0x37:                       // stfdux
   16680       if (!allow_F) goto decode_noF;
   16681       if (dis_fp_store( theInstr )) goto decode_success;
   16682       goto decode_failure;
   16683 
   16684       /* Floating Point Load Double Pair Instructions */
   16685    case 0x39: case 0x3D:
   16686       if (!allow_F) goto decode_noF;
   16687       if (dis_fp_pair( theInstr )) goto decode_success;
   16688       goto decode_failure;
   16689 
   16690    /* 64bit Integer Loads */
   16691    case 0x3A:  // ld, ldu, lwa
   16692       if (!mode64) goto decode_failure;
   16693       if (dis_int_load( theInstr )) goto decode_success;
   16694       goto decode_failure;
   16695 
   16696    case 0x3B:
   16697       if (!allow_F) goto decode_noF;
   16698       opc2 = ifieldOPClo10(theInstr);
   16699 
   16700       switch (opc2) {
   16701          case 0x2:    // dadd - DFP Add
   16702          case 0x202:  // dsub - DFP Subtract
   16703          case 0x22:   // dmul - DFP Mult
   16704          case 0x222:  // ddiv - DFP Divide
   16705             if (!allow_DFP) goto decode_noDFP;
   16706             if (dis_dfp_arith( theInstr ))
   16707                goto decode_success;
   16708          case 0x82:   // dcmpo, DFP comparison ordered instruction
   16709          case 0x282:  // dcmpu, DFP comparison unordered instruction
   16710             if (!allow_DFP)
   16711                goto decode_failure;
   16712             if (dis_dfp_compare( theInstr ) )
   16713                goto decode_success;
   16714             goto decode_failure;
   16715          case 0x102: // dctdp  - DFP convert to DFP long
   16716          case 0x302: // drsp   - DFP round to dfp short
   16717          case 0x122: // dctfix - DFP convert to fixed
   16718             if (!allow_DFP)
   16719                goto decode_failure;
   16720             if (dis_dfp_fmt_conv( theInstr ))
   16721                goto decode_success;
   16722             goto decode_failure;
   16723          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
   16724             if (!allow_VX)
   16725                goto decode_failure;
   16726             if (dis_dfp_fmt_conv( theInstr ))
   16727                goto decode_success;
   16728             goto decode_failure;
   16729          case 0x2A2: // dtstsf - DFP number of significant digits
   16730             if (!allow_DFP)
   16731                goto decode_failure;
   16732             if (dis_dfp_significant_digits(theInstr))
   16733                goto decode_success;
   16734             goto decode_failure;
   16735          case 0x142: // ddedpd   DFP Decode DPD to BCD
   16736          case 0x342: // denbcd   DFP Encode BCD to DPD
   16737             if (!allow_DFP)
   16738                goto decode_failure;
   16739             if (dis_dfp_bcd(theInstr))
   16740                goto decode_success;
   16741             goto decode_failure;
   16742          case 0x162:  // dxex - Extract exponent
   16743          case 0x362:  // diex - Insert exponent
   16744             if (!allow_DFP)
   16745                goto decode_failure;
   16746             if (dis_dfp_extract_insert( theInstr ) )
   16747                goto decode_success;
   16748             goto decode_failure;
   16749          case 0x3CE: // fcfidus (implemented as native insn)
   16750             if (!allow_VX)
   16751                goto decode_noVX;
   16752             if (dis_fp_round( theInstr ))
   16753                goto decode_success;
   16754             goto decode_failure;
   16755          case 0x34E: // fcfids
   16756             if (dis_fp_round( theInstr ))
   16757                goto decode_success;
   16758             goto decode_failure;
   16759       }
   16760 
   16761       opc2 = ifieldOPClo9( theInstr );
   16762       switch (opc2) {
   16763       case 0x42: // dscli, DFP shift left
   16764       case 0x62: // dscri, DFP shift right
   16765          if (!allow_DFP)
   16766             goto decode_failure;
   16767          if (dis_dfp_shift( theInstr ))
   16768             goto decode_success;
   16769          goto decode_failure;
   16770       case 0xc2:  // dtstdc, DFP test data class
   16771       case 0xe2:  // dtstdg, DFP test data group
   16772          if (!allow_DFP)
   16773             goto decode_failure;
   16774          if (dis_dfp_class_test( theInstr ))
   16775             goto decode_success;
   16776          goto decode_failure;
   16777       }
   16778 
   16779       opc2 = ifieldOPClo8( theInstr );
   16780       switch (opc2) {
   16781       case 0x3:   // dqua  - DFP Quantize
   16782       case 0x23:  // drrnd - DFP Reround
   16783       case 0x43:  // dquai - DFP Quantize immediate
   16784          if (!allow_DFP)
   16785             goto decode_failure;
   16786          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
   16787             goto decode_success;
   16788          goto decode_failure;
   16789       case 0xA2: // dtstex - DFP Test exponent
   16790          if (!allow_DFP)
   16791             goto decode_failure;
   16792          if (dis_dfp_exponent_test( theInstr ) )
   16793             goto decode_success;
   16794          goto decode_failure;
   16795       case 0x63: // drintx - Round to an integer value
   16796       case 0xE3: // drintn - Round to an integer value
   16797          if (!allow_DFP)
   16798             goto decode_failure;
   16799          if (dis_dfp_round( theInstr ) ) {
   16800             goto decode_success;
   16801          }
   16802          goto decode_failure;
   16803       default:
   16804          break;  /* fall through to next opc2 check */
   16805       }
   16806 
   16807       opc2 = IFIELD(theInstr, 1, 5);
   16808       switch (opc2) {
   16809       /* Floating Point Arith Instructions */
   16810       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   16811       case 0x19:                       // fmuls
   16812          if (dis_fp_arith(theInstr)) goto decode_success;
   16813          goto decode_failure;
   16814       case 0x16:                       // fsqrts
   16815          if (!allow_FX) goto decode_noFX;
   16816          if (dis_fp_arith(theInstr)) goto decode_success;
   16817          goto decode_failure;
   16818       case 0x18:                       // fres
   16819          if (!allow_GX) goto decode_noGX;
   16820          if (dis_fp_arith(theInstr)) goto decode_success;
   16821          goto decode_failure;
   16822 
   16823       /* Floating Point Mult-Add Instructions */
   16824       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   16825       case 0x1F:                       // fnmadds
   16826          if (dis_fp_multadd(theInstr)) goto decode_success;
   16827          goto decode_failure;
   16828 
   16829       case 0x1A:                       // frsqrtes
   16830          if (!allow_GX) goto decode_noGX;
   16831          if (dis_fp_arith(theInstr)) goto decode_success;
   16832          goto decode_failure;
   16833 
   16834       default:
   16835          goto decode_failure;
   16836       }
   16837       break;
   16838 
   16839    case 0x3C: // VSX instructions (except load/store)
   16840    {
   16841       // All of these VSX instructions use some VMX facilities, so
   16842       // if allow_V is not set, we'll skip trying to decode.
   16843       if (!allow_V) goto decode_noVX;
   16844 
   16845       UInt vsxOpc2 = get_VSX60_opc2(opc2);
   16846       /* The vsxOpc2 returned is the "normalized" value, representing the
   16847        * instructions secondary opcode as taken from the standard secondary
   16848        * opcode field [21:30] (IBM notatition), even if the actual field
   16849        * is non-standard.  These normalized values are given in the opcode
   16850        * appendices of the ISA 2.06 document.
   16851        */
   16852       if (vsxOpc2 == 0)
   16853          goto decode_failure;
   16854 
   16855       switch (vsxOpc2) {
   16856          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   16857          case 0x018: case 0x148: // xxsel, xxspltw
   16858             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   16859             goto decode_failure;
   16860          case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
   16861             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   16862             goto decode_failure;
   16863          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   16864          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   16865          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   16866          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   16867          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   16868          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   16869          case 0x092: // xsrdpi
   16870             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
   16871             goto decode_failure;
   16872          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   16873             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   16874             goto decode_failure;
   16875          case 0x080: case 0x0E0: // xsadddp, xsdivdp
   16876          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   16877          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   16878          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   16879          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   16880          case 0x0C0: case 0x0A0: // xsmuldp, xssubdp
   16881          case 0x096: case 0x0F4: // xssqrtdp, xstdivdp
   16882          case 0x0D4: // xstsqrtdp
   16883             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   16884             goto decode_failure;
   16885          case 0x180: // xvadddp
   16886          case 0x1E0: // xvdivdp
   16887          case 0x1C0: // xvmuldp
   16888          case 0x1A0: // xvsubdp
   16889          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   16890          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   16891          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   16892          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   16893          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   16894          case 0x196: // xvsqrtdp
   16895             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   16896             goto decode_failure;
   16897          case 0x100: // xvaddsp
   16898          case 0x160: // xvdivsp
   16899          case 0x140: // xvmulsp
   16900          case 0x120: // xvsubsp
   16901          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   16902          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   16903          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   16904          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   16905          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   16906          case 0x116: // xvsqrtsp
   16907             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   16908             goto decode_failure;
   16909 
   16910          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
   16911          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
   16912          case 0x090: // xscvdpuxws
   16913             // The above VSX conversion instructions employ some ISA 2.06
   16914             // floating point conversion instructions under the covers,
   16915             // so if allow_VX (which means "supports ISA 2.06") is not set,
   16916             // we'll skip the decode.
   16917             if (!allow_VX) goto decode_noVX;
   16918             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   16919             goto decode_failure;
   16920 
   16921          case 0x2B0: case 0x2F0: // xscvdpsxds, xscvsxddp
   16922          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   16923          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   16924          case 0x212: // xscvdpsp
   16925          case 0x292: case 0x312: // xscvspdp, xvcvdpsp
   16926          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   16927          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   16928          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   16929          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   16930          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   16931          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   16932             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   16933             goto decode_failure;
   16934 
   16935          case 0x18C: case 0x38C: // xvcmpeqdp[.]
   16936          case 0x10C: case 0x30C: // xvcmpeqsp[.]
   16937          case 0x14C: case 0x34C: // xvcmpgesp[.]
   16938          case 0x12C: case 0x32C: // xvcmpgtsp[.]
   16939          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
   16940          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
   16941              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   16942              goto decode_failure;
   16943 
   16944          case 0x134:  // xvresp
   16945          case 0x1B4:  // xvredp
   16946          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   16947          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   16948          case 0x300: case 0x320: // xvmaxsp, xvminsp
   16949          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   16950          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   16951          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   16952          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   16953          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   16954          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   16955          case 0x112: case 0x156: // xvrspi, xvrspic
   16956          case 0x172: case 0x152: // xvrspim, xvrspip
   16957          case 0x132: // xvrspiz
   16958             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   16959             goto decode_failure;
   16960 
   16961          default:
   16962             goto decode_failure;
   16963       }
   16964       break;
   16965    }
   16966 
   16967    /* 64bit Integer Stores */
   16968    case 0x3E:  // std, stdu
   16969       if (!mode64) goto decode_failure;
   16970       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   16971       goto decode_failure;
   16972 
   16973    case 0x3F:
   16974       if (!allow_F) goto decode_noF;
   16975       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   16976          so we can simply fall through the first switch statement */
   16977 
   16978       opc2 = IFIELD(theInstr, 1, 5);
   16979       switch (opc2) {
   16980       /* Floating Point Arith Instructions */
   16981       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   16982       case 0x19:                       // fmul
   16983          if (dis_fp_arith(theInstr)) goto decode_success;
   16984          goto decode_failure;
   16985       case 0x16:                       // fsqrt
   16986          if (!allow_FX) goto decode_noFX;
   16987          if (dis_fp_arith(theInstr)) goto decode_success;
   16988          goto decode_failure;
   16989       case 0x17: case 0x1A:            // fsel, frsqrte
   16990          if (!allow_GX) goto decode_noGX;
   16991          if (dis_fp_arith(theInstr)) goto decode_success;
   16992          goto decode_failure;
   16993 
   16994       /* Floating Point Mult-Add Instructions */
   16995       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   16996       case 0x1F:                       // fnmadd
   16997          if (dis_fp_multadd(theInstr)) goto decode_success;
   16998          goto decode_failure;
   16999 
   17000       case 0x18:                       // fre
   17001          if (!allow_GX) goto decode_noGX;
   17002          if (dis_fp_arith(theInstr)) goto decode_success;
   17003          goto decode_failure;
   17004 
   17005       default:
   17006          break; // Fall through
   17007       }
   17008 
   17009       opc2 = IFIELD(theInstr, 1, 10);
   17010       switch (opc2) {
   17011       /* 128-bit DFP instructions */
   17012       case 0x2:    // daddq - DFP Add
   17013       case 0x202:  // dsubq - DFP Subtract
   17014       case 0x22:   // dmulq - DFP Mult
   17015       case 0x222:  // ddivq - DFP Divide
   17016          if (!allow_DFP) goto decode_noDFP;
   17017          if (dis_dfp_arithq( theInstr ))
   17018             goto decode_success;
   17019          goto decode_failure;
   17020       case 0x162:  // dxexq - DFP Extract exponent
   17021       case 0x362:  // diexq - DFP Insert exponent
   17022          if (!allow_DFP)
   17023             goto decode_failure;
   17024          if (dis_dfp_extract_insertq( theInstr ))
   17025             goto decode_success;
   17026          goto decode_failure;
   17027 
   17028       case 0x82:   // dcmpoq, DFP comparison ordered instruction
   17029       case 0x282:  // dcmpuq, DFP comparison unordered instruction
   17030          if (!allow_DFP)
   17031             goto decode_failure;
   17032          if (dis_dfp_compare( theInstr ) )
   17033             goto decode_success;
   17034          goto decode_failure;
   17035 
   17036       case 0x102: // dctqpq  - DFP convert to DFP extended
   17037       case 0x302: // drdpq   - DFP round to dfp Long
   17038       case 0x122: // dctfixq - DFP convert to fixed quad
   17039       case 0x322: // dcffixq - DFP convert from fixed quad
   17040          if (!allow_DFP)
   17041             goto decode_failure;
   17042          if (dis_dfp_fmt_convq( theInstr ))
   17043             goto decode_success;
   17044          goto decode_failure;
   17045 
   17046       case 0x2A2: // dtstsfq - DFP number of significant digits
   17047          if (!allow_DFP)
   17048             goto decode_failure;
   17049          if (dis_dfp_significant_digits(theInstr))
   17050             goto decode_success;
   17051          goto decode_failure;
   17052 
   17053       case 0x142: // ddedpdq   DFP Decode DPD to BCD
   17054       case 0x342: // denbcdq   DFP Encode BCD to DPD
   17055          if (!allow_DFP)
   17056             goto decode_failure;
   17057          if (dis_dfp_bcdq(theInstr))
   17058             goto decode_success;
   17059          goto decode_failure;
   17060 
   17061       /* Floating Point Compare Instructions */
   17062       case 0x000: // fcmpu
   17063       case 0x020: // fcmpo
   17064          if (dis_fp_cmp(theInstr)) goto decode_success;
   17065          goto decode_failure;
   17066 
   17067       case 0x080: // ftdiv
   17068       case 0x0A0: // ftsqrt
   17069          if (dis_fp_tests(theInstr)) goto decode_success;
   17070          goto decode_failure;
   17071 
   17072       /* Floating Point Rounding/Conversion Instructions */
   17073       case 0x00C: // frsp
   17074       case 0x00E: // fctiw
   17075       case 0x00F: // fctiwz
   17076       case 0x32E: // fctid
   17077       case 0x32F: // fctidz
   17078       case 0x34E: // fcfid
   17079          if (dis_fp_round(theInstr)) goto decode_success;
   17080          goto decode_failure;
   17081       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   17082       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   17083          if (!allow_VX) goto decode_noVX;
   17084          if (dis_fp_round(theInstr)) goto decode_success;
   17085          goto decode_failure;
   17086 
   17087       /* Power6 rounding stuff */
   17088       case 0x1E8: // frim
   17089       case 0x1C8: // frip
   17090       case 0x188: // frin
   17091       case 0x1A8: // friz
   17092          /* A hack to check for P6 capability . . . */
   17093          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   17094              (dis_fp_round(theInstr)))
   17095             goto decode_success;
   17096          goto decode_failure;
   17097 
   17098       /* Floating Point Move Instructions */
   17099       case 0x008: // fcpsgn
   17100       case 0x028: // fneg
   17101       case 0x048: // fmr
   17102       case 0x088: // fnabs
   17103       case 0x108: // fabs
   17104          if (dis_fp_move( theInstr )) goto decode_success;
   17105          goto decode_failure;
   17106 
   17107       /* Floating Point Status/Control Register Instructions */
   17108       case 0x026: // mtfsb1
   17109       case 0x040: // mcrfs
   17110       case 0x046: // mtfsb0
   17111       case 0x086: // mtfsfi
   17112       case 0x247: // mffs
   17113       case 0x2C7: // mtfsf
   17114          // Some of the above instructions need to know more about the
   17115          // ISA level supported by the host.
   17116          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
   17117          goto decode_failure;
   17118 
   17119       default:
   17120          break; // Fall through...
   17121       }
   17122 
   17123       opc2 = ifieldOPClo9( theInstr );
   17124       switch (opc2) {
   17125       case 0x42: // dscli, DFP shift left
   17126       case 0x62: // dscri, DFP shift right
   17127          if (!allow_DFP)
   17128             goto decode_failure;
   17129          if (dis_dfp_shiftq( theInstr ))
   17130             goto decode_success;
   17131          goto decode_failure;
   17132       case 0xc2:  // dtstdc, DFP test data class
   17133       case 0xe2:  // dtstdg, DFP test data group
   17134          if (!allow_DFP)
   17135             goto decode_failure;
   17136          if (dis_dfp_class_test( theInstr ))
   17137             goto decode_success;
   17138          goto decode_failure;
   17139       default:
   17140          break;
   17141       }
   17142 
   17143       opc2 = ifieldOPClo8( theInstr );
   17144       switch (opc2) {
   17145       case 0x3:   // dquaq  - DFP Quantize Quad
   17146       case 0x23:  // drrndq - DFP Reround Quad
   17147       case 0x43:  // dquaiq - DFP Quantize immediate Quad
   17148          if (!allow_DFP)
   17149             goto decode_failure;
   17150          if (dis_dfp_quantize_sig_rrndq( theInstr ))
   17151             goto decode_success;
   17152          goto decode_failure;
   17153       case 0xA2: // dtstexq - DFP Test exponent Quad
   17154          if (dis_dfp_exponent_test( theInstr ) )
   17155             goto decode_success;
   17156          goto decode_failure;
   17157       case 0x63:  // drintxq - DFP Round to an integer value
   17158       case 0xE3:  // drintnq - DFP Round to an integer value
   17159          if (!allow_DFP)
   17160             goto decode_failure;
   17161          if (dis_dfp_roundq( theInstr ))
   17162             goto decode_success;
   17163          goto decode_failure;
   17164 
   17165       default:
   17166          goto decode_failure;
   17167       }
   17168       break;
   17169 
   17170    case 0x13:
   17171       switch (opc2) {
   17172 
   17173       /* Condition Register Logical Instructions */
   17174       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   17175       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   17176       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   17177          if (dis_cond_logic( theInstr )) goto decode_success;
   17178          goto decode_failure;
   17179 
   17180       /* Branch Instructions */
   17181       case 0x210: case 0x010: // bcctr, bclr
   17182          if (dis_branch(theInstr, abiinfo, &dres,
   17183                                   resteerOkFn, callback_opaque))
   17184             goto decode_success;
   17185          goto decode_failure;
   17186 
   17187       /* Memory Synchronization Instructions */
   17188       case 0x096: // isync
   17189          if (dis_memsync( theInstr )) goto decode_success;
   17190          goto decode_failure;
   17191 
   17192       default:
   17193          goto decode_failure;
   17194       }
   17195       break;
   17196 
   17197 
   17198    case 0x1F:
   17199 
   17200       /* For arith instns, bit10 is the OE flag (overflow enable) */
   17201 
   17202       opc2 = IFIELD(theInstr, 1, 9);
   17203       switch (opc2) {
   17204       /* Integer Arithmetic Instructions */
   17205       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   17206       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   17207       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   17208       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   17209       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   17210       case 0x0C8: // subfze
   17211          if (dis_int_arith( theInstr )) goto decode_success;
   17212          goto decode_failure;
   17213 
   17214       case 0x18B: // divweu (implemented as native insn)
   17215       case 0x1AB: // divwe (implemented as native insn)
   17216          if (!allow_VX) goto decode_noVX;
   17217          if (dis_int_arith( theInstr )) goto decode_success;
   17218          goto decode_failure;
   17219 
   17220       /* 64bit Integer Arithmetic */
   17221       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   17222       case 0x1C9: case 0x1E9: // divdu, divd
   17223          if (!mode64) goto decode_failure;
   17224          if (dis_int_arith( theInstr )) goto decode_success;
   17225          goto decode_failure;
   17226 
   17227       case 0x1A9: //  divde (implemented as native insn)
   17228       case 0x189: //  divdeuo (implemented as native insn)
   17229          if (!allow_VX) goto decode_noVX;
   17230          if (!mode64) goto decode_failure;
   17231          if (dis_int_arith( theInstr )) goto decode_success;
   17232          goto decode_failure;
   17233 
   17234       case 0x1FC:                         // cmpb
   17235          if (dis_int_logic( theInstr )) goto decode_success;
   17236          goto decode_failure;
   17237 
   17238       default:
   17239          break;  // Fall through...
   17240       }
   17241 
   17242       /* All remaining opcodes use full 10 bits. */
   17243 
   17244       opc2 = IFIELD(theInstr, 1, 10);
   17245       switch (opc2) {
   17246       /* Integer Compare Instructions  */
   17247       case 0x000: case 0x020: // cmp, cmpl
   17248          if (dis_int_cmp( theInstr )) goto decode_success;
   17249          goto decode_failure;
   17250 
   17251       /* Integer Logical Instructions */
   17252       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   17253       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   17254       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   17255       case 0x19C: case 0x13C:             // orc,  xor
   17256       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   17257          if (dis_int_logic( theInstr )) goto decode_success;
   17258          goto decode_failure;
   17259 
   17260       /* 64bit Integer Logical Instructions */
   17261       case 0x3DA: case 0x03A: // extsw, cntlzd
   17262          if (!mode64) goto decode_failure;
   17263          if (dis_int_logic( theInstr )) goto decode_success;
   17264          goto decode_failure;
   17265 
   17266          /* 64bit Integer Parity Instructions */
   17267       case 0xba: case 0x9a: // prtyd, prtyw
   17268          if (dis_int_parity( theInstr )) goto decode_success;
   17269          goto decode_failure;
   17270 
   17271       /* Integer Shift Instructions */
   17272       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   17273       case 0x218:                         // srw
   17274          if (dis_int_shift( theInstr )) goto decode_success;
   17275          goto decode_failure;
   17276 
   17277       /* 64bit Integer Shift Instructions */
   17278       case 0x01B: case 0x31A: // sld, srad
   17279       case 0x33A: case 0x33B: // sradi
   17280       case 0x21B:             // srd
   17281          if (!mode64) goto decode_failure;
   17282          if (dis_int_shift( theInstr )) goto decode_success;
   17283          goto decode_failure;
   17284 
   17285       /* Integer Load Instructions */
   17286       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   17287       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   17288       case 0x017: case 0x037:             // lwzx,  lwzux
   17289          if (dis_int_load( theInstr )) goto decode_success;
   17290          goto decode_failure;
   17291 
   17292       /* 64bit Integer Load Instructions */
   17293       case 0x035: case 0x015:             // ldux,  ldx
   17294       case 0x175: case 0x155:             // lwaux, lwax
   17295          if (!mode64) goto decode_failure;
   17296          if (dis_int_load( theInstr )) goto decode_success;
   17297          goto decode_failure;
   17298 
   17299       /* Integer Store Instructions */
   17300       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   17301       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   17302          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   17303          goto decode_failure;
   17304 
   17305       /* 64bit Integer Store Instructions */
   17306       case 0x0B5: case 0x095: // stdux, stdx
   17307          if (!mode64) goto decode_failure;
   17308          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   17309          goto decode_failure;
   17310 
   17311       /* Integer Load and Store with Byte Reverse Instructions */
   17312       case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
   17313       case 0x296: case 0x214:             // stwbrx, ldbrx
   17314       case 0x294:                         // stdbrx
   17315          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   17316          goto decode_failure;
   17317 
   17318       /* Integer Load and Store String Instructions */
   17319       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   17320       case 0x295: {                       // stswx
   17321          Bool stopHere = False;
   17322          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   17323          if (!ok) goto decode_failure;
   17324          if (stopHere) {
   17325             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
   17326             dres.jk_StopHere = Ijk_Boring;
   17327             dres.whatNext    = Dis_StopHere;
   17328          }
   17329          goto decode_success;
   17330       }
   17331 
   17332       /* Memory Synchronization Instructions */
   17333       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   17334       case 0x256:                         // sync
   17335          if (dis_memsync( theInstr )) goto decode_success;
   17336          goto decode_failure;
   17337 
   17338       /* 64bit Memory Synchronization Instructions */
   17339       case 0x054: case 0x0D6: // ldarx, stdcx.
   17340          if (!mode64) goto decode_failure;
   17341          if (dis_memsync( theInstr )) goto decode_success;
   17342          goto decode_failure;
   17343 
   17344       /* Processor Control Instructions */
   17345       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   17346       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   17347          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   17348          goto decode_failure;
   17349 
   17350       /* Cache Management Instructions */
   17351       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   17352       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   17353       case 0x3D6:                         // icbi
   17354          if (dis_cache_manage( theInstr, &dres, archinfo ))
   17355             goto decode_success;
   17356          goto decode_failure;
   17357 
   17358 //zz       /* External Control Instructions */
   17359 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   17360 //zz          DIP("external control op => not implemented\n");
   17361 //zz          goto decode_failure;
   17362 
   17363       /* Trap Instructions */
   17364       case 0x004: case 0x044:             // tw,   td
   17365          if (dis_trap(theInstr, &dres)) goto decode_success;
   17366          goto decode_failure;
   17367 
   17368       /* Floating Point Load Instructions */
   17369       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   17370       case 0x277:                         // lfdux
   17371          if (!allow_F) goto decode_noF;
   17372          if (dis_fp_load( theInstr )) goto decode_success;
   17373          goto decode_failure;
   17374 
   17375       /* Floating Point Store Instructions */
   17376       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   17377       case 0x2F7:                         // stfdu, stfiwx
   17378          if (!allow_F) goto decode_noF;
   17379          if (dis_fp_store( theInstr )) goto decode_success;
   17380          goto decode_failure;
   17381       case 0x3D7:                         // stfiwx
   17382          if (!allow_F) goto decode_noF;
   17383          if (!allow_GX) goto decode_noGX;
   17384          if (dis_fp_store( theInstr )) goto decode_success;
   17385          goto decode_failure;
   17386 
   17387          /* Floating Point Double Pair Indexed Instructions */
   17388       case 0x317: // lfdpx (Power6)
   17389       case 0x397: // stfdpx (Power6)
   17390          if (!allow_F) goto decode_noF;
   17391          if (dis_fp_pair(theInstr)) goto decode_success;
   17392          goto decode_failure;
   17393 
   17394       case 0x357:                         // lfiwax
   17395          if (!allow_F) goto decode_noF;
   17396          if (dis_fp_load( theInstr )) goto decode_success;
   17397          goto decode_failure;
   17398 
   17399       case 0x377:                         // lfiwzx
   17400          if (!allow_F) goto decode_noF;
   17401          if (dis_fp_load( theInstr )) goto decode_success;
   17402          goto decode_failure;
   17403 
   17404       /* AltiVec instructions */
   17405 
   17406       /* AV Cache Control - Data streams */
   17407       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   17408          if (!allow_V) goto decode_noV;
   17409          if (dis_av_datastream( theInstr )) goto decode_success;
   17410          goto decode_failure;
   17411 
   17412       /* AV Load */
   17413       case 0x006: case 0x026:             // lvsl, lvsr
   17414       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   17415       case 0x067: case 0x167:             // lvx, lvxl
   17416          if (!allow_V) goto decode_noV;
   17417          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   17418          goto decode_failure;
   17419 
   17420       /* AV Store */
   17421       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   17422       case 0x0E7: case 0x1E7:             // stvx, stvxl
   17423          if (!allow_V) goto decode_noV;
   17424          if (dis_av_store( theInstr )) goto decode_success;
   17425          goto decode_failure;
   17426 
   17427       /* VSX Load */
   17428       case 0x24C: // lxsdx
   17429       case 0x34C: // lxvd2x
   17430       case 0x14C: // lxvdsx
   17431       case 0x30C: // lxvw4x
   17432         // All of these VSX load instructions use some VMX facilities, so
   17433         // if allow_V is not set, we'll skip trying to decode.
   17434         if (!allow_V) goto decode_noV;
   17435 
   17436     	  if (dis_vx_load( theInstr )) goto decode_success;
   17437           goto decode_failure;
   17438 
   17439       /* VSX Store */
   17440       case 0x2CC: // stxsdx
   17441       case 0x3CC: // stxvd2x
   17442       case 0x38C: // stxvw4x
   17443         // All of these VSX store instructions use some VMX facilities, so
   17444         // if allow_V is not set, we'll skip trying to decode.
   17445         if (!allow_V) goto decode_noV;
   17446 
   17447     	  if (dis_vx_store( theInstr )) goto decode_success;
   17448     	  goto decode_failure;
   17449 
   17450       /* Miscellaneous ISA 2.06 instructions */
   17451       case 0x1FA: // popcntd
   17452       case 0x17A: // popcntw
   17453       case 0x7A:  // popcntb
   17454     	  if (dis_int_logic( theInstr )) goto decode_success;
   17455     	  goto decode_failure;
   17456 
   17457       case 0x0FC: // bpermd
   17458          if (dis_int_logic( theInstr )) goto decode_success;
   17459          goto decode_failure;
   17460 
   17461       default:
   17462          /* Deal with some other cases that we would otherwise have
   17463             punted on. */
   17464          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   17465          /* only decode this insn when reserved bit 0 (31 in IBM's
   17466             notation) is zero */
   17467          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   17468             UInt rT = ifieldRegDS( theInstr );
   17469             UInt rA = ifieldRegA( theInstr );
   17470             UInt rB = ifieldRegB( theInstr );
   17471             UInt bi = ifieldRegC( theInstr );
   17472             putIReg(
   17473                rT,
   17474                IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
   17475                              getIReg(rB),
   17476                              rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   17477                                      : getIReg(rA) )
   17478             );
   17479             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   17480             goto decode_success;
   17481          }
   17482          goto decode_failure;
   17483       }
   17484       break;
   17485 
   17486 
   17487    case 0x04:
   17488       /* AltiVec instructions */
   17489 
   17490       opc2 = IFIELD(theInstr, 0, 6);
   17491       switch (opc2) {
   17492       /* AV Mult-Add, Mult-Sum */
   17493       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   17494       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   17495       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   17496          if (!allow_V) goto decode_noV;
   17497          if (dis_av_multarith( theInstr )) goto decode_success;
   17498          goto decode_failure;
   17499 
   17500       /* AV Permutations */
   17501       case 0x2A:                       // vsel
   17502       case 0x2B:                       // vperm
   17503       case 0x2C:                       // vsldoi
   17504          if (!allow_V) goto decode_noV;
   17505          if (dis_av_permute( theInstr )) goto decode_success;
   17506          goto decode_failure;
   17507 
   17508       /* AV Floating Point Mult-Add/Sub */
   17509       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   17510          if (!allow_V) goto decode_noV;
   17511          if (dis_av_fp_arith( theInstr )) goto decode_success;
   17512          goto decode_failure;
   17513 
   17514       default:
   17515          break;  // Fall through...
   17516       }
   17517 
   17518       opc2 = IFIELD(theInstr, 0, 11);
   17519       switch (opc2) {
   17520       /* AV Arithmetic */
   17521       case 0x180:                         // vaddcuw
   17522       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   17523       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   17524       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   17525       case 0x580:                         // vsubcuw
   17526       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   17527       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   17528       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   17529       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   17530       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   17531       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   17532       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   17533       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   17534       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   17535       case 0x008: case 0x048:             // vmuloub, vmulouh
   17536       case 0x108: case 0x148:             // vmulosb, vmulosh
   17537       case 0x208: case 0x248:             // vmuleub, vmuleuh
   17538       case 0x308: case 0x348:             // vmulesb, vmulesh
   17539       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   17540       case 0x688: case 0x788:             // vsum2sws, vsumsws
   17541          if (!allow_V) goto decode_noV;
   17542          if (dis_av_arith( theInstr )) goto decode_success;
   17543          goto decode_failure;
   17544 
   17545       /* AV Rotate, Shift */
   17546       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   17547       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   17548       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   17549       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   17550       case 0x1C4: case 0x2C4:             // vsl, vsr
   17551       case 0x40C: case 0x44C:             // vslo, vsro
   17552          if (!allow_V) goto decode_noV;
   17553          if (dis_av_shift( theInstr )) goto decode_success;
   17554          goto decode_failure;
   17555 
   17556       /* AV Logic */
   17557       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   17558       case 0x4C4: case 0x504:             // vxor, vnor
   17559          if (!allow_V) goto decode_noV;
   17560          if (dis_av_logic( theInstr )) goto decode_success;
   17561          goto decode_failure;
   17562 
   17563       /* AV Processor Control */
   17564       case 0x604: case 0x644:             // mfvscr, mtvscr
   17565          if (!allow_V) goto decode_noV;
   17566          if (dis_av_procctl( theInstr )) goto decode_success;
   17567          goto decode_failure;
   17568 
   17569       /* AV Floating Point Arithmetic */
   17570       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   17571       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   17572       case 0x1CA:                         // vlogefp
   17573       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   17574          if (!allow_V) goto decode_noV;
   17575          if (dis_av_fp_arith( theInstr )) goto decode_success;
   17576          goto decode_failure;
   17577 
   17578       /* AV Floating Point Round/Convert */
   17579       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   17580       case 0x2CA:                         // vrfim
   17581       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   17582       case 0x3CA:                         // vctsxs
   17583          if (!allow_V) goto decode_noV;
   17584          if (dis_av_fp_convert( theInstr )) goto decode_success;
   17585          goto decode_failure;
   17586 
   17587       /* AV Merge, Splat */
   17588       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   17589       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   17590       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   17591       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   17592          if (!allow_V) goto decode_noV;
   17593          if (dis_av_permute( theInstr )) goto decode_success;
   17594          goto decode_failure;
   17595 
   17596       /* AV Pack, Unpack */
   17597       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   17598       case 0x0CE:                         // vpkuwus
   17599       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   17600       case 0x1CE:                         // vpkswss
   17601       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   17602       case 0x2CE:                         // vupklsh
   17603       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   17604          if (!allow_V) goto decode_noV;
   17605          if (dis_av_pack( theInstr )) goto decode_success;
   17606          goto decode_failure;
   17607 
   17608       default:
   17609          break;  // Fall through...
   17610       }
   17611 
   17612       opc2 = IFIELD(theInstr, 0, 10);
   17613       switch (opc2) {
   17614 
   17615       /* AV Compare */
   17616       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   17617       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   17618       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   17619          if (!allow_V) goto decode_noV;
   17620          if (dis_av_cmp( theInstr )) goto decode_success;
   17621          goto decode_failure;
   17622 
   17623       /* AV Floating Point Compare */
   17624       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   17625       case 0x3C6:                         // vcmpbfp
   17626          if (!allow_V) goto decode_noV;
   17627          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   17628          goto decode_failure;
   17629 
   17630       default:
   17631          goto decode_failure;
   17632       }
   17633       break;
   17634 
   17635    default:
   17636       goto decode_failure;
   17637 
   17638    decode_noF:
   17639       vassert(!allow_F);
   17640       vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
   17641       goto decode_failure;
   17642    decode_noV:
   17643       vassert(!allow_V);
   17644       vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
   17645       goto decode_failure;
   17646    decode_noVX:
   17647       vassert(!allow_VX);
   17648       vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
   17649       goto decode_failure;
   17650    decode_noFX:
   17651       vassert(!allow_FX);
   17652       vex_printf("disInstr(ppc): "
   17653                  "declined to decode a GeneralPurpose-Optional insn.\n");
   17654       goto decode_failure;
   17655    decode_noGX:
   17656       vassert(!allow_GX);
   17657       vex_printf("disInstr(ppc): "
   17658                  "declined to decode a Graphics-Optional insn.\n");
   17659       goto decode_failure;
   17660    decode_noDFP:
   17661       vassert(!allow_DFP);
   17662       vex_printf("disInstr(ppc): "
   17663                "declined to decode a Decimal Floating Point insn.\n");
   17664       goto decode_failure;
   17665 
   17666 
   17667    decode_failure:
   17668    /* All decode failures end up here. */
   17669    opc2 = (theInstr) & 0x7FF;
   17670    vex_printf("disInstr(ppc): unhandled instruction: "
   17671               "0x%x\n", theInstr);
   17672    vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   17673               opc1, opc1, opc2, opc2);
   17674 
   17675    /* Tell the dispatcher that this insn cannot be decoded, and so has
   17676       not been executed, and (is currently) the next to be executed.
   17677       CIA should be up-to-date since it made so at the start of each
   17678       insn, but nevertheless be paranoid and update it again right
   17679       now. */
   17680    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   17681    dres.whatNext    = Dis_StopHere;
   17682    dres.jk_StopHere = Ijk_NoDecode;
   17683    dres.len         = 0;
   17684    return dres;
   17685 
   17686    } /* switch (opc) for the main (primary) opcode switch. */
   17687 
   17688   decode_success:
   17689    /* All decode successes end up here. */
   17690    switch (dres.whatNext) {
   17691       case Dis_Continue:
   17692          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
   17693          break;
   17694       case Dis_ResteerU:
   17695       case Dis_ResteerC:
   17696          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
   17697          break;
   17698       case Dis_StopHere:
   17699          break;
   17700       default:
   17701          vassert(0);
   17702    }
   17703    DIP("\n");
   17704 
   17705    if (dres.len == 0) {
   17706       dres.len = 4;
   17707    } else {
   17708       vassert(dres.len == 20);
   17709    }
   17710    return dres;
   17711 }
   17712 
   17713 #undef DIP
   17714 #undef DIS
   17715 
   17716 
   17717 /*------------------------------------------------------------*/
   17718 /*--- Top-level fn                                         ---*/
   17719 /*------------------------------------------------------------*/
   17720 
   17721 /* Disassemble a single instruction into IR.  The instruction
   17722    is located in host memory at &guest_code[delta]. */
   17723 
   17724 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   17725                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   17726                          Bool         resteerCisOk,
   17727                          void*        callback_opaque,
   17728                          UChar*       guest_code_IN,
   17729                          Long         delta,
   17730                          Addr64       guest_IP,
   17731                          VexArch      guest_arch,
   17732                          VexArchInfo* archinfo,
   17733                          VexAbiInfo*  abiinfo,
   17734                          Bool         host_bigendian_IN )
   17735 {
   17736    IRType     ty;
   17737    DisResult  dres;
   17738    UInt       mask32, mask64;
   17739    UInt hwcaps_guest = archinfo->hwcaps;
   17740 
   17741    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   17742 
   17743    /* global -- ick */
   17744    mode64 = guest_arch == VexArchPPC64;
   17745    ty = mode64 ? Ity_I64 : Ity_I32;
   17746 
   17747    /* do some sanity checks */
   17748    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   17749             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   17750             | VEX_HWCAPS_PPC32_DFP;
   17751 
   17752    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   17753 		   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP;
   17754 
   17755    if (mode64) {
   17756       vassert((hwcaps_guest & mask32) == 0);
   17757    } else {
   17758       vassert((hwcaps_guest & mask64) == 0);
   17759    }
   17760 
   17761    /* Set globals (see top of this file) */
   17762    guest_code           = guest_code_IN;
   17763    irsb                 = irsb_IN;
   17764    host_is_bigendian    = host_bigendian_IN;
   17765 
   17766    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   17767    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   17768 
   17769    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
   17770                              delta, archinfo, abiinfo );
   17771 
   17772    return dres;
   17773 }
   17774 
   17775 
   17776 /*------------------------------------------------------------*/
   17777 /*--- Unused stuff                                         ---*/
   17778 /*------------------------------------------------------------*/
   17779 
   17780 ///* A potentially more memcheck-friendly implementation of Clz32, with
   17781 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   17782 //
   17783 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   17784 //{
   17785 //   /* Welcome ... to SSA R Us. */
   17786 //   IRTemp n1  = newTemp(Ity_I32);
   17787 //   IRTemp n2  = newTemp(Ity_I32);
   17788 //   IRTemp n3  = newTemp(Ity_I32);
   17789 //   IRTemp n4  = newTemp(Ity_I32);
   17790 //   IRTemp n5  = newTemp(Ity_I32);
   17791 //   IRTemp n6  = newTemp(Ity_I32);
   17792 //   IRTemp n7  = newTemp(Ity_I32);
   17793 //   IRTemp n8  = newTemp(Ity_I32);
   17794 //   IRTemp n9  = newTemp(Ity_I32);
   17795 //   IRTemp n10 = newTemp(Ity_I32);
   17796 //   IRTemp n11 = newTemp(Ity_I32);
   17797 //   IRTemp n12 = newTemp(Ity_I32);
   17798 //
   17799 //   /* First, propagate the most significant 1-bit into all lower
   17800 //      positions in the word. */
   17801 //   /* unsigned int clz ( unsigned int n )
   17802 //      {
   17803 //         n |= (n >> 1);
   17804 //         n |= (n >> 2);
   17805 //         n |= (n >> 4);
   17806 //         n |= (n >> 8);
   17807 //         n |= (n >> 16);
   17808 //         return bitcount(~n);
   17809 //      }
   17810 //   */
   17811 //   assign(n1, mkexpr(arg));
   17812 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   17813 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   17814 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   17815 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   17816 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   17817 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   17818 //      a word of the form 1---10---0, then do a population-count idiom
   17819 //      (to count the 1s, which is the number of leading zeroes, or 32
   17820 //      if the original word was 0. */
   17821 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   17822 //
   17823 //   /* unsigned int bitcount ( unsigned int n )
   17824 //      {
   17825 //         n = n - ((n >> 1) & 0x55555555);
   17826 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   17827 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   17828 //         n = n + (n >> 8);
   17829 //         n = (n + (n >> 16)) & 0x3F;
   17830 //         return n;
   17831 //      }
   17832 //   */
   17833 //   assign(n8,
   17834 //          binop(Iop_Sub32,
   17835 //                mkexpr(n7),
   17836 //                binop(Iop_And32,
   17837 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   17838 //                      mkU32(0x55555555))));
   17839 //   assign(n9,
   17840 //          binop(Iop_Add32,
   17841 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   17842 //                binop(Iop_And32,
   17843 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   17844 //                      mkU32(0x33333333))));
   17845 //   assign(n10,
   17846 //          binop(Iop_And32,
   17847 //                binop(Iop_Add32,
   17848 //                      mkexpr(n9),
   17849 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   17850 //                mkU32(0x0F0F0F0F)));
   17851 //   assign(n11,
   17852 //          binop(Iop_Add32,
   17853 //                mkexpr(n10),
   17854 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   17855 //   assign(n12,
   17856 //          binop(Iop_Add32,
   17857 //                mkexpr(n11),
   17858 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   17859 //   return
   17860 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   17861 //}
   17862 
   17863 /*--------------------------------------------------------------------*/
   17864 /*--- end                                         guest_ppc_toIR.c ---*/
   17865 /*--------------------------------------------------------------------*/
   17866