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-2011 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_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
    226 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
    227 #define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
    228 #define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
    229 #define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
    230 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
    231 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
    232 
    233 
    234 /*------------------------------------------------------------*/
    235 /*--- Extract instruction fields                          --- */
    236 /*------------------------------------------------------------*/
    237 
    238 /* Extract field from insn, given idx (zero = lsb) and field length */
    239 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    240 
    241 /* Extract primary opcode, instr[31:26] */
    242 static UChar ifieldOPC( UInt instr ) {
    243    return toUChar( IFIELD( instr, 26, 6 ) );
    244 }
    245 
    246 /* Extract 10-bit secondary opcode, instr[10:1] */
    247 static UInt ifieldOPClo10 ( UInt instr) {
    248    return IFIELD( instr, 1, 10 );
    249 }
    250 
    251 /* Extract 9-bit secondary opcode, instr[9:1] */
    252 static UInt ifieldOPClo9 ( UInt instr) {
    253    return IFIELD( instr, 1, 9 );
    254 }
    255 
    256 /* Extract 5-bit secondary opcode, instr[5:1] */
    257 static UInt ifieldOPClo5 ( UInt instr) {
    258    return IFIELD( instr, 1, 5 );
    259 }
    260 
    261 /* Extract RD (destination register) field, instr[25:21] */
    262 static UChar ifieldRegDS( UInt instr ) {
    263    return toUChar( IFIELD( instr, 21, 5 ) );
    264 }
    265 
    266 /* Extract XT (destination register) field, instr[0,25:21] */
    267 static UChar ifieldRegXT ( UInt instr )
    268 {
    269   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
    270   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
    271   return (upper_bit << 5) | lower_bits;
    272 }
    273 
    274 /* Extract XS (store source register) field, instr[0,25:21] */
    275 static inline UChar ifieldRegXS ( UInt instr )
    276 {
    277   return ifieldRegXT ( instr );
    278 }
    279 
    280 /* Extract RA (1st source register) field, instr[20:16] */
    281 static UChar ifieldRegA ( UInt instr ) {
    282    return toUChar( IFIELD( instr, 16, 5 ) );
    283 }
    284 
    285 /* Extract XA (1st source register) field, instr[2,20:16] */
    286 static UChar ifieldRegXA ( UInt instr )
    287 {
    288   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
    289   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
    290   return (upper_bit << 5) | lower_bits;
    291 }
    292 
    293 /* Extract RB (2nd source register) field, instr[15:11] */
    294 static UChar ifieldRegB ( UInt instr ) {
    295    return toUChar( IFIELD( instr, 11, 5 ) );
    296 }
    297 
    298 /* Extract XB (2nd source register) field, instr[1,15:11] */
    299 static UChar ifieldRegXB ( UInt instr )
    300 {
    301   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
    302   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
    303   return (upper_bit << 5) | lower_bits;
    304 }
    305 
    306 /* Extract RC (3rd source register) field, instr[10:6] */
    307 static UChar ifieldRegC ( UInt instr ) {
    308    return toUChar( IFIELD( instr, 6, 5 ) );
    309 }
    310 
    311 /* Extract XC (3rd source register) field, instr[3,10:6] */
    312 static UChar ifieldRegXC ( UInt instr )
    313 {
    314   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
    315   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
    316   return (upper_bit << 5) | lower_bits;
    317 }
    318 
    319 /* Extract bit 10, instr[10] */
    320 static UChar ifieldBIT10 ( UInt instr ) {
    321    return toUChar( IFIELD( instr, 10, 1 ) );
    322 }
    323 
    324 /* Extract 2nd lowest bit, instr[1] */
    325 static UChar ifieldBIT1 ( UInt instr ) {
    326    return toUChar( IFIELD( instr, 1, 1 ) );
    327 }
    328 
    329 /* Extract lowest bit, instr[0] */
    330 static UChar ifieldBIT0 ( UInt instr ) {
    331    return toUChar( instr & 0x1 );
    332 }
    333 
    334 /* Extract unsigned bottom half, instr[15:0] */
    335 static UInt ifieldUIMM16 ( UInt instr ) {
    336    return instr & 0xFFFF;
    337 }
    338 
    339 /* Extract unsigned bottom 26 bits, instr[25:0] */
    340 static UInt ifieldUIMM26 ( UInt instr ) {
    341    return instr & 0x3FFFFFF;
    342 }
    343 
    344 /* Extract DM field, instr[9:8] */
    345 static UChar ifieldDM ( UInt instr ) {
    346    return toUChar( IFIELD( instr, 8, 2 ) );
    347 }
    348 
    349 /* Extract SHW field, instr[9:8] */
    350 static inline UChar ifieldSHW ( UInt instr )
    351 {
    352   return ifieldDM ( instr );
    353 }
    354 
    355 /*------------------------------------------------------------*/
    356 /*--- Guest-state identifiers                              ---*/
    357 /*------------------------------------------------------------*/
    358 
    359 typedef enum {
    360     PPC_GST_CIA,    // Current Instruction Address
    361     PPC_GST_LR,     // Link Register
    362     PPC_GST_CTR,    // Count Register
    363     PPC_GST_XER,    // Overflow, carry flags, byte count
    364     PPC_GST_CR,     // Condition Register
    365     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    366     PPC_GST_VRSAVE, // Vector Save/Restore Register
    367     PPC_GST_VSCR,   // Vector Status and Control Register
    368     PPC_GST_EMWARN, // Emulation warnings
    369     PPC_GST_TISTART,// For icbi: start of area to invalidate
    370     PPC_GST_TILEN,  // For icbi: length of area to invalidate
    371     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    372     PPC_GST_SPRG3_RO, // SPRG3
    373     PPC_GST_MAX
    374 } PPC_GST;
    375 
    376 #define MASK_FPSCR_RN   0x3
    377 #define MASK_FPSCR_FPRF 0x1F000
    378 #define MASK_VSCR_VALID 0x00010001
    379 
    380 
    381 /*------------------------------------------------------------*/
    382 /*---  FP Helpers                                          ---*/
    383 /*------------------------------------------------------------*/
    384 
    385 /* Produce the 32-bit pattern corresponding to the supplied
    386    float. */
    387 static UInt float_to_bits ( Float f )
    388 {
    389    union { UInt i; Float f; } u;
    390    vassert(4 == sizeof(UInt));
    391    vassert(4 == sizeof(Float));
    392    vassert(4 == sizeof(u));
    393    u.f = f;
    394    return u.i;
    395 }
    396 
    397 
    398 /*------------------------------------------------------------*/
    399 /*--- Misc Helpers                                         ---*/
    400 /*------------------------------------------------------------*/
    401 
    402 /* Generate mask with 1's from 'begin' through 'end',
    403    wrapping if begin > end.
    404    begin->end works from right to left, 0=lsb
    405 */
    406 static UInt MASK32( UInt begin, UInt end )
    407 {
    408    UInt m1, m2, mask;
    409    vassert(begin < 32);
    410    vassert(end < 32);
    411    m1   = ((UInt)(-1)) << begin;
    412    m2   = ((UInt)(-1)) << end << 1;
    413    mask = m1 ^ m2;
    414    if (begin > end) mask = ~mask;  // wrap mask
    415    return mask;
    416 }
    417 
    418 /* ditto for 64bit mask */
    419 static ULong MASK64( UInt begin, UInt end )
    420 {
    421    ULong m1, m2, mask;
    422    vassert(begin < 64);
    423    vassert(end < 64);
    424    m1   = ((ULong)(-1)) << begin;
    425    m2   = ((ULong)(-1)) << end << 1;
    426    mask = m1 ^ m2;
    427    if (begin > end) mask = ~mask;  // wrap mask
    428    return mask;
    429 }
    430 
    431 static Addr64 nextInsnAddr( void )
    432 {
    433    return guest_CIA_curr_instr + 4;
    434 }
    435 
    436 
    437 /*------------------------------------------------------------*/
    438 /*--- Helper bits and pieces for deconstructing the        ---*/
    439 /*--- ppc32/64 insn stream.                                ---*/
    440 /*------------------------------------------------------------*/
    441 
    442 /* Add a statement to the list held by "irsb". */
    443 static void stmt ( IRStmt* st )
    444 {
    445    addStmtToIRSB( irsb, st );
    446 }
    447 
    448 /* Generate a new temporary of the given type. */
    449 static IRTemp newTemp ( IRType ty )
    450 {
    451    vassert(isPlausibleIRType(ty));
    452    return newIRTemp( irsb->tyenv, ty );
    453 }
    454 
    455 /* Various simple conversions */
    456 
    457 static UChar extend_s_5to8 ( UChar x )
    458 {
    459    return toUChar((((Int)x) << 27) >> 27);
    460 }
    461 
    462 static UInt extend_s_8to32( UChar x )
    463 {
    464    return (UInt)((((Int)x) << 24) >> 24);
    465 }
    466 
    467 static UInt extend_s_16to32 ( UInt x )
    468 {
    469    return (UInt)((((Int)x) << 16) >> 16);
    470 }
    471 
    472 static ULong extend_s_16to64 ( UInt x )
    473 {
    474    return (ULong)((((Long)x) << 48) >> 48);
    475 }
    476 
    477 static ULong extend_s_26to64 ( UInt x )
    478 {
    479    return (ULong)((((Long)x) << 38) >> 38);
    480 }
    481 
    482 static ULong extend_s_32to64 ( UInt x )
    483 {
    484    return (ULong)((((Long)x) << 32) >> 32);
    485 }
    486 
    487 /* Do a big-endian load of a 32-bit word, regardless of the endianness
    488    of the underlying host. */
    489 static UInt getUIntBigendianly ( UChar* p )
    490 {
    491    UInt w = 0;
    492    w = (w << 8) | p[0];
    493    w = (w << 8) | p[1];
    494    w = (w << 8) | p[2];
    495    w = (w << 8) | p[3];
    496    return w;
    497 }
    498 
    499 
    500 /*------------------------------------------------------------*/
    501 /*--- Helpers for constructing IR.                         ---*/
    502 /*------------------------------------------------------------*/
    503 
    504 static void assign ( IRTemp dst, IRExpr* e )
    505 {
    506    stmt( IRStmt_WrTmp(dst, e) );
    507 }
    508 
    509 /* This generates a normal (non store-conditional) store. */
    510 static void storeBE ( IRExpr* addr, IRExpr* data )
    511 {
    512    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    513    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    514    stmt( IRStmt_Store(Iend_BE, addr, data) );
    515 }
    516 
    517 static IRExpr* unop ( IROp op, IRExpr* a )
    518 {
    519    return IRExpr_Unop(op, a);
    520 }
    521 
    522 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    523 {
    524    return IRExpr_Binop(op, a1, a2);
    525 }
    526 
    527 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    528 {
    529    return IRExpr_Triop(op, a1, a2, a3);
    530 }
    531 
    532 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    533                               IRExpr* a3, IRExpr* a4 )
    534 {
    535    return IRExpr_Qop(op, a1, a2, a3, a4);
    536 }
    537 
    538 static IRExpr* mkexpr ( IRTemp tmp )
    539 {
    540    return IRExpr_RdTmp(tmp);
    541 }
    542 
    543 static IRExpr* mkU8 ( UChar i )
    544 {
    545    return IRExpr_Const(IRConst_U8(i));
    546 }
    547 
    548 static IRExpr* mkU16 ( UInt i )
    549 {
    550    return IRExpr_Const(IRConst_U16(i));
    551 }
    552 
    553 static IRExpr* mkU32 ( UInt i )
    554 {
    555    return IRExpr_Const(IRConst_U32(i));
    556 }
    557 
    558 static IRExpr* mkU64 ( ULong i )
    559 {
    560    return IRExpr_Const(IRConst_U64(i));
    561 }
    562 
    563 static IRExpr* mkV128 ( UShort i )
    564 {
    565    vassert(i == 0 || i == 0xffff);
    566    return IRExpr_Const(IRConst_V128(i));
    567 }
    568 
    569 /* This generates a normal (non load-linked) load. */
    570 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
    571 {
    572    return IRExpr_Load(Iend_BE, ty, addr);
    573 }
    574 
    575 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    576 {
    577    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    578    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    579    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    580                                           unop(Iop_1Uto32, arg2)));
    581 }
    582 
    583 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    584 {
    585    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    586    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    587    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    588                                            unop(Iop_1Uto32, arg2)));
    589 }
    590 
    591 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    592 static void expand8Ux16( IRExpr* vIn,
    593                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    594 {
    595    IRTemp ones8x16 = newTemp(Ity_V128);
    596 
    597    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    598    vassert(vEvn && *vEvn == IRTemp_INVALID);
    599    vassert(vOdd && *vOdd == IRTemp_INVALID);
    600    *vEvn = newTemp(Ity_V128);
    601    *vOdd = newTemp(Ity_V128);
    602 
    603    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    604    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    605    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    606                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    607 }
    608 
    609 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    610 static void expand8Sx16( IRExpr* vIn,
    611                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    612 {
    613    IRTemp ones8x16 = newTemp(Ity_V128);
    614 
    615    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    616    vassert(vEvn && *vEvn == IRTemp_INVALID);
    617    vassert(vOdd && *vOdd == IRTemp_INVALID);
    618    *vEvn = newTemp(Ity_V128);
    619    *vOdd = newTemp(Ity_V128);
    620 
    621    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    622    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    623    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    624                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    625 }
    626 
    627 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    628 static void expand16Ux8( IRExpr* vIn,
    629                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    630 {
    631    IRTemp ones16x8 = newTemp(Ity_V128);
    632 
    633    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    634    vassert(vEvn && *vEvn == IRTemp_INVALID);
    635    vassert(vOdd && *vOdd == IRTemp_INVALID);
    636    *vEvn = newTemp(Ity_V128);
    637    *vOdd = newTemp(Ity_V128);
    638 
    639    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    640    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    641    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    642                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    643 }
    644 
    645 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    646 static void expand16Sx8( IRExpr* vIn,
    647                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    648 {
    649    IRTemp ones16x8 = newTemp(Ity_V128);
    650 
    651    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    652    vassert(vEvn && *vEvn == IRTemp_INVALID);
    653    vassert(vOdd && *vOdd == IRTemp_INVALID);
    654    *vEvn = newTemp(Ity_V128);
    655    *vOdd = newTemp(Ity_V128);
    656 
    657    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    658    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    659    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    660                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    661 }
    662 
    663 /* break V128 to 4xF64's*/
    664 static void breakV128to4xF64( IRExpr* t128,
    665                               /*OUTs*/
    666                               IRTemp* t3, IRTemp* t2,
    667                               IRTemp* t1, IRTemp* t0 )
    668 {
    669    IRTemp hi64 = newTemp(Ity_I64);
    670    IRTemp lo64 = newTemp(Ity_I64);
    671 
    672    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    673    vassert(t0 && *t0 == IRTemp_INVALID);
    674    vassert(t1 && *t1 == IRTemp_INVALID);
    675    vassert(t2 && *t2 == IRTemp_INVALID);
    676    vassert(t3 && *t3 == IRTemp_INVALID);
    677    *t0 = newTemp(Ity_F64);
    678    *t1 = newTemp(Ity_F64);
    679    *t2 = newTemp(Ity_F64);
    680    *t3 = newTemp(Ity_F64);
    681 
    682    assign( hi64, unop(Iop_V128HIto64, t128) );
    683    assign( lo64, unop(Iop_V128to64,   t128) );
    684    assign( *t3,
    685            unop( Iop_F32toF64,
    686                  unop( Iop_ReinterpI32asF32,
    687                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
    688    assign( *t2,
    689            unop( Iop_F32toF64,
    690                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
    691    assign( *t1,
    692            unop( Iop_F32toF64,
    693                  unop( Iop_ReinterpI32asF32,
    694                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
    695    assign( *t0,
    696            unop( Iop_F32toF64,
    697                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
    698 }
    699 
    700 
    701 /* break V128 to 4xI32's, then sign-extend to I64's */
    702 static void breakV128to4x64S( IRExpr* t128,
    703                               /*OUTs*/
    704                               IRTemp* t3, IRTemp* t2,
    705                               IRTemp* t1, IRTemp* t0 )
    706 {
    707    IRTemp hi64 = newTemp(Ity_I64);
    708    IRTemp lo64 = newTemp(Ity_I64);
    709 
    710    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    711    vassert(t0 && *t0 == IRTemp_INVALID);
    712    vassert(t1 && *t1 == IRTemp_INVALID);
    713    vassert(t2 && *t2 == IRTemp_INVALID);
    714    vassert(t3 && *t3 == IRTemp_INVALID);
    715    *t0 = newTemp(Ity_I64);
    716    *t1 = newTemp(Ity_I64);
    717    *t2 = newTemp(Ity_I64);
    718    *t3 = newTemp(Ity_I64);
    719 
    720    assign( hi64, unop(Iop_V128HIto64, t128) );
    721    assign( lo64, unop(Iop_V128to64,   t128) );
    722    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    723    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    724    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    725    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    726 }
    727 
    728 /* break V128 to 4xI32's, then zero-extend to I64's */
    729 static void breakV128to4x64U ( IRExpr* t128,
    730                                /*OUTs*/
    731                                IRTemp* t3, IRTemp* t2,
    732                                IRTemp* t1, IRTemp* t0 )
    733 {
    734    IRTemp hi64 = newTemp(Ity_I64);
    735    IRTemp lo64 = newTemp(Ity_I64);
    736 
    737    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    738    vassert(t0 && *t0 == IRTemp_INVALID);
    739    vassert(t1 && *t1 == IRTemp_INVALID);
    740    vassert(t2 && *t2 == IRTemp_INVALID);
    741    vassert(t3 && *t3 == IRTemp_INVALID);
    742    *t0 = newTemp(Ity_I64);
    743    *t1 = newTemp(Ity_I64);
    744    *t2 = newTemp(Ity_I64);
    745    *t3 = newTemp(Ity_I64);
    746 
    747    assign( hi64, unop(Iop_V128HIto64, t128) );
    748    assign( lo64, unop(Iop_V128to64,   t128) );
    749    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    750    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    751    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    752    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    753 }
    754 
    755 static void breakV128to4x32( IRExpr* t128,
    756                               /*OUTs*/
    757                               IRTemp* t3, IRTemp* t2,
    758                               IRTemp* t1, IRTemp* t0 )
    759 {
    760    IRTemp hi64 = newTemp(Ity_I64);
    761    IRTemp lo64 = newTemp(Ity_I64);
    762 
    763    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    764    vassert(t0 && *t0 == IRTemp_INVALID);
    765    vassert(t1 && *t1 == IRTemp_INVALID);
    766    vassert(t2 && *t2 == IRTemp_INVALID);
    767    vassert(t3 && *t3 == IRTemp_INVALID);
    768    *t0 = newTemp(Ity_I32);
    769    *t1 = newTemp(Ity_I32);
    770    *t2 = newTemp(Ity_I32);
    771    *t3 = newTemp(Ity_I32);
    772 
    773    assign( hi64, unop(Iop_V128HIto64, t128) );
    774    assign( lo64, unop(Iop_V128to64,   t128) );
    775    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
    776    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
    777    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
    778    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
    779 }
    780 
    781 
    782 /* Signed saturating narrow 64S to 32 */
    783 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    784 {
    785    IRTemp hi32 = newTemp(Ity_I32);
    786    IRTemp lo32 = newTemp(Ity_I32);
    787 
    788    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    789 
    790    assign( hi32, unop(Iop_64HIto32, t64));
    791    assign( lo32, unop(Iop_64to32,   t64));
    792 
    793    return IRExpr_Mux0X(
    794              /* if (hi32 == (lo32 >>s 31)) */
    795              unop(Iop_1Uto8,
    796                   binop(Iop_CmpEQ32, mkexpr(hi32),
    797                         binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
    798              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    799              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    800                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
    801              /* then: within signed-32 range: lo half good enough */
    802              mkexpr(lo32) );
    803 }
    804 
    805 /* Unsigned saturating narrow 64S to 32 */
    806 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    807 {
    808    IRTemp hi32 = newTemp(Ity_I32);
    809    IRTemp lo32 = newTemp(Ity_I32);
    810 
    811    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    812 
    813    assign( hi32, unop(Iop_64HIto32, t64));
    814    assign( lo32, unop(Iop_64to32,   t64));
    815 
    816    return IRExpr_Mux0X(
    817             /* if (top 32 bits of t64 are 0) */
    818             unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
    819             /* else: positive saturate -> 0xFFFFFFFF */
    820             mkU32(0xFFFFFFFF),
    821             /* then: within unsigned-32 range: lo half good enough */
    822             mkexpr(lo32) );
    823 }
    824 
    825 /* Signed saturate narrow 64->32, combining to V128 */
    826 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    827                                  IRExpr* t1, IRExpr* t0 )
    828 {
    829    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    830    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    831    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    832    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    833    return binop(Iop_64HLtoV128,
    834                 binop(Iop_32HLto64,
    835                       mkQNarrow64Sto32( t3 ),
    836                       mkQNarrow64Sto32( t2 )),
    837                 binop(Iop_32HLto64,
    838                       mkQNarrow64Sto32( t1 ),
    839                       mkQNarrow64Sto32( t0 )));
    840 }
    841 
    842 /* Unsigned saturate narrow 64->32, combining to V128 */
    843 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    844                                  IRExpr* t1, IRExpr* t0 )
    845 {
    846    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    847    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    848    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    849    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    850    return binop(Iop_64HLtoV128,
    851                 binop(Iop_32HLto64,
    852                       mkQNarrow64Uto32( t3 ),
    853                       mkQNarrow64Uto32( t2 )),
    854                 binop(Iop_32HLto64,
    855                       mkQNarrow64Uto32( t1 ),
    856                       mkQNarrow64Uto32( t0 )));
    857 }
    858 
    859 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    860 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    861       binop(Iop_MullEven8Ux16, \
    862             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    863             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    864 
    865 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    866       binop(Iop_MullEven8Sx16, \
    867             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    868             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    869 
    870 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    871       binop(Iop_MullEven16Ux8, \
    872             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    873             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    874 
    875 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    876       binop(Iop_MullEven16Sx8, \
    877             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    878             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    879 
    880 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
    881 {
    882    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    883    return unop(Iop_32Sto64, unop(Iop_64to32, src));
    884 }
    885 
    886 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
    887 {
    888    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    889    return unop(Iop_32Uto64, unop(Iop_64to32, src));
    890 }
    891 
    892 static IROp mkSzOp ( IRType ty, IROp op8 )
    893 {
    894    Int adj;
    895    vassert(ty == Ity_I8  || ty == Ity_I16 ||
    896            ty == Ity_I32 || ty == Ity_I64);
    897    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
    898            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
    899            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
    900            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
    901            op8 == Iop_Not8 );
    902    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
    903    return adj + op8;
    904 }
    905 
    906 /* Make sure we get valid 32 and 64bit addresses */
    907 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
    908 {
    909    vassert(ty == Ity_I32 || ty == Ity_I64);
    910    return ( ty == Ity_I64 ?
    911             (Addr64)addr :
    912             (Addr64)extend_s_32to64( toUInt(addr) ) );
    913 }
    914 
    915 /* sz, ULong -> IRExpr */
    916 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
    917 {
    918    vassert(ty == Ity_I32 || ty == Ity_I64);
    919    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
    920 }
    921 
    922 /* sz, ULong -> IRConst */
    923 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
    924 {
    925    vassert(ty == Ity_I32 || ty == Ity_I64);
    926    return ( ty == Ity_I64 ?
    927             IRConst_U64(imm64) :
    928             IRConst_U32((UInt)imm64) );
    929 }
    930 
    931 /* Sign extend imm16 -> IRExpr* */
    932 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
    933 {
    934    vassert(ty == Ity_I32 || ty == Ity_I64);
    935    return ( ty == Ity_I64 ?
    936             mkU64(extend_s_16to64(imm16)) :
    937             mkU32(extend_s_16to32(imm16)) );
    938 }
    939 
    940 /* Sign extend imm32 -> IRExpr* */
    941 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
    942 {
    943    vassert(ty == Ity_I32 || ty == Ity_I64);
    944    return ( ty == Ity_I64 ?
    945             mkU64(extend_s_32to64(imm32)) :
    946             mkU32(imm32) );
    947 }
    948 
    949 /* IR narrows I32/I64 -> I8/I16/I32 */
    950 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
    951 {
    952    vassert(ty == Ity_I32 || ty == Ity_I64);
    953    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
    954 }
    955 
    956 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
    957 {
    958    vassert(ty == Ity_I32 || ty == Ity_I64);
    959    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
    960 }
    961 
    962 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
    963 {
    964    vassert(ty == Ity_I32 || ty == Ity_I64);
    965    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
    966 }
    967 
    968 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
    969 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
    970 {
    971    IROp op;
    972    vassert(ty == Ity_I32 || ty == Ity_I64);
    973    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
    974    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
    975    return unop(op, src);
    976 }
    977 
    978 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
    979 {
    980    IROp op;
    981    vassert(ty == Ity_I32 || ty == Ity_I64);
    982    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
    983    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
    984    return unop(op, src);
    985 }
    986 
    987 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
    988 {
    989    vassert(ty == Ity_I32 || ty == Ity_I64);
    990    if (ty == Ity_I32)
    991       return src;
    992    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
    993 }
    994 
    995 
    996 static Int integerGuestRegOffset ( UInt archreg )
    997 {
    998    vassert(archreg < 32);
    999 
   1000    // jrs: probably not necessary; only matters if we reference sub-parts
   1001    // of the ppc registers, but that isn't the case
   1002    // later: this might affect Altivec though?
   1003    vassert(host_is_bigendian);
   1004 
   1005    switch (archreg) {
   1006    case  0: return offsetofPPCGuestState(guest_GPR0);
   1007    case  1: return offsetofPPCGuestState(guest_GPR1);
   1008    case  2: return offsetofPPCGuestState(guest_GPR2);
   1009    case  3: return offsetofPPCGuestState(guest_GPR3);
   1010    case  4: return offsetofPPCGuestState(guest_GPR4);
   1011    case  5: return offsetofPPCGuestState(guest_GPR5);
   1012    case  6: return offsetofPPCGuestState(guest_GPR6);
   1013    case  7: return offsetofPPCGuestState(guest_GPR7);
   1014    case  8: return offsetofPPCGuestState(guest_GPR8);
   1015    case  9: return offsetofPPCGuestState(guest_GPR9);
   1016    case 10: return offsetofPPCGuestState(guest_GPR10);
   1017    case 11: return offsetofPPCGuestState(guest_GPR11);
   1018    case 12: return offsetofPPCGuestState(guest_GPR12);
   1019    case 13: return offsetofPPCGuestState(guest_GPR13);
   1020    case 14: return offsetofPPCGuestState(guest_GPR14);
   1021    case 15: return offsetofPPCGuestState(guest_GPR15);
   1022    case 16: return offsetofPPCGuestState(guest_GPR16);
   1023    case 17: return offsetofPPCGuestState(guest_GPR17);
   1024    case 18: return offsetofPPCGuestState(guest_GPR18);
   1025    case 19: return offsetofPPCGuestState(guest_GPR19);
   1026    case 20: return offsetofPPCGuestState(guest_GPR20);
   1027    case 21: return offsetofPPCGuestState(guest_GPR21);
   1028    case 22: return offsetofPPCGuestState(guest_GPR22);
   1029    case 23: return offsetofPPCGuestState(guest_GPR23);
   1030    case 24: return offsetofPPCGuestState(guest_GPR24);
   1031    case 25: return offsetofPPCGuestState(guest_GPR25);
   1032    case 26: return offsetofPPCGuestState(guest_GPR26);
   1033    case 27: return offsetofPPCGuestState(guest_GPR27);
   1034    case 28: return offsetofPPCGuestState(guest_GPR28);
   1035    case 29: return offsetofPPCGuestState(guest_GPR29);
   1036    case 30: return offsetofPPCGuestState(guest_GPR30);
   1037    case 31: return offsetofPPCGuestState(guest_GPR31);
   1038    default: break;
   1039    }
   1040    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
   1041 }
   1042 
   1043 static IRExpr* getIReg ( UInt archreg )
   1044 {
   1045    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1046    vassert(archreg < 32);
   1047    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
   1048 }
   1049 
   1050 /* Ditto, but write to a reg instead. */
   1051 static void putIReg ( UInt archreg, IRExpr* e )
   1052 {
   1053    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1054    vassert(archreg < 32);
   1055    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
   1056    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
   1057 }
   1058 
   1059 
   1060 /* Floating point egisters are mapped to VSX registers[0..31]. */
   1061 static Int floatGuestRegOffset ( UInt archreg )
   1062 {
   1063    vassert(archreg < 32);
   1064 
   1065    switch (archreg) {
   1066    case  0: return offsetofPPCGuestState(guest_VSR0);
   1067    case  1: return offsetofPPCGuestState(guest_VSR1);
   1068    case  2: return offsetofPPCGuestState(guest_VSR2);
   1069    case  3: return offsetofPPCGuestState(guest_VSR3);
   1070    case  4: return offsetofPPCGuestState(guest_VSR4);
   1071    case  5: return offsetofPPCGuestState(guest_VSR5);
   1072    case  6: return offsetofPPCGuestState(guest_VSR6);
   1073    case  7: return offsetofPPCGuestState(guest_VSR7);
   1074    case  8: return offsetofPPCGuestState(guest_VSR8);
   1075    case  9: return offsetofPPCGuestState(guest_VSR9);
   1076    case 10: return offsetofPPCGuestState(guest_VSR10);
   1077    case 11: return offsetofPPCGuestState(guest_VSR11);
   1078    case 12: return offsetofPPCGuestState(guest_VSR12);
   1079    case 13: return offsetofPPCGuestState(guest_VSR13);
   1080    case 14: return offsetofPPCGuestState(guest_VSR14);
   1081    case 15: return offsetofPPCGuestState(guest_VSR15);
   1082    case 16: return offsetofPPCGuestState(guest_VSR16);
   1083    case 17: return offsetofPPCGuestState(guest_VSR17);
   1084    case 18: return offsetofPPCGuestState(guest_VSR18);
   1085    case 19: return offsetofPPCGuestState(guest_VSR19);
   1086    case 20: return offsetofPPCGuestState(guest_VSR20);
   1087    case 21: return offsetofPPCGuestState(guest_VSR21);
   1088    case 22: return offsetofPPCGuestState(guest_VSR22);
   1089    case 23: return offsetofPPCGuestState(guest_VSR23);
   1090    case 24: return offsetofPPCGuestState(guest_VSR24);
   1091    case 25: return offsetofPPCGuestState(guest_VSR25);
   1092    case 26: return offsetofPPCGuestState(guest_VSR26);
   1093    case 27: return offsetofPPCGuestState(guest_VSR27);
   1094    case 28: return offsetofPPCGuestState(guest_VSR28);
   1095    case 29: return offsetofPPCGuestState(guest_VSR29);
   1096    case 30: return offsetofPPCGuestState(guest_VSR30);
   1097    case 31: return offsetofPPCGuestState(guest_VSR31);
   1098    default: break;
   1099    }
   1100    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
   1101 }
   1102 
   1103 static IRExpr* getFReg ( UInt archreg )
   1104 {
   1105    vassert(archreg < 32);
   1106    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
   1107 }
   1108 
   1109 /* Ditto, but write to a reg instead. */
   1110 static void putFReg ( UInt archreg, IRExpr* e )
   1111 {
   1112    vassert(archreg < 32);
   1113    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1114    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
   1115 }
   1116 
   1117 static Int vsxGuestRegOffset ( UInt archreg )
   1118 {
   1119    vassert(archreg < 64);
   1120    switch (archreg) {
   1121    case  0: return offsetofPPCGuestState(guest_VSR0);
   1122    case  1: return offsetofPPCGuestState(guest_VSR1);
   1123    case  2: return offsetofPPCGuestState(guest_VSR2);
   1124    case  3: return offsetofPPCGuestState(guest_VSR3);
   1125    case  4: return offsetofPPCGuestState(guest_VSR4);
   1126    case  5: return offsetofPPCGuestState(guest_VSR5);
   1127    case  6: return offsetofPPCGuestState(guest_VSR6);
   1128    case  7: return offsetofPPCGuestState(guest_VSR7);
   1129    case  8: return offsetofPPCGuestState(guest_VSR8);
   1130    case  9: return offsetofPPCGuestState(guest_VSR9);
   1131    case 10: return offsetofPPCGuestState(guest_VSR10);
   1132    case 11: return offsetofPPCGuestState(guest_VSR11);
   1133    case 12: return offsetofPPCGuestState(guest_VSR12);
   1134    case 13: return offsetofPPCGuestState(guest_VSR13);
   1135    case 14: return offsetofPPCGuestState(guest_VSR14);
   1136    case 15: return offsetofPPCGuestState(guest_VSR15);
   1137    case 16: return offsetofPPCGuestState(guest_VSR16);
   1138    case 17: return offsetofPPCGuestState(guest_VSR17);
   1139    case 18: return offsetofPPCGuestState(guest_VSR18);
   1140    case 19: return offsetofPPCGuestState(guest_VSR19);
   1141    case 20: return offsetofPPCGuestState(guest_VSR20);
   1142    case 21: return offsetofPPCGuestState(guest_VSR21);
   1143    case 22: return offsetofPPCGuestState(guest_VSR22);
   1144    case 23: return offsetofPPCGuestState(guest_VSR23);
   1145    case 24: return offsetofPPCGuestState(guest_VSR24);
   1146    case 25: return offsetofPPCGuestState(guest_VSR25);
   1147    case 26: return offsetofPPCGuestState(guest_VSR26);
   1148    case 27: return offsetofPPCGuestState(guest_VSR27);
   1149    case 28: return offsetofPPCGuestState(guest_VSR28);
   1150    case 29: return offsetofPPCGuestState(guest_VSR29);
   1151    case 30: return offsetofPPCGuestState(guest_VSR30);
   1152    case 31: return offsetofPPCGuestState(guest_VSR31);
   1153    case 32: return offsetofPPCGuestState(guest_VSR32);
   1154    case 33: return offsetofPPCGuestState(guest_VSR33);
   1155    case 34: return offsetofPPCGuestState(guest_VSR34);
   1156    case 35: return offsetofPPCGuestState(guest_VSR35);
   1157    case 36: return offsetofPPCGuestState(guest_VSR36);
   1158    case 37: return offsetofPPCGuestState(guest_VSR37);
   1159    case 38: return offsetofPPCGuestState(guest_VSR38);
   1160    case 39: return offsetofPPCGuestState(guest_VSR39);
   1161    case 40: return offsetofPPCGuestState(guest_VSR40);
   1162    case 41: return offsetofPPCGuestState(guest_VSR41);
   1163    case 42: return offsetofPPCGuestState(guest_VSR42);
   1164    case 43: return offsetofPPCGuestState(guest_VSR43);
   1165    case 44: return offsetofPPCGuestState(guest_VSR44);
   1166    case 45: return offsetofPPCGuestState(guest_VSR45);
   1167    case 46: return offsetofPPCGuestState(guest_VSR46);
   1168    case 47: return offsetofPPCGuestState(guest_VSR47);
   1169    case 48: return offsetofPPCGuestState(guest_VSR48);
   1170    case 49: return offsetofPPCGuestState(guest_VSR49);
   1171    case 50: return offsetofPPCGuestState(guest_VSR50);
   1172    case 51: return offsetofPPCGuestState(guest_VSR51);
   1173    case 52: return offsetofPPCGuestState(guest_VSR52);
   1174    case 53: return offsetofPPCGuestState(guest_VSR53);
   1175    case 54: return offsetofPPCGuestState(guest_VSR54);
   1176    case 55: return offsetofPPCGuestState(guest_VSR55);
   1177    case 56: return offsetofPPCGuestState(guest_VSR56);
   1178    case 57: return offsetofPPCGuestState(guest_VSR57);
   1179    case 58: return offsetofPPCGuestState(guest_VSR58);
   1180    case 59: return offsetofPPCGuestState(guest_VSR59);
   1181    case 60: return offsetofPPCGuestState(guest_VSR60);
   1182    case 61: return offsetofPPCGuestState(guest_VSR61);
   1183    case 62: return offsetofPPCGuestState(guest_VSR62);
   1184    case 63: return offsetofPPCGuestState(guest_VSR63);
   1185    default: break;
   1186    }
   1187    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
   1188 }
   1189 
   1190 /* Vector registers are mapped to VSX registers[32..63]. */
   1191 static Int vectorGuestRegOffset ( UInt archreg )
   1192 {
   1193    vassert(archreg < 32);
   1194 
   1195    switch (archreg) {
   1196    case  0: return offsetofPPCGuestState(guest_VSR32);
   1197    case  1: return offsetofPPCGuestState(guest_VSR33);
   1198    case  2: return offsetofPPCGuestState(guest_VSR34);
   1199    case  3: return offsetofPPCGuestState(guest_VSR35);
   1200    case  4: return offsetofPPCGuestState(guest_VSR36);
   1201    case  5: return offsetofPPCGuestState(guest_VSR37);
   1202    case  6: return offsetofPPCGuestState(guest_VSR38);
   1203    case  7: return offsetofPPCGuestState(guest_VSR39);
   1204    case  8: return offsetofPPCGuestState(guest_VSR40);
   1205    case  9: return offsetofPPCGuestState(guest_VSR41);
   1206    case 10: return offsetofPPCGuestState(guest_VSR42);
   1207    case 11: return offsetofPPCGuestState(guest_VSR43);
   1208    case 12: return offsetofPPCGuestState(guest_VSR44);
   1209    case 13: return offsetofPPCGuestState(guest_VSR45);
   1210    case 14: return offsetofPPCGuestState(guest_VSR46);
   1211    case 15: return offsetofPPCGuestState(guest_VSR47);
   1212    case 16: return offsetofPPCGuestState(guest_VSR48);
   1213    case 17: return offsetofPPCGuestState(guest_VSR49);
   1214    case 18: return offsetofPPCGuestState(guest_VSR50);
   1215    case 19: return offsetofPPCGuestState(guest_VSR51);
   1216    case 20: return offsetofPPCGuestState(guest_VSR52);
   1217    case 21: return offsetofPPCGuestState(guest_VSR53);
   1218    case 22: return offsetofPPCGuestState(guest_VSR54);
   1219    case 23: return offsetofPPCGuestState(guest_VSR55);
   1220    case 24: return offsetofPPCGuestState(guest_VSR56);
   1221    case 25: return offsetofPPCGuestState(guest_VSR57);
   1222    case 26: return offsetofPPCGuestState(guest_VSR58);
   1223    case 27: return offsetofPPCGuestState(guest_VSR59);
   1224    case 28: return offsetofPPCGuestState(guest_VSR60);
   1225    case 29: return offsetofPPCGuestState(guest_VSR61);
   1226    case 30: return offsetofPPCGuestState(guest_VSR62);
   1227    case 31: return offsetofPPCGuestState(guest_VSR63);
   1228    default: break;
   1229    }
   1230    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1231 }
   1232 
   1233 static IRExpr* getVReg ( UInt archreg )
   1234 {
   1235    vassert(archreg < 32);
   1236    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1237 }
   1238 
   1239 /* Ditto, but write to a reg instead. */
   1240 static void putVReg ( UInt archreg, IRExpr* e )
   1241 {
   1242    vassert(archreg < 32);
   1243    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1244    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1245 }
   1246 
   1247 /* Get contents of VSX guest register */
   1248 static IRExpr* getVSReg ( UInt archreg )
   1249 {
   1250    vassert(archreg < 64);
   1251    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
   1252 }
   1253 
   1254 /* Ditto, but write to a VSX reg instead. */
   1255 static void putVSReg ( UInt archreg, IRExpr* e )
   1256 {
   1257    vassert(archreg < 64);
   1258    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1259    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
   1260 }
   1261 
   1262 
   1263 static Int guestCR321offset ( UInt cr )
   1264 {
   1265    switch (cr) {
   1266    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1267    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1268    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1269    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1270    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1271    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1272    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1273    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1274    default: vpanic("guestCR321offset(ppc)");
   1275    }
   1276 }
   1277 
   1278 static Int guestCR0offset ( UInt cr )
   1279 {
   1280    switch (cr) {
   1281    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1282    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1283    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1284    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1285    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1286    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1287    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1288    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1289    default: vpanic("guestCR3offset(ppc)");
   1290    }
   1291 }
   1292 
   1293 /* Generate an IR sequence to do a popcount operation on the supplied
   1294    IRTemp, and return a new IRTemp holding the result.  'ty' may be
   1295    Ity_I32 or Ity_I64 only. */
   1296 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src )
   1297 {
   1298    Int i, shift[6];
   1299    IRTemp mask[6];
   1300    IRTemp old = IRTemp_INVALID;
   1301    IRTemp nyu = IRTemp_INVALID;
   1302 
   1303    vassert(ty == Ity_I64 || ty == Ity_I32);
   1304 
   1305    if (ty == Ity_I32) {
   1306       for (i = 0; i < 5; i++) {
   1307          mask[i]  = newTemp(ty);
   1308          shift[i] = 1 << i;
   1309       }
   1310       assign(mask[0], mkU32(0x55555555));
   1311       assign(mask[1], mkU32(0x33333333));
   1312       assign(mask[2], mkU32(0x0F0F0F0F));
   1313       assign(mask[3], mkU32(0x00FF00FF));
   1314       assign(mask[4], mkU32(0x0000FFFF));
   1315       old = src;
   1316       for (i = 0; i < 5; i++) {
   1317          nyu = newTemp(ty);
   1318          assign(nyu,
   1319                 binop(Iop_Add32,
   1320                       binop(Iop_And32,
   1321                             mkexpr(old),
   1322                             mkexpr(mask[i])),
   1323                       binop(Iop_And32,
   1324                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1325                             mkexpr(mask[i]))));
   1326          old = nyu;
   1327       }
   1328       return nyu;
   1329    }
   1330 // else, ty == Ity_I64
   1331    for (i = 0; i < 6; i++) {
   1332       mask[i] = newTemp( Ity_I64 );
   1333       shift[i] = 1 << i;
   1334    }
   1335    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
   1336    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
   1337    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
   1338    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
   1339    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
   1340    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
   1341    old = src;
   1342    for (i = 0; i < 6; i++) {
   1343       nyu = newTemp( Ity_I64 );
   1344       assign( nyu,
   1345               binop( Iop_Add64,
   1346                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
   1347                      binop( Iop_And64,
   1348                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
   1349                             mkexpr( mask[i] ) ) ) );
   1350       old = nyu;
   1351    }
   1352    return nyu;
   1353 }
   1354 
   1355 
   1356 // ROTL(src32/64, rot_amt5/6)
   1357 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1358                                           IRExpr* rot_amt )
   1359 {
   1360    IRExpr *mask, *rot;
   1361    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1362 
   1363    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1364       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1365       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1366       rot  = binop(Iop_Or64,
   1367                 binop(Iop_Shl64, src, mask),
   1368                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1369    } else {
   1370       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1371       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1372       rot  = binop(Iop_Or32,
   1373                 binop(Iop_Shl32, src, mask),
   1374                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1375    }
   1376    /* Note: the MuxOX is not merely an optimisation; it's needed
   1377       because otherwise the Shr is a shift by the word size when
   1378       mask denotes zero.  For rotates by immediates, a lot of
   1379       this junk gets folded out. */
   1380    return IRExpr_Mux0X( mask, /*     zero rotate */ src,
   1381                               /* non-zero rotate */ rot );
   1382 }
   1383 
   1384 /* Standard effective address calc: (rA + rB) */
   1385 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1386 {
   1387    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1388    vassert(rA < 32);
   1389    vassert(rB < 32);
   1390    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1391 }
   1392 
   1393 /* Standard effective address calc: (rA + simm) */
   1394 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1395 {
   1396    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1397    vassert(rA < 32);
   1398    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1399                 mkSzExtendS16(ty, simm16));
   1400 }
   1401 
   1402 /* Standard effective address calc: (rA|0) */
   1403 static IRExpr* ea_rAor0 ( UInt rA )
   1404 {
   1405    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1406    vassert(rA < 32);
   1407    if (rA == 0) {
   1408       return mkSzImm(ty, 0);
   1409    } else {
   1410       return getIReg(rA);
   1411    }
   1412 }
   1413 
   1414 /* Standard effective address calc: (rA|0) + rB */
   1415 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1416 {
   1417    vassert(rA < 32);
   1418    vassert(rB < 32);
   1419    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1420 }
   1421 
   1422 /* Standard effective address calc: (rA|0) + simm16 */
   1423 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1424 {
   1425    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1426    vassert(rA < 32);
   1427    if (rA == 0) {
   1428       return mkSzExtendS16(ty, simm16);
   1429    } else {
   1430       return ea_rA_simm( rA, simm16 );
   1431    }
   1432 }
   1433 
   1434 
   1435 /* Align effective address */
   1436 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1437 {
   1438    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1439    Long mask;
   1440    switch (align) {
   1441    case 1:  return addr;                    // byte aligned
   1442    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
   1443    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
   1444    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
   1445    default:
   1446       vex_printf("addr_align: align = %u\n", align);
   1447       vpanic("addr_align(ppc)");
   1448    }
   1449 
   1450    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1451    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1452 }
   1453 
   1454 
   1455 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1456    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1457    restart of the current insn. */
   1458 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1459 {
   1460    vassert(align == 4 || align == 8);
   1461    if (mode64) {
   1462       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1463       stmt(
   1464          IRStmt_Exit(
   1465             binop(Iop_CmpNE64,
   1466                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1467                   mkU64(0)),
   1468             Ijk_SigBUS,
   1469             IRConst_U64( guest_CIA_curr_instr )
   1470          )
   1471       );
   1472    } else {
   1473       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1474       stmt(
   1475          IRStmt_Exit(
   1476             binop(Iop_CmpNE32,
   1477                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1478                   mkU32(0)),
   1479             Ijk_SigBUS,
   1480             IRConst_U32( guest_CIA_curr_instr )
   1481          )
   1482       );
   1483    }
   1484 }
   1485 
   1486 
   1487 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1488    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1489    N) becomes undefined.  That is at function calls and returns.  ELF
   1490    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1491    the address of the next instruction to be executed.
   1492 */
   1493 static void make_redzone_AbiHint ( VexAbiInfo* vbi,
   1494                                    IRTemp nia, HChar* who )
   1495 {
   1496    Int szB = vbi->guest_stack_redzone_size;
   1497    if (0) vex_printf("AbiHint: %s\n", who);
   1498    vassert(szB >= 0);
   1499    if (szB > 0) {
   1500       if (mode64) {
   1501          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1502          stmt( IRStmt_AbiHint(
   1503                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1504                   szB,
   1505                   mkexpr(nia)
   1506          ));
   1507       } else {
   1508          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1509          stmt( IRStmt_AbiHint(
   1510                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1511                   szB,
   1512                   mkexpr(nia)
   1513          ));
   1514       }
   1515    }
   1516 }
   1517 
   1518 
   1519 /*------------------------------------------------------------*/
   1520 /*--- Helpers for condition codes.                         ---*/
   1521 /*------------------------------------------------------------*/
   1522 
   1523 /* Condition register layout.
   1524 
   1525    In the hardware, CR is laid out like this.  The leftmost end is the
   1526    most significant bit in the register; however the IBM documentation
   1527    numbers the bits backwards for some reason.
   1528 
   1529    CR0      CR1    ..........   CR6       CR7
   1530    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1531    31  28                             3    0     (normal bit numbering)
   1532 
   1533    Each CR field is 4 bits:  [<,>,==,SO]
   1534 
   1535    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1536 
   1537    Indexing from BI to guest state:
   1538 
   1539      let    n = BI / 4
   1540           off = BI % 4
   1541      this references CR n:
   1542 
   1543         off==0   ->  guest_CRn_321 >> 3
   1544         off==1   ->  guest_CRn_321 >> 2
   1545         off==2   ->  guest_CRn_321 >> 1
   1546         off==3   ->  guest_CRn_SO
   1547 
   1548    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1549    (normal notation) and in guest_CRn_321 the significant bits are
   1550    3, 2 and 1 (normal notation).
   1551 */
   1552 
   1553 static void putCR321 ( UInt cr, IRExpr* e )
   1554 {
   1555    vassert(cr < 8);
   1556    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1557    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1558 }
   1559 
   1560 static void putCR0 ( UInt cr, IRExpr* e )
   1561 {
   1562    vassert(cr < 8);
   1563    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1564    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1565 }
   1566 
   1567 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1568 {
   1569    vassert(cr < 8);
   1570    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1571 }
   1572 
   1573 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1574 {
   1575    vassert(cr < 8);
   1576    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1577 }
   1578 
   1579 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1580    return it at the bottom of an I32; the top 31 bits are guaranteed
   1581    to be zero. */
   1582 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1583 {
   1584    UInt n   = bi / 4;
   1585    UInt off = bi % 4;
   1586    vassert(bi < 32);
   1587    if (off == 3) {
   1588       /* Fetch the SO bit for this CR field */
   1589       /* Note: And32 is redundant paranoia iff guest state only has 0
   1590          or 1 in that slot. */
   1591       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1592    } else {
   1593       /* Fetch the <, > or == bit for this CR field */
   1594       return binop( Iop_And32,
   1595                     binop( Iop_Shr32,
   1596                            unop(Iop_8Uto32, getCR321(n)),
   1597                            mkU8(toUChar(3-off)) ),
   1598                     mkU32(1) );
   1599    }
   1600 }
   1601 
   1602 /* Dually, write the least significant bit of BIT to the specified CR
   1603    bit.  Indexing as per getCRbit. */
   1604 static void putCRbit ( UInt bi, IRExpr* bit )
   1605 {
   1606    UInt    n, off;
   1607    IRExpr* safe;
   1608    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1609    safe = binop(Iop_And32, bit, mkU32(1));
   1610    n   = bi / 4;
   1611    off = bi % 4;
   1612    vassert(bi < 32);
   1613    if (off == 3) {
   1614       /* This is the SO bit for this CR field */
   1615       putCR0(n, unop(Iop_32to8, safe));
   1616    } else {
   1617       off = 3 - off;
   1618       vassert(off == 1 || off == 2 || off == 3);
   1619       putCR321(
   1620          n,
   1621          unop( Iop_32to8,
   1622                binop( Iop_Or32,
   1623                       /* old value with field masked out */
   1624                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1625                                        mkU32(~(1 << off))),
   1626                       /* new value in the right place */
   1627                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1628                )
   1629          )
   1630       );
   1631    }
   1632 }
   1633 
   1634 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1635    return it somewhere in an I32; it does not matter where, but
   1636    whichever bit it is, all other bits are guaranteed to be zero.  In
   1637    other words, the I32-typed expression will be zero if the bit is
   1638    zero and nonzero if the bit is 1.  Write into *where the index
   1639    of where the bit will be. */
   1640 
   1641 static
   1642 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   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       *where = 0;
   1652       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1653    } else {
   1654       /* Fetch the <, > or == bit for this CR field */
   1655       *where = 3-off;
   1656       return binop( Iop_And32,
   1657                     unop(Iop_8Uto32, getCR321(n)),
   1658                     mkU32(1 << (3-off)) );
   1659    }
   1660 }
   1661 
   1662 /* Set the CR0 flags following an arithmetic operation.
   1663    (Condition Register CR0 Field Definition, PPC32 p60)
   1664 */
   1665 static IRExpr* getXER_SO ( void );
   1666 static void set_CR0 ( IRExpr* result )
   1667 {
   1668    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1669            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1670    if (mode64) {
   1671       putCR321( 0, unop(Iop_64to8,
   1672                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1673    } else {
   1674       putCR321( 0, unop(Iop_32to8,
   1675                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1676    }
   1677    putCR0( 0, getXER_SO() );
   1678 }
   1679 
   1680 
   1681 /* Set the CR6 flags following an AltiVec compare operation.
   1682  * NOTE: This also works for VSX single-precision compares.
   1683  * */
   1684 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1685 {
   1686    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1687       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1688       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1689    */
   1690    IRTemp v0 = newTemp(Ity_V128);
   1691    IRTemp v1 = newTemp(Ity_V128);
   1692    IRTemp v2 = newTemp(Ity_V128);
   1693    IRTemp v3 = newTemp(Ity_V128);
   1694    IRTemp rOnes  = newTemp(Ity_I8);
   1695    IRTemp rZeros = newTemp(Ity_I8);
   1696 
   1697    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1698 
   1699    assign( v0, result );
   1700    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1701    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1702    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1703 
   1704    assign( rZeros, unop(Iop_1Uto8,
   1705        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1706              unop(Iop_Not32,
   1707                   unop(Iop_V128to32,
   1708                        binop(Iop_OrV128,
   1709                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1710                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1711                   ))) );
   1712 
   1713    if (test_all_ones) {
   1714       assign( rOnes, unop(Iop_1Uto8,
   1715          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1716                unop(Iop_V128to32,
   1717                     binop(Iop_AndV128,
   1718                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   1719                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   1720                     ))) );
   1721       putCR321( 6, binop(Iop_Or8,
   1722                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   1723                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   1724    } else {
   1725       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   1726    }
   1727    putCR0( 6, mkU8(0) );
   1728 }
   1729 
   1730 
   1731 
   1732 /*------------------------------------------------------------*/
   1733 /*--- Helpers for XER flags.                               ---*/
   1734 /*------------------------------------------------------------*/
   1735 
   1736 static void putXER_SO ( IRExpr* e )
   1737 {
   1738    IRExpr* so;
   1739    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1740    so = binop(Iop_And8, e, mkU8(1));
   1741    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   1742 }
   1743 
   1744 static void putXER_OV ( IRExpr* e )
   1745 {
   1746    IRExpr* ov;
   1747    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1748    ov = binop(Iop_And8, e, mkU8(1));
   1749    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   1750 }
   1751 
   1752 static void putXER_CA ( IRExpr* e )
   1753 {
   1754    IRExpr* ca;
   1755    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1756    ca = binop(Iop_And8, e, mkU8(1));
   1757    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   1758 }
   1759 
   1760 static void putXER_BC ( IRExpr* e )
   1761 {
   1762    IRExpr* bc;
   1763    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1764    bc = binop(Iop_And8, e, mkU8(0x7F));
   1765    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   1766 }
   1767 
   1768 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   1769 {
   1770    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   1771 }
   1772 
   1773 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   1774 {
   1775    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   1776 }
   1777 
   1778 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   1779 {
   1780    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   1781 }
   1782 
   1783 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   1784 {
   1785    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   1786 }
   1787 
   1788 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   1789 {
   1790    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   1791    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   1792 }
   1793 
   1794 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   1795 {
   1796    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1797 }
   1798 
   1799 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   1800 {
   1801    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1802    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   1803 }
   1804 
   1805 
   1806 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   1807    %XER.SO accordingly. */
   1808 
   1809 static void set_XER_OV_32( UInt op, IRExpr* res,
   1810                            IRExpr* argL, IRExpr* argR )
   1811 {
   1812    IRTemp  t64;
   1813    IRExpr* xer_ov;
   1814    vassert(op < PPCG_FLAG_OP_NUMBER);
   1815    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   1816    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   1817    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   1818 
   1819 #  define INT32_MIN 0x80000000
   1820 
   1821 #  define XOR2(_aa,_bb) \
   1822       binop(Iop_Xor32,(_aa),(_bb))
   1823 
   1824 #  define XOR3(_cc,_dd,_ee) \
   1825       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   1826 
   1827 #  define AND3(_ff,_gg,_hh) \
   1828       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   1829 
   1830 #define NOT(_jj) \
   1831       unop(Iop_Not32, (_jj))
   1832 
   1833    switch (op) {
   1834    case /* 0  */ PPCG_FLAG_OP_ADD:
   1835    case /* 1  */ PPCG_FLAG_OP_ADDE:
   1836       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   1837       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   1838       xer_ov
   1839          = AND3( XOR3(argL,argR,mkU32(-1)),
   1840                  XOR2(argL,res),
   1841                  mkU32(INT32_MIN) );
   1842       /* xer_ov can only be 0 or 1<<31 */
   1843       xer_ov
   1844          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1845       break;
   1846 
   1847    case /* 2  */ PPCG_FLAG_OP_DIVW:
   1848       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   1849       xer_ov
   1850          = mkOR1(
   1851               mkAND1(
   1852                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   1853                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   1854               ),
   1855               binop(Iop_CmpEQ32, argR, mkU32(0) )
   1856            );
   1857       xer_ov
   1858          = unop(Iop_1Uto32, xer_ov);
   1859       break;
   1860 
   1861    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   1862       /* argR == 0 */
   1863       xer_ov
   1864          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   1865       break;
   1866 
   1867    case /* 4  */ PPCG_FLAG_OP_MULLW:
   1868       /* OV true if result can't be represented in 32 bits
   1869          i.e sHi != sign extension of sLo */
   1870       t64 = newTemp(Ity_I64);
   1871       assign( t64, binop(Iop_MullS32, argL, argR) );
   1872       xer_ov
   1873          = binop( Iop_CmpNE32,
   1874                   unop(Iop_64HIto32, mkexpr(t64)),
   1875                   binop( Iop_Sar32,
   1876                          unop(Iop_64to32, mkexpr(t64)),
   1877                          mkU8(31))
   1878                   );
   1879       xer_ov
   1880          = unop(Iop_1Uto32, xer_ov);
   1881       break;
   1882 
   1883    case /* 5  */ PPCG_FLAG_OP_NEG:
   1884       /* argL == INT32_MIN */
   1885       xer_ov
   1886          = unop( Iop_1Uto32,
   1887                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   1888       break;
   1889 
   1890    case /* 6  */ PPCG_FLAG_OP_SUBF:
   1891    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   1892    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   1893       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   1894       xer_ov
   1895          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   1896                  XOR2(NOT(argL),res),
   1897                  mkU32(INT32_MIN) );
   1898       /* xer_ov can only be 0 or 1<<31 */
   1899       xer_ov
   1900          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1901       break;
   1902 
   1903    case PPCG_FLAG_OP_DIVWEU:
   1904       xer_ov
   1905                = binop( Iop_Or32,
   1906                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   1907                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
   1908       break;
   1909 
   1910    case PPCG_FLAG_OP_DIVWE:
   1911 
   1912       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
   1913        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
   1914        * an overflow is implied.
   1915        */
   1916       xer_ov = binop( Iop_Or32,
   1917                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   1918                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
   1919                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
   1920                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
   1921       break;
   1922 
   1923 
   1924 
   1925    default:
   1926       vex_printf("set_XER_OV: op = %u\n", op);
   1927       vpanic("set_XER_OV(ppc)");
   1928    }
   1929 
   1930    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   1931    putXER_OV( unop(Iop_32to8, xer_ov) );
   1932 
   1933    /* Update the summary overflow */
   1934    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   1935 
   1936 #  undef INT32_MIN
   1937 #  undef AND3
   1938 #  undef XOR3
   1939 #  undef XOR2
   1940 #  undef NOT
   1941 }
   1942 
   1943 static void set_XER_OV_64( UInt op, IRExpr* res,
   1944                            IRExpr* argL, IRExpr* argR )
   1945 {
   1946    IRExpr* xer_ov;
   1947    vassert(op < PPCG_FLAG_OP_NUMBER);
   1948    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   1949    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   1950    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   1951 
   1952 #  define INT64_MIN 0x8000000000000000ULL
   1953 
   1954 #  define XOR2(_aa,_bb) \
   1955       binop(Iop_Xor64,(_aa),(_bb))
   1956 
   1957 #  define XOR3(_cc,_dd,_ee) \
   1958       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   1959 
   1960 #  define AND3(_ff,_gg,_hh) \
   1961       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   1962 
   1963 #define NOT(_jj) \
   1964       unop(Iop_Not64, (_jj))
   1965 
   1966    switch (op) {
   1967    case /* 0  */ PPCG_FLAG_OP_ADD:
   1968    case /* 1  */ PPCG_FLAG_OP_ADDE:
   1969       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   1970       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   1971       xer_ov
   1972          = AND3( XOR3(argL,argR,mkU64(-1)),
   1973                  XOR2(argL,res),
   1974                  mkU64(INT64_MIN) );
   1975       /* xer_ov can only be 0 or 1<<63 */
   1976       xer_ov
   1977          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   1978       break;
   1979 
   1980    case /* 2  */ PPCG_FLAG_OP_DIVW:
   1981       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   1982       xer_ov
   1983          = mkOR1(
   1984               mkAND1(
   1985                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   1986                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   1987               ),
   1988               binop(Iop_CmpEQ64, argR, mkU64(0) )
   1989            );
   1990       break;
   1991 
   1992    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   1993       /* argR == 0 */
   1994       xer_ov
   1995          = binop(Iop_CmpEQ64, argR, mkU64(0));
   1996       break;
   1997 
   1998    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   1999       /* OV true if result can't be represented in 64 bits
   2000          i.e sHi != sign extension of sLo */
   2001       xer_ov
   2002          = binop( Iop_CmpNE32,
   2003                   unop(Iop_64HIto32, res),
   2004                   binop( Iop_Sar32,
   2005                          unop(Iop_64to32, res),
   2006                          mkU8(31))
   2007                   );
   2008       break;
   2009    }
   2010 
   2011    case /* 5  */ PPCG_FLAG_OP_NEG:
   2012       /* argL == INT64_MIN */
   2013       xer_ov
   2014          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   2015       break;
   2016 
   2017    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2018    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2019    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2020       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   2021       xer_ov
   2022          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   2023                  XOR2(NOT(argL),res),
   2024                  mkU64(INT64_MIN) );
   2025       /* xer_ov can only be 0 or 1<<63 */
   2026       xer_ov
   2027          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2028       break;
   2029 
   2030    case PPCG_FLAG_OP_DIVDE:
   2031 
   2032       /* If argR == 0, we must set the OV bit.  But there's another condition
   2033        * where we can get overflow set for divde . . . when the
   2034        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
   2035        * both dividend and divisor are non-zero, it implies an overflow.
   2036        */
   2037       xer_ov
   2038                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2039                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
   2040                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
   2041                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
   2042       break;
   2043 
   2044    case PPCG_FLAG_OP_DIVDEU:
   2045      /* If argR == 0 or if argL >= argR, set OV. */
   2046      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2047                          binop( Iop_CmpLE64U, argR, argL ) );
   2048      break;
   2049 
   2050    default:
   2051       vex_printf("set_XER_OV: op = %u\n", op);
   2052       vpanic("set_XER_OV(ppc64)");
   2053    }
   2054 
   2055    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2056    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   2057 
   2058    /* Update the summary overflow */
   2059    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2060 
   2061 #  undef INT64_MIN
   2062 #  undef AND3
   2063 #  undef XOR3
   2064 #  undef XOR2
   2065 #  undef NOT
   2066 }
   2067 
   2068 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   2069                          IRExpr* argL, IRExpr* argR )
   2070 {
   2071    if (ty == Ity_I32)
   2072       set_XER_OV_32( op, res, argL, argR );
   2073    else
   2074       set_XER_OV_64( op, res, argL, argR );
   2075 }
   2076 
   2077 
   2078 
   2079 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   2080    value being OLDCA.  Set %XER.CA accordingly. */
   2081 
   2082 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   2083                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2084 {
   2085    IRExpr* xer_ca;
   2086    vassert(op < PPCG_FLAG_OP_NUMBER);
   2087    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   2088    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   2089    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   2090    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   2091 
   2092    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2093       seems reasonable given that it's always generated by
   2094       getXER_CA32(), which masks it accordingly.  In any case it being
   2095       0 or 1 is an invariant of the ppc guest state representation;
   2096       if it has any other value, that invariant has been violated. */
   2097 
   2098    switch (op) {
   2099    case /* 0 */ PPCG_FLAG_OP_ADD:
   2100       /* res <u argL */
   2101       xer_ca
   2102          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   2103       break;
   2104 
   2105    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2106       /* res <u argL || (old_ca==1 && res==argL) */
   2107       xer_ca
   2108          = mkOR1(
   2109               binop(Iop_CmpLT32U, res, argL),
   2110               mkAND1(
   2111                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2112                  binop(Iop_CmpEQ32, res, argL)
   2113               )
   2114            );
   2115       xer_ca
   2116          = unop(Iop_1Uto32, xer_ca);
   2117       break;
   2118 
   2119    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2120       /* res <u argR || (old_ca==1 && res==argR) */
   2121       xer_ca
   2122          = mkOR1(
   2123               binop(Iop_CmpLT32U, res, argR),
   2124               mkAND1(
   2125                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2126                  binop(Iop_CmpEQ32, res, argR)
   2127               )
   2128            );
   2129       xer_ca
   2130          = unop(Iop_1Uto32, xer_ca);
   2131       break;
   2132 
   2133    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2134    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2135       /* res <=u argR */
   2136       xer_ca
   2137          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   2138       break;
   2139 
   2140    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2141       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2142          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2143          bit of argL. */
   2144       /* This term valid for shift amount < 32 only */
   2145       xer_ca
   2146          = binop(
   2147               Iop_And32,
   2148               binop(Iop_Sar32, argL, mkU8(31)),
   2149               binop( Iop_And32,
   2150                      argL,
   2151                      binop( Iop_Sub32,
   2152                             binop(Iop_Shl32, mkU32(1),
   2153                                              unop(Iop_32to8,argR)),
   2154                             mkU32(1) )
   2155                      )
   2156               );
   2157       xer_ca
   2158          = IRExpr_Mux0X(
   2159               /* shift amt > 31 ? */
   2160               unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
   2161               /* no -- be like srawi */
   2162               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
   2163               /* yes -- get sign bit of argL */
   2164               binop(Iop_Shr32, argL, mkU8(31))
   2165            );
   2166       break;
   2167 
   2168    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2169       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   2170          0.  Since the shift amount is known to be in the range
   2171          0 .. 31 inclusive the following seems viable:
   2172          xer.ca == 1 iff the following is nonzero:
   2173          (argL >>s 31)           -- either all 0s or all 1s
   2174          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2175       xer_ca
   2176          = binop(
   2177               Iop_And32,
   2178               binop(Iop_Sar32, argL, mkU8(31)),
   2179               binop( Iop_And32,
   2180                      argL,
   2181                      binop( Iop_Sub32,
   2182                             binop(Iop_Shl32, mkU32(1),
   2183                                              unop(Iop_32to8,argR)),
   2184                             mkU32(1) )
   2185                      )
   2186               );
   2187       xer_ca
   2188          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   2189       break;
   2190 
   2191    default:
   2192       vex_printf("set_XER_CA: op = %u\n", op);
   2193       vpanic("set_XER_CA(ppc)");
   2194    }
   2195 
   2196    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2197    putXER_CA( unop(Iop_32to8, xer_ca) );
   2198 }
   2199 
   2200 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   2201                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2202 {
   2203    IRExpr* xer_ca;
   2204    vassert(op < PPCG_FLAG_OP_NUMBER);
   2205    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   2206    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   2207    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   2208    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   2209 
   2210    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2211       seems reasonable given that it's always generated by
   2212       getXER_CA32(), which masks it accordingly.  In any case it being
   2213       0 or 1 is an invariant of the ppc guest state representation;
   2214       if it has any other value, that invariant has been violated. */
   2215 
   2216    switch (op) {
   2217    case /* 0 */ PPCG_FLAG_OP_ADD:
   2218       /* res <u argL */
   2219       xer_ca
   2220          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   2221       break;
   2222 
   2223    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2224       /* res <u argL || (old_ca==1 && res==argL) */
   2225       xer_ca
   2226          = mkOR1(
   2227               binop(Iop_CmpLT64U, res, argL),
   2228               mkAND1(
   2229                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2230                  binop(Iop_CmpEQ64, res, argL)
   2231                  )
   2232               );
   2233       xer_ca
   2234          = unop(Iop_1Uto32, xer_ca);
   2235       break;
   2236 
   2237    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2238       /* res <u argR || (old_ca==1 && res==argR) */
   2239       xer_ca
   2240          = mkOR1(
   2241               binop(Iop_CmpLT64U, res, argR),
   2242               mkAND1(
   2243                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2244                  binop(Iop_CmpEQ64, res, argR)
   2245               )
   2246            );
   2247       xer_ca
   2248          = unop(Iop_1Uto32, xer_ca);
   2249       break;
   2250 
   2251    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2252    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2253       /* res <=u argR */
   2254       xer_ca
   2255          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   2256       break;
   2257 
   2258 
   2259    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2260       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   2261          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2262          bit of argL. */
   2263          /* This term valid for shift amount < 31 only */
   2264 
   2265       xer_ca
   2266          = binop(
   2267               Iop_And64,
   2268               binop(Iop_Sar64, argL, mkU8(31)),
   2269               binop( Iop_And64,
   2270                      argL,
   2271                      binop( Iop_Sub64,
   2272                             binop(Iop_Shl64, mkU64(1),
   2273                                              unop(Iop_64to8,argR)),
   2274                             mkU64(1) )
   2275               )
   2276            );
   2277       xer_ca
   2278          = IRExpr_Mux0X(
   2279               /* shift amt > 31 ? */
   2280               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
   2281               /* no -- be like srawi */
   2282               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   2283               /* yes -- get sign bit of argL */
   2284               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   2285            );
   2286       break;
   2287 
   2288    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2289       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2290          Since the shift amount is known to be in the range 0 .. 31
   2291          inclusive the following seems viable:
   2292          xer.ca == 1 iff the following is nonzero:
   2293          (argL >>s 31)           -- either all 0s or all 1s
   2294          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2295 
   2296       xer_ca
   2297          = binop(
   2298               Iop_And64,
   2299               binop(Iop_Sar64, argL, mkU8(31)),
   2300               binop( Iop_And64,
   2301                      argL,
   2302                      binop( Iop_Sub64,
   2303                             binop(Iop_Shl64, mkU64(1),
   2304                                              unop(Iop_64to8,argR)),
   2305                             mkU64(1) )
   2306               )
   2307            );
   2308       xer_ca
   2309          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2310       break;
   2311 
   2312 
   2313    case /* 12 */ PPCG_FLAG_OP_SRAD:
   2314       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2315          If it is <= 63, behave like SRADI; else XER.CA is the sign
   2316          bit of argL. */
   2317          /* This term valid for shift amount < 63 only */
   2318 
   2319       xer_ca
   2320          = binop(
   2321               Iop_And64,
   2322               binop(Iop_Sar64, argL, mkU8(63)),
   2323               binop( Iop_And64,
   2324                      argL,
   2325                      binop( Iop_Sub64,
   2326                             binop(Iop_Shl64, mkU64(1),
   2327                                              unop(Iop_64to8,argR)),
   2328                             mkU64(1) )
   2329               )
   2330            );
   2331       xer_ca
   2332          = IRExpr_Mux0X(
   2333               /* shift amt > 63 ? */
   2334               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
   2335               /* no -- be like sradi */
   2336               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   2337               /* yes -- get sign bit of argL */
   2338               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   2339            );
   2340       break;
   2341 
   2342 
   2343    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2344       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2345          Since the shift amount is known to be in the range 0 .. 63
   2346          inclusive, the following seems viable:
   2347          xer.ca == 1 iff the following is nonzero:
   2348          (argL >>s 63)           -- either all 0s or all 1s
   2349          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2350 
   2351       xer_ca
   2352          = binop(
   2353               Iop_And64,
   2354               binop(Iop_Sar64, argL, mkU8(63)),
   2355               binop( Iop_And64,
   2356                      argL,
   2357                      binop( Iop_Sub64,
   2358                             binop(Iop_Shl64, mkU64(1),
   2359                                              unop(Iop_64to8,argR)),
   2360                             mkU64(1) )
   2361               )
   2362            );
   2363       xer_ca
   2364          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2365       break;
   2366 
   2367    default:
   2368       vex_printf("set_XER_CA: op = %u\n", op);
   2369       vpanic("set_XER_CA(ppc64)");
   2370    }
   2371 
   2372    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2373    putXER_CA( unop(Iop_32to8, xer_ca) );
   2374 }
   2375 
   2376 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2377                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2378 {
   2379    if (ty == Ity_I32)
   2380       set_XER_CA_32( op, res, argL, argR, oldca );
   2381    else
   2382       set_XER_CA_64( op, res, argL, argR, oldca );
   2383 }
   2384 
   2385 
   2386 
   2387 /*------------------------------------------------------------*/
   2388 /*--- Read/write to guest-state                           --- */
   2389 /*------------------------------------------------------------*/
   2390 
   2391 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2392 {
   2393    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2394    switch (reg) {
   2395    case PPC_GST_SPRG3_RO:
   2396       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2397 
   2398    case PPC_GST_CIA:
   2399       return IRExpr_Get( OFFB_CIA, ty );
   2400 
   2401    case PPC_GST_LR:
   2402       return IRExpr_Get( OFFB_LR, ty );
   2403 
   2404    case PPC_GST_CTR:
   2405       return IRExpr_Get( OFFB_CTR, ty );
   2406 
   2407    case PPC_GST_VRSAVE:
   2408       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2409 
   2410    case PPC_GST_VSCR:
   2411       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2412                               mkU32(MASK_VSCR_VALID));
   2413 
   2414    case PPC_GST_CR: {
   2415       /* Synthesise the entire CR into a single word.  Expensive. */
   2416 #     define FIELD(_n)                                               \
   2417          binop(Iop_Shl32,                                            \
   2418                unop(Iop_8Uto32,                                      \
   2419                     binop(Iop_Or8,                                   \
   2420                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2421                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2422                     )                                                \
   2423                ),                                                    \
   2424                mkU8(4 * (7-(_n)))                                    \
   2425          )
   2426       return binop(Iop_Or32,
   2427                    binop(Iop_Or32,
   2428                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2429                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2430                          ),
   2431                    binop(Iop_Or32,
   2432                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2433                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2434                          )
   2435                    );
   2436 #     undef FIELD
   2437    }
   2438 
   2439    case PPC_GST_XER:
   2440       return binop(Iop_Or32,
   2441                    binop(Iop_Or32,
   2442                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2443                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2444                    binop(Iop_Or32,
   2445                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2446                          getXER_BC32()));
   2447 
   2448    default:
   2449       vex_printf("getGST(ppc): reg = %u", reg);
   2450       vpanic("getGST(ppc)");
   2451    }
   2452 }
   2453 
   2454 /* Get a masked word from the given reg */
   2455 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2456 {
   2457    IRTemp val = newTemp(Ity_I32);
   2458    vassert( reg < PPC_GST_MAX );
   2459 
   2460    switch (reg) {
   2461 
   2462    case PPC_GST_FPSCR: {
   2463       /* Vex-generated code expects the FPSCR to be set as follows:
   2464          all exceptions masked, round-to-nearest.
   2465          This corresponds to a FPSCR value of 0x0. */
   2466 
   2467       /* We're only keeping track of the rounding mode,
   2468          so if the mask isn't asking for this, just return 0x0 */
   2469       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
   2470          assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
   2471       } else {
   2472          assign( val, mkU32(0x0) );
   2473       }
   2474       break;
   2475    }
   2476 
   2477    default:
   2478       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2479       vpanic("getGST_masked(ppc)");
   2480    }
   2481 
   2482    if (mask != 0xFFFFFFFF) {
   2483       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2484    } else {
   2485       return mkexpr(val);
   2486    }
   2487 }
   2488 
   2489 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2490    and return it at the bottom of an I32; the top 27 bits are
   2491    guaranteed to be zero. */
   2492 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2493 {
   2494    UInt shft, mask;
   2495 
   2496    vassert( fld < 8 );
   2497    vassert( reg < PPC_GST_MAX );
   2498 
   2499    shft = 4*(7-fld);
   2500    mask = 0xF<<shft;
   2501 
   2502    switch (reg) {
   2503    case PPC_GST_XER:
   2504       vassert(fld ==7);
   2505       return binop(Iop_Or32,
   2506                    binop(Iop_Or32,
   2507                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2508                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2509                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2510       break;
   2511 
   2512    default:
   2513       if (shft == 0)
   2514          return getGST_masked( reg, mask );
   2515       else
   2516          return binop(Iop_Shr32,
   2517                       getGST_masked( reg, mask ),
   2518                       mkU8(toUChar( shft )));
   2519    }
   2520 }
   2521 
   2522 static void putGST ( PPC_GST reg, IRExpr* src )
   2523 {
   2524    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2525    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2526    vassert( reg < PPC_GST_MAX );
   2527    switch (reg) {
   2528    case PPC_GST_IP_AT_SYSCALL:
   2529       vassert( ty_src == ty );
   2530       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2531       break;
   2532    case PPC_GST_CIA:
   2533       vassert( ty_src == ty );
   2534       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2535       break;
   2536    case PPC_GST_LR:
   2537       vassert( ty_src == ty );
   2538       stmt( IRStmt_Put( OFFB_LR, src ) );
   2539       break;
   2540    case PPC_GST_CTR:
   2541       vassert( ty_src == ty );
   2542       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2543       break;
   2544    case PPC_GST_VRSAVE:
   2545       vassert( ty_src == Ity_I32 );
   2546       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2547       break;
   2548    case PPC_GST_VSCR:
   2549       vassert( ty_src == Ity_I32 );
   2550       stmt( IRStmt_Put( OFFB_VSCR,
   2551                         binop(Iop_And32, src,
   2552                               mkU32(MASK_VSCR_VALID)) ) );
   2553       break;
   2554    case PPC_GST_XER:
   2555       vassert( ty_src == Ity_I32 );
   2556       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2557       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2558       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2559       putXER_BC( unop(Iop_32to8, src) );
   2560       break;
   2561 
   2562    case PPC_GST_EMWARN:
   2563       vassert( ty_src == Ity_I32 );
   2564       stmt( IRStmt_Put( OFFB_EMWARN,src) );
   2565       break;
   2566 
   2567    case PPC_GST_TISTART:
   2568       vassert( ty_src == ty );
   2569       stmt( IRStmt_Put( OFFB_TISTART, src) );
   2570       break;
   2571 
   2572    case PPC_GST_TILEN:
   2573       vassert( ty_src == ty );
   2574       stmt( IRStmt_Put( OFFB_TILEN, src) );
   2575       break;
   2576 
   2577    default:
   2578       vex_printf("putGST(ppc): reg = %u", reg);
   2579       vpanic("putGST(ppc)");
   2580    }
   2581 }
   2582 
   2583 /* Write masked src to the given reg */
   2584 static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
   2585 {
   2586    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2587    vassert( reg < PPC_GST_MAX );
   2588    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2589 
   2590    switch (reg) {
   2591    case PPC_GST_FPSCR: {
   2592       /* Allow writes to Rounding Mode */
   2593       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
   2594          /* construct new fpround from new and old values as per mask:
   2595             new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
   2596          stmt(
   2597             IRStmt_Put(
   2598                OFFB_FPROUND,
   2599                binop(
   2600                   Iop_Or32,
   2601                   binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
   2602                   binop(
   2603                      Iop_And32,
   2604                      IRExpr_Get(OFFB_FPROUND,Ity_I32),
   2605                      mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
   2606                   )
   2607                )
   2608             )
   2609          );
   2610       }
   2611 
   2612       /* Give EmWarn for attempted writes to:
   2613          - Exception Controls
   2614          - Non-IEEE Mode
   2615       */
   2616       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   2617          VexEmWarn ew = EmWarn_PPCexns;
   2618 
   2619          /* If any of the src::exception_control bits are actually set,
   2620             side-exit to the next insn, reporting the warning,
   2621             so that Valgrind's dispatcher sees the warning. */
   2622          putGST( PPC_GST_EMWARN, mkU32(ew) );
   2623          stmt(
   2624             IRStmt_Exit(
   2625                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
   2626                Ijk_EmWarn,
   2627                mkSzConst( ty, nextInsnAddr()) ));
   2628       }
   2629 
   2630       /* Ignore all other writes */
   2631       break;
   2632    }
   2633 
   2634    default:
   2635       vex_printf("putGST_masked(ppc): reg = %u", reg);
   2636       vpanic("putGST_masked(ppc)");
   2637    }
   2638 }
   2639 
   2640 /* Write the least significant nibble of src to the specified
   2641    REG[FLD] (as per IBM/hardware notation). */
   2642 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   2643 {
   2644    UInt shft, mask;
   2645 
   2646    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2647    vassert( fld < 8 );
   2648    vassert( reg < PPC_GST_MAX );
   2649 
   2650    shft = 4*(7-fld);
   2651    mask = 0xF<<shft;
   2652 
   2653    switch (reg) {
   2654    case PPC_GST_CR:
   2655       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   2656       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   2657       break;
   2658 
   2659    default:
   2660       if (shft == 0) {
   2661          putGST_masked( reg, src, mask );
   2662       } else {
   2663          putGST_masked( reg,
   2664                         binop(Iop_Shl32, src, mkU8(toUChar(shft))),
   2665                         mask );
   2666       }
   2667    }
   2668 }
   2669 
   2670 /*------------------------------------------------------------*/
   2671 /* Helpers for VSX instructions that do floating point
   2672  * operations and need to determine if a src contains a
   2673  * special FP value.
   2674  *
   2675  *------------------------------------------------------------*/
   2676 
   2677 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
   2678 #define FP_FRAC_PART(x) binop( Iop_And64, \
   2679                                mkexpr( x ), \
   2680                                mkU64( NONZERO_FRAC_MASK ) )
   2681 
   2682 // Returns exponent part of a single precision floating point as I32
   2683 static IRExpr * fp_exp_part_sp(IRTemp src)
   2684 {
   2685    return binop( Iop_And32,
   2686                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   2687                  mkU32( 0xff ) );
   2688 }
   2689 
   2690 // Returns exponent part of floating point as I32
   2691 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
   2692 {
   2693    IRExpr * exp;
   2694    if (sp)
   2695       return fp_exp_part_sp(src);
   2696 
   2697    if (!mode64)
   2698       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
   2699                                                       mkexpr( src ) ),
   2700                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
   2701    else
   2702       exp = unop( Iop_64to32,
   2703                   binop( Iop_And64,
   2704                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
   2705                          mkU64( 0x7ff ) ) );
   2706    return exp;
   2707 }
   2708 
   2709 static IRExpr * is_Inf_sp(IRTemp src)
   2710 {
   2711    IRTemp frac_part = newTemp(Ity_I32);
   2712    IRExpr * Inf_exp;
   2713 
   2714    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
   2715    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
   2716    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
   2717 }
   2718 
   2719 
   2720 // Infinity: exp = 7ff and fraction is zero; s = 0/1
   2721 static IRExpr * is_Inf(IRTemp src, Bool sp)
   2722 {
   2723    IRExpr * Inf_exp, * hi32, * low32;
   2724    IRTemp frac_part;
   2725 
   2726    if (sp)
   2727       return is_Inf_sp(src);
   2728 
   2729    frac_part = newTemp(Ity_I64);
   2730    assign( frac_part, FP_FRAC_PART(src) );
   2731    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
   2732    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   2733    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   2734    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   2735                                   mkU32( 0 ) ) );
   2736 }
   2737 
   2738 static IRExpr * is_Zero_sp(IRTemp src)
   2739 {
   2740    IRTemp sign_less_part = newTemp(Ity_I32);
   2741    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
   2742    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
   2743 }
   2744 
   2745 // Zero: exp is zero and fraction is zero; s = 0/1
   2746 static IRExpr * is_Zero(IRTemp src, Bool sp)
   2747 {
   2748    IRExpr * hi32, * low32;
   2749    IRTemp sign_less_part;
   2750    if (sp)
   2751       return is_Zero_sp(src);
   2752 
   2753    sign_less_part = newTemp(Ity_I64);
   2754 
   2755    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
   2756    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
   2757    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
   2758    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   2759                               mkU32( 0 ) );
   2760 }
   2761 
   2762 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
   2763  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
   2764  *  This function returns an IRExpr value of '1' for any type of NaN.
   2765  */
   2766 static IRExpr * is_NaN(IRTemp src)
   2767 {
   2768    IRExpr * NaN_exp, * hi32, * low32;
   2769    IRTemp frac_part = newTemp(Ity_I64);
   2770 
   2771    assign( frac_part, FP_FRAC_PART(src) );
   2772    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   2773    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   2774    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
   2775                     mkU32( 0x7ff ) );
   2776 
   2777    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   2778                                                mkU32( 0 ) ) );
   2779 }
   2780 
   2781 /* This function returns an IRExpr value of '1' for any type of NaN.
   2782  * The passed 'src' argument is assumed to be Ity_I32.
   2783  */
   2784 static IRExpr * is_NaN_32(IRTemp src)
   2785 {
   2786 #define NONZERO_FRAC_MASK32 0x007fffffULL
   2787 #define FP_FRAC_PART32(x) binop( Iop_And32, \
   2788                                  mkexpr( x ), \
   2789                                  mkU32( NONZERO_FRAC_MASK32 ) )
   2790 
   2791    IRExpr * frac_part = FP_FRAC_PART32(src);
   2792    IRExpr * exp_part = binop( Iop_And32,
   2793                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   2794                               mkU32( 0x0ff ) );
   2795    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
   2796 
   2797    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
   2798 }
   2799 
   2800 /* This helper function performs the negation part of operations of the form:
   2801  *    "Negate Multiply-<op>"
   2802  *  where "<op>" is either "Add" or "Sub".
   2803  *
   2804  * This function takes one argument -- the floating point intermediate result (converted to
   2805  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
   2806  * the operation described above.
   2807  */
   2808 static IRTemp getNegatedResult(IRTemp intermediateResult)
   2809 {
   2810    ULong signbit_mask = 0x8000000000000000ULL;
   2811    IRTemp signbit_32 = newTemp(Ity_I32);
   2812    IRTemp resultantSignbit = newTemp(Ity_I1);
   2813    IRTemp negatedResult = newTemp(Ity_I64);
   2814    assign( signbit_32, binop( Iop_Shr32,
   2815                           unop( Iop_64HIto32,
   2816                                  binop( Iop_And64, mkexpr( intermediateResult ),
   2817                                         mkU64( signbit_mask ) ) ),
   2818                                  mkU8( 31 ) ) );
   2819    /* We negate the signbit if and only if the intermediate result from the
   2820     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   2821     */
   2822    assign( resultantSignbit,
   2823         unop( Iop_Not1,
   2824               binop( Iop_CmpEQ32,
   2825                      binop( Iop_Xor32,
   2826                             mkexpr( signbit_32 ),
   2827                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
   2828                      mkU32( 1 ) ) ) );
   2829 
   2830    assign( negatedResult,
   2831         binop( Iop_Or64,
   2832                binop( Iop_And64,
   2833                       mkexpr( intermediateResult ),
   2834                       mkU64( ~signbit_mask ) ),
   2835                binop( Iop_32HLto64,
   2836                       binop( Iop_Shl32,
   2837                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   2838                              mkU8( 31 ) ),
   2839                       mkU32( 0 ) ) ) );
   2840 
   2841    return negatedResult;
   2842 }
   2843 
   2844 /* This helper function performs the negation part of operations of the form:
   2845  *    "Negate Multiply-<op>"
   2846  *  where "<op>" is either "Add" or "Sub".
   2847  *
   2848  * This function takes one argument -- the floating point intermediate result (converted to
   2849  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
   2850  * the operation described above.
   2851  */
   2852 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
   2853 {
   2854    UInt signbit_mask = 0x80000000;
   2855    IRTemp signbit_32 = newTemp(Ity_I32);
   2856    IRTemp resultantSignbit = newTemp(Ity_I1);
   2857    IRTemp negatedResult = newTemp(Ity_I32);
   2858    assign( signbit_32, binop( Iop_Shr32,
   2859                                  binop( Iop_And32, mkexpr( intermediateResult ),
   2860                                         mkU32( signbit_mask ) ),
   2861                                  mkU8( 31 ) ) );
   2862    /* We negate the signbit if and only if the intermediate result from the
   2863     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   2864     */
   2865    assign( resultantSignbit,
   2866         unop( Iop_Not1,
   2867               binop( Iop_CmpEQ32,
   2868                      binop( Iop_Xor32,
   2869                             mkexpr( signbit_32 ),
   2870                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
   2871                      mkU32( 1 ) ) ) );
   2872 
   2873    assign( negatedResult,
   2874            binop( Iop_Or32,
   2875                   binop( Iop_And32,
   2876                          mkexpr( intermediateResult ),
   2877                          mkU32( ~signbit_mask ) ),
   2878                   binop( Iop_Shl32,
   2879                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   2880                          mkU8( 31 ) ) ) );
   2881 
   2882    return negatedResult;
   2883 }
   2884 
   2885 /*------------------------------------------------------------*/
   2886 /*--- Integer Instruction Translation                     --- */
   2887 /*------------------------------------------------------------*/
   2888 
   2889 /*
   2890   Integer Arithmetic Instructions
   2891 */
   2892 static Bool dis_int_arith ( UInt theInstr )
   2893 {
   2894    /* D-Form, XO-Form */
   2895    UChar opc1    = ifieldOPC(theInstr);
   2896    UChar rD_addr = ifieldRegDS(theInstr);
   2897    UChar rA_addr = ifieldRegA(theInstr);
   2898    UInt  uimm16  = ifieldUIMM16(theInstr);
   2899    UChar rB_addr = ifieldRegB(theInstr);
   2900    UChar flag_OE = ifieldBIT10(theInstr);
   2901    UInt  opc2    = ifieldOPClo9(theInstr);
   2902    UChar flag_rC = ifieldBIT0(theInstr);
   2903 
   2904    Long   simm16 = extend_s_16to64(uimm16);
   2905    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2906    IRTemp rA     = newTemp(ty);
   2907    IRTemp rB     = newTemp(ty);
   2908    IRTemp rD     = newTemp(ty);
   2909 
   2910    Bool do_rc = False;
   2911 
   2912    assign( rA, getIReg(rA_addr) );
   2913    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   2914 
   2915    switch (opc1) {
   2916    /* D-Form */
   2917    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   2918       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2919       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2920                          mkSzExtendS16(ty, uimm16) ) );
   2921       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   2922                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2923                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2924       break;
   2925 
   2926    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   2927       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2928       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2929                          mkSzExtendS16(ty, uimm16) ) );
   2930       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   2931                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2932                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2933       do_rc = True;  // Always record to CR
   2934       flag_rC = 1;
   2935       break;
   2936 
   2937    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   2938       // li rD,val   == addi rD,0,val
   2939       // la disp(rA) == addi rD,rA,disp
   2940       if ( rA_addr == 0 ) {
   2941          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   2942          assign( rD, mkSzExtendS16(ty, uimm16) );
   2943       } else {
   2944          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2945          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2946                             mkSzExtendS16(ty, uimm16) ) );
   2947       }
   2948       break;
   2949 
   2950    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   2951       // lis rD,val == addis rD,0,val
   2952       if ( rA_addr == 0 ) {
   2953          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   2954          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   2955       } else {
   2956          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
   2957          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2958                             mkSzExtendS32(ty, uimm16 << 16) ) );
   2959       }
   2960       break;
   2961 
   2962    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   2963       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2964       if (mode64)
   2965          assign( rD, unop(Iop_128to64,
   2966                           binop(Iop_MullS64, mkexpr(rA),
   2967                                 mkSzExtendS16(ty, uimm16))) );
   2968       else
   2969          assign( rD, unop(Iop_64to32,
   2970                           binop(Iop_MullS32, mkexpr(rA),
   2971                                 mkSzExtendS16(ty, uimm16))) );
   2972       break;
   2973 
   2974    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   2975       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2976       // rD = simm16 - rA
   2977       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   2978                          mkSzExtendS16(ty, uimm16),
   2979                          mkexpr(rA)) );
   2980       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   2981                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2982                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2983       break;
   2984 
   2985    /* XO-Form */
   2986    case 0x1F:
   2987       do_rc = True;    // All below record to CR
   2988 
   2989       switch (opc2) {
   2990       case 0x10A: // add  (Add, PPC32 p347)
   2991          DIP("add%s%s r%u,r%u,r%u\n",
   2992              flag_OE ? "o" : "", flag_rC ? ".":"",
   2993              rD_addr, rA_addr, rB_addr);
   2994          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2995                             mkexpr(rA), mkexpr(rB) ) );
   2996          if (flag_OE) {
   2997             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   2998                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2999          }
   3000          break;
   3001 
   3002       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   3003          DIP("addc%s%s r%u,r%u,r%u\n",
   3004              flag_OE ? "o" : "", flag_rC ? ".":"",
   3005              rD_addr, rA_addr, rB_addr);
   3006          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3007                             mkexpr(rA), mkexpr(rB)) );
   3008          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3009                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3010                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3011          if (flag_OE) {
   3012             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3013                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3014          }
   3015          break;
   3016 
   3017       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   3018          IRTemp old_xer_ca = newTemp(ty);
   3019          DIP("adde%s%s r%u,r%u,r%u\n",
   3020              flag_OE ? "o" : "", flag_rC ? ".":"",
   3021              rD_addr, rA_addr, rB_addr);
   3022          // rD = rA + rB + XER[CA]
   3023          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3024          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3025                             binop( mkSzOp(ty, Iop_Add8),
   3026                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3027          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3028                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3029                      mkexpr(old_xer_ca) );
   3030          if (flag_OE) {
   3031             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3032                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3033          }
   3034          break;
   3035       }
   3036 
   3037       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   3038          IRTemp old_xer_ca = newTemp(ty);
   3039          IRExpr *min_one;
   3040          if (rB_addr != 0) {
   3041             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   3042             return False;
   3043          }
   3044          DIP("addme%s%s r%u,r%u,r%u\n",
   3045              flag_OE ? "o" : "", flag_rC ? ".":"",
   3046              rD_addr, rA_addr, rB_addr);
   3047          // rD = rA + (-1) + XER[CA]
   3048          // => Just another form of adde
   3049          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3050          min_one = mkSzImm(ty, (Long)-1);
   3051          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3052                             binop( mkSzOp(ty, Iop_Add8),
   3053                                    min_one, mkexpr(old_xer_ca)) ));
   3054          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3055                      mkexpr(rD), mkexpr(rA), min_one,
   3056                      mkexpr(old_xer_ca) );
   3057          if (flag_OE) {
   3058             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3059                         mkexpr(rD), mkexpr(rA), min_one );
   3060          }
   3061          break;
   3062       }
   3063 
   3064       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   3065          IRTemp old_xer_ca = newTemp(ty);
   3066          if (rB_addr != 0) {
   3067             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   3068             return False;
   3069          }
   3070          DIP("addze%s%s r%u,r%u,r%u\n",
   3071              flag_OE ? "o" : "", flag_rC ? ".":"",
   3072              rD_addr, rA_addr, rB_addr);
   3073          // rD = rA + (0) + XER[CA]
   3074          // => Just another form of adde
   3075          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3076          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3077                             mkexpr(rA), mkexpr(old_xer_ca)) );
   3078          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3079                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3080                      mkexpr(old_xer_ca) );
   3081          if (flag_OE) {
   3082             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3083                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3084          }
   3085          break;
   3086       }
   3087 
   3088       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   3089          DIP("divw%s%s r%u,r%u,r%u\n",
   3090              flag_OE ? "o" : "", flag_rC ? ".":"",
   3091              rD_addr, rA_addr, rB_addr);
   3092          if (mode64) {
   3093             /* Note:
   3094                XER settings are mode independent, and reflect the
   3095                overflow of the low-order 32bit result
   3096                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3097             */
   3098             /* rD[hi32] are undefined: setting them to sign of lo32
   3099                 - makes set_CR0 happy */
   3100             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   3101             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   3102             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   3103                                                          divisor) ) );
   3104             if (flag_OE) {
   3105                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3106                            mkexpr(rD), dividend, divisor );
   3107             }
   3108          } else {
   3109             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   3110             if (flag_OE) {
   3111                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3112                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3113             }
   3114          }
   3115          /* Note:
   3116             if (0x8000_0000 / -1) or (x / 0)
   3117             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3118             => But _no_ exception raised. */
   3119          break;
   3120 
   3121       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   3122          DIP("divwu%s%s r%u,r%u,r%u\n",
   3123              flag_OE ? "o" : "", flag_rC ? ".":"",
   3124              rD_addr, rA_addr, rB_addr);
   3125          if (mode64) {
   3126             /* Note:
   3127                XER settings are mode independent, and reflect the
   3128                overflow of the low-order 32bit result
   3129                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3130             */
   3131             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   3132             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   3133             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   3134                                                          divisor) ) );
   3135             if (flag_OE) {
   3136                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3137                            mkexpr(rD), dividend, divisor );
   3138             }
   3139          } else {
   3140             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   3141             if (flag_OE) {
   3142                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3143                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3144             }
   3145          }
   3146          /* Note: ditto comment divw, for (x / 0) */
   3147          break;
   3148 
   3149       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   3150          if (flag_OE != 0) {
   3151             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   3152             return False;
   3153          }
   3154          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3155              rD_addr, rA_addr, rB_addr);
   3156          if (mode64) {
   3157             /* rD[hi32] are undefined: setting them to sign of lo32
   3158                 - makes set_CR0 happy */
   3159             assign( rD, binop(Iop_Sar64,
   3160                            binop(Iop_Mul64,
   3161                                  mk64lo32Sto64( mkexpr(rA) ),
   3162                                  mk64lo32Sto64( mkexpr(rB) )),
   3163                               mkU8(32)) );
   3164          } else {
   3165             assign( rD, unop(Iop_64HIto32,
   3166                              binop(Iop_MullS32,
   3167                                    mkexpr(rA), mkexpr(rB))) );
   3168          }
   3169          break;
   3170 
   3171       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   3172          if (flag_OE != 0) {
   3173             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   3174             return False;
   3175          }
   3176          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3177              rD_addr, rA_addr, rB_addr);
   3178          if (mode64) {
   3179             /* rD[hi32] are undefined: setting them to sign of lo32
   3180                 - makes set_CR0 happy */
   3181             assign( rD, binop(Iop_Sar64,
   3182                            binop(Iop_Mul64,
   3183                                  mk64lo32Uto64( mkexpr(rA) ),
   3184                                  mk64lo32Uto64( mkexpr(rB) ) ),
   3185                               mkU8(32)) );
   3186          } else {
   3187             assign( rD, unop(Iop_64HIto32,
   3188                              binop(Iop_MullU32,
   3189                                    mkexpr(rA), mkexpr(rB))) );
   3190          }
   3191          break;
   3192 
   3193       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   3194          DIP("mullw%s%s r%u,r%u,r%u\n",
   3195              flag_OE ? "o" : "", flag_rC ? ".":"",
   3196              rD_addr, rA_addr, rB_addr);
   3197          if (mode64) {
   3198             /* rD[hi32] are undefined: setting them to sign of lo32
   3199                 - set_XER_OV() and set_CR0() depend on this */
   3200             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   3201             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   3202             assign( rD, binop(Iop_MullS32, a, b) );
   3203             if (flag_OE) {
   3204                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3205                            mkexpr(rD),
   3206                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   3207             }
   3208          } else {
   3209             assign( rD, unop(Iop_64to32,
   3210                              binop(Iop_MullU32,
   3211                                    mkexpr(rA), mkexpr(rB))) );
   3212             if (flag_OE) {
   3213                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3214                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3215             }
   3216          }
   3217          break;
   3218 
   3219       case 0x068: // neg        (Negate, PPC32 p493)
   3220          if (rB_addr != 0) {
   3221             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   3222             return False;
   3223          }
   3224          DIP("neg%s%s r%u,r%u\n",
   3225              flag_OE ? "o" : "", flag_rC ? ".":"",
   3226              rD_addr, rA_addr);
   3227          // rD = (~rA) + 1
   3228          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3229                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   3230                             mkSzImm(ty, 1)) );
   3231          if (flag_OE) {
   3232             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   3233                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3234          }
   3235          break;
   3236 
   3237       case 0x028: // subf       (Subtract From, PPC32 p537)
   3238          DIP("subf%s%s r%u,r%u,r%u\n",
   3239              flag_OE ? "o" : "", flag_rC ? ".":"",
   3240              rD_addr, rA_addr, rB_addr);
   3241          // rD = rB - rA
   3242          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3243                             mkexpr(rB), mkexpr(rA)) );
   3244          if (flag_OE) {
   3245             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   3246                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3247          }
   3248          break;
   3249 
   3250       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   3251          DIP("subfc%s%s r%u,r%u,r%u\n",
   3252              flag_OE ? "o" : "", flag_rC ? ".":"",
   3253              rD_addr, rA_addr, rB_addr);
   3254          // rD = rB - rA
   3255          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3256                             mkexpr(rB), mkexpr(rA)) );
   3257          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   3258                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3259                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3260          if (flag_OE) {
   3261             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   3262                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3263          }
   3264          break;
   3265 
   3266       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   3267          IRTemp old_xer_ca = newTemp(ty);
   3268          DIP("subfe%s%s r%u,r%u,r%u\n",
   3269              flag_OE ? "o" : "", flag_rC ? ".":"",
   3270              rD_addr, rA_addr, rB_addr);
   3271          // rD = (log not)rA + rB + XER[CA]
   3272          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3273          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3274                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3275                             binop( mkSzOp(ty, Iop_Add8),
   3276                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3277          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3278                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3279                      mkexpr(old_xer_ca) );
   3280          if (flag_OE) {
   3281             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3282                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3283          }
   3284          break;
   3285       }
   3286 
   3287       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   3288          IRTemp old_xer_ca = newTemp(ty);
   3289          IRExpr *min_one;
   3290          if (rB_addr != 0) {
   3291             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   3292             return False;
   3293          }
   3294          DIP("subfme%s%s r%u,r%u\n",
   3295              flag_OE ? "o" : "", flag_rC ? ".":"",
   3296              rD_addr, rA_addr);
   3297          // rD = (log not)rA + (-1) + XER[CA]
   3298          // => Just another form of subfe
   3299          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3300          min_one = mkSzImm(ty, (Long)-1);
   3301          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3302                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3303                             binop( mkSzOp(ty, Iop_Add8),
   3304                                    min_one, mkexpr(old_xer_ca))) );
   3305          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3306                      mkexpr(rD), mkexpr(rA), min_one,
   3307                      mkexpr(old_xer_ca) );
   3308          if (flag_OE) {
   3309             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3310                         mkexpr(rD), mkexpr(rA), min_one );
   3311          }
   3312          break;
   3313       }
   3314 
   3315       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   3316          IRTemp old_xer_ca = newTemp(ty);
   3317          if (rB_addr != 0) {
   3318             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   3319             return False;
   3320          }
   3321          DIP("subfze%s%s r%u,r%u\n",
   3322              flag_OE ? "o" : "", flag_rC ? ".":"",
   3323              rD_addr, rA_addr);
   3324          // rD = (log not)rA + (0) + XER[CA]
   3325          // => Just another form of subfe
   3326          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3327          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3328                            unop( mkSzOp(ty, Iop_Not8),
   3329                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   3330          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3331                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3332                      mkexpr(old_xer_ca) );
   3333          if (flag_OE) {
   3334             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3335                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3336          }
   3337          break;
   3338       }
   3339 
   3340 
   3341       /* 64bit Arithmetic */
   3342       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   3343          if (flag_OE != 0) {
   3344             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   3345             return False;
   3346          }
   3347          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3348              rD_addr, rA_addr, rB_addr);
   3349          assign( rD, unop(Iop_128HIto64,
   3350                           binop(Iop_MullS64,
   3351                                 mkexpr(rA), mkexpr(rB))) );
   3352 
   3353          break;
   3354 
   3355       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   3356          if (flag_OE != 0) {
   3357             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   3358             return False;
   3359          }
   3360          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3361              rD_addr, rA_addr, rB_addr);
   3362          assign( rD, unop(Iop_128HIto64,
   3363                           binop(Iop_MullU64,
   3364                                 mkexpr(rA), mkexpr(rB))) );
   3365          break;
   3366 
   3367       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   3368          DIP("mulld%s%s r%u,r%u,r%u\n",
   3369              flag_OE ? "o" : "", flag_rC ? ".":"",
   3370              rD_addr, rA_addr, rB_addr);
   3371          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   3372          if (flag_OE) {
   3373             set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3374                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3375          }
   3376          break;
   3377 
   3378       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   3379          DIP("divd%s%s r%u,r%u,r%u\n",
   3380              flag_OE ? "o" : "", flag_rC ? ".":"",
   3381              rD_addr, rA_addr, rB_addr);
   3382          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   3383          if (flag_OE) {
   3384             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3385                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3386          }
   3387          break;
   3388          /* Note:
   3389             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   3390             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3391             => But _no_ exception raised. */
   3392 
   3393       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   3394          DIP("divdu%s%s r%u,r%u,r%u\n",
   3395              flag_OE ? "o" : "", flag_rC ? ".":"",
   3396              rD_addr, rA_addr, rB_addr);
   3397          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   3398          if (flag_OE) {
   3399             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3400                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3401          }
   3402          break;
   3403          /* Note: ditto comment divd, for (x / 0) */
   3404 
   3405       case 0x18B: // divweu (Divide Word Extended Unsigned)
   3406       {
   3407         /*
   3408          *  If (RA) >= (RB), or if an attempt is made to perform the division
   3409          *         <anything> / 0
   3410          * then the contents of register RD are undefined as are (if Rc=1) the contents of
   3411          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
   3412          * to 1.
   3413          */
   3414          IRTemp res = newTemp(Ity_I32);
   3415          IRExpr * dividend, * divisor;
   3416          DIP("divweu%s%s r%u,r%u,r%u\n",
   3417              flag_OE ? "o" : "", flag_rC ? ".":"",
   3418                                          rD_addr, rA_addr, rB_addr);
   3419          if (mode64) {
   3420             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3421             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3422             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3423             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3424          } else {
   3425             dividend = mkexpr( rA );
   3426             divisor =  mkexpr( rB );
   3427             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   3428             assign( rD, mkexpr( res) );
   3429          }
   3430 
   3431          if (flag_OE) {
   3432             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
   3433                            mkexpr(res), dividend, divisor );
   3434          }
   3435          break;
   3436       }
   3437 
   3438       case 0x1AB: // divwe (Divide Word Extended)
   3439       {
   3440          /*
   3441           * If the quotient cannot be represented in 32 bits, or if an
   3442           * attempt is made to perform the division
   3443           *      <anything> / 0
   3444           * then the contents of register RD are undefined as are (if
   3445           * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3446           * Field 0. In these cases, if OE=1 then OV is set to 1.
   3447           */
   3448 
   3449          IRTemp res = newTemp(Ity_I32);
   3450          IRExpr * dividend, * divisor;
   3451          DIP("divwe%s%s r%u,r%u,r%u\n",
   3452              flag_OE ? "o" : "", flag_rC ? ".":"",
   3453                                          rD_addr, rA_addr, rB_addr);
   3454          if (mode64) {
   3455             dividend = unop( Iop_64to32, mkexpr( rA ) );
   3456             divisor = unop( Iop_64to32, mkexpr( rB ) );
   3457             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3458             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   3459          } else {
   3460             dividend = mkexpr( rA );
   3461             divisor =  mkexpr( rB );
   3462             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   3463             assign( rD, mkexpr( res) );
   3464          }
   3465 
   3466          if (flag_OE) {
   3467             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
   3468                            mkexpr(res), dividend, divisor );
   3469          }
   3470          break;
   3471       }
   3472 
   3473 
   3474       case 0x1A9: // divde (Divide Doubleword Extended)
   3475         /*
   3476          * If the quotient cannot be represented in 64 bits, or if an
   3477          * attempt is made to perform the division
   3478          *      <anything> / 0
   3479          * then the contents of register RD are undefined as are (if
   3480          * Rc=1) the contents of the LT, GT, and EQ bits of CR
   3481          * Field 0. In these cases, if OE=1 then OV is set to 1.
   3482          */
   3483          DIP("divde%s%s r%u,r%u,r%u\n",
   3484              flag_OE ? "o" : "", flag_rC ? ".":"",
   3485              rD_addr, rA_addr, rB_addr);
   3486          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
   3487          if (flag_OE) {
   3488             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
   3489                            mkexpr( rA ), mkexpr( rB ) );
   3490          }
   3491          break;
   3492 
   3493       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
   3494         // Same CR and OV rules as given for divweu above
   3495         DIP("divdeu%s%s r%u,r%u,r%u\n",
   3496             flag_OE ? "o" : "", flag_rC ? ".":"",
   3497             rD_addr, rA_addr, rB_addr);
   3498         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
   3499         if (flag_OE) {
   3500            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
   3501                           mkexpr( rA ), mkexpr( rB ) );
   3502         }
   3503         break;
   3504 
   3505       default:
   3506          vex_printf("dis_int_arith(ppc)(opc2)\n");
   3507          return False;
   3508       }
   3509       break;
   3510 
   3511    default:
   3512       vex_printf("dis_int_arith(ppc)(opc1)\n");
   3513       return False;
   3514    }
   3515 
   3516    putIReg( rD_addr, mkexpr(rD) );
   3517 
   3518    if (do_rc && flag_rC) {
   3519       set_CR0( mkexpr(rD) );
   3520    }
   3521    return True;
   3522 }
   3523 
   3524 
   3525 
   3526 /*
   3527   Integer Compare Instructions
   3528 */
   3529 static Bool dis_int_cmp ( UInt theInstr )
   3530 {
   3531    /* D-Form, X-Form */
   3532    UChar opc1    = ifieldOPC(theInstr);
   3533    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   3534    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   3535    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   3536    UChar rA_addr = ifieldRegA(theInstr);
   3537    UInt  uimm16  = ifieldUIMM16(theInstr);
   3538    UChar rB_addr = ifieldRegB(theInstr);
   3539    UInt  opc2    = ifieldOPClo10(theInstr);
   3540    UChar b0      = ifieldBIT0(theInstr);
   3541 
   3542    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   3543    IRExpr *a = getIReg(rA_addr);
   3544    IRExpr *b;
   3545 
   3546    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   3547       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   3548       return False;
   3549    }
   3550 
   3551    if (b22 != 0) {
   3552       vex_printf("dis_int_cmp(ppc)(b22)\n");
   3553       return False;
   3554    }
   3555 
   3556    switch (opc1) {
   3557    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   3558       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   3559           (Int)extend_s_16to32(uimm16));
   3560       b = mkSzExtendS16( ty, uimm16 );
   3561       if (flag_L == 1) {
   3562          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3563       } else {
   3564          a = mkNarrowTo32( ty, a );
   3565          b = mkNarrowTo32( ty, b );
   3566          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   3567       }
   3568       putCR0( crfD, getXER_SO() );
   3569       break;
   3570 
   3571    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   3572       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   3573       b = mkSzImm( ty, uimm16 );
   3574       if (flag_L == 1) {
   3575          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3576       } else {
   3577          a = mkNarrowTo32( ty, a );
   3578          b = mkNarrowTo32( ty, b );
   3579          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3580       }
   3581       putCR0( crfD, getXER_SO() );
   3582       break;
   3583 
   3584    /* X Form */
   3585    case 0x1F:
   3586       if (b0 != 0) {
   3587          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   3588          return False;
   3589       }
   3590       b = getIReg(rB_addr);
   3591 
   3592       switch (opc2) {
   3593       case 0x000: // cmp (Compare, PPC32 p367)
   3594          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3595          /* Comparing a reg with itself produces a result which
   3596             doesn't depend on the contents of the reg.  Therefore
   3597             remove the false dependency, which has been known to cause
   3598             memcheck to produce false errors. */
   3599          if (rA_addr == rB_addr)
   3600             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3601                     ? mkU64(0)  : mkU32(0);
   3602          if (flag_L == 1) {
   3603             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   3604          } else {
   3605             a = mkNarrowTo32( ty, a );
   3606             b = mkNarrowTo32( ty, b );
   3607             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   3608          }
   3609          putCR0( crfD, getXER_SO() );
   3610          break;
   3611 
   3612       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   3613          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   3614          /* Comparing a reg with itself produces a result which
   3615             doesn't depend on the contents of the reg.  Therefore
   3616             remove the false dependency, which has been known to cause
   3617             memcheck to produce false errors. */
   3618          if (rA_addr == rB_addr)
   3619             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   3620                     ? mkU64(0)  : mkU32(0);
   3621          if (flag_L == 1) {
   3622             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   3623          } else {
   3624             a = mkNarrowTo32( ty, a );
   3625             b = mkNarrowTo32( ty, b );
   3626             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   3627          }
   3628          putCR0( crfD, getXER_SO() );
   3629          break;
   3630 
   3631       default:
   3632          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   3633          return False;
   3634       }
   3635       break;
   3636 
   3637    default:
   3638       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   3639       return False;
   3640    }
   3641 
   3642    return True;
   3643 }
   3644 
   3645 
   3646 /*
   3647   Integer Logical Instructions
   3648 */
   3649 static Bool dis_int_logic ( UInt theInstr )
   3650 {
   3651    /* D-Form, X-Form */
   3652    UChar opc1    = ifieldOPC(theInstr);
   3653    UChar rS_addr = ifieldRegDS(theInstr);
   3654    UChar rA_addr = ifieldRegA(theInstr);
   3655    UInt  uimm16  = ifieldUIMM16(theInstr);
   3656    UChar rB_addr = ifieldRegB(theInstr);
   3657    UInt  opc2    = ifieldOPClo10(theInstr);
   3658    UChar flag_rC = ifieldBIT0(theInstr);
   3659 
   3660    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3661    IRTemp rS     = newTemp(ty);
   3662    IRTemp rA     = newTemp(ty);
   3663    IRTemp rB     = newTemp(ty);
   3664    IRExpr* irx;
   3665    Bool do_rc    = False;
   3666 
   3667    assign( rS, getIReg(rS_addr) );
   3668    assign( rB, getIReg(rB_addr) );
   3669 
   3670    switch (opc1) {
   3671    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   3672       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3673       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3674                          mkSzImm(ty, uimm16)) );
   3675       do_rc = True;  // Always record to CR
   3676       flag_rC = 1;
   3677       break;
   3678 
   3679    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   3680       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3681       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3682                          mkSzImm(ty, uimm16 << 16)) );
   3683       do_rc = True;  // Always record to CR
   3684       flag_rC = 1;
   3685       break;
   3686 
   3687    case 0x18: // ori (OR Immediate, PPC32 p497)
   3688       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3689       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3690                          mkSzImm(ty, uimm16)) );
   3691       break;
   3692 
   3693    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   3694       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3695       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3696                          mkSzImm(ty, uimm16 << 16)) );
   3697       break;
   3698 
   3699    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   3700       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3701       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3702                          mkSzImm(ty, uimm16)) );
   3703       break;
   3704 
   3705    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   3706       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3707       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3708                          mkSzImm(ty, uimm16 << 16)) );
   3709       break;
   3710 
   3711    /* X Form */
   3712    case 0x1F:
   3713       do_rc = True; // All below record to CR, except for where we return at case end.
   3714 
   3715       switch (opc2) {
   3716       case 0x01C: // and (AND, PPC32 p356)
   3717          DIP("and%s r%u,r%u,r%u\n",
   3718              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3719          assign(rA, binop( mkSzOp(ty, Iop_And8),
   3720                            mkexpr(rS), mkexpr(rB)));
   3721          break;
   3722 
   3723       case 0x03C: // andc (AND with Complement, PPC32 p357)
   3724          DIP("andc%s r%u,r%u,r%u\n",
   3725              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3726          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3727                            unop( mkSzOp(ty, Iop_Not8),
   3728                                  mkexpr(rB))));
   3729          break;
   3730 
   3731       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   3732          IRExpr* lo32;
   3733          if (rB_addr!=0) {
   3734             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   3735             return False;
   3736          }
   3737          DIP("cntlzw%s r%u,r%u\n",
   3738              flag_rC ? ".":"", rA_addr, rS_addr);
   3739 
   3740          // mode64: count in low word only
   3741          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   3742 
   3743          // Iop_Clz32 undefined for arg==0, so deal with that case:
   3744          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   3745          assign(rA, mkWidenFrom32(ty,
   3746                          IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3747                                        mkU32(32),
   3748                                        unop(Iop_Clz32, lo32)),
   3749                          False));
   3750 
   3751          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   3752          break;
   3753       }
   3754 
   3755       case 0x11C: // eqv (Equivalent, PPC32 p396)
   3756          DIP("eqv%s r%u,r%u,r%u\n",
   3757              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3758          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3759                            binop( mkSzOp(ty, Iop_Xor8),
   3760                                   mkexpr(rS), mkexpr(rB))) );
   3761          break;
   3762 
   3763       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   3764          if (rB_addr!=0) {
   3765             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   3766             return False;
   3767          }
   3768          DIP("extsb%s r%u,r%u\n",
   3769              flag_rC ? ".":"", rA_addr, rS_addr);
   3770          if (mode64)
   3771             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   3772          else
   3773             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   3774          break;
   3775 
   3776       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   3777          if (rB_addr!=0) {
   3778             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   3779             return False;
   3780          }
   3781          DIP("extsh%s r%u,r%u\n",
   3782              flag_rC ? ".":"", rA_addr, rS_addr);
   3783          if (mode64)
   3784             assign( rA, unop(Iop_16Sto64,
   3785                              unop(Iop_64to16, mkexpr(rS))) );
   3786          else
   3787             assign( rA, unop(Iop_16Sto32,
   3788                              unop(Iop_32to16, mkexpr(rS))) );
   3789          break;
   3790 
   3791       case 0x1DC: // nand (NAND, PPC32 p492)
   3792          DIP("nand%s r%u,r%u,r%u\n",
   3793              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3794          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3795                            binop( mkSzOp(ty, Iop_And8),
   3796                                   mkexpr(rS), mkexpr(rB))) );
   3797          break;
   3798 
   3799       case 0x07C: // nor (NOR, PPC32 p494)
   3800          DIP("nor%s r%u,r%u,r%u\n",
   3801              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3802          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3803                            binop( mkSzOp(ty, Iop_Or8),
   3804                                   mkexpr(rS), mkexpr(rB))) );
   3805          break;
   3806 
   3807       case 0x1BC: // or (OR, PPC32 p495)
   3808          if ((!flag_rC) && rS_addr == rB_addr) {
   3809             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   3810             assign( rA, mkexpr(rS) );
   3811          } else {
   3812             DIP("or%s r%u,r%u,r%u\n",
   3813                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3814             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   3815                                mkexpr(rS), mkexpr(rB)) );
   3816          }
   3817          break;
   3818 
   3819       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   3820          DIP("orc%s r%u,r%u,r%u\n",
   3821              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3822          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3823                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   3824          break;
   3825 
   3826       case 0x13C: // xor (XOR, PPC32 p549)
   3827          DIP("xor%s r%u,r%u,r%u\n",
   3828              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3829          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   3830                             mkexpr(rS), mkexpr(rB)) );
   3831          break;
   3832 
   3833 
   3834       /* 64bit Integer Logical Instructions */
   3835       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   3836          if (rB_addr!=0) {
   3837             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   3838             return False;
   3839          }
   3840          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   3841          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   3842          break;
   3843 
   3844       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   3845          if (rB_addr!=0) {
   3846             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   3847             return False;
   3848          }
   3849          DIP("cntlzd%s r%u,r%u\n",
   3850              flag_rC ? ".":"", rA_addr, rS_addr);
   3851          // Iop_Clz64 undefined for arg==0, so deal with that case:
   3852          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   3853          assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3854                                   mkU64(64),
   3855                                   unop(Iop_Clz64, mkexpr(rS)) ));
   3856          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   3857          break;
   3858 
   3859       case 0x1FC: // cmpb (Power6: compare bytes)
   3860          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   3861 
   3862          if (mode64)
   3863             assign( rA, unop( Iop_V128to64,
   3864                               binop( Iop_CmpEQ8x16,
   3865                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   3866                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   3867                                      )) );
   3868          else
   3869             assign( rA, unop( Iop_V128to32,
   3870                               binop( Iop_CmpEQ8x16,
   3871                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   3872                                      unop( Iop_32UtoV128, mkexpr(rB) )
   3873                                      )) );
   3874          break;
   3875 
   3876       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   3877          IRTemp frB = newTemp(Ity_F64);
   3878          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   3879 
   3880          assign( frB, getFReg(rB_addr));  // always F64
   3881          if (mode64)
   3882             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   3883          else
   3884             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   3885 
   3886          putIReg( rS_addr, mkexpr(rA));
   3887          return True;
   3888       }
   3889 
   3890       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   3891          IRTemp frA = newTemp(Ity_F64);
   3892          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   3893 
   3894          if (mode64)
   3895             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   3896          else
   3897             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   3898 
   3899          putFReg( rS_addr, mkexpr(frA));
   3900          return True;
   3901       }
   3902       case 0x1FA: // popcntd (population count doubleword
   3903       {
   3904     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
   3905         IRTemp result = gen_POPCOUNT(ty, rS);
   3906     	  putIReg( rA_addr, mkexpr(result) );
   3907     	  return True;
   3908       }
   3909       case 0x17A: // popcntw (Population Count Words)
   3910       {
   3911          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
   3912          if (mode64) {
   3913             IRTemp resultHi, resultLo;
   3914             IRTemp argLo = newTemp(Ity_I32);
   3915             IRTemp argHi = newTemp(Ity_I32);
   3916             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   3917             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   3918             resultLo = gen_POPCOUNT(Ity_I32, argLo);
   3919             resultHi = gen_POPCOUNT(Ity_I32, argHi);
   3920             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
   3921          } else {
   3922             IRTemp result = gen_POPCOUNT(ty, rS);
   3923             putIReg( rA_addr, mkexpr(result) );
   3924          }
   3925          return True;
   3926       }
   3927        case 0x0FC: // bpermd (Bit Permute Doubleword)
   3928        {
   3929           /* This is a lot of rigmarole to emulate bpermd like this, as it
   3930            * could be done much faster by implementing a call to the native
   3931            * instruction.  However, where possible I want to avoid using new
   3932            * native instructions so that we can use valgrind to emulate those
   3933            * instructions on older PPC64 hardware.
   3934            */
   3935  #define BPERMD_IDX_MASK 0x00000000000000FFULL
   3936  #define BPERMD_BIT_MASK 0x8000000000000000ULL
   3937           int i;
   3938           IRExpr * rS_expr = mkexpr(rS);
   3939           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
   3940           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   3941           for (i = 0; i < 8; i++) {
   3942              IRTemp idx_tmp = newTemp( Ity_I64 );
   3943              IRTemp perm_bit = newTemp( Ity_I64 );
   3944              IRTemp idx = newTemp( Ity_I8 );
   3945              IRTemp idx_LT64 = newTemp( Ity_I1 );
   3946              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
   3947 
   3948              assign( idx_tmp,
   3949                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
   3950              assign( idx_LT64,
   3951                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
   3952              assign( idx,
   3953                            binop( Iop_And8,
   3954                                   unop( Iop_1Sto8,
   3955                                         mkexpr(idx_LT64) ),
   3956                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
   3957              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
   3958               * to determine which bit of rB to use for the perm bit, and then we shift
   3959               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
   3960               * to set the final perm bit.
   3961               */
   3962              assign( idx_LT64_ity64,
   3963                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
   3964              assign( perm_bit,
   3965                            binop( Iop_And64,
   3966                                   mkexpr( idx_LT64_ity64 ),
   3967                                   binop( Iop_Shr64,
   3968                                          binop( Iop_And64,
   3969                                                 mkU64( BPERMD_BIT_MASK ),
   3970                                                 binop( Iop_Shl64,
   3971                                                        mkexpr( rB ),
   3972                                                        mkexpr( idx ) ) ),
   3973                                          mkU8( 63 ) ) ) );
   3974              res = binop( Iop_Or64,
   3975                                 res,
   3976                                 binop( Iop_Shl64,
   3977                                        mkexpr( perm_bit ),
   3978                                        mkU8( i ) ) );
   3979              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
   3980           }
   3981           putIReg(rA_addr, res);
   3982           return True;
   3983        }
   3984 
   3985       default:
   3986          vex_printf("dis_int_logic(ppc)(opc2)\n");
   3987          return False;
   3988       }
   3989       break;
   3990 
   3991    default:
   3992       vex_printf("dis_int_logic(ppc)(opc1)\n");
   3993       return False;
   3994    }
   3995 
   3996    putIReg( rA_addr, mkexpr(rA) );
   3997 
   3998    if (do_rc && flag_rC) {
   3999       set_CR0( mkexpr(rA) );
   4000    }
   4001    return True;
   4002 }
   4003 
   4004 /*
   4005   Integer Parity Instructions
   4006 */
   4007 static Bool dis_int_parity ( UInt theInstr )
   4008 {
   4009    /* X-Form */
   4010    UChar opc1    = ifieldOPC(theInstr);
   4011    UChar rS_addr = ifieldRegDS(theInstr);
   4012    UChar rA_addr = ifieldRegA(theInstr);
   4013    UChar rB_addr = ifieldRegB(theInstr);
   4014    UInt  opc2    = ifieldOPClo10(theInstr);
   4015    UChar b0      = ifieldBIT0(theInstr);
   4016    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4017 
   4018    IRTemp rS     = newTemp(ty);
   4019    IRTemp rA     = newTemp(ty);
   4020    IRTemp iTot1  = newTemp(Ity_I32);
   4021    IRTemp iTot2  = newTemp(Ity_I32);
   4022    IRTemp iTot3  = newTemp(Ity_I32);
   4023    IRTemp iTot4  = newTemp(Ity_I32);
   4024    IRTemp iTot5  = newTemp(Ity_I32);
   4025    IRTemp iTot6  = newTemp(Ity_I32);
   4026    IRTemp iTot7  = newTemp(Ity_I32);
   4027    IRTemp iTot8  = newTemp(Ity_I32);
   4028    IRTemp rS1    = newTemp(ty);
   4029    IRTemp rS2    = newTemp(ty);
   4030    IRTemp rS3    = newTemp(ty);
   4031    IRTemp rS4    = newTemp(ty);
   4032    IRTemp rS5    = newTemp(ty);
   4033    IRTemp rS6    = newTemp(ty);
   4034    IRTemp rS7    = newTemp(ty);
   4035    IRTemp iHi    = newTemp(Ity_I32);
   4036    IRTemp iLo    = newTemp(Ity_I32);
   4037    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   4038    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   4039 
   4040    if (opc1 != 0x1f || rB_addr || b0) {
   4041       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   4042       return False;
   4043    }
   4044 
   4045    assign( rS, getIReg(rS_addr) );
   4046 
   4047    switch (opc2) {
   4048    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   4049       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   4050       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4051       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4052       assign( iTot2, binop(Iop_Add32,
   4053                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4054                            mkexpr(iTot1)) );
   4055       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4056       assign( iTot3, binop(Iop_Add32,
   4057                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4058                            mkexpr(iTot2)) );
   4059       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4060       assign( iTot4, binop(Iop_Add32,
   4061                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4062                            mkexpr(iTot3)) );
   4063       if (mode64) {
   4064          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4065          assign( iTot5, binop(Iop_Add32,
   4066                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   4067                               mkexpr(iTot4)) );
   4068          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4069          assign( iTot6, binop(Iop_Add32,
   4070                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4071                               mkexpr(iTot5)) );
   4072          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4073          assign( iTot7, binop(Iop_Add32,
   4074                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4075                               mkexpr(iTot6)) );
   4076          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   4077          assign( iTot8, binop(Iop_Add32,
   4078                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4079                               mkexpr(iTot7)) );
   4080          assign( rA, unop(Iop_32Uto64,
   4081                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   4082       } else
   4083          assign( rA, mkexpr(iTot4) );
   4084 
   4085       break;
   4086    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   4087       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4088       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4089       assign( iTot2, binop(Iop_Add32,
   4090                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4091                            mkexpr(iTot1)) );
   4092       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4093       assign( iTot3, binop(Iop_Add32,
   4094                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4095                            mkexpr(iTot2)) );
   4096       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4097       assign( iTot4, binop(Iop_Add32,
   4098                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4099                            mkexpr(iTot3)) );
   4100       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   4101 
   4102       if (mode64) {
   4103          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4104          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   4105          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4106          assign( iTot6, binop(Iop_Add32,
   4107                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4108                               mkexpr(iTot5)) );
   4109          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4110          assign( iTot7, binop(Iop_Add32,
   4111                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4112                               mkexpr(iTot6)) );
   4113          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   4114          assign( iTot8, binop(Iop_Add32,
   4115                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4116                               mkexpr(iTot7)) );
   4117          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   4118             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   4119       } else
   4120          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   4121       break;
   4122    default:
   4123       vex_printf("dis_int_parity(ppc)(opc2)\n");
   4124       return False;
   4125    }
   4126 
   4127    putIReg( rA_addr, mkexpr(rA) );
   4128 
   4129    return True;
   4130 }
   4131 
   4132 
   4133 /*
   4134   Integer Rotate Instructions
   4135 */
   4136 static Bool dis_int_rot ( UInt theInstr )
   4137 {
   4138    /* M-Form, MDS-Form */
   4139    UChar opc1    = ifieldOPC(theInstr);
   4140    UChar rS_addr = ifieldRegDS(theInstr);
   4141    UChar rA_addr = ifieldRegA(theInstr);
   4142    UChar rB_addr = ifieldRegB(theInstr);
   4143    UChar sh_imm  = rB_addr;
   4144    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   4145    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   4146    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   4147    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   4148    UChar b1      = ifieldBIT1(theInstr);
   4149    UChar flag_rC = ifieldBIT0(theInstr);
   4150 
   4151    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4152    IRTemp rS     = newTemp(ty);
   4153    IRTemp rA     = newTemp(ty);
   4154    IRTemp rB     = newTemp(ty);
   4155    IRTemp rot    = newTemp(ty);
   4156    IRExpr *r;
   4157    UInt   mask32;
   4158    ULong  mask64;
   4159 
   4160    assign( rS, getIReg(rS_addr) );
   4161    assign( rB, getIReg(rB_addr) );
   4162 
   4163    switch (opc1) {
   4164    case 0x14: {
   4165       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   4166       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4167           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4168       if (mode64) {
   4169          // tmp32 = (ROTL(rS_Lo32, Imm)
   4170          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   4171          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4172          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4173          r = unop(Iop_32Uto64, r);
   4174          assign( rot, binop(Iop_Or64, r,
   4175                             binop(Iop_Shl64, r, mkU8(32))) );
   4176          assign( rA,
   4177             binop(Iop_Or64,
   4178                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   4179                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   4180       }
   4181       else {
   4182          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   4183          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4184          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4185          assign( rA,
   4186             binop(Iop_Or32,
   4187                   binop(Iop_And32, mkU32(mask32), r),
   4188                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   4189       }
   4190       break;
   4191    }
   4192 
   4193    case 0x15: {
   4194       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   4195       vassert(MaskBeg < 32);
   4196       vassert(MaskEnd < 32);
   4197       vassert(sh_imm  < 32);
   4198 
   4199       if (mode64) {
   4200          IRTemp rTmp = newTemp(Ity_I64);
   4201          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4202          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4203              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4204          // tmp32 = (ROTL(rS_Lo32, Imm)
   4205          // rA = ((tmp32 || tmp32) & mask64)
   4206          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4207          r = unop(Iop_32Uto64, r);
   4208          assign( rTmp, r );
   4209          r = NULL;
   4210          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   4211                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   4212          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4213       }
   4214       else {
   4215          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   4216             /* Special-case the ,n,0,31-n form as that is just n-bit
   4217                shift left, PPC32 p501 */
   4218             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4219                 rA_addr, rS_addr, sh_imm);
   4220             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   4221          }
   4222          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   4223             /* Special-case the ,32-n,n,31 form as that is just n-bit
   4224                unsigned shift right, PPC32 p501 */
   4225             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4226                 rA_addr, rS_addr, MaskBeg);
   4227             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   4228          }
   4229          else {
   4230             /* General case. */
   4231             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4232             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4233                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4234             // rA = ROTL(rS, Imm) & mask
   4235             assign( rA, binop(Iop_And32,
   4236                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   4237                               mkU32(mask32)) );
   4238          }
   4239       }
   4240       break;
   4241    }
   4242 
   4243    case 0x17: {
   4244       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   4245       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   4246           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   4247       if (mode64) {
   4248          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4249          /* weird insn alert!
   4250             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   4251             rA = ((tmp32 || tmp32) & mask64)
   4252          */
   4253          // note, ROTL does the masking, so we don't do it here
   4254          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   4255                    unop(Iop_64to8, mkexpr(rB)) );
   4256          r = unop(Iop_32Uto64, r);
   4257          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   4258          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4259       } else {
   4260          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4261          // rA = ROTL(rS, rB[0-4]) & mask
   4262          // note, ROTL does the masking, so we don't do it here
   4263          assign( rA, binop(Iop_And32,
   4264                            ROTL(mkexpr(rS),
   4265                                 unop(Iop_32to8, mkexpr(rB))),
   4266                            mkU32(mask32)) );
   4267       }
   4268       break;
   4269    }
   4270 
   4271    /* 64bit Integer Rotates */
   4272    case 0x1E: {
   4273       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   4274       sh_imm |= b1 << 5;
   4275 
   4276       vassert( msk_imm < 64 );
   4277       vassert( sh_imm < 64 );
   4278 
   4279       switch (opc2) {
   4280       case 0x4: {
   4281          /* r = ROTL64( rS, rB_lo6) */
   4282          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   4283 
   4284          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   4285             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4286                 rA_addr, rS_addr, rB_addr, msk_imm);
   4287             // note, ROTL does the masking, so we don't do it here
   4288             mask64 = MASK64(0, 63-msk_imm);
   4289             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4290             break;
   4291          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   4292             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4293                 rA_addr, rS_addr, rB_addr, msk_imm);
   4294             mask64 = MASK64(63-msk_imm, 63);
   4295             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4296             break;
   4297          }
   4298          break;
   4299       }
   4300       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   4301          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4302              rA_addr, rS_addr, sh_imm, msk_imm);
   4303          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4304          mask64 = MASK64(sh_imm, 63-msk_imm);
   4305          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4306          break;
   4307          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   4308          /*
   4309            Hmm... looks like this'll do the job more simply:
   4310            r = SHL(rS, sh_imm)
   4311            m = ~(1 << (63-msk_imm))
   4312            assign(rA, r & m);
   4313          */
   4314 
   4315       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   4316          if (mode64
   4317              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   4318             /* special-case the ,64-n,n form as that is just
   4319                unsigned shift-right by n */
   4320             DIP("srdi%s r%u,r%u,%u\n",
   4321                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   4322             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   4323          } else {
   4324             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4325                 rA_addr, rS_addr, sh_imm, msk_imm);
   4326             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4327             mask64 = MASK64(0, 63-msk_imm);
   4328             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4329          }
   4330          break;
   4331 
   4332       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   4333          if (mode64
   4334              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   4335             /* special-case the ,n,63-n form as that is just
   4336                shift-left by n */
   4337             DIP("sldi%s r%u,r%u,%u\n",
   4338                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   4339             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   4340          } else {
   4341             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4342                 rA_addr, rS_addr, sh_imm, msk_imm);
   4343             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4344             mask64 = MASK64(63-msk_imm, 63);
   4345             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4346          }
   4347          break;
   4348 
   4349       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   4350          IRTemp rA_orig = newTemp(ty);
   4351          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4352              rA_addr, rS_addr, sh_imm, msk_imm);
   4353          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4354          mask64 = MASK64(sh_imm, 63-msk_imm);
   4355          assign( rA_orig, getIReg(rA_addr) );
   4356          assign( rA, binop(Iop_Or64,
   4357                            binop(Iop_And64, mkU64(mask64),  r),
   4358                            binop(Iop_And64, mkU64(~mask64),
   4359                                             mkexpr(rA_orig))) );
   4360          break;
   4361       }
   4362       default:
   4363          vex_printf("dis_int_rot(ppc)(opc2)\n");
   4364          return False;
   4365       }
   4366       break;
   4367    }
   4368 
   4369    default:
   4370       vex_printf("dis_int_rot(ppc)(opc1)\n");
   4371       return False;
   4372    }
   4373 
   4374    putIReg( rA_addr, mkexpr(rA) );
   4375 
   4376    if (flag_rC) {
   4377       set_CR0( mkexpr(rA) );
   4378    }
   4379    return True;
   4380 }
   4381 
   4382 
   4383 /*
   4384   Integer Load Instructions
   4385 */
   4386 static Bool dis_int_load ( UInt theInstr )
   4387 {
   4388    /* D-Form, X-Form, DS-Form */
   4389    UChar opc1     = ifieldOPC(theInstr);
   4390    UChar rD_addr  = ifieldRegDS(theInstr);
   4391    UChar rA_addr  = ifieldRegA(theInstr);
   4392    UInt  uimm16   = ifieldUIMM16(theInstr);
   4393    UChar rB_addr  = ifieldRegB(theInstr);
   4394    UInt  opc2     = ifieldOPClo10(theInstr);
   4395    UChar b1       = ifieldBIT1(theInstr);
   4396    UChar b0       = ifieldBIT0(theInstr);
   4397 
   4398    Int     simm16 = extend_s_16to32(uimm16);
   4399    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4400    IRTemp  EA     = newTemp(ty);
   4401    IRExpr* val;
   4402 
   4403    switch (opc1) {
   4404    case 0x1F: // register offset
   4405       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4406       break;
   4407    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   4408               // lowest 2 bits of immediate before forming EA
   4409       simm16 = simm16 & 0xFFFFFFFC;
   4410    default:   // immediate offset
   4411       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4412       break;
   4413    }
   4414 
   4415    switch (opc1) {
   4416    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   4417       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4418       val = loadBE(Ity_I8, mkexpr(EA));
   4419       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4420       break;
   4421 
   4422    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   4423       if (rA_addr == 0 || rA_addr == rD_addr) {
   4424          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   4425          return False;
   4426       }
   4427       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4428       val = loadBE(Ity_I8, mkexpr(EA));
   4429       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4430       putIReg( rA_addr, mkexpr(EA) );
   4431       break;
   4432 
   4433    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   4434       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4435       val = loadBE(Ity_I16, mkexpr(EA));
   4436       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4437       break;
   4438 
   4439    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   4440       if (rA_addr == 0 || rA_addr == rD_addr) {
   4441          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   4442          return False;
   4443       }
   4444       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4445       val = loadBE(Ity_I16, mkexpr(EA));
   4446       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4447       putIReg( rA_addr, mkexpr(EA) );
   4448       break;
   4449 
   4450    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   4451       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4452       val = loadBE(Ity_I16, mkexpr(EA));
   4453       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4454       break;
   4455 
   4456    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   4457       if (rA_addr == 0 || rA_addr == rD_addr) {
   4458          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   4459          return False;
   4460       }
   4461       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4462       val = loadBE(Ity_I16, mkexpr(EA));
   4463       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4464       putIReg( rA_addr, mkexpr(EA) );
   4465       break;
   4466 
   4467    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   4468       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4469       val = loadBE(Ity_I32, mkexpr(EA));
   4470       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4471       break;
   4472 
   4473    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   4474       if (rA_addr == 0 || rA_addr == rD_addr) {
   4475          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   4476          return False;
   4477       }
   4478       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   4479       val = loadBE(Ity_I32, mkexpr(EA));
   4480       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4481       putIReg( rA_addr, mkexpr(EA) );
   4482       break;
   4483 
   4484    /* X Form */
   4485    case 0x1F:
   4486       if (b0 != 0) {
   4487          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   4488          return False;
   4489       }
   4490 
   4491       switch (opc2) {
   4492       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   4493          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4494          if (rA_addr == 0 || rA_addr == rD_addr) {
   4495             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4496             return False;
   4497          }
   4498          val = loadBE(Ity_I8, mkexpr(EA));
   4499          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4500          putIReg( rA_addr, mkexpr(EA) );
   4501          break;
   4502 
   4503       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   4504          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4505          val = loadBE(Ity_I8, mkexpr(EA));
   4506          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   4507          break;
   4508 
   4509       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   4510          if (rA_addr == 0 || rA_addr == rD_addr) {
   4511             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   4512             return False;
   4513          }
   4514          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4515          val = loadBE(Ity_I16, mkexpr(EA));
   4516          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4517          putIReg( rA_addr, mkexpr(EA) );
   4518          break;
   4519 
   4520       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   4521          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4522          val = loadBE(Ity_I16, mkexpr(EA));
   4523          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   4524          break;
   4525 
   4526       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   4527          if (rA_addr == 0 || rA_addr == rD_addr) {
   4528             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   4529             return False;
   4530          }
   4531          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4532          val = loadBE(Ity_I16, mkexpr(EA));
   4533          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4534          putIReg( rA_addr, mkexpr(EA) );
   4535          break;
   4536 
   4537       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   4538          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4539          val = loadBE(Ity_I16, mkexpr(EA));
   4540          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   4541          break;
   4542 
   4543       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   4544          if (rA_addr == 0 || rA_addr == rD_addr) {
   4545             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   4546             return False;
   4547          }
   4548          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4549          val = loadBE(Ity_I32, mkexpr(EA));
   4550          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4551          putIReg( rA_addr, mkexpr(EA) );
   4552          break;
   4553 
   4554       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   4555          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4556          val = loadBE(Ity_I32, mkexpr(EA));
   4557          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   4558          break;
   4559 
   4560 
   4561       /* 64bit Loads */
   4562       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   4563          if (rA_addr == 0 || rA_addr == rD_addr) {
   4564             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   4565             return False;
   4566          }
   4567          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4568          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4569          putIReg( rA_addr, mkexpr(EA) );
   4570          break;
   4571 
   4572       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   4573          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4574          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4575          break;
   4576 
   4577       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   4578          if (rA_addr == 0 || rA_addr == rD_addr) {
   4579             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   4580             return False;
   4581          }
   4582          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4583          putIReg( rD_addr,
   4584                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4585          putIReg( rA_addr, mkexpr(EA) );
   4586          break;
   4587 
   4588       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   4589          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4590          putIReg( rD_addr,
   4591                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4592          break;
   4593 
   4594       default:
   4595          vex_printf("dis_int_load(ppc)(opc2)\n");
   4596          return False;
   4597       }
   4598       break;
   4599 
   4600    /* DS Form - 64bit Loads.  In each case EA will have been formed
   4601       with the lowest 2 bits masked off the immediate offset. */
   4602    case 0x3A:
   4603       switch ((b1<<1) | b0) {
   4604       case 0x0: // ld (Load DWord, PPC64 p472)
   4605          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4606          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4607          break;
   4608 
   4609       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   4610          if (rA_addr == 0 || rA_addr == rD_addr) {
   4611             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   4612             return False;
   4613          }
   4614          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4615          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   4616          putIReg( rA_addr, mkexpr(EA) );
   4617          break;
   4618 
   4619       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   4620          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4621          putIReg( rD_addr,
   4622                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   4623          break;
   4624 
   4625       default:
   4626          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4627          return False;
   4628       }
   4629       break;
   4630 
   4631    default:
   4632       vex_printf("dis_int_load(ppc)(opc1)\n");
   4633       return False;
   4634    }
   4635    return True;
   4636 }
   4637 
   4638 
   4639 
   4640 /*
   4641   Integer Store Instructions
   4642 */
   4643 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
   4644 {
   4645    /* D-Form, X-Form, DS-Form */
   4646    UChar opc1    = ifieldOPC(theInstr);
   4647    UInt  rS_addr = ifieldRegDS(theInstr);
   4648    UInt  rA_addr = ifieldRegA(theInstr);
   4649    UInt  uimm16  = ifieldUIMM16(theInstr);
   4650    UInt  rB_addr = ifieldRegB(theInstr);
   4651    UInt  opc2    = ifieldOPClo10(theInstr);
   4652    UChar b1      = ifieldBIT1(theInstr);
   4653    UChar b0      = ifieldBIT0(theInstr);
   4654 
   4655    Int    simm16 = extend_s_16to32(uimm16);
   4656    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4657    IRTemp rS     = newTemp(ty);
   4658    IRTemp rB     = newTemp(ty);
   4659    IRTemp EA     = newTemp(ty);
   4660 
   4661    assign( rB, getIReg(rB_addr) );
   4662    assign( rS, getIReg(rS_addr) );
   4663 
   4664    switch (opc1) {
   4665    case 0x1F: // register offset
   4666       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4667       break;
   4668    case 0x3E: // immediate offset: 64bit: std/stdu: mask off
   4669               // lowest 2 bits of immediate before forming EA
   4670       simm16 = simm16 & 0xFFFFFFFC;
   4671    default:   // immediate offset
   4672       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   4673       break;
   4674    }
   4675 
   4676    switch (opc1) {
   4677    case 0x26: // stb (Store B, PPC32 p509)
   4678       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4679       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4680       break;
   4681 
   4682    case 0x27: // stbu (Store B, Update, PPC32 p510)
   4683       if (rA_addr == 0 ) {
   4684          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   4685          return False;
   4686       }
   4687       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4688       putIReg( rA_addr, mkexpr(EA) );
   4689       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4690       break;
   4691 
   4692    case 0x2C: // sth (Store HW, PPC32 p522)
   4693       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4694       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4695       break;
   4696 
   4697    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   4698       if (rA_addr == 0) {
   4699          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   4700          return False;
   4701       }
   4702       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4703       putIReg( rA_addr, mkexpr(EA) );
   4704       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4705       break;
   4706 
   4707    case 0x24: // stw (Store W, PPC32 p530)
   4708       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4709       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4710       break;
   4711 
   4712    case 0x25: // stwu (Store W, Update, PPC32 p534)
   4713       if (rA_addr == 0) {
   4714          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   4715          return False;
   4716       }
   4717       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4718       putIReg( rA_addr, mkexpr(EA) );
   4719       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4720       break;
   4721 
   4722    /* X Form : all these use EA_indexed */
   4723    case 0x1F:
   4724       if (b0 != 0) {
   4725          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   4726          return False;
   4727       }
   4728 
   4729       switch (opc2) {
   4730       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   4731          if (rA_addr == 0) {
   4732             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   4733             return False;
   4734          }
   4735          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4736          putIReg( rA_addr, mkexpr(EA) );
   4737          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4738          break;
   4739 
   4740       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   4741          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4742          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4743          break;
   4744 
   4745       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   4746          if (rA_addr == 0) {
   4747             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   4748             return False;
   4749          }
   4750          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4751          putIReg( rA_addr, mkexpr(EA) );
   4752          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4753          break;
   4754 
   4755       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   4756          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4757          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4758          break;
   4759 
   4760       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   4761          if (rA_addr == 0) {
   4762             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   4763             return False;
   4764          }
   4765          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4766          putIReg( rA_addr, mkexpr(EA) );
   4767          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4768          break;
   4769 
   4770       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   4771          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4772          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4773          break;
   4774 
   4775 
   4776       /* 64bit Stores */
   4777       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   4778          if (rA_addr == 0) {
   4779             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   4780             return False;
   4781          }
   4782          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4783          putIReg( rA_addr, mkexpr(EA) );
   4784          storeBE( mkexpr(EA), mkexpr(rS) );
   4785          break;
   4786 
   4787       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   4788          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4789          storeBE( mkexpr(EA), mkexpr(rS) );
   4790          break;
   4791 
   4792       default:
   4793          vex_printf("dis_int_store(ppc)(opc2)\n");
   4794          return False;
   4795       }
   4796       break;
   4797 
   4798    /* DS Form - 64bit Stores.  In each case EA will have been formed
   4799       with the lowest 2 bits masked off the immediate offset. */
   4800    case 0x3E:
   4801       switch ((b1<<1) | b0) {
   4802       case 0x0: // std (Store DWord, PPC64 p580)
   4803          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4804          storeBE( mkexpr(EA), mkexpr(rS) );
   4805          break;
   4806 
   4807       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   4808          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4809          putIReg( rA_addr, mkexpr(EA) );
   4810          storeBE( mkexpr(EA), mkexpr(rS) );
   4811          break;
   4812 
   4813       default:
   4814          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4815          return False;
   4816       }
   4817       break;
   4818 
   4819    default:
   4820       vex_printf("dis_int_store(ppc)(opc1)\n");
   4821       return False;
   4822    }
   4823    return True;
   4824 }
   4825 
   4826 
   4827 
   4828 /*
   4829   Integer Load/Store Multiple Instructions
   4830 */
   4831 static Bool dis_int_ldst_mult ( UInt theInstr )
   4832 {
   4833    /* D-Form */
   4834    UChar opc1     = ifieldOPC(theInstr);
   4835    UChar rD_addr  = ifieldRegDS(theInstr);
   4836    UChar rS_addr  = rD_addr;
   4837    UChar rA_addr  = ifieldRegA(theInstr);
   4838    UInt  uimm16   = ifieldUIMM16(theInstr);
   4839 
   4840    Int     simm16 = extend_s_16to32(uimm16);
   4841    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4842    IRTemp  EA     = newTemp(ty);
   4843    UInt    r      = 0;
   4844    UInt    ea_off = 0;
   4845    IRExpr* irx_addr;
   4846 
   4847    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   4848 
   4849    switch (opc1) {
   4850    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   4851       if (rA_addr >= rD_addr) {
   4852          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   4853          return False;
   4854       }
   4855       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4856       for (r = rD_addr; r <= 31; r++) {
   4857          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4858          putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
   4859                                        False) );
   4860          ea_off += 4;
   4861       }
   4862       break;
   4863 
   4864    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   4865       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4866       for (r = rS_addr; r <= 31; r++) {
   4867          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4868          storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   4869          ea_off += 4;
   4870       }
   4871       break;
   4872 
   4873    default:
   4874       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   4875       return False;
   4876    }
   4877    return True;
   4878 }
   4879 
   4880 
   4881 
   4882 /*
   4883   Integer Load/Store String Instructions
   4884 */
   4885 static
   4886 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   4887                              IRTemp EA,        // EA
   4888                              Int    rD,        // first dst register
   4889                              Int    maxBytes ) // 32 or 128
   4890 {
   4891    Int     i, shift = 24;
   4892    IRExpr* e_nbytes = mkexpr(tNBytes);
   4893    IRExpr* e_EA     = mkexpr(EA);
   4894    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   4895 
   4896    vassert(rD >= 0 && rD < 32);
   4897    rD--; if (rD < 0) rD = 31;
   4898 
   4899    for (i = 0; i < maxBytes; i++) {
   4900       /* if (nBytes < (i+1)) goto NIA; */
   4901       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   4902                          Ijk_Boring,
   4903                          mkSzConst( ty, nextInsnAddr()) ));
   4904       /* when crossing into a new dest register, set it to zero. */
   4905       if ((i % 4) == 0) {
   4906          rD++; if (rD == 32) rD = 0;
   4907          putIReg(rD, mkSzImm(ty, 0));
   4908          shift = 24;
   4909       }
   4910       /* rD |=  (8Uto32(*(EA+i))) << shift */
   4911       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   4912       putIReg(
   4913          rD,
   4914          mkWidenFrom32(
   4915             ty,
   4916             binop(
   4917                Iop_Or32,
   4918                mkNarrowTo32(ty, getIReg(rD)),
   4919                binop(
   4920                   Iop_Shl32,
   4921                   unop(
   4922                      Iop_8Uto32,
   4923                      loadBE(Ity_I8,
   4924                             binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
   4925                   ),
   4926                   mkU8(toUChar(shift))
   4927                )
   4928             ),
   4929             /*Signed*/False
   4930 	 )
   4931       );
   4932       shift -= 8;
   4933    }
   4934 }
   4935 
   4936 static
   4937 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   4938                               IRTemp EA,        // EA
   4939                               Int    rS,        // first src register
   4940                               Int    maxBytes ) // 32 or 128
   4941 {
   4942    Int     i, shift = 24;
   4943    IRExpr* e_nbytes = mkexpr(tNBytes);
   4944    IRExpr* e_EA     = mkexpr(EA);
   4945    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   4946 
   4947    vassert(rS >= 0 && rS < 32);
   4948    rS--; if (rS < 0) rS = 31;
   4949 
   4950    for (i = 0; i < maxBytes; i++) {
   4951       /* if (nBytes < (i+1)) goto NIA; */
   4952       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   4953                          Ijk_Boring,
   4954                          mkSzConst( ty, nextInsnAddr() ) ));
   4955       /* check for crossing into a new src register. */
   4956       if ((i % 4) == 0) {
   4957          rS++; if (rS == 32) rS = 0;
   4958          shift = 24;
   4959       }
   4960       /* *(EA+i) = 32to8(rS >> shift) */
   4961       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   4962       storeBE(
   4963          binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   4964          unop(Iop_32to8,
   4965               binop(Iop_Shr32,
   4966                     mkNarrowTo32(ty, getIReg(rS)),
   4967                     mkU8(toUChar(shift))))
   4968       );
   4969       shift -= 8;
   4970    }
   4971 }
   4972 
   4973 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   4974 {
   4975    /* X-Form */
   4976    UChar opc1     = ifieldOPC(theInstr);
   4977    UChar rD_addr  = ifieldRegDS(theInstr);
   4978    UChar rS_addr  = rD_addr;
   4979    UChar rA_addr  = ifieldRegA(theInstr);
   4980    UChar rB_addr  = ifieldRegB(theInstr);
   4981    UChar NumBytes = rB_addr;
   4982    UInt  opc2     = ifieldOPClo10(theInstr);
   4983    UChar b0       = ifieldBIT0(theInstr);
   4984 
   4985    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   4986    IRTemp t_EA    = newTemp(ty);
   4987    IRTemp t_nbytes = IRTemp_INVALID;
   4988 
   4989    *stopHere = False;
   4990 
   4991    if (opc1 != 0x1F || b0 != 0) {
   4992       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   4993       return False;
   4994    }
   4995 
   4996    switch (opc2) {
   4997    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   4998       /* NB: does not reject the case where RA is in the range of
   4999          registers to be loaded.  It should. */
   5000       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   5001       assign( t_EA, ea_rAor0(rA_addr) );
   5002       if (NumBytes == 8 && !mode64) {
   5003          /* Special case hack */
   5004          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   5005          putIReg( rD_addr,
   5006                   loadBE(Ity_I32, mkexpr(t_EA)) );
   5007          putIReg( (rD_addr+1) % 32,
   5008                   loadBE(Ity_I32,
   5009                          binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   5010       } else {
   5011          t_nbytes = newTemp(Ity_I32);
   5012          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5013          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5014          *stopHere = True;
   5015       }
   5016       return True;
   5017 
   5018    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   5019       /* NB: does not reject the case where RA is in the range of
   5020          registers to be loaded.  It should.  Although considering
   5021          that that can only be detected at run time, it's not easy to
   5022          do so. */
   5023       if (rD_addr == rA_addr || rD_addr == rB_addr)
   5024          return False;
   5025       if (rD_addr == 0 && rA_addr == 0)
   5026          return False;
   5027       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5028       t_nbytes = newTemp(Ity_I32);
   5029       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5030       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5031       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   5032       *stopHere = True;
   5033       return True;
   5034 
   5035    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   5036       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   5037       assign( t_EA, ea_rAor0(rA_addr) );
   5038       if (NumBytes == 8 && !mode64) {
   5039          /* Special case hack */
   5040          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   5041          storeBE( mkexpr(t_EA),
   5042                   getIReg(rD_addr) );
   5043          storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   5044                   getIReg((rD_addr+1) % 32) );
   5045       } else {
   5046          t_nbytes = newTemp(Ity_I32);
   5047          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5048          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5049          *stopHere = True;
   5050       }
   5051       return True;
   5052 
   5053    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   5054       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5055       t_nbytes = newTemp(Ity_I32);
   5056       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5057       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5058       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   5059       *stopHere = True;
   5060       return True;
   5061 
   5062    default:
   5063       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   5064       return False;
   5065    }
   5066    return True;
   5067 }
   5068 
   5069 
   5070 /* ------------------------------------------------------------------
   5071    Integer Branch Instructions
   5072    ------------------------------------------------------------------ */
   5073 
   5074 /*
   5075   Branch helper function
   5076   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   5077   Returns an I32 which is 0x00000000 if the ctr condition failed
   5078   and 0xFFFFFFFF otherwise.
   5079 */
   5080 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   5081 {
   5082    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5083    IRTemp ok = newTemp(Ity_I32);
   5084 
   5085    if ((BO >> 2) & 1) {     // independent of ctr
   5086       assign( ok, mkU32(0xFFFFFFFF) );
   5087    } else {
   5088       if ((BO >> 1) & 1) {  // ctr == 0 ?
   5089          assign( ok, unop( Iop_1Sto32,
   5090                            binop( mkSzOp(ty, Iop_CmpEQ8),
   5091                                   getGST( PPC_GST_CTR ),
   5092                                   mkSzImm(ty,0))) );
   5093       } else {              // ctr != 0 ?
   5094          assign( ok, unop( Iop_1Sto32,
   5095                            binop( mkSzOp(ty, Iop_CmpNE8),
   5096                                   getGST( PPC_GST_CTR ),
   5097                                   mkSzImm(ty,0))) );
   5098       }
   5099    }
   5100    return mkexpr(ok);
   5101 }
   5102 
   5103 
   5104 /*
   5105   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   5106   Returns an I32 which is either 0 if the condition failed or
   5107   some arbitrary nonzero value otherwise. */
   5108 
   5109 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   5110 {
   5111    Int where;
   5112    IRTemp res   = newTemp(Ity_I32);
   5113    IRTemp cr_bi = newTemp(Ity_I32);
   5114 
   5115    if ((BO >> 4) & 1) {
   5116       assign( res, mkU32(1) );
   5117    } else {
   5118       // ok = (CR[BI] == BO[3]) Note, the following relies on
   5119       // getCRbit_anywhere returning a value which
   5120       // is either zero or has exactly 1 bit set.
   5121       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   5122 
   5123       if ((BO >> 3) & 1) {
   5124          /* We can use cr_bi as-is. */
   5125          assign( res, mkexpr(cr_bi) );
   5126       } else {
   5127          /* We have to invert the sense of the information held in
   5128             cr_bi.  For that we need to know which bit
   5129             getCRbit_anywhere regards as significant. */
   5130          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   5131                                        mkU32(1<<where)) );
   5132       }
   5133    }
   5134    return mkexpr(res);
   5135 }
   5136 
   5137 
   5138 /*
   5139   Integer Branch Instructions
   5140 */
   5141 static Bool dis_branch ( UInt theInstr,
   5142                          VexAbiInfo* vbi,
   5143                          /*OUT*/DisResult* dres,
   5144                          Bool (*resteerOkFn)(void*,Addr64),
   5145                          void* callback_opaque )
   5146 {
   5147    UChar opc1    = ifieldOPC(theInstr);
   5148    UChar BO      = ifieldRegDS(theInstr);
   5149    UChar BI      = ifieldRegA(theInstr);
   5150    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   5151    UChar b11to15 = ifieldRegB(theInstr);
   5152    UInt  opc2    = ifieldOPClo10(theInstr);
   5153    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   5154    UChar flag_AA = ifieldBIT1(theInstr);
   5155    UChar flag_LK = ifieldBIT0(theInstr);
   5156 
   5157    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   5158    Addr64   tgt       = 0;
   5159    Int      BD        = extend_s_16to32(BD_u16);
   5160    IRTemp   do_branch = newTemp(Ity_I32);
   5161    IRTemp   ctr_ok    = newTemp(Ity_I32);
   5162    IRTemp   cond_ok   = newTemp(Ity_I32);
   5163    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   5164    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   5165    IRTemp   lr_old    = newTemp(ty);
   5166 
   5167    /* Hack to pass through code that just wants to read the PC */
   5168    if (theInstr == 0x429F0005) {
   5169       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   5170       putGST( PPC_GST_LR, e_nia );
   5171       return True;
   5172    }
   5173 
   5174    /* The default what-next.  Individual cases can override it. */
   5175    dres->whatNext = Dis_StopHere;
   5176 
   5177    switch (opc1) {
   5178    case 0x12: // b     (Branch, PPC32 p360)
   5179       if (flag_AA) {
   5180          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   5181       } else {
   5182          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   5183                              (Long)extend_s_26to64(LI_u26) );
   5184       }
   5185       if (mode64) {
   5186          DIP("b%s%s 0x%llx\n",
   5187              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   5188       } else {
   5189          DIP("b%s%s 0x%x\n",
   5190              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   5191       }
   5192 
   5193       if (flag_LK) {
   5194          putGST( PPC_GST_LR, e_nia );
   5195          if (vbi->guest_ppc_zap_RZ_at_bl
   5196              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   5197             IRTemp t_tgt = newTemp(ty);
   5198             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   5199             make_redzone_AbiHint( vbi, t_tgt,
   5200                                   "branch-and-link (unconditional call)" );
   5201          }
   5202       }
   5203 
   5204       if (resteerOkFn( callback_opaque, tgt )) {
   5205          dres->whatNext   = Dis_ResteerU;
   5206          dres->continueAt = tgt;
   5207       } else {
   5208          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
   5209          irsb->next     = mkSzImm(ty, tgt);
   5210       }
   5211       break;
   5212 
   5213    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   5214       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   5215           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   5216 
   5217       if (!(BO & 0x4)) {
   5218          putGST( PPC_GST_CTR,
   5219                  binop(mkSzOp(ty, Iop_Sub8),
   5220                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5221       }
   5222 
   5223       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   5224          cond_ok is either zero or nonzero, since that's the cheapest
   5225          way to compute it.  Anding them together gives a value which
   5226          is either zero or non zero and so that's what we must test
   5227          for in the IRStmt_Exit. */
   5228       assign( ctr_ok,  branch_ctr_ok( BO ) );
   5229       assign( cond_ok, branch_cond_ok( BO, BI ) );
   5230       assign( do_branch,
   5231               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5232 
   5233       if (flag_AA) {
   5234          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   5235       } else {
   5236          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   5237                             (Long)extend_s_16to64(BD_u16));
   5238       }
   5239       if (flag_LK)
   5240          putGST( PPC_GST_LR, e_nia );
   5241 
   5242       stmt( IRStmt_Exit(
   5243                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   5244                flag_LK ? Ijk_Call : Ijk_Boring,
   5245                mkSzConst(ty, tgt) ) );
   5246 
   5247       irsb->jumpkind = Ijk_Boring;
   5248       irsb->next     = e_nia;
   5249       break;
   5250 
   5251    case 0x13:
   5252       /* For bclr and bcctr, it appears that the lowest two bits of
   5253          b11to15 are a branch hint, and so we only need to ensure it's
   5254          of the form 000XX. */
   5255       if ((b11to15 & ~3) != 0) {
   5256          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
   5257          return False;
   5258       }
   5259 
   5260       switch (opc2) {
   5261       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   5262          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   5263             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   5264             return False;
   5265          }
   5266          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5267 
   5268          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5269 
   5270          /* FIXME: this is confusing.  lr_old holds the old value
   5271             of ctr, not lr :-) */
   5272          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   5273 
   5274          if (flag_LK)
   5275             putGST( PPC_GST_LR, e_nia );
   5276 
   5277          stmt( IRStmt_Exit(
   5278                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   5279                   Ijk_Boring,
   5280                   c_nia ));
   5281 
   5282          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   5283             make_redzone_AbiHint( vbi, lr_old,
   5284                                   "b-ctr-l (indirect call)" );
   5285 	 }
   5286 
   5287          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
   5288          irsb->next     = mkexpr(lr_old);
   5289          break;
   5290 
   5291       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   5292          Bool vanilla_return = False;
   5293          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   5294             DIP("blr\n");
   5295             vanilla_return = True;
   5296          } else {
   5297             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5298          }
   5299 
   5300          if (!(BO & 0x4)) {
   5301             putGST( PPC_GST_CTR,
   5302                     binop(mkSzOp(ty, Iop_Sub8),
   5303                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5304          }
   5305 
   5306          /* See comments above for 'bc' about this */
   5307          assign( ctr_ok,  branch_ctr_ok( BO ) );
   5308          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5309          assign( do_branch,
   5310                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5311 
   5312          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   5313 
   5314          if (flag_LK)
   5315             putGST( PPC_GST_LR,  e_nia );
   5316 
   5317          stmt( IRStmt_Exit(
   5318                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   5319                   Ijk_Boring,
   5320                   c_nia ));
   5321 
   5322          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   5323             make_redzone_AbiHint( vbi, lr_old,
   5324                                   "branch-to-lr (unconditional return)" );
   5325          }
   5326 
   5327          /* blrl is pretty strange; it's like a return that sets the
   5328             return address of its caller to the insn following this
   5329             one.  Mark it as a return. */
   5330          irsb->jumpkind = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   5331          irsb->next     = mkexpr(lr_old);
   5332          break;
   5333       }
   5334       default:
   5335          vex_printf("dis_int_branch(ppc)(opc2)\n");
   5336          return False;
   5337       }
   5338       break;
   5339 
   5340    default:
   5341       vex_printf("dis_int_branch(ppc)(opc1)\n");
   5342       return False;
   5343    }
   5344 
   5345    return True;
   5346 }
   5347 
   5348 
   5349 
   5350 /*
   5351   Condition Register Logical Instructions
   5352 */
   5353 static Bool dis_cond_logic ( UInt theInstr )
   5354 {
   5355    /* XL-Form */
   5356    UChar opc1      = ifieldOPC(theInstr);
   5357    UChar crbD_addr = ifieldRegDS(theInstr);
   5358    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   5359    UChar crbA_addr = ifieldRegA(theInstr);
   5360    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   5361    UChar crbB_addr = ifieldRegB(theInstr);
   5362    UInt  opc2      = ifieldOPClo10(theInstr);
   5363    UChar b0        = ifieldBIT0(theInstr);
   5364 
   5365    IRTemp crbD     = newTemp(Ity_I32);
   5366    IRTemp crbA     = newTemp(Ity_I32);
   5367    IRTemp crbB     = newTemp(Ity_I32);
   5368 
   5369    if (opc1 != 19 || b0 != 0) {
   5370       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   5371       return False;
   5372    }
   5373 
   5374    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   5375       if (((crbD_addr & 0x3) != 0) ||
   5376           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   5377          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   5378          return False;
   5379       }
   5380       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   5381       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   5382       putCR321( crfD_addr, getCR321(crfS_addr) );
   5383    } else {
   5384       assign( crbA, getCRbit(crbA_addr) );
   5385       if (crbA_addr == crbB_addr)
   5386          crbB = crbA;
   5387       else
   5388          assign( crbB, getCRbit(crbB_addr) );
   5389 
   5390       switch (opc2) {
   5391       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   5392          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5393          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   5394          break;
   5395       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   5396          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5397          assign( crbD, binop(Iop_And32,
   5398                              mkexpr(crbA),
   5399                              unop(Iop_Not32, mkexpr(crbB))) );
   5400          break;
   5401       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   5402          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5403          assign( crbD, unop(Iop_Not32,
   5404                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   5405          break;
   5406       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   5407          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5408          assign( crbD, unop(Iop_Not32,
   5409                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   5410          break;
   5411       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   5412          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5413          assign( crbD, unop(Iop_Not32,
   5414                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   5415          break;
   5416       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   5417          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5418          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   5419          break;
   5420       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   5421          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5422          assign( crbD, binop(Iop_Or32,
   5423                              mkexpr(crbA),
   5424                              unop(Iop_Not32, mkexpr(crbB))) );
   5425          break;
   5426       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   5427          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   5428          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   5429          break;
   5430       default:
   5431          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   5432          return False;
   5433       }
   5434 
   5435       putCRbit( crbD_addr, mkexpr(crbD) );
   5436    }
   5437    return True;
   5438 }
   5439 
   5440 
   5441 /*
   5442   Trap instructions
   5443 */
   5444 
   5445 /* Do the code generation for a trap.  Returned Bool is true iff
   5446    this is an unconditional trap.  If the two arg IRExpr*s are
   5447    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   5448    then they are 64-bit, and we must be disassembling 64-bit
   5449    instructions. */
   5450 static Bool do_trap ( UChar TO,
   5451                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   5452 {
   5453    IRTemp argL, argR;
   5454    IRExpr *argLe, *argRe, *cond, *tmp;
   5455 
   5456    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   5457 
   5458    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   5459    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   5460    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   5461    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   5462    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   5463    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   5464    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   5465    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   5466    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   5467    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   5468 
   5469    const UChar b11100 = 0x1C;
   5470    const UChar b00111 = 0x07;
   5471 
   5472    if (is32bit) {
   5473       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   5474       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   5475    } else {
   5476       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   5477       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   5478       vassert( mode64 );
   5479    }
   5480 
   5481    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   5482       /* Unconditional trap.  Just do the exit without
   5483          testing the arguments. */
   5484       stmt( IRStmt_Exit(
   5485                binop(opCMPEQ, const0, const0),
   5486                Ijk_SigTRAP,
   5487                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
   5488       ));
   5489       return True; /* unconditional trap */
   5490    }
   5491 
   5492    if (is32bit) {
   5493       argL = newTemp(Ity_I32);
   5494       argR = newTemp(Ity_I32);
   5495    } else {
   5496       argL = newTemp(Ity_I64);
   5497       argR = newTemp(Ity_I64);
   5498    }
   5499 
   5500    assign( argL, argL0 );
   5501    assign( argR, argR0 );
   5502 
   5503    argLe = mkexpr(argL);
   5504    argRe = mkexpr(argR);
   5505 
   5506    cond = const0;
   5507    if (TO & 16) { // L <s R
   5508       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   5509       cond = binop(opOR, tmp, cond);
   5510    }
   5511    if (TO & 8) { // L >s R
   5512       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   5513       cond = binop(opOR, tmp, cond);
   5514    }
   5515    if (TO & 4) { // L == R
   5516       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   5517       cond = binop(opOR, tmp, cond);
   5518    }
   5519    if (TO & 2) { // L <u R
   5520       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   5521       cond = binop(opOR, tmp, cond);
   5522    }
   5523    if (TO & 1) { // L >u R
   5524       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   5525       cond = binop(opOR, tmp, cond);
   5526    }
   5527    stmt( IRStmt_Exit(
   5528             binop(opCMPNE, cond, const0),
   5529             Ijk_SigTRAP,
   5530             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
   5531    ));
   5532    return False; /* not an unconditional trap */
   5533 }
   5534 
   5535 static Bool dis_trapi ( UInt theInstr,
   5536                         /*OUT*/DisResult* dres )
   5537 {
   5538    /* D-Form */
   5539    UChar  opc1    = ifieldOPC(theInstr);
   5540    UChar  TO      = ifieldRegDS(theInstr);
   5541    UChar  rA_addr = ifieldRegA(theInstr);
   5542    UInt   uimm16  = ifieldUIMM16(theInstr);
   5543    ULong  simm16  = extend_s_16to64(uimm16);
   5544    Addr64 cia     = guest_CIA_curr_instr;
   5545    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5546    Bool   uncond  = False;
   5547 
   5548    switch (opc1) {
   5549    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   5550       uncond = do_trap( TO,
   5551                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   5552                                : getIReg(rA_addr),
   5553                         mkU32( (UInt)simm16 ),
   5554                         cia );
   5555       if (TO == 4) {
   5556          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5557       } else {
   5558          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5559       }
   5560       break;
   5561    case 0x02: // tdi
   5562       if (!mode64)
   5563          return False;
   5564       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   5565       if (TO == 4) {
   5566          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   5567       } else {
   5568          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   5569       }
   5570       break;
   5571    default:
   5572       return False;
   5573    }
   5574 
   5575    if (uncond) {
   5576       /* If the trap shows signs of being unconditional, don't
   5577          continue decoding past it. */
   5578       irsb->next     = mkSzImm( ty, nextInsnAddr() );
   5579       irsb->jumpkind = Ijk_Boring;
   5580       dres->whatNext = Dis_StopHere;
   5581    }
   5582 
   5583    return True;
   5584 }
   5585 
   5586 static Bool dis_trap ( UInt theInstr,
   5587                         /*OUT*/DisResult* dres )
   5588 {
   5589    /* X-Form */
   5590    UInt   opc2    = ifieldOPClo10(theInstr);
   5591    UChar  TO      = ifieldRegDS(theInstr);
   5592    UChar  rA_addr = ifieldRegA(theInstr);
   5593    UChar  rB_addr = ifieldRegB(theInstr);
   5594    Addr64 cia     = guest_CIA_curr_instr;
   5595    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5596    Bool   uncond  = False;
   5597 
   5598    if (ifieldBIT0(theInstr) != 0)
   5599       return False;
   5600 
   5601    switch (opc2) {
   5602    case 0x004: // tw  (Trap Word, PPC64 p540)
   5603       uncond = do_trap( TO,
   5604                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   5605                                : getIReg(rA_addr),
   5606                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   5607                                : getIReg(rB_addr),
   5608                         cia );
   5609       if (TO == 4) {
   5610          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   5611       } else {
   5612          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   5613       }
   5614       break;
   5615    case 0x044: // td (Trap Doubleword, PPC64 p534)
   5616       if (!mode64)
   5617          return False;
   5618       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   5619       if (TO == 4) {
   5620          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   5621       } else {
   5622          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   5623       }
   5624       break;
   5625    default:
   5626       return False;
   5627    }
   5628 
   5629    if (uncond) {
   5630       /* If the trap shows signs of being unconditional, don't
   5631          continue decoding past it. */
   5632       irsb->next     = mkSzImm( ty, nextInsnAddr() );
   5633       irsb->jumpkind = Ijk_Boring;
   5634       dres->whatNext = Dis_StopHere;
   5635    }
   5636 
   5637    return True;
   5638 }
   5639 
   5640 
   5641 /*
   5642   System Linkage Instructions
   5643 */
   5644 static Bool dis_syslink ( UInt theInstr,
   5645                           VexAbiInfo* abiinfo, DisResult* dres )
   5646 {
   5647    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5648 
   5649    if (theInstr != 0x44000002) {
   5650       vex_printf("dis_syslink(ppc)(theInstr)\n");
   5651       return False;
   5652    }
   5653 
   5654    // sc  (System Call, PPC32 p504)
   5655    DIP("sc\n");
   5656 
   5657    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
   5658       Valgrind can back the guest up to this instruction if it needs
   5659       to restart the syscall. */
   5660    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   5661 
   5662    /* It's important that all ArchRegs carry their up-to-date value
   5663       at this point.  So we declare an end-of-block here, which
   5664       forces any TempRegs caching ArchRegs to be flushed. */
   5665    irsb->next     = abiinfo->guest_ppc_sc_continues_at_LR
   5666                        ? getGST( PPC_GST_LR )
   5667                        : mkSzImm( ty, nextInsnAddr() );
   5668    irsb->jumpkind = Ijk_Sys_syscall;
   5669 
   5670    dres->whatNext = Dis_StopHere;
   5671    return True;
   5672 }
   5673 
   5674 
   5675 /*
   5676   Memory Synchronization Instructions
   5677 
   5678   Note on Reservations:
   5679   We rely on the assumption that V will in fact only allow one thread at
   5680   once to run.  In effect, a thread can make a reservation, but we don't
   5681   check any stores it does.  Instead, the reservation is cancelled when
   5682   the scheduler switches to another thread (run_thread_for_a_while()).
   5683 */
   5684 static Bool dis_memsync ( UInt theInstr )
   5685 {
   5686    /* X-Form, XL-Form */
   5687    UChar opc1    = ifieldOPC(theInstr);
   5688    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   5689    UChar flag_L  = ifieldRegDS(theInstr);
   5690    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   5691    UChar rD_addr = ifieldRegDS(theInstr);
   5692    UChar rS_addr = rD_addr;
   5693    UChar rA_addr = ifieldRegA(theInstr);
   5694    UChar rB_addr = ifieldRegB(theInstr);
   5695    UInt  opc2    = ifieldOPClo10(theInstr);
   5696    UChar b0      = ifieldBIT0(theInstr);
   5697 
   5698    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5699    IRTemp EA     = newTemp(ty);
   5700 
   5701    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5702 
   5703    switch (opc1) {
   5704    /* XL-Form */
   5705    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   5706       if (opc2 != 0x096) {
   5707          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   5708          return False;
   5709       }
   5710       if (b11to25 != 0 || b0 != 0) {
   5711          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   5712          return False;
   5713       }
   5714       DIP("isync\n");
   5715       stmt( IRStmt_MBE(Imbe_Fence) );
   5716       break;
   5717 
   5718    /* X-Form */
   5719    case 0x1F:
   5720       switch (opc2) {
   5721       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
   5722          if (b11to25 != 0 || b0 != 0) {
   5723             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
   5724             return False;
   5725          }
   5726          DIP("eieio\n");
   5727          /* Insert a memory fence, just to be on the safe side. */
   5728          stmt( IRStmt_MBE(Imbe_Fence) );
   5729          break;
   5730 
   5731       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   5732          IRTemp res;
   5733          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5734             in the documentation) is merely a hint bit to the
   5735             hardware, I think as to whether or not contention is
   5736             likely.  So we can just ignore it. */
   5737          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5738 
   5739          // trap if misaligned
   5740          gen_SIGBUS_if_misaligned( EA, 4 );
   5741 
   5742          // and actually do the load
   5743          res = newTemp(Ity_I32);
   5744          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5745 
   5746          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   5747          break;
   5748       }
   5749 
   5750       case 0x096: {
   5751          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   5752          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   5753          // so isn't quite as straightforward as it might otherwise be.
   5754          IRTemp rS = newTemp(Ity_I32);
   5755          IRTemp resSC;
   5756          if (b0 != 1) {
   5757             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   5758             return False;
   5759          }
   5760          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5761 
   5762          // trap if misaligned
   5763          gen_SIGBUS_if_misaligned( EA, 4 );
   5764 
   5765          // Get the data to be stored, and narrow to 32 bits if necessary
   5766          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   5767 
   5768          // Do the store, and get success/failure bit into resSC
   5769          resSC = newTemp(Ity_I1);
   5770          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5771 
   5772          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5773          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5774          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5775          putCR0(0, getXER_SO());
   5776 
   5777          /* Note:
   5778             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5779             whether rS is stored is dependent on that value. */
   5780          /* So I guess we can just ignore this case? */
   5781          break;
   5782       }
   5783 
   5784       case 0x256: // sync (Synchronize, PPC32 p543),
   5785                   // also lwsync (L==1), ptesync (L==2)
   5786          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   5787 
   5788             The PowerPC architecture used in IBM chips has expanded
   5789             the sync instruction into two variants: lightweight sync
   5790             and heavyweight sync.  The original sync instruction is
   5791             the new heavyweight sync and lightweight sync is a strict
   5792             subset of the heavyweight sync functionality. This allows
   5793             the programmer to specify a less expensive operation on
   5794             high-end systems when the full sync functionality is not
   5795             necessary.
   5796 
   5797             The basic "sync" mnemonic now utilizes an operand. "sync"
   5798             without an operand now becomes a extended mnemonic for
   5799             heavyweight sync.  Processors without the lwsync
   5800             instruction will not decode the L field and will perform a
   5801             heavyweight sync.  Everything is backward compatible.
   5802 
   5803             sync    =       sync 0
   5804             lwsync  =       sync 1
   5805             ptesync =       sync 2    *** TODO - not implemented ***
   5806          */
   5807          if (b11to20 != 0 || b0 != 0) {
   5808             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   5809             return False;
   5810          }
   5811          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   5812             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   5813             return False;
   5814          }
   5815          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   5816          /* Insert a memory fence.  It's sometimes important that these
   5817             are carried through to the generated code. */
   5818          stmt( IRStmt_MBE(Imbe_Fence) );
   5819          break;
   5820 
   5821       /* 64bit Memsync */
   5822       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   5823          IRTemp res;
   5824          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5825             in the documentation) is merely a hint bit to the
   5826             hardware, I think as to whether or not contention is
   5827             likely.  So we can just ignore it. */
   5828          if (!mode64)
   5829             return False;
   5830          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5831 
   5832          // trap if misaligned
   5833          gen_SIGBUS_if_misaligned( EA, 8 );
   5834 
   5835          // and actually do the load
   5836          res = newTemp(Ity_I64);
   5837          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5838 
   5839          putIReg( rD_addr, mkexpr(res) );
   5840          break;
   5841       }
   5842 
   5843       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   5844          // A marginally simplified version of the stwcx. case
   5845          IRTemp rS = newTemp(Ity_I64);
   5846          IRTemp resSC;
   5847          if (b0 != 1) {
   5848             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   5849             return False;
   5850          }
   5851          if (!mode64)
   5852             return False;
   5853          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5854 
   5855          // trap if misaligned
   5856          gen_SIGBUS_if_misaligned( EA, 8 );
   5857 
   5858          // Get the data to be stored
   5859          assign( rS, getIReg(rS_addr) );
   5860 
   5861          // Do the store, and get success/failure bit into resSC
   5862          resSC = newTemp(Ity_I1);
   5863          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5864 
   5865          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5866          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5867          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5868          putCR0(0, getXER_SO());
   5869 
   5870          /* Note:
   5871             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5872             whether rS is stored is dependent on that value. */
   5873          /* So I guess we can just ignore this case? */
   5874          break;
   5875       }
   5876 
   5877       default:
   5878          vex_printf("dis_memsync(ppc)(opc2)\n");
   5879          return False;
   5880       }
   5881       break;
   5882 
   5883    default:
   5884       vex_printf("dis_memsync(ppc)(opc1)\n");
   5885       return False;
   5886    }
   5887    return True;
   5888 }
   5889 
   5890 
   5891 
   5892 /*
   5893   Integer Shift Instructions
   5894 */
   5895 static Bool dis_int_shift ( UInt theInstr )
   5896 {
   5897    /* X-Form, XS-Form */
   5898    UChar opc1    = ifieldOPC(theInstr);
   5899    UChar rS_addr = ifieldRegDS(theInstr);
   5900    UChar rA_addr = ifieldRegA(theInstr);
   5901    UChar rB_addr = ifieldRegB(theInstr);
   5902    UChar sh_imm  = rB_addr;
   5903    UInt  opc2    = ifieldOPClo10(theInstr);
   5904    UChar b1      = ifieldBIT1(theInstr);
   5905    UChar flag_rC = ifieldBIT0(theInstr);
   5906 
   5907    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   5908    IRTemp  rA         = newTemp(ty);
   5909    IRTemp  rS         = newTemp(ty);
   5910    IRTemp  rB         = newTemp(ty);
   5911    IRTemp  outofrange = newTemp(Ity_I8);
   5912    IRTemp  rS_lo32    = newTemp(Ity_I32);
   5913    IRTemp  rB_lo32    = newTemp(Ity_I32);
   5914    IRExpr* e_tmp;
   5915 
   5916    assign( rS, getIReg(rS_addr) );
   5917    assign( rB, getIReg(rB_addr) );
   5918    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   5919    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   5920 
   5921    if (opc1 == 0x1F) {
   5922       switch (opc2) {
   5923       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   5924          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   5925              rA_addr, rS_addr, rB_addr);
   5926          /* rA = rS << rB */
   5927          /* ppc32 semantics are:
   5928             slw(x,y) = (x << (y & 31))         -- primary result
   5929                        & ~((y << 26) >>s 31)   -- make result 0
   5930                                                   for y in 32 .. 63
   5931          */
   5932          e_tmp =
   5933             binop( Iop_And32,
   5934                binop( Iop_Shl32,
   5935                       mkexpr(rS_lo32),
   5936                       unop( Iop_32to8,
   5937                             binop(Iop_And32,
   5938                                   mkexpr(rB_lo32), mkU32(31)))),
   5939                unop( Iop_Not32,
   5940                      binop( Iop_Sar32,
   5941                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   5942                             mkU8(31))) );
   5943          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   5944          break;
   5945       }
   5946 
   5947       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   5948          IRTemp sh_amt = newTemp(Ity_I32);
   5949          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   5950              rA_addr, rS_addr, rB_addr);
   5951          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   5952             amt = rB & 63
   5953             rA = Sar32( rS, amt > 31 ? 31 : amt )
   5954             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   5955          */
   5956          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   5957                                           mkexpr(rB_lo32)) );
   5958          assign( outofrange,
   5959                  unop( Iop_1Uto8,
   5960                        binop(Iop_CmpLT32U, mkU32(31),
   5961                                            mkexpr(sh_amt)) ));
   5962          e_tmp = binop( Iop_Sar32,
   5963                         mkexpr(rS_lo32),
   5964                         unop( Iop_32to8,
   5965                               IRExpr_Mux0X( mkexpr(outofrange),
   5966                                             mkexpr(sh_amt),
   5967                                             mkU32(31)) ) );
   5968          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   5969 
   5970          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   5971                      mkexpr(rA),
   5972                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   5973                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   5974                      mkWidenFrom32(ty, getXER_CA32(), True) );
   5975          break;
   5976       }
   5977 
   5978       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   5979          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   5980              rA_addr, rS_addr, sh_imm);
   5981          vassert(sh_imm < 32);
   5982          if (mode64) {
   5983             assign( rA, binop(Iop_Sar64,
   5984                               binop(Iop_Shl64, getIReg(rS_addr),
   5985                                                mkU8(32)),
   5986                               mkU8(32 + sh_imm)) );
   5987          } else {
   5988             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   5989                                          mkU8(sh_imm)) );
   5990          }
   5991 
   5992          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   5993                      mkexpr(rA),
   5994                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   5995                      mkSzImm(ty, sh_imm),
   5996                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   5997          break;
   5998 
   5999       case 0x218: // srw (Shift Right Word, PPC32 p508)
   6000          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6001              rA_addr, rS_addr, rB_addr);
   6002          /* rA = rS >>u rB */
   6003          /* ppc32 semantics are:
   6004             srw(x,y) = (x >>u (y & 31))        -- primary result
   6005                        & ~((y << 26) >>s 31)   -- make result 0
   6006                                                   for y in 32 .. 63
   6007          */
   6008          e_tmp =
   6009             binop(
   6010                Iop_And32,
   6011                binop( Iop_Shr32,
   6012                       mkexpr(rS_lo32),
   6013                       unop( Iop_32to8,
   6014                             binop(Iop_And32, mkexpr(rB_lo32),
   6015                                              mkU32(31)))),
   6016                unop( Iop_Not32,
   6017                      binop( Iop_Sar32,
   6018                             binop(Iop_Shl32, mkexpr(rB_lo32),
   6019                                              mkU8(26)),
   6020                             mkU8(31))));
   6021          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6022          break;
   6023 
   6024 
   6025       /* 64bit Shifts */
   6026       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   6027          DIP("sld%s r%u,r%u,r%u\n",
   6028              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6029          /* rA = rS << rB */
   6030          /* ppc64 semantics are:
   6031             slw(x,y) = (x << (y & 63))         -- primary result
   6032                        & ~((y << 57) >>s 63)   -- make result 0
   6033                                                   for y in 64 ..
   6034          */
   6035          assign( rA,
   6036             binop(
   6037                Iop_And64,
   6038                binop( Iop_Shl64,
   6039                       mkexpr(rS),
   6040                       unop( Iop_64to8,
   6041                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6042                unop( Iop_Not64,
   6043                      binop( Iop_Sar64,
   6044                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6045                             mkU8(63)))) );
   6046          break;
   6047 
   6048       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   6049          IRTemp sh_amt = newTemp(Ity_I64);
   6050          DIP("srad%s r%u,r%u,r%u\n",
   6051              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6052          /* amt = rB & 127
   6053             rA = Sar64( rS, amt > 63 ? 63 : amt )
   6054             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   6055          */
   6056          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   6057          assign( outofrange,
   6058                  unop( Iop_1Uto8,
   6059                        binop(Iop_CmpLT64U, mkU64(63),
   6060                                            mkexpr(sh_amt)) ));
   6061          assign( rA,
   6062                  binop( Iop_Sar64,
   6063                         mkexpr(rS),
   6064                         unop( Iop_64to8,
   6065                               IRExpr_Mux0X( mkexpr(outofrange),
   6066                                             mkexpr(sh_amt),
   6067                                             mkU64(63)) ))
   6068                );
   6069          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   6070                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   6071                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6072          break;
   6073       }
   6074 
   6075       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   6076          sh_imm |= b1<<5;
   6077          vassert(sh_imm < 64);
   6078          DIP("sradi%s r%u,r%u,%u\n",
   6079              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   6080          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   6081 
   6082          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   6083                      mkexpr(rA),
   6084                      getIReg(rS_addr),
   6085                      mkU64(sh_imm),
   6086                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6087          break;
   6088 
   6089       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   6090          DIP("srd%s r%u,r%u,r%u\n",
   6091              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6092          /* rA = rS >>u rB */
   6093          /* ppc semantics are:
   6094             srw(x,y) = (x >>u (y & 63))        -- primary result
   6095                        & ~((y << 57) >>s 63)   -- make result 0
   6096                                                   for y in 64 .. 127
   6097          */
   6098          assign( rA,
   6099             binop(
   6100                Iop_And64,
   6101                binop( Iop_Shr64,
   6102                       mkexpr(rS),
   6103                       unop( Iop_64to8,
   6104                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6105                unop( Iop_Not64,
   6106                      binop( Iop_Sar64,
   6107                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6108                             mkU8(63)))) );
   6109          break;
   6110 
   6111       default:
   6112          vex_printf("dis_int_shift(ppc)(opc2)\n");
   6113          return False;
   6114       }
   6115    } else {
   6116       vex_printf("dis_int_shift(ppc)(opc1)\n");
   6117       return False;
   6118    }
   6119 
   6120    putIReg( rA_addr, mkexpr(rA) );
   6121 
   6122    if (flag_rC) {
   6123       set_CR0( mkexpr(rA) );
   6124    }
   6125    return True;
   6126 }
   6127 
   6128 
   6129 
   6130 /*
   6131   Integer Load/Store Reverse Instructions
   6132 */
   6133 /* Generates code to swap the byte order in an Ity_I32. */
   6134 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   6135 {
   6136    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6137    return
   6138       binop(Iop_Or32,
   6139          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   6140       binop(Iop_Or32,
   6141          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6142                           mkU32(0x00FF0000)),
   6143       binop(Iop_Or32,
   6144          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6145                           mkU32(0x0000FF00)),
   6146          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   6147                           mkU32(0x000000FF) )
   6148       )));
   6149 }
   6150 
   6151 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   6152    and zeroes the upper half. */
   6153 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   6154 {
   6155    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   6156    return
   6157       binop(Iop_Or32,
   6158          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   6159                           mkU32(0x0000FF00)),
   6160          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   6161                           mkU32(0x000000FF))
   6162       );
   6163 }
   6164 
   6165 static Bool dis_int_ldst_rev ( UInt theInstr )
   6166 {
   6167    /* X-Form */
   6168    UChar opc1    = ifieldOPC(theInstr);
   6169    UChar rD_addr = ifieldRegDS(theInstr);
   6170    UChar rS_addr = rD_addr;
   6171    UChar rA_addr = ifieldRegA(theInstr);
   6172    UChar rB_addr = ifieldRegB(theInstr);
   6173    UInt  opc2    = ifieldOPClo10(theInstr);
   6174    UChar b0      = ifieldBIT0(theInstr);
   6175 
   6176    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6177    IRTemp EA = newTemp(ty);
   6178    IRTemp w1 = newTemp(Ity_I32);
   6179    IRTemp w2 = newTemp(Ity_I32);
   6180 
   6181    if (opc1 != 0x1F || b0 != 0) {
   6182       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   6183       return False;
   6184    }
   6185 
   6186    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6187 
   6188    switch (opc2) {
   6189 
   6190       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   6191          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6192          assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
   6193          assign( w2, gen_byterev16(w1) );
   6194          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6195                                          /* Signed */False) );
   6196          break;
   6197 
   6198       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   6199          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6200          assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
   6201          assign( w2, gen_byterev32(w1) );
   6202          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   6203                                          /* Signed */False) );
   6204          break;
   6205 
   6206       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
   6207       {
   6208          IRExpr * nextAddr;
   6209          IRTemp w3 = newTemp( Ity_I32 );
   6210          IRTemp w4 = newTemp( Ity_I32 );
   6211          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   6212          assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
   6213          assign( w2, gen_byterev32( w1 ) );
   6214          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   6215                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
   6216          assign( w3, loadBE( Ity_I32, nextAddr ) );
   6217          assign( w4, gen_byterev32( w3 ) );
   6218          putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
   6219          break;
   6220       }
   6221 
   6222       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   6223          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6224          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6225          storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   6226          break;
   6227 
   6228       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   6229          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6230          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6231          storeBE( mkexpr(EA), gen_byterev32(w1) );
   6232          break;
   6233 
   6234       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
   6235       {
   6236          IRTemp lo = newTemp(Ity_I32);
   6237          IRTemp hi = newTemp(Ity_I32);
   6238          IRTemp rS = newTemp(Ity_I64);
   6239          assign( rS, getIReg( rS_addr ) );
   6240          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6241          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
   6242          assign(hi, unop(Iop_64to32, mkexpr(rS)));
   6243          storeBE( mkexpr( EA ),
   6244                   binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
   6245          break;
   6246       }
   6247 
   6248       default:
   6249          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   6250          return False;
   6251    }
   6252    return True;
   6253 }
   6254 
   6255 
   6256 
   6257 /*
   6258   Processor Control Instructions
   6259 */
   6260 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
   6261 {
   6262    UChar opc1     = ifieldOPC(theInstr);
   6263 
   6264    /* X-Form */
   6265    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   6266    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   6267    UChar rD_addr  = ifieldRegDS(theInstr);
   6268    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   6269 
   6270    /* XFX-Form */
   6271    UChar rS_addr  = rD_addr;
   6272    UInt  SPR      = b11to20;
   6273    UInt  TBR      = b11to20;
   6274    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   6275    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   6276    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   6277 
   6278    UInt  opc2     = ifieldOPClo10(theInstr);
   6279    UChar b0       = ifieldBIT0(theInstr);
   6280 
   6281    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6282    IRTemp rS = newTemp(ty);
   6283    assign( rS, getIReg(rS_addr) );
   6284 
   6285    /* Reorder SPR field as per PPC32 p470 */
   6286    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   6287    /* Reorder TBR field as per PPC32 p475 */
   6288    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   6289 
   6290    if (opc1 != 0x1F || b0 != 0) {
   6291       vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
   6292       return False;
   6293    }
   6294 
   6295    switch (opc2) {
   6296    /* X-Form */
   6297    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   6298       if (b21to22 != 0 || b11to20 != 0) {
   6299          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   6300          return False;
   6301       }
   6302       DIP("mcrxr crf%d\n", crfD);
   6303       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   6304       putGST_field( PPC_GST_CR,
   6305                     getGST_field( PPC_GST_XER, 7 ),
   6306                     crfD );
   6307 
   6308       // Clear XER[0-3]
   6309       putXER_SO( mkU8(0) );
   6310       putXER_OV( mkU8(0) );
   6311       putXER_CA( mkU8(0) );
   6312       break;
   6313    }
   6314 
   6315    case 0x013:
   6316       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   6317       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   6318       // However it seems that the 'mfcr' behaviour is an acceptable
   6319       // implementation of mfocr (from the 2.02 arch spec)
   6320       if (b11to20 == 0) {
   6321          DIP("mfcr r%u\n", rD_addr);
   6322          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6323                                          /* Signed */False) );
   6324          break;
   6325       }
   6326       if (b20 == 1 && b11 == 0) {
   6327          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   6328          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   6329                                          /* Signed */False) );
   6330          break;
   6331       }
   6332       /* not decodable */
   6333       return False;
   6334 
   6335    /* XFX-Form */
   6336    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   6337 
   6338       switch (SPR) {  // Choose a register...
   6339       case 0x1:
   6340          DIP("mfxer r%u\n", rD_addr);
   6341          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   6342                                          /* Signed */False) );
   6343          break;
   6344       case 0x8:
   6345          DIP("mflr r%u\n", rD_addr);
   6346          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   6347          break;
   6348       case 0x9:
   6349          DIP("mfctr r%u\n", rD_addr);
   6350          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   6351          break;
   6352       case 0x100:
   6353          DIP("mfvrsave r%u\n", rD_addr);
   6354          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   6355                                          /* Signed */False) );
   6356          break;
   6357 
   6358       case 0x103:
   6359          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   6360          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   6361          break;
   6362 
   6363       /* Even a lowly PPC7400 can run the associated helper, so no
   6364          obvious need for feature testing at this point. */
   6365       case 268 /* 0x10C */:
   6366       case 269 /* 0x10D */: {
   6367          UInt     arg  = SPR==268 ? 0 : 1;
   6368          IRTemp   val  = newTemp(Ity_I32);
   6369          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   6370          IRDirty* d    = unsafeIRDirty_1_N(
   6371                             val,
   6372                             0/*regparms*/,
   6373                             "ppc32g_dirtyhelper_MFSPR_268_269",
   6374                             fnptr_to_fnentry
   6375                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   6376                             args
   6377                          );
   6378          /* execute the dirty call, dumping the result in val. */
   6379          stmt( IRStmt_Dirty(d) );
   6380          putIReg( rD_addr,
   6381                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6382          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6383          break;
   6384       }
   6385 
   6386       /* Again, runs natively on PPC7400 (7447, really).  Not
   6387          bothering with a feature test. */
   6388       case 287: /* 0x11F */ {
   6389          IRTemp   val  = newTemp(Ity_I32);
   6390          IRExpr** args = mkIRExprVec_0();
   6391          IRDirty* d    = unsafeIRDirty_1_N(
   6392                             val,
   6393                             0/*regparms*/,
   6394                             "ppc32g_dirtyhelper_MFSPR_287",
   6395                             fnptr_to_fnentry
   6396                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   6397                             args
   6398                          );
   6399          /* execute the dirty call, dumping the result in val. */
   6400          stmt( IRStmt_Dirty(d) );
   6401          putIReg( rD_addr,
   6402                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   6403          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   6404          break;
   6405       }
   6406 
   6407       default:
   6408          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   6409          return False;
   6410       }
   6411       break;
   6412 
   6413    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   6414       IRTemp   val  = newTemp(Ity_I64);
   6415       IRExpr** args = mkIRExprVec_0();
   6416       IRDirty* d    = unsafeIRDirty_1_N(
   6417                               val,
   6418                               0/*regparms*/,
   6419                               "ppcg_dirtyhelper_MFTB",
   6420                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   6421                               args );
   6422       /* execute the dirty call, dumping the result in val. */
   6423       stmt( IRStmt_Dirty(d) );
   6424 
   6425       switch (TBR) {
   6426       case 269:
   6427          DIP("mftbu r%u", rD_addr);
   6428          putIReg( rD_addr,
   6429                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   6430                                 /* Signed */False) );
   6431          break;
   6432       case 268:
   6433          DIP("mftb r%u", rD_addr);
   6434          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   6435                                       unop(Iop_64to32, mkexpr(val)) );
   6436          break;
   6437       default:
   6438          return False; /* illegal instruction */
   6439       }
   6440       break;
   6441    }
   6442 
   6443    case 0x090: {
   6444       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   6445       // b20==1: mtocrf (Move to One Cond Reg Field)
   6446       Int   cr;
   6447       UChar shft;
   6448       if (b11 != 0)
   6449          return False;
   6450       if (b20 == 1) {
   6451          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   6452             1 field is written.  It seems more robust to decline to
   6453             decode the insn if so. */
   6454          switch (CRM) {
   6455             case 0x01: case 0x02: case 0x04: case 0x08:
   6456             case 0x10: case 0x20: case 0x40: case 0x80:
   6457                break;
   6458             default:
   6459                return False;
   6460          }
   6461       }
   6462       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   6463                            CRM, rS_addr);
   6464       /* Write to each field specified by CRM */
   6465       for (cr = 0; cr < 8; cr++) {
   6466          if ((CRM & (1 << (7-cr))) == 0)
   6467             continue;
   6468          shft = 4*(7-cr);
   6469          putGST_field( PPC_GST_CR,
   6470                        binop(Iop_Shr32,
   6471                              mkNarrowTo32(ty, mkexpr(rS)),
   6472                              mkU8(shft)), cr );
   6473       }
   6474       break;
   6475    }
   6476 
   6477    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   6478 
   6479       switch (SPR) {  // Choose a register...
   6480       case 0x1:
   6481          DIP("mtxer r%u\n", rS_addr);
   6482          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   6483          break;
   6484       case 0x8:
   6485          DIP("mtlr r%u\n", rS_addr);
   6486          putGST( PPC_GST_LR, mkexpr(rS) );
   6487          break;
   6488       case 0x9:
   6489          DIP("mtctr r%u\n", rS_addr);
   6490          putGST( PPC_GST_CTR, mkexpr(rS) );
   6491          break;
   6492       case 0x100:
   6493          DIP("mtvrsave r%u\n", rS_addr);
   6494          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   6495          break;
   6496 
   6497       default:
   6498          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   6499          return False;
   6500       }
   6501       break;
   6502 
   6503    default:
   6504       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   6505       return False;
   6506    }
   6507    return True;
   6508 }
   6509 
   6510 
   6511 /*
   6512   Cache Management Instructions
   6513 */
   6514 static Bool dis_cache_manage ( UInt         theInstr,
   6515                                DisResult*   dres,
   6516                                VexArchInfo* guest_archinfo )
   6517 {
   6518    /* X-Form */
   6519    UChar opc1    = ifieldOPC(theInstr);
   6520    UChar b21to25 = ifieldRegDS(theInstr);
   6521    UChar rA_addr = ifieldRegA(theInstr);
   6522    UChar rB_addr = ifieldRegB(theInstr);
   6523    UInt  opc2    = ifieldOPClo10(theInstr);
   6524    UChar b0      = ifieldBIT0(theInstr);
   6525    UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
   6526    Bool  is_dcbzl = False;
   6527 
   6528    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6529 
   6530    /* For dcbt, the lowest two bits of b21to25 encode an
   6531       access-direction hint (TH field) which we ignore.  Well, that's
   6532       what the PowerPC documentation says.  In fact xlc -O4 on POWER5
   6533       seems to generate values of 8 and 10 for b21to25. */
   6534    if (opc1 == 0x1F && opc2 == 0x116) {
   6535      /* b21to25 &= ~3; */ /* if the docs were true */
   6536      b21to25 = 0; /* blunt instrument */
   6537    }
   6538    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   6539       if (b21to25 == 1) {
   6540          is_dcbzl = True;
   6541          b21to25 = 0;
   6542          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   6543             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   6544             return False;
   6545          }
   6546       }
   6547    }
   6548 
   6549    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
   6550       if (0) vex_printf("dis_cache_manage %d %d %d\n",
   6551                         (Int)opc1, (Int)b21to25, (Int)b0);
   6552       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
   6553       return False;
   6554    }
   6555 
   6556    /* stay sane .. */
   6557    vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
   6558 
   6559    switch (opc2) {
   6560 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   6561 //zz       vassert(0); /* AWAITING TEST CASE */
   6562 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   6563 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   6564 //zz       break;
   6565 
   6566    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   6567       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   6568       /* nop as far as vex is concerned */
   6569       break;
   6570 
   6571    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   6572       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   6573       /* nop as far as vex is concerned */
   6574       break;
   6575 
   6576    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   6577       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   6578       /* nop as far as vex is concerned */
   6579       break;
   6580 
   6581    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   6582       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   6583       /* nop as far as vex is concerned */
   6584       break;
   6585 
   6586    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   6587                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   6588       /* Clear all bytes in cache block at (rA|0) + rB. */
   6589       IRTemp  EA   = newTemp(ty);
   6590       IRTemp  addr = newTemp(ty);
   6591       IRExpr* irx_addr;
   6592       UInt    i;
   6593       UInt clearszB;
   6594       if (is_dcbzl) {
   6595           clearszB = guest_archinfo->ppc_dcbzl_szB;
   6596           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   6597       }
   6598       else {
   6599           clearszB = guest_archinfo->ppc_dcbz_szB;
   6600           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   6601       }
   6602 
   6603       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6604 
   6605       if (mode64) {
   6606          /* Round EA down to the start of the containing block. */
   6607          assign( addr, binop( Iop_And64,
   6608                               mkexpr(EA),
   6609                               mkU64( ~((ULong)clearszB-1) )) );
   6610 
   6611          for (i = 0; i < clearszB / 8; i++) {
   6612             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   6613             storeBE( irx_addr, mkU64(0) );
   6614          }
   6615       } else {
   6616          /* Round EA down to the start of the containing block. */
   6617          assign( addr, binop( Iop_And32,
   6618                               mkexpr(EA),
   6619                               mkU32( ~(clearszB-1) )) );
   6620 
   6621          for (i = 0; i < clearszB / 4; i++) {
   6622             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   6623             storeBE( irx_addr, mkU32(0) );
   6624          }
   6625       }
   6626       break;
   6627    }
   6628 
   6629    case 0x3D6: {
   6630       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   6631       /* Invalidate all translations containing code from the cache
   6632          block at (rA|0) + rB. */
   6633       IRTemp EA   = newTemp(ty);
   6634       IRTemp addr = newTemp(ty);
   6635       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   6636       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6637 
   6638       /* Round EA down to the start of the containing block. */
   6639       assign( addr, binop( mkSzOp(ty, Iop_And8),
   6640                            mkexpr(EA),
   6641                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   6642       putGST( PPC_GST_TISTART, mkexpr(addr) );
   6643       putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
   6644 
   6645       /* be paranoid ... */
   6646       stmt( IRStmt_MBE(Imbe_Fence) );
   6647 
   6648       irsb->jumpkind = Ijk_TInval;
   6649       irsb->next     = mkSzImm(ty, nextInsnAddr());
   6650       dres->whatNext = Dis_StopHere;
   6651       break;
   6652    }
   6653 
   6654    default:
   6655       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   6656       return False;
   6657    }
   6658    return True;
   6659 }
   6660 
   6661 
   6662 /*------------------------------------------------------------*/
   6663 /*--- Floating Point Helpers                               ---*/
   6664 /*------------------------------------------------------------*/
   6665 
   6666 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   6667 /* Produces a value in 0 .. 3, which is encoded as per the type
   6668    IRRoundingMode.  PPCRoundingMode encoding is different to
   6669    IRRoundingMode, so need to map it.
   6670 */
   6671 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   6672 {
   6673 /*
   6674    rounding mode | PPC | IR
   6675    ------------------------
   6676    to nearest    | 00  | 00
   6677    to zero       | 01  | 11
   6678    to +infinity  | 10  | 10
   6679    to -infinity  | 11  | 01
   6680 */
   6681    IRTemp rm_PPC32 = newTemp(Ity_I32);
   6682    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   6683 
   6684    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   6685    return binop( Iop_Xor32,
   6686                  mkexpr(rm_PPC32),
   6687                  binop( Iop_And32,
   6688                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   6689                         mkU32(2) ));
   6690 }
   6691 
   6692 
   6693 /*------------------------------------------------------------*/
   6694 /*--- Floating Point Instruction Translation               ---*/
   6695 /*------------------------------------------------------------*/
   6696 
   6697 /*
   6698   Floating Point Load Instructions
   6699 */
   6700 static Bool dis_fp_load ( UInt theInstr )
   6701 {
   6702    /* X-Form, D-Form */
   6703    UChar opc1      = ifieldOPC(theInstr);
   6704    UChar frD_addr  = ifieldRegDS(theInstr);
   6705    UChar rA_addr   = ifieldRegA(theInstr);
   6706    UChar rB_addr   = ifieldRegB(theInstr);
   6707    UInt  opc2      = ifieldOPClo10(theInstr);
   6708    UChar b0        = ifieldBIT0(theInstr);
   6709    UInt  uimm16    = ifieldUIMM16(theInstr);
   6710 
   6711    Int    simm16 = extend_s_16to32(uimm16);
   6712    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6713    IRTemp EA     = newTemp(ty);
   6714    IRTemp rA     = newTemp(ty);
   6715    IRTemp rB     = newTemp(ty);
   6716    IRTemp iHi    = newTemp(Ity_I32);
   6717    IRTemp iLo    = newTemp(Ity_I32);
   6718 
   6719    assign( rA, getIReg(rA_addr) );
   6720    assign( rB, getIReg(rB_addr) );
   6721 
   6722    /* These are completely straightforward from a rounding and status
   6723       bits perspective: no rounding involved and no funny status or CR
   6724       bits affected. */
   6725 
   6726    switch (opc1) {
   6727    case 0x30: // lfs (Load Float Single, PPC32 p441)
   6728       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6729       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6730       putFReg( frD_addr,
   6731                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6732       break;
   6733 
   6734    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   6735       if (rA_addr == 0)
   6736          return False;
   6737       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6738       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6739       putFReg( frD_addr,
   6740                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6741       putIReg( rA_addr, mkexpr(EA) );
   6742       break;
   6743 
   6744    case 0x32: // lfd (Load Float Double, PPC32 p437)
   6745       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6746       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6747       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6748       break;
   6749 
   6750    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   6751       if (rA_addr == 0)
   6752          return False;
   6753       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6754       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6755       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6756       putIReg( rA_addr, mkexpr(EA) );
   6757       break;
   6758 
   6759    case 0x1F:
   6760       if (b0 != 0) {
   6761          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   6762          return False;
   6763       }
   6764 
   6765       switch(opc2) {
   6766       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   6767          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6768          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6769          putFReg( frD_addr, unop( Iop_F32toF64,
   6770                                   loadBE(Ity_F32, mkexpr(EA))) );
   6771          break;
   6772 
   6773       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   6774          if (rA_addr == 0)
   6775             return False;
   6776          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6777          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6778          putFReg( frD_addr,
   6779                   unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6780          putIReg( rA_addr, mkexpr(EA) );
   6781          break;
   6782 
   6783       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   6784          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6785          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6786          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6787          break;
   6788 
   6789       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   6790          if (rA_addr == 0)
   6791             return False;
   6792          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6793          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6794          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6795          putIReg( rA_addr, mkexpr(EA) );
   6796          break;
   6797 
   6798       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   6799          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6800          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6801          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   6802          assign( iHi, binop(Iop_Sub32,
   6803                             mkU32(0),
   6804                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   6805          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   6806                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   6807          break;
   6808 
   6809       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
   6810       {
   6811          IRTemp dw = newTemp( Ity_I64 );
   6812          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6813          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6814          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   6815          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
   6816          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
   6817          break;
   6818       }
   6819 
   6820       default:
   6821          vex_printf("dis_fp_load(ppc)(opc2)\n");
   6822          return False;
   6823       }
   6824       break;
   6825 
   6826    default:
   6827       vex_printf("dis_fp_load(ppc)(opc1)\n");
   6828       return False;
   6829    }
   6830    return True;
   6831 }
   6832 
   6833 
   6834 
   6835 /*
   6836   Floating Point Store Instructions
   6837 */
   6838 static Bool dis_fp_store ( UInt theInstr )
   6839 {
   6840    /* X-Form, D-Form */
   6841    UChar opc1      = ifieldOPC(theInstr);
   6842    UChar frS_addr  = ifieldRegDS(theInstr);
   6843    UChar rA_addr   = ifieldRegA(theInstr);
   6844    UChar rB_addr   = ifieldRegB(theInstr);
   6845    UInt  opc2      = ifieldOPClo10(theInstr);
   6846    UChar b0        = ifieldBIT0(theInstr);
   6847    Int   uimm16    = ifieldUIMM16(theInstr);
   6848 
   6849    Int    simm16 = extend_s_16to32(uimm16);
   6850    IRTemp frS    = newTemp(Ity_F64);
   6851    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6852    IRTemp EA     = newTemp(ty);
   6853    IRTemp rA     = newTemp(ty);
   6854    IRTemp rB     = newTemp(ty);
   6855 
   6856    assign( frS, getFReg(frS_addr) );
   6857    assign( rA,  getIReg(rA_addr) );
   6858    assign( rB,  getIReg(rB_addr) );
   6859 
   6860    /* These are straightforward from a status bits perspective: no
   6861       funny status or CR bits affected.  For single precision stores,
   6862       the values are truncated and denormalised (not rounded) to turn
   6863       them into single precision values. */
   6864 
   6865    switch (opc1) {
   6866 
   6867    case 0x34: // stfs (Store Float Single, PPC32 p518)
   6868       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6869       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6870       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   6871          the value to be stored in the correct way, without any
   6872          rounding. */
   6873       storeBE( mkexpr(EA),
   6874                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6875       break;
   6876 
   6877    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   6878       if (rA_addr == 0)
   6879          return False;
   6880       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6881       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6882       /* See comment for stfs */
   6883       storeBE( mkexpr(EA),
   6884                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6885       putIReg( rA_addr, mkexpr(EA) );
   6886       break;
   6887 
   6888    case 0x36: // stfd (Store Float Double, PPC32 p513)
   6889       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6890       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6891       storeBE( mkexpr(EA), mkexpr(frS) );
   6892       break;
   6893 
   6894    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   6895       if (rA_addr == 0)
   6896          return False;
   6897       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6898       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6899       storeBE( mkexpr(EA), mkexpr(frS) );
   6900       putIReg( rA_addr, mkexpr(EA) );
   6901       break;
   6902 
   6903    case 0x1F:
   6904       if (b0 != 0) {
   6905          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   6906          return False;
   6907       }
   6908       switch(opc2) {
   6909       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   6910          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6911          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6912          /* See note for stfs */
   6913          storeBE( mkexpr(EA),
   6914                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6915          break;
   6916 
   6917       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   6918          if (rA_addr == 0)
   6919             return False;
   6920          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6921          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6922          /* See note for stfs */
   6923          storeBE( mkexpr(EA),
   6924                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6925          putIReg( rA_addr, mkexpr(EA) );
   6926          break;
   6927 
   6928       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   6929          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6930          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6931          storeBE( mkexpr(EA), mkexpr(frS) );
   6932          break;
   6933 
   6934       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   6935          if (rA_addr == 0)
   6936             return False;
   6937          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6938          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6939          storeBE( mkexpr(EA), mkexpr(frS) );
   6940          putIReg( rA_addr, mkexpr(EA) );
   6941          break;
   6942 
   6943       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   6944          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6945          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6946          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6947          storeBE( mkexpr(EA),
   6948                   unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   6949          break;
   6950 
   6951       default:
   6952          vex_printf("dis_fp_store(ppc)(opc2)\n");
   6953          return False;
   6954       }
   6955       break;
   6956 
   6957    default:
   6958       vex_printf("dis_fp_store(ppc)(opc1)\n");
   6959       return False;
   6960    }
   6961    return True;
   6962 }
   6963 
   6964 
   6965 
   6966 /*
   6967   Floating Point Arith Instructions
   6968 */
   6969 static Bool dis_fp_arith ( UInt theInstr )
   6970 {
   6971    /* A-Form */
   6972    UChar opc1     = ifieldOPC(theInstr);
   6973    UChar frD_addr = ifieldRegDS(theInstr);
   6974    UChar frA_addr = ifieldRegA(theInstr);
   6975    UChar frB_addr = ifieldRegB(theInstr);
   6976    UChar frC_addr = ifieldRegC(theInstr);
   6977    UChar opc2     = ifieldOPClo5(theInstr);
   6978    UChar flag_rC  = ifieldBIT0(theInstr);
   6979 
   6980    IRTemp  frD = newTemp(Ity_F64);
   6981    IRTemp  frA = newTemp(Ity_F64);
   6982    IRTemp  frB = newTemp(Ity_F64);
   6983    IRTemp  frC = newTemp(Ity_F64);
   6984    IRExpr* rm  = get_IR_roundingmode();
   6985 
   6986    /* By default, we will examine the results of the operation and set
   6987       fpscr[FPRF] accordingly. */
   6988    Bool set_FPRF = True;
   6989 
   6990    /* By default, if flag_RC is set, we will clear cr1 after the
   6991       operation.  In reality we should set cr1 to indicate the
   6992       exception status of the operation, but since we're not
   6993       simulating exceptions, the exception status will appear to be
   6994       zero.  Hence cr1 should be cleared if this is a . form insn. */
   6995    Bool clear_CR1 = True;
   6996 
   6997    assign( frA, getFReg(frA_addr));
   6998    assign( frB, getFReg(frB_addr));
   6999    assign( frC, getFReg(frC_addr));
   7000 
   7001    switch (opc1) {
   7002    case 0x3B:
   7003       switch (opc2) {
   7004       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   7005          if (frC_addr != 0)
   7006             return False;
   7007          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7008              frD_addr, frA_addr, frB_addr);
   7009          assign( frD, triop( Iop_DivF64r32,
   7010                              rm, mkexpr(frA), mkexpr(frB) ));
   7011          break;
   7012 
   7013       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   7014          if (frC_addr != 0)
   7015             return False;
   7016          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7017              frD_addr, frA_addr, frB_addr);
   7018          assign( frD, triop( Iop_SubF64r32,
   7019                              rm, mkexpr(frA), mkexpr(frB) ));
   7020          break;
   7021 
   7022       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   7023          if (frC_addr != 0)
   7024             return False;
   7025          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7026              frD_addr, frA_addr, frB_addr);
   7027          assign( frD, triop( Iop_AddF64r32,
   7028                              rm, mkexpr(frA), mkexpr(frB) ));
   7029          break;
   7030 
   7031       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   7032          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7033          if (frA_addr != 0 || frC_addr != 0)
   7034             return False;
   7035          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   7036              frD_addr, frB_addr);
   7037          // however illogically, on ppc970 this insn behaves identically
   7038          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   7039          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   7040          break;
   7041 
   7042       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   7043          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7044          if (frA_addr != 0 || frC_addr != 0)
   7045             return False;
   7046          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   7047              frD_addr, frB_addr);
   7048          { IRExpr* ieee_one
   7049               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7050            assign( frD, triop( Iop_DivF64r32,
   7051                                rm,
   7052                                ieee_one, mkexpr(frB) ));
   7053          }
   7054          break;
   7055 
   7056       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   7057          if (frB_addr != 0)
   7058             return False;
   7059          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7060              frD_addr, frA_addr, frC_addr);
   7061          assign( frD, triop( Iop_MulF64r32,
   7062                              rm, mkexpr(frA), mkexpr(frC) ));
   7063          break;
   7064 
   7065       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   7066          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7067          // Undocumented instruction?
   7068          if (frA_addr != 0 || frC_addr != 0)
   7069             return False;
   7070          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   7071              frD_addr, frB_addr);
   7072          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7073          break;
   7074 
   7075       default:
   7076          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   7077          return False;
   7078       }
   7079       break;
   7080 
   7081    case 0x3F:
   7082       switch (opc2) {
   7083       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   7084          if (frC_addr != 0)
   7085             return False;
   7086          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7087              frD_addr, frA_addr, frB_addr);
   7088          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   7089          break;
   7090 
   7091       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   7092          if (frC_addr != 0)
   7093             return False;
   7094          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7095              frD_addr, frA_addr, frB_addr);
   7096          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   7097          break;
   7098 
   7099       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   7100          if (frC_addr != 0)
   7101             return False;
   7102          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7103              frD_addr, frA_addr, frB_addr);
   7104          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   7105          break;
   7106 
   7107       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   7108          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   7109          if (frA_addr != 0 || frC_addr != 0)
   7110             return False;
   7111          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   7112              frD_addr, frB_addr);
   7113          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   7114          break;
   7115 
   7116       case 0x17: { // fsel (Floating Select, PPC32 p426)
   7117          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7118          IRTemp cc    = newTemp(Ity_I32);
   7119          IRTemp cc_b0 = newTemp(Ity_I32);
   7120 
   7121          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7122              frD_addr, frA_addr, frC_addr, frB_addr);
   7123 
   7124          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   7125          // => GT|EQ == (cc & 0x1 == 0)
   7126          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   7127                                        IRExpr_Const(IRConst_F64(0))) );
   7128          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   7129 
   7130          // frD = (frA >= 0.0) ? frC : frB
   7131          //     = (cc_b0 == 0) ? frC : frB
   7132          assign( frD,
   7133                  IRExpr_Mux0X(
   7134                     unop(Iop_1Uto8,
   7135                          binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
   7136                     mkexpr(frB),
   7137                     mkexpr(frC) ));
   7138 
   7139          /* One of the rare ones which don't mess with FPRF */
   7140          set_FPRF = False;
   7141          break;
   7142       }
   7143 
   7144       case 0x18: // fre (Floating Reciprocal Estimate)
   7145          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7146          // Note: unclear whether this insn really exists or not
   7147          // ppc970 doesn't have it, but POWER5 does
   7148          if (frA_addr != 0 || frC_addr != 0)
   7149             return False;
   7150          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   7151              frD_addr, frB_addr);
   7152          { IRExpr* ieee_one
   7153               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   7154            assign( frD, triop( Iop_DivF64,
   7155                                rm,
   7156                                ieee_one, mkexpr(frB) ));
   7157          }
   7158          break;
   7159 
   7160       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   7161          if (frB_addr != 0)
   7162             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   7163          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7164              frD_addr, frA_addr, frC_addr);
   7165          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   7166          break;
   7167 
   7168       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   7169          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   7170          if (frA_addr != 0 || frC_addr != 0)
   7171             return False;
   7172          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   7173              frD_addr, frB_addr);
   7174          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   7175          break;
   7176 
   7177       default:
   7178          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   7179          return False;
   7180       }
   7181       break;
   7182 
   7183    default:
   7184       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   7185       return False;
   7186    }
   7187 
   7188    putFReg( frD_addr, mkexpr(frD) );
   7189 
   7190    if (set_FPRF) {
   7191       // XXX XXX XXX FIXME
   7192       // set FPRF from frD
   7193    }
   7194 
   7195    if (flag_rC && clear_CR1) {
   7196       putCR321( 1, mkU8(0) );
   7197       putCR0( 1, mkU8(0) );
   7198    }
   7199 
   7200    return True;
   7201 }
   7202 
   7203 
   7204 
   7205 /*
   7206   Floating Point Mult-Add Instructions
   7207 */
   7208 static Bool dis_fp_multadd ( UInt theInstr )
   7209 {
   7210    /* A-Form */
   7211    UChar opc1     = ifieldOPC(theInstr);
   7212    UChar frD_addr = ifieldRegDS(theInstr);
   7213    UChar frA_addr = ifieldRegA(theInstr);
   7214    UChar frB_addr = ifieldRegB(theInstr);
   7215    UChar frC_addr = ifieldRegC(theInstr);
   7216    UChar opc2     = ifieldOPClo5(theInstr);
   7217    UChar flag_rC  = ifieldBIT0(theInstr);
   7218 
   7219    IRTemp  frD = newTemp(Ity_F64);
   7220    IRTemp  frA = newTemp(Ity_F64);
   7221    IRTemp  frB = newTemp(Ity_F64);
   7222    IRTemp  frC = newTemp(Ity_F64);
   7223    IRTemp  rmt = newTemp(Ity_I32);
   7224    IRExpr* rm;
   7225 
   7226    /* By default, we will examine the results of the operation and set
   7227       fpscr[FPRF] accordingly. */
   7228    Bool set_FPRF = True;
   7229 
   7230    /* By default, if flag_RC is set, we will clear cr1 after the
   7231       operation.  In reality we should set cr1 to indicate the
   7232       exception status of the operation, but since we're not
   7233       simulating exceptions, the exception status will appear to be
   7234       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7235    Bool clear_CR1 = True;
   7236 
   7237    /* Bind the rounding mode expression to a temp; there's no
   7238       point in creating gratuitous CSEs, as we know we'll need
   7239       to use it twice. */
   7240    assign( rmt, get_IR_roundingmode() );
   7241    rm = mkexpr(rmt);
   7242 
   7243    assign( frA, getFReg(frA_addr));
   7244    assign( frB, getFReg(frB_addr));
   7245    assign( frC, getFReg(frC_addr));
   7246 
   7247    /* The rounding in this is all a bit dodgy.  The idea is to only do
   7248       one rounding.  That clearly isn't achieveable without dedicated
   7249       four-input IR primops, although in the single precision case we
   7250       can sort-of simulate it by doing the inner multiply in double
   7251       precision.
   7252 
   7253       In the negated cases, the negation happens after rounding. */
   7254 
   7255    switch (opc1) {
   7256    case 0x3B:
   7257       switch (opc2) {
   7258       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   7259          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7260              frD_addr, frA_addr, frC_addr, frB_addr);
   7261          assign( frD, qop( Iop_MSubF64r32, rm,
   7262                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7263          break;
   7264 
   7265       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   7266          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7267              frD_addr, frA_addr, frC_addr, frB_addr);
   7268          assign( frD, qop( Iop_MAddF64r32, rm,
   7269                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7270          break;
   7271 
   7272       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   7273          DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7274              frD_addr, frA_addr, frC_addr, frB_addr);
   7275          assign( frD, unop( Iop_NegF64,
   7276                       qop( Iop_MSubF64r32, rm,
   7277                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   7278          break;
   7279 
   7280       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   7281          DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7282              frD_addr, frA_addr, frC_addr, frB_addr);
   7283          assign( frD, unop( Iop_NegF64,
   7284                       qop( Iop_MAddF64r32, rm,
   7285                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   7286          break;
   7287 
   7288       default:
   7289          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   7290          return False;
   7291       }
   7292       break;
   7293 
   7294    case 0x3F:
   7295       switch (opc2) {
   7296       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   7297          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7298              frD_addr, frA_addr, frC_addr, frB_addr);
   7299          assign( frD, qop( Iop_MSubF64, rm,
   7300                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7301          break;
   7302 
   7303       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   7304          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7305              frD_addr, frA_addr, frC_addr, frB_addr);
   7306          assign( frD, qop( Iop_MAddF64, rm,
   7307                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   7308          break;
   7309 
   7310       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   7311          DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7312              frD_addr, frA_addr, frC_addr, frB_addr);
   7313          assign( frD, unop( Iop_NegF64,
   7314                       qop( Iop_MSubF64, rm,
   7315                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   7316          break;
   7317 
   7318       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   7319          DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   7320              frD_addr, frA_addr, frC_addr, frB_addr);
   7321          assign( frD, unop( Iop_NegF64,
   7322                       qop( Iop_MAddF64, rm,
   7323                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   7324          break;
   7325 
   7326       default:
   7327          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   7328          return False;
   7329       }
   7330       break;
   7331 
   7332    default:
   7333       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   7334       return False;
   7335    }
   7336 
   7337    putFReg( frD_addr, mkexpr(frD) );
   7338 
   7339    if (set_FPRF) {
   7340       // XXX XXX XXX FIXME
   7341       // set FPRF from frD
   7342    }
   7343 
   7344    if (flag_rC && clear_CR1) {
   7345       putCR321( 1, mkU8(0) );
   7346       putCR0( 1, mkU8(0) );
   7347    }
   7348 
   7349    return True;
   7350 }
   7351 
   7352 /*
   7353  * fe_flag is set to 1 if any of the following conditions occurs:
   7354  *  - The floating-point operand in register FRB is a Zero, a
   7355  *    NaN, an Infinity, or a negative value.
   7356  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
   7357  *  Otherwise fe_flag is set to 0.
   7358  *
   7359  * fg_flag is set to 1 if either of the following conditions occurs.
   7360  *   - The floating-point operand in register FRB is a Zero, an
   7361  *     Infinity, or a denormalized value.
   7362  *  Otherwise fg_flag is set to 0.
   7363  *
   7364  */
   7365 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   7366 {
   7367    // The following temps are for holding intermediate results
   7368    IRTemp e_b = newTemp(Ity_I32);
   7369    IRExpr * fe_flag,  * fg_flag;
   7370    IRTemp frB_exp_shR = newTemp(Ity_I32);
   7371    UInt bias = sp? 127 : 1023;
   7372    IRExpr * frbNaN, * frbDenorm, * frBNeg;
   7373    IRExpr * eb_LTE;
   7374    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   7375    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   7376    *fe_flag_tmp = newTemp(Ity_I32);
   7377    *fg_flag_tmp = newTemp(Ity_I32);
   7378    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
   7379    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   7380 
   7381    //////////////////  fe_flag tests BEGIN //////////////////////
   7382    /* We first do all tests that may result in setting fe_flag to '1'.
   7383     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
   7384     * for details.)
   7385     */
   7386    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
   7387    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
   7388    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
   7389    {
   7390       // Test_value = -970 for double precision
   7391       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
   7392       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
   7393    }
   7394    frBNeg = binop( Iop_CmpEQ32,
   7395                    binop( Iop_Shr32,
   7396                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
   7397                           mkU8( 31 ) ),
   7398                    mkU32( 1 ) );
   7399    //////////////////  fe_flag tests END //////////////////////
   7400 
   7401    //////////////////  fg_flag tests BEGIN //////////////////////
   7402    /*
   7403     * The following tests were already performed above in the fe_flag
   7404     * tests.  So these conditions will result in both fe_ and fg_ flags
   7405     * being set.
   7406     *   - Test if FRB is Zero
   7407     *   - Test if FRB is an Infinity
   7408     */
   7409 
   7410    /*
   7411     * Test if FRB holds a denormalized value.  A denormalized value is one where
   7412     * the exp is 0 and the fraction is non-zero.
   7413     */
   7414    if (sp) {
   7415       IRTemp frac_part = newTemp(Ity_I32);
   7416       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
   7417       frbDenorm
   7418                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   7419                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
   7420    } else {
   7421       IRExpr * hi32, * low32, * fraction_is_nonzero;
   7422       IRTemp frac_part = newTemp(Ity_I64);
   7423 
   7424       assign( frac_part, FP_FRAC_PART(frB_Int) );
   7425       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   7426       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   7427       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   7428                                                 mkU32( 0 ) );
   7429       frbDenorm
   7430                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   7431                          fraction_is_nonzero );
   7432    }
   7433    //////////////////  fg_flag tests END //////////////////////
   7434 
   7435    /////////////////////////
   7436    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
   7437                     mkOR1( frbNaN,
   7438                            mkOR1( mkexpr( frbInf_tmp ),
   7439                                   mkOR1( frBNeg, eb_LTE ) ) ) );
   7440 
   7441    fe_flag = unop(Iop_1Uto32, fe_flag);
   7442 
   7443    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
   7444                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
   7445    fg_flag = unop(Iop_1Uto32, fg_flag);
   7446    assign (*fg_flag_tmp, fg_flag);
   7447    assign (*fe_flag_tmp, fe_flag);
   7448 }
   7449 /*
   7450  * fe_flag is set to 1 if any of the following conditions occurs:
   7451  *  - The double-precision floating-point operand in register FRA is a NaN or an
   7452  *    Infinity.
   7453  *  - The double-precision floating-point operand in register FRB is a Zero, a
   7454  *    NaN, or an Infinity.
   7455  *  - e_b is less than or equal to -1022.
   7456  *  - e_b is greater than or equal to 1021.
   7457  *  - The double-precision floating-point operand in register FRA is not a zero
   7458  *    and the difference, e_a - e_b, is greater than or equal to 1023.
   7459  *  - The double-precision floating-point operand in register FRA is not a zero
   7460  *    and the difference, e_a - e_b, is less than or equal to -1021.
   7461  *  - The double-precision floating-point operand in register FRA is not a zero
   7462  *    and e_a is less than or equal to -970
   7463  *  Otherwise fe_flag is set to 0.
   7464  *
   7465  * fg_flag is set to 1 if either of the following conditions occurs.
   7466  *   - The double-precision floating-point operand in register FRA is an Infinity.
   7467  *   - The double-precision floating-point operand in register FRB is a Zero, an
   7468  *     Infinity, or a denormalized value.
   7469  *  Otherwise fg_flag is set to 0.
   7470  *
   7471  */
   7472 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   7473 {
   7474    // The following temps are for holding intermediate results
   7475    IRTemp e_a = newTemp(Ity_I32);
   7476    IRTemp e_b = newTemp(Ity_I32);
   7477    IRTemp frA_exp_shR = newTemp(Ity_I32);
   7478    IRTemp frB_exp_shR = newTemp(Ity_I32);
   7479 
   7480    UInt bias = sp? 127 : 1023;
   7481    *fe_flag_tmp = newTemp(Ity_I32);
   7482    *fg_flag_tmp = newTemp(Ity_I32);
   7483 
   7484    /* The following variables hold boolean results from tests
   7485     * that are OR'ed together for setting the fe_ and fg_ flags.
   7486     * For some cases, the booleans are used more than once, so
   7487     * I make those IRTemp's instead of IRExpr's.
   7488     */
   7489    IRExpr * fraNaN, * frbNaN, * frbDenorm;
   7490    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
   7491    IRTemp  fraInf_tmp = newTemp(Ity_I1);
   7492    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   7493    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   7494    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
   7495 
   7496 /* The following are the flags that are set by OR'ing the results of
   7497  * all the tests done for tdiv.  These flags are the input to the specified CR.
   7498  */
   7499    IRExpr * fe_flag, * fg_flag;
   7500 
   7501    // Create temps that will be used throughout the following tests.
   7502    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
   7503    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
   7504    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
   7505    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
   7506    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   7507 
   7508 
   7509    //////////////////  fe_flag tests BEGIN //////////////////////
   7510    /* We first do all tests that may result in setting fe_flag to '1'. */
   7511 
   7512    /*
   7513     * Test if the double-precision floating-point operand in register FRA is
   7514     * a NaN:
   7515     */
   7516    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
   7517    /*
   7518     * Test if the double-precision floating-point operand in register FRA is
   7519     * an Infinity.
   7520     */
   7521    assign(fraInf_tmp, is_Inf(frA_int, sp));
   7522 
   7523    /*
   7524     * Test if the double-precision floating-point operand in register FRB is
   7525     * a NaN:
   7526     */
   7527    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
   7528    /*
   7529     * Test if the double-precision floating-point operand in register FRB is
   7530     * an Infinity.
   7531     */
   7532    assign( frbInf_tmp, is_Inf(frB_int, sp) );
   7533    /*
   7534     * Test if the double-precision floating-point operand in register FRB is
   7535     * a Zero.
   7536     */
   7537    assign( frbZero_tmp, is_Zero(frB_int, sp) );
   7538 
   7539    /*
   7540     * Test if e_b <= -1022 for double precision;
   7541     * or e_b <= -126 for single precision
   7542     */
   7543    {
   7544       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
   7545       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
   7546    }
   7547 
   7548    /*
   7549     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
   7550     * or e_b >= -125 (125 < e_b) for single precision
   7551     */
   7552    {
   7553       Int test_value = sp ? 125 : 1021;
   7554       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
   7555    }
   7556 
   7557    /*
   7558     * Test if FRA != Zero and (e_a - e_b) >= bias
   7559     */
   7560    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
   7561    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
   7562                        binop( Iop_CmpLT32S, mkU32( bias ),
   7563                               binop( Iop_Sub32, mkexpr( e_a ),
   7564                                      mkexpr( e_b ) ) ) );
   7565 
   7566    /*
   7567     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
   7568     */
   7569    {
   7570       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
   7571 
   7572       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
   7573                           binop( Iop_CmpLE32S,
   7574                                  binop( Iop_Sub32,
   7575                                         mkexpr( e_a ),
   7576                                         mkexpr( e_b ) ),
   7577                                         mkU32( test_value ) ) );
   7578    }
   7579 
   7580    /*
   7581     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
   7582     */
   7583    {
   7584       UInt test_value = 0xfffffc36;  //Int test_value = -970;
   7585 
   7586       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
   7587                                                         mkexpr( e_a ),
   7588                                                         mkU32( test_value ) ) );
   7589    }
   7590    //////////////////  fe_flag tests END //////////////////////
   7591 
   7592    //////////////////  fg_flag tests BEGIN //////////////////////
   7593    /*
   7594     * The following tests were already performed above in the fe_flag
   7595     * tests.  So these conditions will result in both fe_ and fg_ flags
   7596     * being set.
   7597     *   - Test if FRA is an Infinity
   7598     *   - Test if FRB ix Zero
   7599     *   - Test if FRB is an Infinity
   7600     */
   7601 
   7602    /*
   7603     * Test if FRB holds a denormalized value.  A denormalized value is one where
   7604     * the exp is 0 and the fraction is non-zero.
   7605     */
   7606    {
   7607       IRExpr * fraction_is_nonzero;
   7608 
   7609       if (sp) {
   7610          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
   7611                                       mkU32( 0 ) );
   7612       } else {
   7613          IRExpr * hi32, * low32;
   7614          IRTemp frac_part = newTemp(Ity_I64);
   7615          assign( frac_part, FP_FRAC_PART(frB_int) );
   7616 
   7617          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   7618          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   7619          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   7620                                       mkU32( 0 ) );
   7621       }
   7622       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
   7623                                  mkU32( 0x0 ) ), fraction_is_nonzero );
   7624 
   7625    }
   7626    //////////////////  fg_flag tests END //////////////////////
   7627 
   7628    fe_flag
   7629    = mkOR1(
   7630             fraNaN,
   7631             mkOR1(
   7632                    mkexpr( fraInf_tmp ),
   7633                    mkOR1(
   7634                           mkexpr( frbZero_tmp ),
   7635                           mkOR1(
   7636                                  frbNaN,
   7637                                  mkOR1(
   7638                                         mkexpr( frbInf_tmp ),
   7639                                         mkOR1( eb_LTE,
   7640                                                mkOR1( eb_GTE,
   7641                                                       mkOR1( ea_eb_GTE,
   7642                                                              mkOR1( ea_eb_LTE,
   7643                                                                     ea_LTE ) ) ) ) ) ) ) ) );
   7644 
   7645    fe_flag = unop(Iop_1Uto32, fe_flag);
   7646 
   7647    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
   7648                                                  mkOR1( mkexpr( frbInf_tmp ),
   7649                                                         frbDenorm ) ) );
   7650    fg_flag = unop(Iop_1Uto32, fg_flag);
   7651    assign(*fe_flag_tmp, fe_flag);
   7652    assign(*fg_flag_tmp, fg_flag);
   7653 }
   7654 
   7655 /* See description for _do_fp_tdiv() above. */
   7656 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
   7657 {
   7658    IRTemp  fe_flag, fg_flag;
   7659    /////////////////////////
   7660    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   7661     * where fl_flag == 1 on ppc64.
   7662     */
   7663    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
   7664    fe_flag = fg_flag = IRTemp_INVALID;
   7665    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
   7666    return binop( Iop_Or32,
   7667                  binop( Iop_Or32,
   7668                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
   7669                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   7670                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
   7671 }
   7672 
   7673 static Bool dis_fp_tests ( UInt theInstr )
   7674 {
   7675    UChar opc1     = ifieldOPC(theInstr);
   7676    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7677    UChar frB_addr = ifieldRegB(theInstr);
   7678    UChar b0       = ifieldBIT0(theInstr);
   7679    UInt  opc2     = ifieldOPClo10(theInstr);
   7680    IRTemp frB_I64     = newTemp(Ity_I64);
   7681 
   7682    if (opc1 != 0x3F || b0 != 0 ){
   7683       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   7684       return False;
   7685    }
   7686    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
   7687 
   7688    switch (opc2) {
   7689       case 0x080: // ftdiv
   7690       {
   7691          UChar frA_addr = ifieldRegA(theInstr);
   7692          IRTemp frA_I64     = newTemp(Ity_I64);
   7693          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7694          if (b21to22 != 0 ) {
   7695             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   7696             return False;
   7697          }
   7698 
   7699          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
   7700          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   7701 
   7702          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   7703          break;
   7704       }
   7705       case 0x0A0: // ftsqrt
   7706       {
   7707          IRTemp flags = newTemp(Ity_I32);
   7708          IRTemp  fe_flag, fg_flag;
   7709          fe_flag = fg_flag = IRTemp_INVALID;
   7710          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
   7711          if ( b18to22 != 0) {
   7712             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
   7713             return False;
   7714          }
   7715          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
   7716          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
   7717          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   7718           * where fl_flag == 1 on ppc64.
   7719           */
   7720          assign( flags,
   7721                  binop( Iop_Or32,
   7722                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   7723                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   7724                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   7725          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   7726          break;
   7727       }
   7728 
   7729       default:
   7730          vex_printf("dis_fp_tests(ppc)(opc2)\n");
   7731          return False;
   7732 
   7733    }
   7734    return True;
   7735 }
   7736 
   7737 /*
   7738   Floating Point Compare Instructions
   7739 */
   7740 static Bool dis_fp_cmp ( UInt theInstr )
   7741 {
   7742    /* X-Form */
   7743    UChar opc1     = ifieldOPC(theInstr);
   7744    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7745    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7746    UChar frA_addr = ifieldRegA(theInstr);
   7747    UChar frB_addr = ifieldRegB(theInstr);
   7748    UInt  opc2     = ifieldOPClo10(theInstr);
   7749    UChar b0       = ifieldBIT0(theInstr);
   7750 
   7751    IRTemp ccIR    = newTemp(Ity_I32);
   7752    IRTemp ccPPC32 = newTemp(Ity_I32);
   7753 
   7754    IRTemp frA     = newTemp(Ity_F64);
   7755    IRTemp frB     = newTemp(Ity_F64);
   7756 
   7757    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   7758       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   7759       return False;
   7760    }
   7761 
   7762    assign( frA, getFReg(frA_addr));
   7763    assign( frB, getFReg(frB_addr));
   7764 
   7765    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   7766 
   7767    /* Map compare result from IR to PPC32 */
   7768    /*
   7769      FP cmp result | PPC | IR
   7770      --------------------------
   7771      UN            | 0x1 | 0x45
   7772      EQ            | 0x2 | 0x40
   7773      GT            | 0x4 | 0x00
   7774      LT            | 0x8 | 0x01
   7775    */
   7776 
   7777    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   7778    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   7779    assign(
   7780       ccPPC32,
   7781       binop(
   7782          Iop_Shl32,
   7783          mkU32(1),
   7784          unop(
   7785             Iop_32to8,
   7786             binop(
   7787                Iop_Or32,
   7788                binop(
   7789                   Iop_And32,
   7790                   unop(
   7791                      Iop_Not32,
   7792                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   7793                   ),
   7794                   mkU32(2)
   7795                ),
   7796                binop(
   7797                   Iop_And32,
   7798                   binop(
   7799                      Iop_Xor32,
   7800                      mkexpr(ccIR),
   7801                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   7802                   ),
   7803                   mkU32(1)
   7804                )
   7805             )
   7806          )
   7807       )
   7808    );
   7809 
   7810    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   7811 
   7812    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   7813       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   7814    */
   7815    // XXX XXX XXX FIXME
   7816    // Also write the result into FPRF (it's not entirely clear how)
   7817 
   7818    /* Note: Differences between fcmpu and fcmpo are only in exception
   7819       flag settings, which aren't supported anyway. */
   7820    switch (opc2) {
   7821    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   7822       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   7823       break;
   7824    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   7825       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   7826       break;
   7827    default:
   7828       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   7829       return False;
   7830    }
   7831    return True;
   7832 }
   7833 
   7834 
   7835 
   7836 /*
   7837   Floating Point Rounding/Conversion Instructions
   7838 */
   7839 static Bool dis_fp_round ( UInt theInstr )
   7840 {
   7841    /* X-Form */
   7842    UChar opc1     = ifieldOPC(theInstr);
   7843    UChar b16to20  = ifieldRegA(theInstr);
   7844    UChar frD_addr = ifieldRegDS(theInstr);
   7845    UChar frB_addr = ifieldRegB(theInstr);
   7846    UInt  opc2     = ifieldOPClo10(theInstr);
   7847    UChar flag_rC  = ifieldBIT0(theInstr);
   7848 
   7849    IRTemp  frD     = newTemp(Ity_F64);
   7850    IRTemp  frB     = newTemp(Ity_F64);
   7851    IRTemp  r_tmp32 = newTemp(Ity_I32);
   7852    IRTemp  r_tmp64 = newTemp(Ity_I64);
   7853    IRExpr* rm      = get_IR_roundingmode();
   7854 
   7855    /* By default, we will examine the results of the operation and set
   7856       fpscr[FPRF] accordingly. */
   7857    Bool set_FPRF = True;
   7858 
   7859    /* By default, if flag_RC is set, we will clear cr1 after the
   7860       operation.  In reality we should set cr1 to indicate the
   7861       exception status of the operation, but since we're not
   7862       simulating exceptions, the exception status will appear to be
   7863       zero.  Hence cr1 should be cleared if this is a . form insn. */
   7864    Bool clear_CR1 = True;
   7865    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
   7866       vex_printf("dis_fp_round(ppc)(instr)\n");
   7867       return False;
   7868    }
   7869 
   7870    assign( frB, getFReg(frB_addr));
   7871    if (opc1 == 0x3B) {
   7872       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
   7873        * they're very similar to the other instructions handled here, but have
   7874        * a different primary opcode.
   7875        */
   7876       switch (opc2) {
   7877          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
   7878             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7879             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   7880             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
   7881                                                               mkexpr( r_tmp64 ) ) ) );
   7882             goto putFR;
   7883 
   7884          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
   7885             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7886             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   7887             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
   7888             goto putFR;
   7889       }
   7890    }
   7891 
   7892 
   7893    switch (opc2) {
   7894    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   7895       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7896       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   7897       break;
   7898 
   7899    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   7900       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7901       assign( r_tmp32,
   7902               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   7903       assign( frD, unop( Iop_ReinterpI64asF64,
   7904                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   7905       /* FPRF is undefined after fctiw.  Leave unchanged. */
   7906       set_FPRF = False;
   7907       break;
   7908 
   7909    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   7910       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7911       assign( r_tmp32,
   7912               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   7913       assign( frD, unop( Iop_ReinterpI64asF64,
   7914                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   7915       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   7916       set_FPRF = False;
   7917       break;
   7918 
   7919    case 0x08F: case 0x08E: // fctiwu[z]
   7920       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
   7921                flag_rC ? ".":"", frD_addr, frB_addr);
   7922       assign( r_tmp32,
   7923               binop( Iop_F64toI32U,
   7924                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
   7925                      mkexpr( frB ) ) );
   7926       assign( frD, unop( Iop_ReinterpI64asF64,
   7927                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   7928       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   7929       set_FPRF = False;
   7930       break;
   7931 
   7932 
   7933    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   7934       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7935       assign( r_tmp64,
   7936               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   7937       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   7938       /* FPRF is undefined after fctid.  Leave unchanged. */
   7939       set_FPRF = False;
   7940       break;
   7941 
   7942    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   7943       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7944       assign( r_tmp64,
   7945               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   7946       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   7947       /* FPRF is undefined after fctidz.  Leave unchanged. */
   7948       set_FPRF = False;
   7949       break;
   7950 
   7951    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
   7952    {
   7953       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
   7954                flag_rC ? ".":"", frD_addr, frB_addr);
   7955       assign( r_tmp64,
   7956               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
   7957       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   7958       /* FPRF is undefined after fctidz.  Leave unchanged. */
   7959       set_FPRF = False;
   7960       break;
   7961    }
   7962    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   7963       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7964       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   7965       assign( frD,
   7966               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   7967       break;
   7968 
   7969    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
   7970       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7971       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   7972       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
   7973       break;
   7974 
   7975    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   7976       switch(opc2) {
   7977       case 0x188: // frin (Floating Round to Integer Nearest)
   7978          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7979          assign( r_tmp64,
   7980                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   7981          break;
   7982       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   7983          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7984          assign( r_tmp64,
   7985                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   7986          break;
   7987       case 0x1C8: // frip (Floating Round to Integer Plus)
   7988          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7989          assign( r_tmp64,
   7990                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   7991          break;
   7992       case 0x1E8: // frim (Floating Round to Integer Minus)
   7993          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7994          assign( r_tmp64,
   7995                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   7996          break;
   7997       }
   7998 
   7999       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   8000       /* F64 has only log10(2**52) significant digits anyway */
   8001       /* need to preserve sign of zero */
   8002       /*   frD = (fabs(frB) > 9e18) ? frB :
   8003                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   8004       assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
   8005                                      binop(Iop_CmpF64,
   8006                                            IRExpr_Const(IRConst_F64(9e18)),
   8007                                            unop(Iop_AbsF64, mkexpr(frB)))),
   8008                                 IRExpr_Mux0X(unop(Iop_32to8,
   8009                                                   binop(Iop_Shr32,
   8010                                                         unop(Iop_64HIto32,
   8011                                                              unop(Iop_ReinterpF64asI64,
   8012                                                                   mkexpr(frB))), mkU8(31))),
   8013                                              binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
   8014                                              unop(Iop_NegF64,
   8015                                                   unop( Iop_AbsF64,
   8016                                                         binop(Iop_I64StoF64, mkU32(0),
   8017                                                               mkexpr(r_tmp64)) )) ),
   8018                                 mkexpr(frB)));
   8019       break;
   8020 
   8021    default:
   8022       vex_printf("dis_fp_round(ppc)(opc2)\n");
   8023       return False;
   8024    }
   8025 putFR:
   8026    putFReg( frD_addr, mkexpr(frD) );
   8027 
   8028    if (set_FPRF) {
   8029       // XXX XXX XXX FIXME
   8030       // set FPRF from frD
   8031    }
   8032 
   8033    if (flag_rC && clear_CR1) {
   8034       putCR321( 1, mkU8(0) );
   8035       putCR0( 1, mkU8(0) );
   8036    }
   8037 
   8038    return True;
   8039 }
   8040 
   8041 /*
   8042   Floating Point Pair Instructions
   8043 */
   8044 static Bool dis_fp_pair ( UInt theInstr )
   8045 {
   8046    /* X-Form/DS-Form */
   8047    UChar  opc1         = ifieldOPC(theInstr);
   8048    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   8049    UChar  frT_lo_addr  = frT_hi_addr + 1;
   8050    UChar  rA_addr      = ifieldRegA(theInstr);
   8051    UChar  rB_addr      = ifieldRegB(theInstr);
   8052    UInt  uimm16        = ifieldUIMM16(theInstr);
   8053    Int    simm16       = extend_s_16to32(uimm16);
   8054    UInt   opc2         = ifieldOPClo10(theInstr);
   8055    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   8056    IRTemp EA_hi        = newTemp(ty);
   8057    IRTemp EA_lo        = newTemp(ty);
   8058    IRTemp frT_hi       = newTemp(Ity_F64);
   8059    IRTemp frT_lo       = newTemp(Ity_F64);
   8060    UChar b0            = ifieldBIT0(theInstr);
   8061    Bool is_load        = 0;
   8062 
   8063    if ((frT_hi_addr %2) != 0) {
   8064       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   8065       return False;
   8066    }
   8067 
   8068    switch (opc1) {
   8069    case 0x1F: // register offset
   8070       switch(opc2) {
   8071       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   8072          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8073          is_load = 1;
   8074          break;
   8075       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   8076          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   8077          break;
   8078       default:
   8079          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   8080          return False;
   8081       }
   8082 
   8083       if (b0 != 0) {
   8084          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   8085          return False;
   8086       }
   8087       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   8088       break;
   8089    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   8090       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8091       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8092       is_load = 1;
   8093       break;
   8094    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   8095       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   8096       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   8097       break;
   8098    default:   // immediate offset
   8099       vex_printf("dis_fp_pair(ppc)(instr)\n");
   8100       return False;
   8101    }
   8102 
   8103    if (mode64)
   8104       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   8105    else
   8106       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   8107 
   8108    assign( frT_hi, getFReg(frT_hi_addr) );
   8109    assign( frT_lo, getFReg(frT_lo_addr) );
   8110 
   8111    if (is_load) {
   8112       putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
   8113       putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
   8114    } else {
   8115       storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
   8116       storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
   8117    }
   8118 
   8119    return True;
   8120 }
   8121 
   8122 
   8123 /*
   8124   Floating Point Move Instructions
   8125 */
   8126 static Bool dis_fp_move ( UInt theInstr )
   8127 {
   8128    /* X-Form */
   8129    UChar opc1     = ifieldOPC(theInstr);
   8130    UChar frD_addr = ifieldRegDS(theInstr);
   8131    UChar frA_addr = ifieldRegA(theInstr);
   8132    UChar frB_addr = ifieldRegB(theInstr);
   8133    UInt  opc2     = ifieldOPClo10(theInstr);
   8134    UChar flag_rC  = ifieldBIT0(theInstr);
   8135 
   8136    IRTemp frD = newTemp(Ity_F64);
   8137    IRTemp frB = newTemp(Ity_F64);
   8138    IRTemp itmpB = newTemp(Ity_F64);
   8139    IRTemp frA;
   8140    IRTemp signA;
   8141    IRTemp hiD;
   8142 
   8143    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   8144       vex_printf("dis_fp_move(ppc)(instr)\n");
   8145       return False;
   8146    }
   8147 
   8148    assign( frB, getFReg(frB_addr));
   8149 
   8150    switch (opc2) {
   8151    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   8152       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   8153           frB_addr);
   8154       signA = newTemp(Ity_I32);
   8155       hiD = newTemp(Ity_I32);
   8156       itmpB = newTemp(Ity_I64);
   8157       frA = newTemp(Ity_F64);
   8158       assign( frA, getFReg(frA_addr) );
   8159 
   8160       /* get A's sign bit */
   8161       assign(signA, binop(Iop_And32,
   8162                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   8163                                                   mkexpr(frA))),
   8164                           mkU32(0x80000000)) );
   8165 
   8166       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   8167 
   8168       /* mask off B's sign bit and or in A's sign bit */
   8169       assign(hiD, binop(Iop_Or32,
   8170                         binop(Iop_And32,
   8171                               unop(Iop_64HIto32,
   8172                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   8173                               mkU32(0x7fffffff)),
   8174                         mkexpr(signA)) );
   8175 
   8176       /* combine hiD/loB into frD */
   8177       assign( frD, unop(Iop_ReinterpI64asF64,
   8178                         binop(Iop_32HLto64,
   8179                               mkexpr(hiD),
   8180                               unop(Iop_64to32,
   8181                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   8182       break;
   8183 
   8184    case 0x028: // fneg (Floating Negate, PPC32 p416)
   8185       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8186       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   8187       break;
   8188 
   8189    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   8190       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8191       assign( frD, mkexpr(frB) );
   8192       break;
   8193 
   8194    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   8195       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8196       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   8197       break;
   8198 
   8199    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   8200       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   8201       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   8202       break;
   8203 
   8204    default:
   8205       vex_printf("dis_fp_move(ppc)(opc2)\n");
   8206       return False;
   8207    }
   8208 
   8209    putFReg( frD_addr, mkexpr(frD) );
   8210 
   8211    /* None of these change FPRF.  cr1 is set in the usual way though,
   8212       if flag_rC is set. */
   8213 
   8214    if (flag_rC) {
   8215       putCR321( 1, mkU8(0) );
   8216       putCR0( 1, mkU8(0) );
   8217    }
   8218 
   8219    return True;
   8220 }
   8221 
   8222 
   8223 
   8224 /*
   8225   Floating Point Status/Control Register Instructions
   8226 */
   8227 static Bool dis_fp_scr ( UInt theInstr )
   8228 {
   8229    /* Many forms - see each switch case */
   8230    UChar opc1    = ifieldOPC(theInstr);
   8231    UInt  opc2    = ifieldOPClo10(theInstr);
   8232    UChar flag_rC = ifieldBIT0(theInstr);
   8233 
   8234    if (opc1 != 0x3F) {
   8235       vex_printf("dis_fp_scr(ppc)(instr)\n");
   8236       return False;
   8237    }
   8238 
   8239    switch (opc2) {
   8240    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   8241       // Bit crbD of the FPSCR is set.
   8242       UChar crbD    = ifieldRegDS(theInstr);
   8243       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   8244 
   8245       if (b11to20 != 0) {
   8246          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   8247          return False;
   8248       }
   8249       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   8250       putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
   8251       break;
   8252    }
   8253 
   8254    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   8255       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   8256       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   8257       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   8258       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   8259       IRTemp  tmp     = newTemp(Ity_I32);
   8260       IRExpr* fpscr_all;
   8261       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   8262          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   8263          return False;
   8264       }
   8265       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   8266       vassert(crfD < 8);
   8267       vassert(crfS < 8);
   8268       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   8269       assign( tmp, binop(Iop_And32,
   8270                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   8271                         mkU32(0xF)) );
   8272       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   8273       break;
   8274    }
   8275 
   8276    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   8277       // Bit crbD of the FPSCR is cleared.
   8278       UChar crbD    = ifieldRegDS(theInstr);
   8279       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   8280 
   8281       if (b11to20 != 0) {
   8282          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   8283          return False;
   8284       }
   8285       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   8286       putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
   8287       break;
   8288    }
   8289 
   8290    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   8291       UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   8292       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   8293       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   8294       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   8295 
   8296       if (b16to22 != 0 || b11 != 0) {
   8297          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   8298          return False;
   8299       }
   8300       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
   8301       putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
   8302       break;
   8303    }
   8304 
   8305    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   8306       UChar   frD_addr  = ifieldRegDS(theInstr);
   8307       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   8308       IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   8309 
   8310       if (b11to20 != 0) {
   8311          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   8312          return False;
   8313       }
   8314       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   8315       putFReg( frD_addr,
   8316           unop( Iop_ReinterpI64asF64,
   8317                 unop( Iop_32Uto64, fpscr_all )));
   8318       break;
   8319    }
   8320 
   8321    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   8322       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   8323       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   8324       UChar frB_addr = ifieldRegB(theInstr);
   8325       IRTemp frB   = newTemp(Ity_F64);
   8326       IRTemp rB_32 = newTemp(Ity_I32);
   8327       Int i, mask;
   8328 
   8329       if (b25 == 1) {
   8330          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   8331           * a one do a full 64 bit move.  Note, the FPSCR is not really
   8332           * properly modeled.  This instruciton only changes the value of
   8333           * the rounding mode.  The HW exception bits do not get set in
   8334           * the simulator.  1/12/09
   8335           */
   8336          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   8337          mask = 0xFF;
   8338 
   8339       } else {
   8340          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   8341          // Build 32bit mask from FM:
   8342          mask = 0;
   8343          for (i=0; i<8; i++) {
   8344             if ((FM & (1<<(7-i))) == 1) {
   8345                mask |= 0xF << (7-i);
   8346             }
   8347          }
   8348       }
   8349       assign( frB, getFReg(frB_addr));
   8350       assign( rB_32, unop( Iop_64to32,
   8351                            unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
   8352       putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
   8353       break;
   8354    }
   8355 
   8356    default:
   8357       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   8358       return False;
   8359    }
   8360    return True;
   8361 }
   8362 
   8363 
   8364 
   8365 /*------------------------------------------------------------*/
   8366 /*--- AltiVec Instruction Translation                      ---*/
   8367 /*------------------------------------------------------------*/
   8368 
   8369 /*
   8370   Altivec Cache Control Instructions (Data Streams)
   8371 */
   8372 static Bool dis_av_datastream ( UInt theInstr )
   8373 {
   8374    /* X-Form */
   8375    UChar opc1     = ifieldOPC(theInstr);
   8376    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   8377    UChar flag_A   = flag_T;
   8378    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   8379    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   8380    UChar rA_addr  = ifieldRegA(theInstr);
   8381    UChar rB_addr  = ifieldRegB(theInstr);
   8382    UInt  opc2     = ifieldOPClo10(theInstr);
   8383    UChar b0       = ifieldBIT0(theInstr);
   8384 
   8385    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   8386       vex_printf("dis_av_datastream(ppc)(instr)\n");
   8387       return False;
   8388    }
   8389 
   8390    switch (opc2) {
   8391    case 0x156: // dst (Data Stream Touch, AV p115)
   8392       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   8393                                 rA_addr, rB_addr, STRM);
   8394       break;
   8395 
   8396    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   8397       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   8398                                   rA_addr, rB_addr, STRM);
   8399       break;
   8400 
   8401    case 0x336: // dss (Data Stream Stop, AV p114)
   8402       if (rA_addr != 0 || rB_addr != 0) {
   8403          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   8404          return False;
   8405       }
   8406       if (flag_A == 0) {
   8407          DIP("dss %d\n", STRM);
   8408       } else {
   8409          DIP("dssall\n");
   8410       }
   8411       break;
   8412 
   8413    default:
   8414       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   8415       return False;
   8416    }
   8417    return True;
   8418 }
   8419 
   8420 /*
   8421   AltiVec Processor Control Instructions
   8422 */
   8423 static Bool dis_av_procctl ( UInt theInstr )
   8424 {
   8425    /* VX-Form */
   8426    UChar opc1    = ifieldOPC(theInstr);
   8427    UChar vD_addr = ifieldRegDS(theInstr);
   8428    UChar vA_addr = ifieldRegA(theInstr);
   8429    UChar vB_addr = ifieldRegB(theInstr);
   8430    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   8431 
   8432    if (opc1 != 0x4) {
   8433       vex_printf("dis_av_procctl(ppc)(instr)\n");
   8434       return False;
   8435    }
   8436 
   8437    switch (opc2) {
   8438    case 0x604: // mfvscr (Move from VSCR, AV p129)
   8439       if (vA_addr != 0 || vB_addr != 0) {
   8440          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   8441          return False;
   8442       }
   8443       DIP("mfvscr v%d\n", vD_addr);
   8444       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   8445       break;
   8446 
   8447    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   8448       IRTemp vB = newTemp(Ity_V128);
   8449       if (vD_addr != 0 || vA_addr != 0) {
   8450          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   8451          return False;
   8452       }
   8453       DIP("mtvscr v%d\n", vB_addr);
   8454       assign( vB, getVReg(vB_addr));
   8455       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   8456       break;
   8457    }
   8458    default:
   8459       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   8460       return False;
   8461    }
   8462    return True;
   8463 }
   8464 
   8465 /*
   8466  * VSX scalar and vector convert instructions
   8467  */
   8468 static Bool
   8469 dis_vx_conv ( UInt theInstr, UInt opc2 )
   8470 {
   8471    /* XX2-Form */
   8472    UChar opc1 = ifieldOPC( theInstr );
   8473    UChar XT = ifieldRegXT( theInstr );
   8474    UChar XB = ifieldRegXB( theInstr );
   8475    IRTemp xB, xB2;
   8476    IRTemp b3, b2, b1, b0;
   8477    xB = xB2 = IRTemp_INVALID;
   8478 
   8479    if (opc1 != 0x3C) {
   8480       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   8481       return False;
   8482    }
   8483 
   8484    /* Create and assign temps only as needed for the given instruction. */
   8485    switch (opc2) {
   8486       // scalar double-precision floating point argument
   8487       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090:
   8488          xB = newTemp(Ity_F64);
   8489          assign( xB,
   8490                  unop( Iop_ReinterpI64asF64,
   8491                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   8492          break;
   8493       // vector double-precision floating point arguments
   8494       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   8495 
   8496          xB = newTemp(Ity_F64);
   8497          xB2 = newTemp(Ity_F64);
   8498          assign( xB,
   8499                  unop( Iop_ReinterpI64asF64,
   8500                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   8501          assign( xB2,
   8502                  unop( Iop_ReinterpI64asF64,
   8503                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   8504          break;
   8505       // vector single precision or [un]signed integer word arguments
   8506       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   8507       case 0x1f0: case 0x1d0:
   8508          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   8509          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   8510          break;
   8511          // vector [un]signed integer doubleword argument
   8512       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   8513          xB = newTemp(Ity_I64);
   8514          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   8515          xB2 = newTemp(Ity_I64);
   8516          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   8517          break;
   8518       // scalar [un]signed integer doubleword argument
   8519       case 0x2F0: case 0x2D0:
   8520          xB = newTemp(Ity_I64);
   8521          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   8522          break;
   8523       // scalar single precision argument
   8524       case 0x292: // xscvspdp
   8525          xB = newTemp(Ity_I32);
   8526          assign( xB,
   8527                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   8528          break;
   8529 
   8530       /* Certain instructions have their complete implementation in the main switch statement
   8531        * that follows this one; thus we have a "do nothing" case for those instructions here.
   8532        */
   8533       case 0x170: case 0x150:
   8534          break; // do nothing
   8535 
   8536       default:
   8537          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   8538          return False;
   8539    }
   8540 
   8541 
   8542    switch (opc2) {
   8543       case 0x2B0:
   8544          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   8545          //             to Signed Integer Doubleword format with Saturate)
   8546          DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8547          putVSReg( XT,
   8548                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   8549                                                  mkU32( Irrm_ZERO ),
   8550                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   8551          break;
   8552       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   8553                   //             Convert to Signed Integer Word format with Saturate)
   8554          DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8555          putVSReg( XT,
   8556                    binop( Iop_64HLtoV128,
   8557                           unop( Iop_32Sto64,
   8558                                 binop( Iop_F64toI32S,
   8559                                        mkU32( Irrm_ZERO ),
   8560                                        mkexpr( xB ) ) ),
   8561                                        mkU64( 0ULL ) ) );
   8562          break;
   8563       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   8564                   //             to Unsigned Integer Doubleword format with Saturate)
   8565          DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8566          putVSReg( XT,
   8567                    binop( Iop_64HLtoV128,
   8568                           binop( Iop_F64toI64U,
   8569                                  mkU32( Irrm_ZERO ),
   8570                                  mkexpr( xB ) ),
   8571                                  mkU64( 0ULL ) ) );
   8572          break;
   8573       case 0x2F0:
   8574          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   8575          //            Double-Precision format)
   8576          DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8577          putVSReg( XT,
   8578                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   8579                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   8580                                                        mkexpr( xB ) ) ),
   8581                                                        mkU64( 0 ) ) );
   8582          break;
   8583       case 0x2D0:
   8584          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   8585          //            Double-Precision format)
   8586          DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8587          putVSReg( XT,
   8588                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   8589                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   8590                                                        mkexpr( xB ) ) ),
   8591                                                        mkU64( 0 ) ) );
   8592          break;
   8593       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   8594                   //             to Signed Integer Word format with Saturate)
   8595       {
   8596          IRTemp hiResult_32 = newTemp(Ity_I32);
   8597          IRTemp loResult_32 = newTemp(Ity_I32);
   8598          IRExpr* rmZero = mkU32(Irrm_ZERO);
   8599 
   8600          DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8601          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   8602          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   8603          putVSReg( XT,
   8604                    binop( Iop_64HLtoV128,
   8605                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   8606                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   8607          break;
   8608       }
   8609       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   8610          //  (VSX Vector truncate Single-Precision to integer and
   8611          //   Convert to [Un]signed Integer Word format with Saturate)
   8612       {
   8613          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   8614          IRTemp tempResult = newTemp(Ity_V128);
   8615          IRTemp res0 = newTemp(Ity_I32);
   8616          IRTemp res1 = newTemp(Ity_I32);
   8617          IRTemp res2 = newTemp(Ity_I32);
   8618          IRTemp res3 = newTemp(Ity_I32);
   8619          IRTemp hi64 = newTemp(Ity_I64);
   8620          IRTemp lo64 = newTemp(Ity_I64);
   8621          Bool un_signed = (opc2 == 0x110);
   8622          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   8623 
   8624          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
   8625          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   8626           * then result is set to 0x80000000.  */
   8627          assign(tempResult, unop(op, getVSReg(XB)));
   8628          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   8629          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   8630          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   8631          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   8632          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   8633          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   8634 
   8635          b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)),
   8636                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   8637                                   mkexpr(res3),
   8638                                   // then: result is 0x{8|0}80000000
   8639                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   8640          b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)),
   8641                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   8642                                   mkexpr(res2),
   8643                                   // then: result is 0x{8|0}80000000
   8644                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   8645          b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)),
   8646                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   8647                                   mkexpr(res1),
   8648                                   // then: result is 0x{8|0}80000000
   8649                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   8650          b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)),
   8651                                   // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   8652                                   mkexpr(res0),
   8653                                   // then: result is 0x{8|0}80000000
   8654                                   mkU32(un_signed ? 0x00000000 : 0x80000000));
   8655 
   8656          putVSReg( XT,
   8657                    binop( Iop_64HLtoV128,
   8658                           binop( Iop_32HLto64, b3_result, b2_result ),
   8659                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   8660          break;
   8661       }
   8662       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   8663                   //           Convert to Single-Precision format
   8664          DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8665          putVSReg( XT,
   8666                    binop( Iop_64HLtoV128,
   8667                           binop( Iop_32HLto64,
   8668                                  unop( Iop_ReinterpF32asI32,
   8669                                        unop( Iop_TruncF64asF32,
   8670                                              binop( Iop_RoundF64toF32,
   8671                                                     get_IR_roundingmode(),
   8672                                                     mkexpr( xB ) ) ) ),
   8673                                  mkU32( 0 ) ),
   8674                           mkU64( 0ULL ) ) );
   8675          break;
   8676       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   8677                   //             and Convert to Unsigned Integer Word format with Saturate)
   8678          DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8679          putVSReg( XT,
   8680                    binop( Iop_64HLtoV128,
   8681                           binop( Iop_32HLto64,
   8682                                  mkU32( 0 ),
   8683                                  binop( Iop_F64toI32U,
   8684                                         mkU32( Irrm_ZERO ),
   8685                                         mkexpr( xB ) ) ),
   8686                           mkU64( 0ULL ) ) );
   8687          break;
   8688       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format)
   8689          DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8690          putVSReg( XT,
   8691                    binop( Iop_64HLtoV128,
   8692                           unop( Iop_ReinterpF64asI64,
   8693                                 unop( Iop_F32toF64,
   8694                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   8695                           mkU64( 0ULL ) ) );
   8696          break;
   8697       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   8698                   //           and Convert to Single-Precision format)
   8699          DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8700          putVSReg( XT,
   8701                    binop( Iop_64HLtoV128,
   8702                           binop( Iop_32HLto64,
   8703                                  unop( Iop_ReinterpF32asI32,
   8704                                        unop( Iop_TruncF64asF32,
   8705                                              binop( Iop_RoundF64toF32,
   8706                                                     get_IR_roundingmode(),
   8707                                                     mkexpr( xB ) ) ) ),
   8708                                  mkU32( 0 ) ),
   8709                           binop( Iop_32HLto64,
   8710                                  unop( Iop_ReinterpF32asI32,
   8711                                        unop( Iop_TruncF64asF32,
   8712                                              binop( Iop_RoundF64toF32,
   8713                                                     get_IR_roundingmode(),
   8714                                                     mkexpr( xB2 ) ) ) ),
   8715                                  mkU32( 0 ) ) ) );
   8716          break;
   8717       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   8718                   //             and Convert to Unsigned Integer Doubleword format
   8719                   //             with Saturate)
   8720          DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8721          putVSReg( XT,
   8722                    binop( Iop_64HLtoV128,
   8723                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   8724                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   8725          break;
   8726       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   8727                   //             Convert to Unsigned Integer Word format with Saturate)
   8728          DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8729          putVSReg( XT,
   8730                    binop( Iop_64HLtoV128,
   8731                           binop( Iop_32HLto64,
   8732                                  binop( Iop_F64toI32U,
   8733                                         mkU32( Irrm_ZERO ),
   8734                                         mkexpr( xB ) ),
   8735                                  mkU32( 0 ) ),
   8736                           binop( Iop_32HLto64,
   8737                                  binop( Iop_F64toI32U,
   8738                                         mkU32( Irrm_ZERO ),
   8739                                         mkexpr( xB2 ) ),
   8740                                  mkU32( 0 ) ) ) );
   8741          break;
   8742       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   8743          DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8744          putVSReg( XT,
   8745                    binop( Iop_64HLtoV128,
   8746                           unop( Iop_ReinterpF64asI64,
   8747                                 unop( Iop_F32toF64,
   8748                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   8749                           unop( Iop_ReinterpF64asI64,
   8750                                 unop( Iop_F32toF64,
   8751                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   8752          break;
   8753       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   8754                   //           Convert to Signed Integer Doubleword format with Saturate)
   8755          DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8756          putVSReg( XT,
   8757                    binop( Iop_64HLtoV128,
   8758                           binop( Iop_F64toI64S,
   8759                                  mkU32( Irrm_ZERO ),
   8760                                  unop( Iop_F32toF64,
   8761                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   8762                           binop( Iop_F64toI64S,
   8763                                  mkU32( Irrm_ZERO ),
   8764                                  unop( Iop_F32toF64,
   8765                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   8766          break;
   8767       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   8768                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   8769          DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8770          putVSReg( XT,
   8771                    binop( Iop_64HLtoV128,
   8772                           binop( Iop_F64toI64U,
   8773                                  mkU32( Irrm_ZERO ),
   8774                                  unop( Iop_F32toF64,
   8775                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   8776                           binop( Iop_F64toI64U,
   8777                                  mkU32( Irrm_ZERO ),
   8778                                  unop( Iop_F32toF64,
   8779                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   8780          break;
   8781       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   8782                   //             Convert to Signed Integer Doubleword format with Saturate)
   8783          DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8784          putVSReg( XT,
   8785                    binop( Iop_64HLtoV128,
   8786                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   8787                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   8788          break;
   8789       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   8790                   //            to Double-Precision format)
   8791          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8792          putVSReg( XT,
   8793                    binop( Iop_64HLtoV128,
   8794                           unop( Iop_ReinterpF64asI64,
   8795                                 binop( Iop_I64StoF64,
   8796                                        get_IR_roundingmode(),
   8797                                        mkexpr( xB ) ) ),
   8798                           unop( Iop_ReinterpF64asI64,
   8799                                 binop( Iop_I64StoF64,
   8800                                        get_IR_roundingmode(),
   8801                                        mkexpr( xB2 ) ) ) ) );
   8802          break;
   8803       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   8804                   //            to Double-Precision format)
   8805          DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8806          putVSReg( XT,
   8807                    binop( Iop_64HLtoV128,
   8808                           unop( Iop_ReinterpF64asI64,
   8809                                 binop( Iop_I64UtoF64,
   8810                                        get_IR_roundingmode(),
   8811                                        mkexpr( xB ) ) ),
   8812                           unop( Iop_ReinterpF64asI64,
   8813                                 binop( Iop_I64UtoF64,
   8814                                        get_IR_roundingmode(),
   8815                                        mkexpr( xB2 ) ) ) ) );
   8816 
   8817          break;
   8818       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   8819                   //            to Single-Precision format)
   8820          DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8821          putVSReg( XT,
   8822                    binop( Iop_64HLtoV128,
   8823                           binop( Iop_32HLto64,
   8824                                  unop( Iop_ReinterpF32asI32,
   8825                                        unop( Iop_TruncF64asF32,
   8826                                              binop( Iop_RoundF64toF32,
   8827                                                     get_IR_roundingmode(),
   8828                                                     binop( Iop_I64StoF64,
   8829                                                            get_IR_roundingmode(),
   8830                                                            mkexpr( xB ) ) ) ) ),
   8831                                  mkU32( 0 ) ),
   8832                           binop( Iop_32HLto64,
   8833                                  unop( Iop_ReinterpF32asI32,
   8834                                        unop( Iop_TruncF64asF32,
   8835                                              binop( Iop_RoundF64toF32,
   8836                                                     get_IR_roundingmode(),
   8837                                                     binop( Iop_I64StoF64,
   8838                                                            get_IR_roundingmode(),
   8839                                                            mkexpr( xB2 ) ) ) ) ),
   8840                                  mkU32( 0 ) ) ) );
   8841          break;
   8842       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   8843                   //            to Single-Precision format)
   8844          DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
   8845          putVSReg( XT,
   8846                    binop( Iop_64HLtoV128,
   8847                           binop( Iop_32HLto64,
   8848                                  unop( Iop_ReinterpF32asI32,
   8849                                        unop( Iop_TruncF64asF32,
   8850                                              binop( Iop_RoundF64toF32,
   8851                                                     get_IR_roundingmode(),
   8852                                                     binop( Iop_I64UtoF64,
   8853                                                            get_IR_roundingmode(),
   8854                                                            mkexpr( xB ) ) ) ) ),
   8855                                  mkU32( 0 ) ),
   8856                           binop( Iop_32HLto64,
   8857                                  unop( Iop_ReinterpF32asI32,
   8858                                        unop( Iop_TruncF64asF32,
   8859                                              binop( Iop_RoundF64toF32,
   8860                                                     get_IR_roundingmode(),
   8861                                                     binop( Iop_I64UtoF64,
   8862                                                            get_IR_roundingmode(),
   8863                                                            mkexpr( xB2 ) ) ) ) ),
   8864                                  mkU32( 0 ) ) ) );
   8865          break;
   8866 
   8867       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   8868          DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8869          putVSReg( XT,
   8870                    binop( Iop_64HLtoV128,
   8871                           unop( Iop_ReinterpF64asI64,
   8872                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   8873                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   8874                           unop( Iop_ReinterpF64asI64,
   8875                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   8876                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   8877          break;
   8878       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   8879          DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8880          putVSReg( XT,
   8881                    binop( Iop_64HLtoV128,
   8882                           unop( Iop_ReinterpF64asI64,
   8883                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   8884                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   8885                           unop( Iop_ReinterpF64asI64,
   8886                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   8887                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   8888          break;
   8889       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   8890          DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8891          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   8892          break;
   8893       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   8894          DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
   8895          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   8896          break;
   8897 
   8898       default:
   8899          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   8900          return False;
   8901    }
   8902    return True;
   8903 }
   8904 
   8905 /*
   8906  * VSX vector Double Precision Floating Point Arithmetic Instructions
   8907  */
   8908 static Bool
   8909 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   8910 {
   8911    /* XX3-Form */
   8912    UChar opc1 = ifieldOPC( theInstr );
   8913    UChar XT = ifieldRegXT( theInstr );
   8914    UChar XA = ifieldRegXA( theInstr );
   8915    UChar XB = ifieldRegXB( theInstr );
   8916    IRExpr* rm = get_IR_roundingmode();
   8917    IRTemp frA = newTemp(Ity_F64);
   8918    IRTemp frB = newTemp(Ity_F64);
   8919    IRTemp frA2 = newTemp(Ity_F64);
   8920    IRTemp frB2 = newTemp(Ity_F64);
   8921 
   8922    if (opc1 != 0x3C) {
   8923       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   8924       return False;
   8925    }
   8926 
   8927    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   8928    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   8929    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   8930    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   8931 
   8932    switch (opc2) {
   8933       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   8934       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   8935       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   8936       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   8937       {
   8938          IROp mOp;
   8939          Char * oper_name;
   8940          switch (opc2) {
   8941             case 0x1E0:
   8942                mOp = Iop_DivF64;
   8943                oper_name = "div";
   8944                break;
   8945             case 0x1C0:
   8946                mOp = Iop_MulF64;
   8947                oper_name = "mul";
   8948                break;
   8949             case 0x180:
   8950                mOp = Iop_AddF64;
   8951                oper_name = "add";
   8952                break;
   8953             case 0x1A0:
   8954                mOp = Iop_SubF64;
   8955                oper_name = "sub";
   8956                break;
   8957 
   8958             default:
   8959                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   8960          }
   8961          IRTemp hiResult = newTemp(Ity_I64);
   8962          IRTemp loResult = newTemp(Ity_I64);
   8963          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
   8964 
   8965          assign( hiResult,
   8966                  unop( Iop_ReinterpF64asI64,
   8967                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   8968          assign( loResult,
   8969                  unop( Iop_ReinterpF64asI64,
   8970                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   8971          putVSReg( XT,
   8972                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   8973          break;
   8974       }
   8975       case 0x196: // xvsqrtdp
   8976       {
   8977          IRTemp hiResult = newTemp(Ity_I64);
   8978          IRTemp loResult = newTemp(Ity_I64);
   8979          DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   8980 
   8981          assign( hiResult,
   8982                  unop( Iop_ReinterpF64asI64,
   8983                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   8984          assign( loResult,
   8985                  unop( Iop_ReinterpF64asI64,
   8986                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   8987          putVSReg( XT,
   8988                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   8989          break;
   8990       }
   8991       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   8992       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   8993       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   8994       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   8995       {
   8996          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   8997           *    XT == FRC
   8998           *    XA == FRA
   8999           *    XB == FRB
   9000           *
   9001           * and for xvm{add|sub}adp . . .
   9002           *    XT == FRB
   9003           *    XA == FRA
   9004           *    XB == FRC
   9005           */
   9006          Bool negate;
   9007          IROp mOp = Iop_INVALID;
   9008          Char * oper_name = NULL;
   9009          Bool mdp = False;
   9010 
   9011          switch (opc2) {
   9012             case 0x184: case 0x1A4:
   9013             case 0x384: case 0x3A4:
   9014                mOp = Iop_MAddF64;
   9015                oper_name = "add";
   9016                mdp = (opc2 & 0x0FF) == 0x0A4;
   9017                break;
   9018 
   9019             case 0x1C4: case 0x1E4:
   9020             case 0x3C4: case 0x3E4:
   9021                mOp = Iop_MSubF64;
   9022                oper_name = "sub";
   9023                mdp = (opc2 & 0x0FF) == 0x0E4;
   9024                break;
   9025 
   9026             default:
   9027                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   9028          }
   9029 
   9030          switch (opc2) {
   9031             case 0x384: case 0x3A4:
   9032             case 0x3C4: case 0x3E4:
   9033                negate = True;
   9034                break;
   9035             default:
   9036                negate = False;
   9037          }
   9038          IRTemp hiResult = newTemp(Ity_I64);
   9039          IRTemp loResult = newTemp(Ity_I64);
   9040          IRTemp frT = newTemp(Ity_F64);
   9041          IRTemp frT2 = newTemp(Ity_F64);
   9042          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   9043              (UInt)XT, (UInt)XA, (UInt)XB);
   9044          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   9045          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   9046 
   9047          assign( hiResult,
   9048                  unop( Iop_ReinterpF64asI64,
   9049                        qop( mOp,
   9050                             rm,
   9051                             mkexpr( frA ),
   9052                             mkexpr( mdp ? frT : frB ),
   9053                             mkexpr( mdp ? frB : frT ) ) ) );
   9054          assign( loResult,
   9055                  unop( Iop_ReinterpF64asI64,
   9056                        qop( mOp,
   9057                             rm,
   9058                             mkexpr( frA2 ),
   9059                             mkexpr( mdp ? frT2 : frB2 ),
   9060                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   9061          putVSReg( XT,
   9062                    binop( Iop_64HLtoV128,
   9063                           mkexpr( negate ? getNegatedResult( hiResult )
   9064                                          : hiResult ),
   9065                           mkexpr( negate ? getNegatedResult( loResult )
   9066                                          : loResult ) ) );
   9067          break;
   9068       }
   9069       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   9070       {
   9071          IRTemp frBHi_I64 = newTemp(Ity_I64);
   9072          IRTemp frBLo_I64 = newTemp(Ity_I64);
   9073          IRTemp flagsHi = newTemp(Ity_I32);
   9074          IRTemp flagsLo = newTemp(Ity_I32);
   9075          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   9076          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   9077          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   9078 
   9079          DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   9080          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   9081          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   9082          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   9083          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   9084          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   9085           * where fl_flag == 1 on ppc64.
   9086           */
   9087          assign( flagsHi,
   9088                  binop( Iop_Or32,
   9089                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9090                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   9091                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   9092          assign( flagsLo,
   9093                  binop( Iop_Or32,
   9094                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9095                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   9096                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   9097          putGST_field( PPC_GST_CR,
   9098                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   9099                        crfD );
   9100          break;
   9101       }
   9102       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   9103       {
   9104          IRTemp frBHi_I64 = newTemp(Ity_I64);
   9105          IRTemp frBLo_I64 = newTemp(Ity_I64);
   9106          IRTemp frAHi_I64 = newTemp(Ity_I64);
   9107          IRTemp frALo_I64 = newTemp(Ity_I64);
   9108          IRTemp flagsHi = newTemp(Ity_I32);
   9109          IRTemp flagsLo = newTemp(Ity_I32);
   9110          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   9111          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   9112          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   9113 
   9114          DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   9115          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   9116          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   9117          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   9118          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   9119 
   9120          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   9121          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   9122          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   9123           * where fl_flag == 1 on ppc64.
   9124           */
   9125          assign( flagsHi,
   9126                  binop( Iop_Or32,
   9127                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9128                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   9129                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   9130          assign( flagsLo,
   9131                  binop( Iop_Or32,
   9132                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9133                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   9134                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   9135          putGST_field( PPC_GST_CR,
   9136                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   9137                        crfD );
   9138          break;
   9139       }
   9140 
   9141       default:
   9142          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   9143          return False;
   9144    }
   9145    return True;
   9146 }
   9147 
   9148 /*
   9149  * VSX vector Single Precision Floating Point Arithmetic Instructions
   9150  */
   9151 static Bool
   9152 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   9153 {
   9154    /* XX3-Form */
   9155    UChar opc1 = ifieldOPC( theInstr );
   9156    UChar XT = ifieldRegXT( theInstr );
   9157    UChar XA = ifieldRegXA( theInstr );
   9158    UChar XB = ifieldRegXB( theInstr );
   9159    IRExpr* rm = get_IR_roundingmode();
   9160    IRTemp a3, a2, a1, a0;
   9161    IRTemp b3, b2, b1, b0;
   9162    IRTemp res0 = newTemp(Ity_I32);
   9163    IRTemp res1 = newTemp(Ity_I32);
   9164    IRTemp res2 = newTemp(Ity_I32);
   9165    IRTemp res3 = newTemp(Ity_I32);
   9166 
   9167    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   9168    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   9169 
   9170    if (opc1 != 0x3C) {
   9171       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   9172       return False;
   9173    }
   9174 
   9175    switch (opc2) {
   9176       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   9177          DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   9178          putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) );
   9179          break;
   9180 
   9181       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   9182          DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   9183          putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) );
   9184          break;
   9185 
   9186       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   9187          DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   9188          putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) );
   9189          break;
   9190 
   9191       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   9192       {
   9193          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   9194           * So there are two choices:
   9195           *   1. Implement the xvdivsp with a native insn; or
   9196           *   2. Extract the 4 single precision floats from each vector
   9197           *      register inputs and perform fdivs on each pair
   9198           * I will do the latter, due to the general philosophy of
   9199           * reusing existing implementations when practical.
   9200           */
   9201          DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   9202          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   9203          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9204 
   9205          assign( res0,
   9206               unop( Iop_ReinterpF32asI32,
   9207                     unop( Iop_TruncF64asF32,
   9208                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   9209          assign( res1,
   9210                  unop( Iop_ReinterpF32asI32,
   9211                        unop( Iop_TruncF64asF32,
   9212                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   9213          assign( res2,
   9214                  unop( Iop_ReinterpF32asI32,
   9215                        unop( Iop_TruncF64asF32,
   9216                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   9217          assign( res3,
   9218                  unop( Iop_ReinterpF32asI32,
   9219                        unop( Iop_TruncF64asF32,
   9220                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   9221 
   9222          putVSReg( XT,
   9223                    binop( Iop_64HLtoV128,
   9224                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   9225                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   9226          break;
   9227       }
   9228       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   9229       {
   9230          DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
   9231          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9232          /* Note: The native xvsqrtsp insruction does not always give the same precision
   9233           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   9234           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   9235           * to the actual instruction.
   9236           */
   9237 
   9238          assign( res0,
   9239                  unop( Iop_ReinterpF32asI32,
   9240                        unop( Iop_TruncF64asF32,
   9241                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   9242          assign( res1,
   9243                  unop( Iop_ReinterpF32asI32,
   9244                        unop( Iop_TruncF64asF32,
   9245                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   9246          assign( res2,
   9247                  unop( Iop_ReinterpF32asI32,
   9248                        unop( Iop_TruncF64asF32,
   9249                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   9250          assign( res3,
   9251                  unop( Iop_ReinterpF32asI32,
   9252                        unop( Iop_TruncF64asF32,
   9253                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   9254 
   9255          putVSReg( XT,
   9256                    binop( Iop_64HLtoV128,
   9257                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   9258                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   9259          break;
   9260       }
   9261 
   9262       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   9263       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   9264       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   9265       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   9266       {
   9267          IRTemp t3, t2, t1, t0;
   9268          Bool msp = False;
   9269          Bool negate;
   9270          Char * oper_name = NULL;
   9271          IROp mOp = Iop_INVALID;
   9272          switch (opc2) {
   9273             case 0x104: case 0x124:
   9274             case 0x304: case 0x324:
   9275                msp = (opc2 & 0x0FF) == 0x024;
   9276                mOp = Iop_MAddF64r32;
   9277                oper_name = "madd";
   9278                break;
   9279 
   9280             case 0x144: case 0x164:
   9281             case 0x344: case 0x364:
   9282                msp = (opc2 & 0x0FF) == 0x064;
   9283                mOp = Iop_MSubF64r32;
   9284                oper_name = "sub";
   9285                break;
   9286 
   9287             default:
   9288                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   9289          }
   9290 
   9291          switch (opc2) {
   9292             case 0x304: case 0x324:
   9293             case 0x344: case 0x364:
   9294                negate = True;
   9295                break;
   9296 
   9297             default:
   9298                negate = False;
   9299          }
   9300 
   9301          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
   9302              (UInt)XT, (UInt)XA, (UInt)XB);
   9303 
   9304          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   9305          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   9306          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9307          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   9308 
   9309          assign( res0,
   9310                  unop( Iop_ReinterpF32asI32,
   9311                        unop( Iop_TruncF64asF32,
   9312                              qop( mOp,
   9313                                   rm,
   9314                                   mkexpr( a0 ),
   9315                                   mkexpr( msp ? t0 : b0 ),
   9316                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   9317          assign( res1,
   9318                  unop( Iop_ReinterpF32asI32,
   9319                        unop( Iop_TruncF64asF32,
   9320                              qop( mOp,
   9321                                   rm,
   9322                                   mkexpr( a1 ),
   9323                                   mkexpr( msp ? t1 : b1 ),
   9324                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   9325          assign( res2,
   9326                  unop( Iop_ReinterpF32asI32,
   9327                        unop( Iop_TruncF64asF32,
   9328                              qop( mOp,
   9329                                   rm,
   9330                                   mkexpr( a2 ),
   9331                                   mkexpr( msp ? t2 : b2 ),
   9332                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   9333          assign( res3,
   9334                  unop( Iop_ReinterpF32asI32,
   9335                        unop( Iop_TruncF64asF32,
   9336                              qop( mOp,
   9337                                   rm,
   9338                                   mkexpr( a3 ),
   9339                                   mkexpr( msp ? t3 : b3 ),
   9340                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   9341 
   9342          putVSReg( XT,
   9343                    binop( Iop_64HLtoV128,
   9344                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   9345                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   9346                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   9347                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   9348 
   9349          break;
   9350       }
   9351       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   9352       {
   9353          IRTemp flags0 = newTemp(Ity_I32);
   9354          IRTemp flags1 = newTemp(Ity_I32);
   9355          IRTemp flags2 = newTemp(Ity_I32);
   9356          IRTemp flags3 = newTemp(Ity_I32);
   9357          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   9358          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   9359          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   9360          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   9361          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   9362          DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
   9363 
   9364          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9365          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   9366          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   9367          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   9368          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   9369 
   9370          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   9371           * where fl_flag == 1 on ppc64.
   9372           */
   9373          assign( flags0,
   9374                  binop( Iop_Or32,
   9375                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9376                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   9377                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   9378          assign( flags1,
   9379                  binop( Iop_Or32,
   9380                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9381                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   9382                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   9383          assign( flags2,
   9384                  binop( Iop_Or32,
   9385                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9386                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   9387                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   9388          assign( flags3,
   9389                  binop( Iop_Or32,
   9390                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9391                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   9392                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   9393          putGST_field( PPC_GST_CR,
   9394                        binop( Iop_Or32,
   9395                               mkexpr( flags0 ),
   9396                               binop( Iop_Or32,
   9397                                      mkexpr( flags1 ),
   9398                                      binop( Iop_Or32,
   9399                                             mkexpr( flags2 ),
   9400                                             mkexpr( flags3 ) ) ) ),
   9401                        crfD );
   9402 
   9403          break;
   9404       }
   9405       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   9406       {
   9407          IRTemp flags0 = newTemp(Ity_I32);
   9408          IRTemp flags1 = newTemp(Ity_I32);
   9409          IRTemp flags2 = newTemp(Ity_I32);
   9410          IRTemp flags3 = newTemp(Ity_I32);
   9411          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   9412          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   9413          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   9414          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   9415          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   9416          DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
   9417 
   9418          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   9419          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9420          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   9421          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   9422          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   9423          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   9424 
   9425          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   9426           * where fl_flag == 1 on ppc64.
   9427           */
   9428          assign( flags0,
   9429                  binop( Iop_Or32,
   9430                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9431                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   9432                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   9433          assign( flags1,
   9434                  binop( Iop_Or32,
   9435                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9436                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   9437                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   9438          assign( flags2,
   9439                  binop( Iop_Or32,
   9440                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9441                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   9442                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   9443          assign( flags3,
   9444                  binop( Iop_Or32,
   9445                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   9446                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   9447                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   9448          putGST_field( PPC_GST_CR,
   9449                        binop( Iop_Or32,
   9450                               mkexpr( flags0 ),
   9451                               binop( Iop_Or32,
   9452                                      mkexpr( flags1 ),
   9453                                      binop( Iop_Or32,
   9454                                             mkexpr( flags2 ),
   9455                                             mkexpr( flags3 ) ) ) ),
   9456                        crfD );
   9457 
   9458          break;
   9459       }
   9460 
   9461       default:
   9462          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   9463          return False;
   9464    }
   9465    return True;
   9466 }
   9467 
   9468 typedef enum {
   9469    PPC_CMP_EQ = 2,
   9470    PPC_CMP_GT = 4,
   9471    PPC_CMP_GE = 6,
   9472    PPC_CMP_LT = 8
   9473 } ppc_cmp_t;
   9474 
   9475 
   9476 /*
   9477   This helper function takes as input the IRExpr returned
   9478   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   9479   in IR form.  This helper function converts it to PPC form.
   9480 
   9481   Map compare result from IR to PPC
   9482 
   9483   FP cmp result | PPC | IR
   9484   --------------------------
   9485   UN            | 0x1 | 0x45
   9486   EQ            | 0x2 | 0x40
   9487   GT            | 0x4 | 0x00
   9488   LT            | 0x8 | 0x01
   9489 
   9490  condcode = Shl(1, (~(ccIR>>5) & 2)
   9491                     | ((ccIR ^ (ccIR>>6)) & 1)
   9492 */
   9493 static IRTemp
   9494 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   9495 {
   9496    IRTemp condcode = newTemp( Ity_I32 );
   9497    IRTemp ccIR = newTemp( Ity_I32 );
   9498 
   9499    assign(ccIR, ccIR_expr);
   9500    assign( condcode,
   9501            binop( Iop_Shl32,
   9502                   mkU32( 1 ),
   9503                   unop( Iop_32to8,
   9504                         binop( Iop_Or32,
   9505                                binop( Iop_And32,
   9506                                       unop( Iop_Not32,
   9507                                             binop( Iop_Shr32,
   9508                                                    mkexpr( ccIR ),
   9509                                                    mkU8( 5 ) ) ),
   9510                                       mkU32( 2 ) ),
   9511                                binop( Iop_And32,
   9512                                       binop( Iop_Xor32,
   9513                                              mkexpr( ccIR ),
   9514                                              binop( Iop_Shr32,
   9515                                                     mkexpr( ccIR ),
   9516                                                     mkU8( 6 ) ) ),
   9517                                       mkU32( 1 ) ) ) ) ) );
   9518    return condcode;
   9519 }
   9520 
   9521 /*
   9522  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   9523  * following these special rules:
   9524  *   - The max/min of a QNaN and any value is that value
   9525  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   9526  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   9527  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   9528  */
   9529 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   9530 {
   9531    IRTemp frA_isNaN = newTemp(Ity_I1);
   9532    IRTemp frB_isNaN = newTemp(Ity_I1);
   9533    IRTemp frA_isSNaN = newTemp(Ity_I1);
   9534    IRTemp frB_isSNaN = newTemp(Ity_I1);
   9535    IRTemp frA_isQNaN = newTemp(Ity_I1);
   9536    IRTemp frB_isQNaN = newTemp(Ity_I1);
   9537 
   9538    assign( frA_isNaN, is_NaN( frA_I64 ) );
   9539    assign( frB_isNaN, is_NaN( frB_I64 ) );
   9540    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   9541    assign( frA_isSNaN,
   9542            mkAND1( mkexpr(frA_isNaN),
   9543                    binop( Iop_CmpEQ32,
   9544                           binop( Iop_And32,
   9545                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   9546                                  mkU32( 0x00080000 ) ),
   9547                           mkU32( 0 ) ) ) );
   9548    assign( frB_isSNaN,
   9549            mkAND1( mkexpr(frB_isNaN),
   9550                    binop( Iop_CmpEQ32,
   9551                           binop( Iop_And32,
   9552                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   9553                                  mkU32( 0x00080000 ) ),
   9554                           mkU32( 0 ) ) ) );
   9555    assign( frA_isQNaN,
   9556            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   9557    assign( frB_isQNaN,
   9558            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   9559 
   9560    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   9561     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   9562     *   if frA is a SNaN
   9563     *     result = frA converted to QNaN
   9564     *   else if frB is a SNaN
   9565     *     result = frB converted to QNaN
   9566     *   else if frB is a QNaN
   9567     *     result = frA
   9568     *   // One of frA or frB was a NaN in order for this function to be called, so
   9569     *   // if we get to this point, we KNOW that frA must be a QNaN.
   9570     *   else // frA is a QNaN
   9571     *     result = frB
   9572     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   9573     */
   9574 
   9575 #define SNAN_MASK 0x0008000000000000ULL
   9576    return
   9577    IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)),
   9578                 /* else:  if frB is a SNaN */
   9579                 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)),
   9580                              /* else:  if frB is a QNaN */
   9581                              IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)),
   9582                                           /* else:  frA is a QNaN, so result = frB */
   9583                                           mkexpr(frB_I64),
   9584                                           /* then: result = frA */
   9585                                           mkexpr(frA_I64)),
   9586                              /* then: result = frB converted to QNaN */
   9587                              binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))),
   9588                 /* then: result = frA converted to QNaN */
   9589                 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)));
   9590 }
   9591 
   9592 /*
   9593  * Helper function for get_max_min_fp.
   9594  */
   9595 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   9596 {
   9597    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   9598                                                   unop( Iop_ReinterpI64asF64,
   9599                                                         mkexpr( src1 ) ),
   9600                                                   unop( Iop_ReinterpI64asF64,
   9601                                                         mkexpr( src2 ) ) ) );
   9602 
   9603    return IRExpr_Mux0X( unop( Iop_1Uto8,
   9604                               binop( Iop_CmpEQ32,
   9605                                      mkexpr( src1cmpsrc2 ),
   9606                                      mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ),
   9607                         /* else: use src2 */
   9608                         mkexpr( src2 ),
   9609                         /* then: use src1 */
   9610                         mkexpr( src1 ) );
   9611 }
   9612 
   9613 /*
   9614  * Helper function for "Maximum/Minimum Double Precision" operations.
   9615  * Arguments: frA and frb are Ity_I64
   9616  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   9617  */
   9618 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   9619 {
   9620    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   9621     * for ascertaining the maximum between two doubles:
   9622     *   1. The max/min of +0 and -0 is +0.
   9623     *   2. The max/min of a QNaN and any value is that value.
   9624     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   9625     * We perform the check for [+/-]0 here in this function and use the
   9626     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   9627     * to do the standard comparison function.
   9628     */
   9629    IRTemp anyNaN = newTemp(Ity_I1);
   9630    IRTemp frA_isZero = newTemp(Ity_I1);
   9631    IRTemp frB_isZero = newTemp(Ity_I1);
   9632    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
   9633    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
   9634    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
   9635 #define MINUS_ZERO 0x8000000000000000ULL
   9636 
   9637    return IRExpr_Mux0X( unop( Iop_1Uto8,
   9638                               /* If both arguments are zero . . . */
   9639                               mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ),
   9640                         /* else: check if either input is a NaN*/
   9641                         IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ),
   9642                                       /* else: use "comparison helper" */
   9643                                       _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ),
   9644                                       /* then: use "NaN helper" */
   9645                                       _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ),
   9646                         /* then: if frA is -0 and isMin==True, return -0;
   9647                          *     else if frA is +0 and isMin==False; return +0;
   9648                          *     otherwise, simply return frB. */
   9649                         IRExpr_Mux0X( unop( Iop_1Uto8,
   9650                                             binop( Iop_CmpEQ32,
   9651                                                    unop( Iop_64HIto32,
   9652                                                          mkexpr( frA_I64 ) ),
   9653                                                    mkU32( isMin ? 0x80000000 : 0 ) ) ),
   9654                                       mkexpr( frB_I64 ),
   9655                                       mkU64( isMin ? MINUS_ZERO : 0ULL ) ) );
   9656 }
   9657 
   9658 /*
   9659  * Helper function for vector/scalar double precision fp round to integer instructions.
   9660  */
   9661 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix)
   9662 {
   9663 
   9664    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   9665    IRTemp frB = newTemp(Ity_F64);
   9666    IRTemp frD = newTemp(Ity_F64);
   9667    IRTemp intermediateResult = newTemp(Ity_I64);
   9668    IRTemp is_SNAN = newTemp(Ity_I1);
   9669    IRExpr * hi32;
   9670    IRExpr * rxpi_rm;
   9671    switch (opc2 & 0x7F) {
   9672       case 0x72:
   9673          insn_suffix = "m";
   9674          rxpi_rm = mkU32(Irrm_NegINF);
   9675          break;
   9676       case 0x52:
   9677          insn_suffix = "p";
   9678          rxpi_rm = mkU32(Irrm_PosINF);
   9679          break;
   9680       case 0x56:
   9681          insn_suffix = "c";
   9682          rxpi_rm = get_IR_roundingmode();
   9683          break;
   9684       case 0x32:
   9685          insn_suffix = "z";
   9686          rxpi_rm = mkU32(Irrm_ZERO);
   9687          break;
   9688       case 0x12:
   9689          insn_suffix = "";
   9690          rxpi_rm = mkU32(Irrm_NEAREST);
   9691          break;
   9692 
   9693       default: // Impossible to get here
   9694          vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" );
   9695          return NULL;
   9696    }
   9697    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   9698    assign( intermediateResult,
   9699            binop( Iop_F64toI64S, rxpi_rm,
   9700                   mkexpr( frB ) ) );
   9701 
   9702    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   9703    /* F64 has only log10(2**52) significant digits anyway */
   9704    /* need to preserve sign of zero */
   9705    /*   frD = (fabs(frB) > 9e18) ? frB :
   9706             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   9707    assign( frD,
   9708            IRExpr_Mux0X( unop( Iop_32to8,
   9709                                binop( Iop_CmpF64,
   9710                                       IRExpr_Const( IRConst_F64( 9e18 ) ),
   9711                                       unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   9712                          IRExpr_Mux0X( unop( Iop_32to8,
   9713                                              binop( Iop_Shr32,
   9714                                                     unop( Iop_64HIto32,
   9715                                                           mkexpr( frB_I64 ) ),
   9716                                                     mkU8( 31 ) ) ),
   9717                                        binop( Iop_I64StoF64,
   9718                                               mkU32( 0 ),
   9719                                               mkexpr( intermediateResult ) ),
   9720                                        unop( Iop_NegF64,
   9721                                              unop( Iop_AbsF64,
   9722                                                    binop( Iop_I64StoF64,
   9723                                                           mkU32( 0 ),
   9724                                                           mkexpr( intermediateResult ) ) ) ) ),
   9725                          mkexpr( frB ) ) );
   9726 
   9727    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   9728     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   9729     */
   9730 #define SNAN_MASK 0x0008000000000000ULL
   9731    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   9732    assign( is_SNAN,
   9733            mkAND1( is_NaN( frB_I64 ),
   9734                    binop( Iop_CmpEQ32,
   9735                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   9736                           mkU32( 0 ) ) ) );
   9737 
   9738    return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ),
   9739                         mkexpr( frD ),
   9740                         unop( Iop_ReinterpI64asF64,
   9741                               binop( Iop_Xor64,
   9742                                      mkU64( SNAN_MASK ),
   9743                                      mkexpr( frB_I64 ) ) ) );
   9744 }
   9745 
   9746 /*
   9747  * Miscellaneous VSX vector instructions
   9748  */
   9749 static Bool
   9750 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   9751 {
   9752    /* XX3-Form */
   9753    UChar opc1 = ifieldOPC( theInstr );
   9754    UChar XT = ifieldRegXT( theInstr );
   9755    UChar XB = ifieldRegXB( theInstr );
   9756 
   9757    if (opc1 != 0x3C) {
   9758       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   9759       return False;
   9760    }
   9761 
   9762    switch (opc2) {
   9763       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   9764       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   9765                    //             Double-Precision)
   9766       {
   9767          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   9768          IRExpr* rm  = get_IR_roundingmode();
   9769          IRTemp frB = newTemp(Ity_I64);
   9770          IRTemp frB2 = newTemp(Ity_I64);
   9771          Bool redp = opc2 == 0x1B4;
   9772          IRTemp sqrtHi = newTemp(Ity_F64);
   9773          IRTemp sqrtLo = newTemp(Ity_F64);
   9774          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   9775          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   9776 
   9777          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
   9778          if (!redp) {
   9779             assign( sqrtHi,
   9780                     binop( Iop_SqrtF64,
   9781                            rm,
   9782                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   9783             assign( sqrtLo,
   9784                     binop( Iop_SqrtF64,
   9785                            rm,
   9786                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   9787          }
   9788          putVSReg( XT,
   9789                    binop( Iop_64HLtoV128,
   9790                           unop( Iop_ReinterpF64asI64,
   9791                                 triop( Iop_DivF64,
   9792                                        rm,
   9793                                        ieee_one,
   9794                                        redp ? unop( Iop_ReinterpI64asF64,
   9795                                                     mkexpr( frB ) )
   9796                                             : mkexpr( sqrtHi ) ) ),
   9797                           unop( Iop_ReinterpF64asI64,
   9798                                 triop( Iop_DivF64,
   9799                                        rm,
   9800                                        ieee_one,
   9801                                        redp ? unop( Iop_ReinterpI64asF64,
   9802                                                     mkexpr( frB2 ) )
   9803                                             : mkexpr( sqrtLo ) ) ) ) );
   9804          break;
   9805 
   9806       }
   9807       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   9808       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   9809       {
   9810          IRTemp b3, b2, b1, b0;
   9811          IRTemp res0 = newTemp(Ity_I32);
   9812          IRTemp res1 = newTemp(Ity_I32);
   9813          IRTemp res2 = newTemp(Ity_I32);
   9814          IRTemp res3 = newTemp(Ity_I32);
   9815          IRTemp sqrt3 = newTemp(Ity_F64);
   9816          IRTemp sqrt2 = newTemp(Ity_F64);
   9817          IRTemp sqrt1 = newTemp(Ity_F64);
   9818          IRTemp sqrt0 = newTemp(Ity_F64);
   9819          IRExpr* rm  = get_IR_roundingmode();
   9820          Bool resp = opc2 == 0x134;
   9821 
   9822          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   9823 
   9824          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   9825          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
   9826          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9827 
   9828          if (!resp) {
   9829             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   9830             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   9831             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   9832             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   9833          }
   9834 
   9835          assign( res0,
   9836                  unop( Iop_ReinterpF32asI32,
   9837                        unop( Iop_TruncF64asF32,
   9838                              triop( Iop_DivF64r32,
   9839                                     rm,
   9840                                     ieee_one,
   9841                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   9842          assign( res1,
   9843                  unop( Iop_ReinterpF32asI32,
   9844                        unop( Iop_TruncF64asF32,
   9845                              triop( Iop_DivF64r32,
   9846                                     rm,
   9847                                     ieee_one,
   9848                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   9849          assign( res2,
   9850                  unop( Iop_ReinterpF32asI32,
   9851                        unop( Iop_TruncF64asF32,
   9852                              triop( Iop_DivF64r32,
   9853                                     rm,
   9854                                     ieee_one,
   9855                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   9856          assign( res3,
   9857                  unop( Iop_ReinterpF32asI32,
   9858                        unop( Iop_TruncF64asF32,
   9859                              triop( Iop_DivF64r32,
   9860                                     rm,
   9861                                     ieee_one,
   9862                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   9863          putVSReg( XT,
   9864                    binop( Iop_64HLtoV128,
   9865                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   9866                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   9867          break;
   9868       }
   9869       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   9870       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   9871       {
   9872          UChar XA = ifieldRegXA( theInstr );
   9873          IRTemp a3, a2, a1, a0;
   9874          IRTemp b3, b2, b1, b0;
   9875          IRTemp res0 = newTemp( Ity_I32 );
   9876          IRTemp res1 = newTemp( Ity_I32 );
   9877          IRTemp res2 = newTemp( Ity_I32 );
   9878          IRTemp res3 = newTemp( Ity_I32 );
   9879          IRTemp a0_I64 = newTemp( Ity_I64 );
   9880          IRTemp a1_I64 = newTemp( Ity_I64 );
   9881          IRTemp a2_I64 = newTemp( Ity_I64 );
   9882          IRTemp a3_I64 = newTemp( Ity_I64 );
   9883          IRTemp b0_I64 = newTemp( Ity_I64 );
   9884          IRTemp b1_I64 = newTemp( Ity_I64 );
   9885          IRTemp b2_I64 = newTemp( Ity_I64 );
   9886          IRTemp b3_I64 = newTemp( Ity_I64 );
   9887 
   9888          Bool isMin = opc2 == 0x320 ? True : False;
   9889 
   9890          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   9891          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   9892          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
   9893          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   9894          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   9895          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   9896          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   9897          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   9898          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   9899          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   9900          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   9901          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   9902          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   9903          assign( res0,
   9904                  unop( Iop_ReinterpF32asI32,
   9905                        unop( Iop_TruncF64asF32,
   9906                              unop( Iop_ReinterpI64asF64,
   9907                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   9908          assign( res1,
   9909                  unop( Iop_ReinterpF32asI32,
   9910                        unop( Iop_TruncF64asF32,
   9911                              unop( Iop_ReinterpI64asF64,
   9912                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   9913          assign( res2,
   9914                  unop( Iop_ReinterpF32asI32,
   9915                        unop( Iop_TruncF64asF32,
   9916                              unop( Iop_ReinterpI64asF64,
   9917                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   9918          assign( res3,
   9919                  unop( Iop_ReinterpF32asI32,
   9920                        unop( Iop_TruncF64asF32,
   9921                              unop( Iop_ReinterpI64asF64,
   9922                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   9923          putVSReg( XT,
   9924                    binop( Iop_64HLtoV128,
   9925                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   9926                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   9927          break;
   9928       }
   9929       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   9930       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   9931       {
   9932          UChar XA = ifieldRegXA( theInstr );
   9933          IRTemp frA = newTemp(Ity_I64);
   9934          IRTemp frB = newTemp(Ity_I64);
   9935          IRTemp frA2 = newTemp(Ity_I64);
   9936          IRTemp frB2 = newTemp(Ity_I64);
   9937          Bool isMin = opc2 == 0x3A0 ? True : False;
   9938 
   9939          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   9940          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   9941          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   9942          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   9943          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
   9944          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   9945 
   9946          break;
   9947       }
   9948       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   9949       {
   9950          UChar XA = ifieldRegXA( theInstr );
   9951          IRTemp frA = newTemp(Ity_I64);
   9952          IRTemp frB = newTemp(Ity_I64);
   9953          IRTemp frA2 = newTemp(Ity_I64);
   9954          IRTemp frB2 = newTemp(Ity_I64);
   9955          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   9956          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   9957          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   9958          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   9959 
   9960          DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   9961          putVSReg( XT,
   9962                    binop( Iop_64HLtoV128,
   9963                           binop( Iop_Or64,
   9964                                  binop( Iop_And64,
   9965                                         mkexpr( frA ),
   9966                                         mkU64( SIGN_BIT ) ),
   9967                                  binop( Iop_And64,
   9968                                         mkexpr( frB ),
   9969                                         mkU64( SIGN_MASK ) ) ),
   9970                           binop( Iop_Or64,
   9971                                  binop( Iop_And64,
   9972                                         mkexpr( frA2 ),
   9973                                         mkU64( SIGN_BIT ) ),
   9974                                  binop( Iop_And64,
   9975                                         mkexpr( frB2 ),
   9976                                         mkU64( SIGN_MASK ) ) ) ) );
   9977          break;
   9978       }
   9979       case 0x340: // xvcpsgnsp
   9980       {
   9981          UChar XA = ifieldRegXA( theInstr );
   9982          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   9983          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   9984          IRTemp resHi = newTemp(Ity_I64);
   9985          IRTemp resLo = newTemp(Ity_I64);
   9986 
   9987          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   9988          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   9989          DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
   9990          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   9991          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   9992 
   9993          assign( resHi,
   9994                  binop( Iop_32HLto64,
   9995                         binop( Iop_Or32,
   9996                                binop( Iop_And32,
   9997                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   9998                                       mkU32( SIGN_BIT32 ) ),
   9999                                binop( Iop_And32,
   10000                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   10001                                       mkU32( SIGN_MASK32) ) ),
   10002 
   10003                         binop( Iop_Or32,
   10004                                binop( Iop_And32,
   10005                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   10006                                       mkU32( SIGN_BIT32 ) ),
   10007                                binop( Iop_And32,
   10008                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   10009                                       mkU32( SIGN_MASK32 ) ) ) ) );
   10010          assign( resLo,
   10011                  binop( Iop_32HLto64,
   10012                         binop( Iop_Or32,
   10013                                binop( Iop_And32,
   10014                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   10015                                       mkU32( SIGN_BIT32 ) ),
   10016                                binop( Iop_And32,
   10017                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   10018                                       mkU32( SIGN_MASK32 ) ) ),
   10019 
   10020                         binop( Iop_Or32,
   10021                                binop( Iop_And32,
   10022                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   10023                                       mkU32( SIGN_BIT32 ) ),
   10024                                binop( Iop_And32,
   10025                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   10026                                       mkU32( SIGN_MASK32 ) ) ) ) );
   10027          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   10028          break;
   10029       }
   10030       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   10031       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   10032       {
   10033          IRTemp frB = newTemp(Ity_F64);
   10034          IRTemp frB2 = newTemp(Ity_F64);
   10035          IRTemp abs_resultHi = newTemp(Ity_F64);
   10036          IRTemp abs_resultLo = newTemp(Ity_F64);
   10037          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   10038          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   10039          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   10040 
   10041          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
   10042          if (make_negative) {
   10043             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   10044             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   10045 
   10046          } else {
   10047             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   10048             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   10049          }
   10050          putVSReg( XT, binop( Iop_64HLtoV128,
   10051                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   10052                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   10053          break;
   10054       }
   10055       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   10056       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   10057       {
   10058          /*
   10059           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   10060           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   10061           * of this function is so easy using shifts, I choose to emulate this instruction that
   10062           * way versus a native instruction method of implementation.
   10063           */
   10064          Bool make_negative = (opc2 == 0x352) ? True : False;
   10065          IRTemp shiftVector = newTemp(Ity_V128);
   10066          IRTemp absVal_vector = newTemp(Ity_V128);
   10067          assign( shiftVector,
   10068                  binop( Iop_64HLtoV128,
   10069                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   10070                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   10071          assign( absVal_vector,
   10072                    binop( Iop_Shr32x4,
   10073                           binop( Iop_Shl32x4,
   10074                                  getVSReg( XB ),
   10075                                  mkexpr( shiftVector ) ),
   10076                           mkexpr( shiftVector ) ) );
   10077          if (make_negative) {
   10078             IRTemp signBit_vector = newTemp(Ity_V128);
   10079             assign( signBit_vector,
   10080                     binop( Iop_64HLtoV128,
   10081                            binop( Iop_32HLto64,
   10082                                   mkU32( 0x80000000 ),
   10083                                   mkU32( 0x80000000 ) ),
   10084                            binop( Iop_32HLto64,
   10085                                   mkU32( 0x80000000 ),
   10086                                   mkU32( 0x80000000 ) ) ) );
   10087             putVSReg( XT,
   10088                       binop( Iop_OrV128,
   10089                              mkexpr( absVal_vector ),
   10090                              mkexpr( signBit_vector ) ) );
   10091          } else {
   10092             putVSReg( XT, mkexpr( absVal_vector ) );
   10093          }
   10094          break;
   10095       }
   10096       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   10097       {
   10098          IRTemp frB = newTemp(Ity_F64);
   10099          IRTemp frB2 = newTemp(Ity_F64);
   10100          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   10101          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   10102          DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
   10103          putVSReg( XT,
   10104                    binop( Iop_64HLtoV128,
   10105                           unop( Iop_ReinterpF64asI64,
   10106                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   10107                           unop( Iop_ReinterpF64asI64,
   10108                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   10109          break;
   10110       }
   10111       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   10112       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   10113       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   10114       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   10115       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   10116       {
   10117          IRTemp frBHi_I64 = newTemp(Ity_I64);
   10118          IRTemp frBLo_I64 = newTemp(Ity_I64);
   10119          IRExpr * frD_fp_roundHi = NULL;
   10120          IRExpr * frD_fp_roundLo = NULL;
   10121          UChar * insn_suffix = NULL;
   10122 
   10123          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   10124          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix);
   10125          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   10126          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix);
   10127 
   10128          DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   10129          putVSReg( XT,
   10130                    binop( Iop_64HLtoV128,
   10131                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   10132                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   10133          break;
   10134       }
   10135       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   10136       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   10137       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   10138       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   10139       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   10140       {
   10141          UChar * insn_suffix = NULL;
   10142          IROp op;
   10143          if (opc2 != 0x156) {
   10144             // Use pre-defined IRop's for vrfi{m|n|p|z}
   10145             switch (opc2) {
   10146                case 0x112:
   10147                   insn_suffix = "";
   10148                   op = Iop_RoundF32x4_RN;
   10149                   break;
   10150                case 0x172:
   10151                   insn_suffix = "m";
   10152                   op = Iop_RoundF32x4_RM;
   10153                   break;
   10154                case 0x152:
   10155                   insn_suffix = "p";
   10156                   op = Iop_RoundF32x4_RP;
   10157                   break;
   10158                case 0x132:
   10159                   insn_suffix = "z";
   10160                   op = Iop_RoundF32x4_RZ;
   10161                   break;
   10162 
   10163                default:
   10164                   vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" );
   10165                   return False;
   10166             }
   10167             DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   10168             putVSReg( XT, unop( op, getVSReg(XB) ) );
   10169          } else {
   10170             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   10171             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   10172             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   10173             IRTemp b3_I64 = newTemp(Ity_I64);
   10174             IRTemp b2_I64 = newTemp(Ity_I64);
   10175             IRTemp b1_I64 = newTemp(Ity_I64);
   10176             IRTemp b0_I64 = newTemp(Ity_I64);
   10177 
   10178             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   10179             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   10180             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   10181             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   10182             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   10183             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   10184             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   10185             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   10186                                   _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix));
   10187             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   10188                                   _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix));
   10189             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   10190                                   _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix));
   10191             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   10192                                   _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix));
   10193             DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
   10194             putVSReg( XT,
   10195                       binop( Iop_64HLtoV128,
   10196                              binop( Iop_32HLto64,
   10197                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   10198                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   10199                              binop( Iop_32HLto64,
   10200                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   10201                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   10202          }
   10203          break;
   10204       }
   10205 
   10206       default:
   10207          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   10208          return False;
   10209    }
   10210    return True;
   10211 }
   10212 
   10213 
   10214 /*
   10215  * VSX Scalar Floating Point Arithmetic Instructions
   10216  */
   10217 static Bool
   10218 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   10219 {
   10220    /* XX3-Form */
   10221    UChar opc1 = ifieldOPC( theInstr );
   10222    UChar XT = ifieldRegXT( theInstr );
   10223    UChar XA = ifieldRegXA( theInstr );
   10224    UChar XB = ifieldRegXB( theInstr );
   10225    IRExpr* rm = get_IR_roundingmode();
   10226    IRTemp frA = newTemp(Ity_F64);
   10227    IRTemp frB = newTemp(Ity_F64);
   10228 
   10229    if (opc1 != 0x3C) {
   10230       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   10231       return False;
   10232    }
   10233 
   10234    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   10235    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   10236 
   10237    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   10238     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   10239     * element to zero where it makes sense to do so.
   10240     */
   10241    switch (opc2) {
   10242       case 0x080: // xsadddp (VSX scalar add double-precision)
   10243          DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10244          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10245                                                     triop( Iop_AddF64, rm,
   10246                                                            mkexpr( frA ),
   10247                                                            mkexpr( frB ) ) ),
   10248                               mkU64( 0 ) ) );
   10249          break;
   10250       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   10251          DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10252          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10253                                                     triop( Iop_DivF64, rm,
   10254                                                            mkexpr( frA ),
   10255                                                            mkexpr( frB ) ) ),
   10256                               mkU64( 0 ) ) );
   10257          break;
   10258       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   10259       {
   10260          IRTemp frT = newTemp(Ity_F64);
   10261          Bool mdp = opc2 == 0x0A4;
   10262          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   10263          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   10264                                                         getVSReg( XT ) ) ) );
   10265          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10266                                                     qop( Iop_MAddF64, rm,
   10267                                                          mkexpr( frA ),
   10268                                                          mkexpr( mdp ? frT : frB ),
   10269                                                          mkexpr( mdp ? frB : frT ) ) ),
   10270                               mkU64( 0 ) ) );
   10271          break;
   10272       }
   10273       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   10274       {
   10275          IRTemp frT = newTemp(Ity_F64);
   10276          Bool mdp = opc2 == 0x0E4;
   10277          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   10278          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   10279                                                         getVSReg( XT ) ) ) );
   10280          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10281                                                     qop( Iop_MSubF64, rm,
   10282                                                          mkexpr( frA ),
   10283                                                          mkexpr( mdp ? frT : frB ),
   10284                                                          mkexpr( mdp ? frB : frT ) ) ),
   10285                               mkU64( 0 ) ) );
   10286          break;
   10287       }
   10288       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   10289       {
   10290          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   10291           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   10292           * way it blindly negates the signbit, even if the floating point result is a NaN.
   10293           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   10294           */
   10295          Bool mdp = opc2 == 0x2A4;
   10296          IRTemp frT = newTemp(Ity_F64);
   10297          IRTemp maddResult = newTemp(Ity_I64);
   10298 
   10299          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   10300          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   10301                                                         getVSReg( XT ) ) ) );
   10302          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   10303                                                               mkexpr( frA ),
   10304                                                               mkexpr( mdp ? frT : frB ),
   10305                                                               mkexpr( mdp ? frB : frT ) ) ) );
   10306 
   10307          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   10308                               mkU64( 0 ) ) );
   10309          break;
   10310       }
   10311       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   10312       {
   10313          IRTemp frT = newTemp(Ity_F64);
   10314          Bool mdp = opc2 == 0x2E4;
   10315          IRTemp msubResult = newTemp(Ity_I64);
   10316 
   10317          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
   10318          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   10319                                                         getVSReg( XT ) ) ) );
   10320          assign(msubResult, unop( Iop_ReinterpF64asI64,
   10321                                       qop( Iop_MSubF64,
   10322                                            rm,
   10323                                            mkexpr( frA ),
   10324                                            mkexpr( mdp ? frT : frB ),
   10325                                            mkexpr( mdp ? frB : frT ) ) ));
   10326 
   10327          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   10328 
   10329          break;
   10330       }
   10331 
   10332       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   10333          DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10334          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10335                                                     triop( Iop_MulF64, rm,
   10336                                                            mkexpr( frA ),
   10337                                                            mkexpr( frB ) ) ),
   10338                               mkU64( 0 ) ) );
   10339          break;
   10340       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   10341          DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10342          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10343                                                     triop( Iop_SubF64, rm,
   10344                                                            mkexpr( frA ),
   10345                                                            mkexpr( frB ) ) ),
   10346                               mkU64( 0 ) ) );
   10347          break;
   10348 
   10349       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   10350          DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   10351          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   10352                                                      binop( Iop_SqrtF64, rm,
   10353                                                             mkexpr( frB ) ) ),
   10354                                mkU64( 0 ) ) );
   10355          break;
   10356 
   10357       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   10358       {
   10359          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   10360          IRTemp frA_I64 = newTemp(Ity_I64);
   10361          IRTemp frB_I64 = newTemp(Ity_I64);
   10362          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
   10363          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   10364          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   10365          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   10366          break;
   10367       }
   10368       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   10369       {
   10370          IRTemp frB_I64 = newTemp(Ity_I64);
   10371          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   10372          IRTemp flags = newTemp(Ity_I32);
   10373          IRTemp  fe_flag, fg_flag;
   10374          fe_flag = fg_flag = IRTemp_INVALID;
   10375          DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   10376          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   10377          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   10378          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   10379           * where fl_flag == 1 on ppc64.
   10380           */
   10381          assign( flags,
   10382                  binop( Iop_Or32,
   10383                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   10384                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   10385                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   10386          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   10387          break;
   10388       }
   10389 
   10390       default:
   10391          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   10392          return False;
   10393    }
   10394 
   10395    return True;
   10396 }
   10397 
   10398 
   10399 /*
   10400  * VSX Floating Point Compare Instructions
   10401  */
   10402 static Bool
   10403 dis_vx_cmp( UInt theInstr, UInt opc2 )
   10404 {
   10405    /* XX3-Form and XX2-Form */
   10406    UChar opc1 = ifieldOPC( theInstr );
   10407    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   10408    IRTemp ccPPC32;
   10409    UChar XA       = ifieldRegXA ( theInstr );
   10410    UChar XB       = ifieldRegXB ( theInstr );
   10411    IRTemp frA     = newTemp(Ity_F64);
   10412    IRTemp frB     = newTemp(Ity_F64);
   10413 
   10414    if (opc1 != 0x3C) {
   10415       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   10416       return False;
   10417    }
   10418 
   10419    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   10420    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   10421    switch (opc2) {
   10422       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   10423          /* Note: Differences between xscmpudp and xscmpodp are only in
   10424           * exception flag settings, which aren't supported anyway. */
   10425          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   10426                                            crfD, (UInt)XA, (UInt)XB);
   10427          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   10428          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   10429          break;
   10430 
   10431       default:
   10432          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   10433          return False;
   10434    }
   10435    return True;
   10436 }
   10437 
   10438 static void
   10439 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   10440                  ppc_cmp_t cmp_type )
   10441 {
   10442    IRTemp frA_hi     = newTemp(Ity_F64);
   10443    IRTemp frB_hi     = newTemp(Ity_F64);
   10444    IRTemp frA_lo     = newTemp(Ity_F64);
   10445    IRTemp frB_lo     = newTemp(Ity_F64);
   10446    IRTemp ccPPC32    = newTemp(Ity_I32);
   10447    IRTemp ccIR_hi;
   10448    IRTemp ccIR_lo;
   10449 
   10450    IRTemp hiResult = newTemp(Ity_I64);
   10451    IRTemp loResult = newTemp(Ity_I64);
   10452    IRTemp hiEQlo = newTemp(Ity_I1);
   10453    IRTemp all_elem_true = newTemp(Ity_I32);
   10454    IRTemp all_elem_false = newTemp(Ity_I32);
   10455 
   10456    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   10457    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   10458    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   10459    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   10460 
   10461    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   10462                                        mkexpr( frA_hi ),
   10463                                        mkexpr( frB_hi ) ) );
   10464    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   10465                                        mkexpr( frA_lo ),
   10466                                        mkexpr( frB_lo ) ) );
   10467 
   10468    if (cmp_type != PPC_CMP_GE) {
   10469       assign( hiResult,
   10470               unop( Iop_1Sto64,
   10471                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   10472       assign( loResult,
   10473               unop( Iop_1Sto64,
   10474                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   10475    } else {
   10476       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   10477       // the other element compare may return "2" (for "equal to").
   10478       IRTemp lo_GE = newTemp(Ity_I1);
   10479       IRTemp hi_GE = newTemp(Ity_I1);
   10480 
   10481       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   10482                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   10483       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   10484 
   10485       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   10486                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   10487       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   10488    }
   10489 
   10490    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   10491    assign( hiEQlo,
   10492            binop( Iop_CmpEQ32,
   10493                   unop( Iop_64to32, mkexpr( hiResult ) ),
   10494                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   10495    putVSReg( XT,
   10496              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   10497 
   10498    assign( all_elem_true,
   10499            unop( Iop_1Uto32,
   10500                  mkAND1( mkexpr( hiEQlo ),
   10501                          binop( Iop_CmpEQ32,
   10502                                 mkU32( 0xffffffff ),
   10503                                 unop( Iop_64to32,
   10504                                 mkexpr( hiResult ) ) ) ) ) );
   10505 
   10506    assign( all_elem_false,
   10507            unop( Iop_1Uto32,
   10508                  mkAND1( mkexpr( hiEQlo ),
   10509                          binop( Iop_CmpEQ32,
   10510                                 mkU32( 0 ),
   10511                                 unop( Iop_64to32,
   10512                                 mkexpr( hiResult ) ) ) ) ) );
   10513    assign( ccPPC32,
   10514            binop( Iop_Or32,
   10515                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   10516                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   10517 
   10518    if (flag_rC) {
   10519       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   10520    }
   10521 }
   10522 
   10523 /*
   10524  * VSX Vector Compare Instructions
   10525  */
   10526 static Bool
   10527 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   10528 {
   10529    /* XX3-Form */
   10530    UChar opc1 = ifieldOPC( theInstr );
   10531    UChar XT = ifieldRegXT ( theInstr );
   10532    UChar XA = ifieldRegXA ( theInstr );
   10533    UChar XB = ifieldRegXB ( theInstr );
   10534    UChar flag_rC  = ifieldBIT10(theInstr);
   10535    IRTemp vA = newTemp( Ity_V128 );
   10536    IRTemp vB = newTemp( Ity_V128 );
   10537 
   10538    if (opc1 != 0x3C) {
   10539       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   10540       return False;
   10541    }
   10542 
   10543    assign( vA, getVSReg( XA ) );
   10544    assign( vB, getVSReg( XB ) );
   10545 
   10546    switch (opc2) {
   10547       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   10548       {
   10549          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10550              (UInt)XT, (UInt)XA, (UInt)XB);
   10551          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   10552          break;
   10553       }
   10554 
   10555       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   10556       {
   10557          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10558              (UInt)XT, (UInt)XA, (UInt)XB);
   10559          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   10560          break;
   10561       }
   10562 
   10563       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   10564       {
   10565          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10566              (UInt)XT, (UInt)XA, (UInt)XB);
   10567          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   10568          break;
   10569       }
   10570 
   10571       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   10572       {
   10573          IRTemp vD = newTemp(Ity_V128);
   10574 
   10575          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10576              (UInt)XT, (UInt)XA, (UInt)XB);
   10577          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   10578          putVSReg( XT, mkexpr(vD) );
   10579          if (flag_rC) {
   10580             set_AV_CR6( mkexpr(vD), True );
   10581          }
   10582          break;
   10583       }
   10584 
   10585       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   10586       {
   10587          IRTemp vD = newTemp(Ity_V128);
   10588 
   10589          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10590              (UInt)XT, (UInt)XA, (UInt)XB);
   10591          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   10592          putVSReg( XT, mkexpr(vD) );
   10593          if (flag_rC) {
   10594             set_AV_CR6( mkexpr(vD), True );
   10595          }
   10596          break;
   10597       }
   10598 
   10599       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   10600       {
   10601          IRTemp vD = newTemp(Ity_V128);
   10602 
   10603          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   10604              (UInt)XT, (UInt)XA, (UInt)XB);
   10605          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   10606          putVSReg( XT, mkexpr(vD) );
   10607          if (flag_rC) {
   10608             set_AV_CR6( mkexpr(vD), True );
   10609          }
   10610          break;
   10611       }
   10612 
   10613       default:
   10614          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   10615          return False;
   10616    }
   10617    return True;
   10618 }
   10619 /*
   10620  * Miscellaneous VSX Scalar Instructions
   10621  */
   10622 static Bool
   10623 dis_vxs_misc( UInt theInstr, UInt opc2 )
   10624 {
   10625    /* XX3-Form and XX2-Form */
   10626    UChar opc1 = ifieldOPC( theInstr );
   10627    UChar XT = ifieldRegXT ( theInstr );
   10628    UChar XA = ifieldRegXA ( theInstr );
   10629    UChar XB = ifieldRegXB ( theInstr );
   10630    IRTemp vA = newTemp( Ity_V128 );
   10631    IRTemp vB = newTemp( Ity_V128 );
   10632 
   10633    if (opc1 != 0x3C) {
   10634       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   10635       return False;
   10636    }
   10637 
   10638    assign( vA, getVSReg( XA ) );
   10639    assign( vB, getVSReg( XB ) );
   10640 
   10641    /* For all the VSX move instructions, the contents of doubleword element 1
   10642     * of VSX[XT] are undefined after the operation; therefore, we can simply
   10643     * move the entire array element where it makes sense to do so.
   10644     */
   10645 
   10646    switch (opc2) {
   10647       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   10648       {
   10649          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   10650          IRTemp absVal = newTemp(Ity_V128);
   10651          assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
   10652          DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   10653          putVSReg(XT, mkexpr(absVal));
   10654          break;
   10655       }
   10656       case 0x2C0: // xscpsgndp
   10657       {
   10658          /* Scalar copy sign double-precision */
   10659          IRTemp vecA_signbit = newTemp(Ity_V128);
   10660          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   10661          IRTemp vec_result = newTemp(Ity_V128);
   10662          DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10663          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   10664                                                              mkexpr( vB ),
   10665                                                              mkU8( 1 ) ),
   10666                                          mkU8( 1 ) ) );
   10667          assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
   10668                                                           mkexpr( vA ),
   10669                                                           mkU8( 127 ) ),
   10670                                       mkU8( 127 ) ) );
   10671          assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
   10672          putVSReg(XT, mkexpr(vec_result));
   10673          break;
   10674       }
   10675       case 0x2D2: // xsnabsdp
   10676       {
   10677          /* Scalar negative absolute value double-precision */
   10678          IRTemp vec_neg_signbit = newTemp(Ity_V128);
   10679          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   10680          assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
   10681                                                             mkV128( 0xffff ),
   10682                                                             mkU8( 1 ) ) ) );
   10683          putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
   10684          break;
   10685       }
   10686       case 0x2F2: // xsnegdp
   10687       {
   10688          /* Scalar negate double-precision */
   10689          IRTemp vecB_no_signbit = newTemp(Ity_V128);
   10690          IRTemp vecB_signbit_comp = newTemp(Ity_V128);
   10691          DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
   10692          assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
   10693                                                              mkexpr( vB ),
   10694                                                              mkU8( 1 ) ),
   10695                                          mkU8( 1 ) ) );
   10696          assign( vecB_signbit_comp, binop( Iop_ShlV128,
   10697                                            unop( Iop_NotV128,
   10698                                                  binop( Iop_ShrV128,
   10699                                                         mkexpr( vB ),
   10700                                                         mkU8( 127 ) ) ),
   10701                                            mkU8( 127 ) ) );
   10702          putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
   10703                               mkexpr( vecB_signbit_comp ) ) );
   10704          break;
   10705       }
   10706       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   10707       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   10708       {
   10709          IRTemp frA     = newTemp(Ity_I64);
   10710          IRTemp frB     = newTemp(Ity_I64);
   10711          Bool isMin = opc2 == 0x2A0 ? True : False;
   10712          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
   10713 
   10714          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   10715          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   10716          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   10717 
   10718          break;
   10719       }
   10720       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   10721       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   10722       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   10723       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   10724       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   10725       {
   10726          IRTemp frB_I64 = newTemp(Ity_I64);
   10727          IRExpr * frD_fp_round = NULL;
   10728          UChar * insn_suffix = NULL;
   10729 
   10730          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   10731          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix);
   10732 
   10733          DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
   10734          putVSReg( XT,
   10735                    binop( Iop_64HLtoV128,
   10736                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   10737                           mkU64( 0 ) ) );
   10738          break;
   10739       }
   10740       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   10741       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   10742 
   10743       {
   10744          IRTemp frB = newTemp(Ity_F64);
   10745          IRTemp sqrt = newTemp(Ity_F64);
   10746          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   10747          IRExpr* rm  = get_IR_roundingmode();
   10748          Bool redp = opc2 == 0x0B4;
   10749          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
   10750          assign( frB,
   10751                  unop( Iop_ReinterpI64asF64,
   10752                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   10753 
   10754          if (!redp)
   10755             assign( sqrt,
   10756                     binop( Iop_SqrtF64,
   10757                            rm,
   10758                            mkexpr(frB) ) );
   10759          putVSReg( XT,
   10760                       binop( Iop_64HLtoV128,
   10761                              unop( Iop_ReinterpF64asI64,
   10762                                    triop( Iop_DivF64,
   10763                                           rm,
   10764                                           ieee_one,
   10765                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   10766                              mkU64( 0 ) ) );
   10767          break;
   10768       }
   10769 
   10770       default:
   10771          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   10772          return False;
   10773    }
   10774    return True;
   10775 }
   10776 
   10777 /*
   10778  * VSX Logical Instructions
   10779  */
   10780 static Bool
   10781 dis_vx_logic ( UInt theInstr, UInt opc2 )
   10782 {
   10783    /* XX3-Form */
   10784    UChar opc1 = ifieldOPC( theInstr );
   10785    UChar XT = ifieldRegXT ( theInstr );
   10786    UChar XA = ifieldRegXA ( theInstr );
   10787    UChar XB = ifieldRegXB ( theInstr );
   10788    IRTemp vA = newTemp( Ity_V128 );
   10789    IRTemp vB = newTemp( Ity_V128 );
   10790 
   10791    if (opc1 != 0x3C) {
   10792       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   10793       return False;
   10794    }
   10795 
   10796    assign( vA, getVSReg( XA ) );
   10797    assign( vB, getVSReg( XB ) );
   10798 
   10799    switch (opc2) {
   10800       case 0x268: // xxlxor
   10801          DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10802          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   10803          break;
   10804       case 0x248: // xxlor
   10805          DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10806          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   10807          break;
   10808       case 0x288: // xxlnor
   10809          DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10810          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   10811                                                  mkexpr( vB ) ) ) );
   10812          break;
   10813       case 0x208: // xxland
   10814          DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10815          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   10816          break;
   10817       case 0x228: //xxlandc
   10818          DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
   10819          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   10820                                                                mkexpr( vB ) ) ) );
   10821          break;
   10822       default:
   10823          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   10824          return False;
   10825    }
   10826    return True;
   10827 }
   10828 
   10829 /*
   10830  * VSX Load Instructions
   10831  * NOTE: VSX supports word-aligned storage access.
   10832  */
   10833 static Bool
   10834 dis_vx_load ( UInt theInstr )
   10835 {
   10836    /* XX1-Form */
   10837    UChar opc1 = ifieldOPC( theInstr );
   10838    UChar XT = ifieldRegXT ( theInstr );
   10839    UChar rA_addr = ifieldRegA( theInstr );
   10840    UChar rB_addr = ifieldRegB( theInstr );
   10841    UInt opc2 = ifieldOPClo10( theInstr );
   10842 
   10843    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   10844    IRTemp EA = newTemp( ty );
   10845 
   10846    if (opc1 != 0x1F) {
   10847       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   10848       return False;
   10849    }
   10850 
   10851    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   10852 
   10853    switch (opc2) {
   10854    case 0x24C: // lxsdx
   10855    {
   10856       IRExpr * exp;
   10857       DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   10858       exp = loadBE( Ity_I64, mkexpr( EA ) );
   10859       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   10860       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   10861       // are undefined after this operation, we can just do a splat op.
   10862       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   10863       break;
   10864    }
   10865    case 0x34C: // lxvd2x
   10866    {
   10867       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   10868       IRExpr * high, *low;
   10869       ULong ea_off = 8;
   10870       IRExpr* high_addr;
   10871       DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   10872       high = loadBE( Ity_I64, mkexpr( EA ) );
   10873       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   10874             : mkU32( ea_off ) );
   10875       low = loadBE( Ity_I64, high_addr );
   10876       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   10877       break;
   10878    }
   10879    case 0x14C: // lxvdsx
   10880    {
   10881       IRTemp data = newTemp(Ity_I64);
   10882       DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   10883       assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
   10884       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   10885       break;
   10886    }
   10887    case 0x30C:
   10888    {
   10889       IRExpr * t3, *t2, *t1, *t0;
   10890       UInt ea_off = 0;
   10891       IRExpr* irx_addr;
   10892 
   10893       DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
   10894       t3 = loadBE( Ity_I32,  mkexpr( EA ) );
   10895       ea_off += 4;
   10896       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10897                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10898       t2 = loadBE( Ity_I32, irx_addr );
   10899       ea_off += 4;
   10900       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10901                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10902       t1 = loadBE( Ity_I32, irx_addr );
   10903       ea_off += 4;
   10904       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10905                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10906       t0 = loadBE( Ity_I32, irx_addr );
   10907       putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
   10908                            binop( Iop_32HLto64, t1, t0 ) ) );
   10909       break;
   10910    }
   10911    default:
   10912       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   10913       return False;
   10914    }
   10915    return True;
   10916 }
   10917 
   10918 /*
   10919  * VSX Store Instructions
   10920  * NOTE: VSX supports word-aligned storage access.
   10921  */
   10922 static Bool
   10923 dis_vx_store ( UInt theInstr )
   10924 {
   10925    /* XX1-Form */
   10926    UChar opc1 = ifieldOPC( theInstr );
   10927    UChar XS = ifieldRegXS( theInstr );
   10928    UChar rA_addr = ifieldRegA( theInstr );
   10929    UChar rB_addr = ifieldRegB( theInstr );
   10930    IRTemp vS = newTemp( Ity_V128 );
   10931    UInt opc2 = ifieldOPClo10( theInstr );
   10932 
   10933    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   10934    IRTemp EA = newTemp( ty );
   10935 
   10936    if (opc1 != 0x1F) {
   10937       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   10938       return False;
   10939    }
   10940 
   10941    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   10942    assign( vS, getVSReg( XS ) );
   10943 
   10944    switch (opc2) {
   10945    case 0x2CC:
   10946    {
   10947       IRExpr * high64;
   10948       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   10949       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   10950       storeBE( mkexpr( EA ), high64 );
   10951       break;
   10952    }
   10953    case 0x3CC:
   10954    {
   10955       IRExpr * high64, *low64;
   10956       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   10957       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   10958       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   10959       storeBE( mkexpr( EA ), high64 );
   10960       storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
   10961             : mkU32( 8 ) ), low64 );
   10962       break;
   10963    }
   10964    case 0x38C:
   10965    {
   10966       UInt ea_off = 0;
   10967       IRExpr* irx_addr;
   10968       IRTemp hi64 = newTemp( Ity_I64 );
   10969       IRTemp lo64 = newTemp( Ity_I64 );
   10970 
   10971       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
   10972 
   10973       // This instruction supports word-aligned stores, so EA may not be
   10974       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   10975       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   10976       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   10977 
   10978       storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   10979       ea_off += 4;
   10980       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10981                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10982       storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   10983       ea_off += 4;
   10984       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10985                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10986       storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   10987       ea_off += 4;
   10988       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   10989                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   10990       storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   10991 
   10992       break;
   10993    }
   10994    default:
   10995       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   10996       return False;
   10997    }
   10998    return True;
   10999 }
   11000 
   11001 /*
   11002  * VSX permute and other miscealleous instructions
   11003  */
   11004 static Bool
   11005 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   11006 {
   11007    /* XX3-Form */
   11008    UChar opc1 = ifieldOPC( theInstr );
   11009    UChar XT = ifieldRegXT ( theInstr );
   11010    UChar XA = ifieldRegXA ( theInstr );
   11011    UChar XB = ifieldRegXB ( theInstr );
   11012    IRTemp vT = newTemp( Ity_V128 );
   11013    IRTemp vA = newTemp( Ity_V128 );
   11014    IRTemp vB = newTemp( Ity_V128 );
   11015 
   11016    if (opc1 != 0x3C) {
   11017       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   11018       return False;
   11019    }
   11020 
   11021    assign( vA, getVSReg( XA ) );
   11022    assign( vB, getVSReg( XB ) );
   11023 
   11024    switch (opc2) {
   11025       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   11026       {
   11027          UChar SHW = ifieldSHW ( theInstr );
   11028          IRTemp result = newTemp(Ity_V128);
   11029          if ( SHW != 0 ) {
   11030              IRTemp hi = newTemp(Ity_V128);
   11031              IRTemp lo = newTemp(Ity_V128);
   11032              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   11033              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   11034              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   11035          } else
   11036              assign ( result, mkexpr(vA) );
   11037          DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
   11038          putVSReg( XT, mkexpr(result) );
   11039          break;
   11040       }
   11041       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   11042       {
   11043          UChar DM = ifieldDM ( theInstr );
   11044          IRTemp hi = newTemp(Ity_I64);
   11045          IRTemp lo = newTemp(Ity_I64);
   11046 
   11047          if (DM & 0x2)
   11048            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   11049          else
   11050            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   11051 
   11052          if (DM & 0x1)
   11053            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   11054          else
   11055            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   11056 
   11057          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   11058 
   11059          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
   11060          putVSReg( XT, mkexpr( vT ) );
   11061          break;
   11062       }
   11063       case 0x48: // xxmrghw (VSX Merge High Word)
   11064       case 0xc8: // xxmrglw (VSX Merge Low Word)
   11065       {
   11066          char type = (opc2 == 0x48) ? 'h' : 'l';
   11067          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   11068          IRTemp a64 = newTemp(Ity_I64);
   11069          IRTemp ahi32 = newTemp(Ity_I32);
   11070          IRTemp alo32 = newTemp(Ity_I32);
   11071          IRTemp b64 = newTemp(Ity_I64);
   11072          IRTemp bhi32 = newTemp(Ity_I32);
   11073          IRTemp blo32 = newTemp(Ity_I32);
   11074 
   11075          assign( a64, unop(word_op, mkexpr(vA)) );
   11076          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   11077          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   11078 
   11079          assign( b64, unop(word_op, mkexpr(vB)) );
   11080          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   11081          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   11082 
   11083          assign( vT, binop(Iop_64HLtoV128,
   11084                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   11085                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   11086 
   11087          DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
   11088          putVSReg( XT, mkexpr( vT ) );
   11089          break;
   11090       }
   11091       case 0x018: // xxsel (VSX Select)
   11092       {
   11093          UChar XC = ifieldRegXC(theInstr);
   11094          IRTemp vC = newTemp( Ity_V128 );
   11095          assign( vC, getVSReg( XC ) );
   11096          DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
   11097          /* vD = (vA & ~vC) | (vB & vC) */
   11098          putVSReg( XT, binop(Iop_OrV128,
   11099             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   11100             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   11101          break;
   11102       }
   11103       case 0x148: // xxspltw (VSX Splat Word)
   11104       {
   11105          UChar UIM   = ifieldRegA(theInstr) & 3;
   11106          UChar sh_uim = (3 - (UIM)) * 32;
   11107          DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
   11108          putVSReg( XT,
   11109                    unop( Iop_Dup32x4,
   11110                          unop( Iop_V128to32,
   11111                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   11112          break;
   11113       }
   11114 
   11115       default:
   11116          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   11117          return False;
   11118    }
   11119    return True;
   11120 }
   11121 
   11122 /*
   11123   AltiVec Load Instructions
   11124 */
   11125 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
   11126 {
   11127    /* X-Form */
   11128    UChar opc1     = ifieldOPC(theInstr);
   11129    UChar vD_addr  = ifieldRegDS(theInstr);
   11130    UChar rA_addr  = ifieldRegA(theInstr);
   11131    UChar rB_addr  = ifieldRegB(theInstr);
   11132    UInt  opc2     = ifieldOPClo10(theInstr);
   11133    UChar b0       = ifieldBIT0(theInstr);
   11134 
   11135    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   11136    IRTemp EA         = newTemp(ty);
   11137    IRTemp EA_align16 = newTemp(ty);
   11138 
   11139    if (opc1 != 0x1F || b0 != 0) {
   11140       vex_printf("dis_av_load(ppc)(instr)\n");
   11141       return False;
   11142    }
   11143 
   11144    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   11145    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   11146 
   11147    switch (opc2) {
   11148 
   11149    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   11150       IRDirty* d;
   11151       UInt vD_off = vectorGuestRegOffset(vD_addr);
   11152       IRExpr** args = mkIRExprVec_3(
   11153                          mkU32(vD_off),
   11154                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   11155                                           mkU32(0xF)),
   11156                          mkU32(0)/*left*/ );
   11157       if (!mode64) {
   11158          d = unsafeIRDirty_0_N (
   11159                         0/*regparms*/,
   11160                         "ppc32g_dirtyhelper_LVS",
   11161                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   11162                         args );
   11163       } else {
   11164          d = unsafeIRDirty_0_N (
   11165                         0/*regparms*/,
   11166                         "ppc64g_dirtyhelper_LVS",
   11167                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   11168                         args );
   11169       }
   11170       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11171       /* declare guest state effects */
   11172       d->needsBBP = True;
   11173       d->nFxState = 1;
   11174       d->fxState[0].fx     = Ifx_Write;
   11175       d->fxState[0].offset = vD_off;
   11176       d->fxState[0].size   = sizeof(U128);
   11177 
   11178       /* execute the dirty call, side-effecting guest state */
   11179       stmt( IRStmt_Dirty(d) );
   11180       break;
   11181    }
   11182    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   11183       IRDirty* d;
   11184       UInt vD_off = vectorGuestRegOffset(vD_addr);
   11185       IRExpr** args = mkIRExprVec_3(
   11186                          mkU32(vD_off),
   11187                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   11188                                           mkU32(0xF)),
   11189                          mkU32(1)/*right*/ );
   11190       if (!mode64) {
   11191          d = unsafeIRDirty_0_N (
   11192                         0/*regparms*/,
   11193                         "ppc32g_dirtyhelper_LVS",
   11194                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   11195                         args );
   11196       } else {
   11197          d = unsafeIRDirty_0_N (
   11198                         0/*regparms*/,
   11199                         "ppc64g_dirtyhelper_LVS",
   11200                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   11201                         args );
   11202       }
   11203       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11204       /* declare guest state effects */
   11205       d->needsBBP = True;
   11206       d->nFxState = 1;
   11207       d->fxState[0].fx     = Ifx_Write;
   11208       d->fxState[0].offset = vD_off;
   11209       d->fxState[0].size   = sizeof(U128);
   11210 
   11211       /* execute the dirty call, side-effecting guest state */
   11212       stmt( IRStmt_Dirty(d) );
   11213       break;
   11214    }
   11215    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   11216       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11217       /* loads addressed byte into vector[EA[0:3]
   11218          since all other destination bytes are undefined,
   11219          can simply load entire vector from 16-aligned EA */
   11220       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   11221       break;
   11222 
   11223    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   11224       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11225       /* see note for lvebx */
   11226       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   11227       break;
   11228 
   11229    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   11230       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11231       /* see note for lvebx */
   11232       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   11233       break;
   11234 
   11235    case 0x067: // lvx (Load Vector Indexed, AV p127)
   11236       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11237       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   11238       break;
   11239 
   11240    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   11241       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   11242       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   11243       break;
   11244 
   11245    default:
   11246       vex_printf("dis_av_load(ppc)(opc2)\n");
   11247       return False;
   11248    }
   11249    return True;
   11250 }
   11251 
   11252 /*
   11253   AltiVec Store Instructions
   11254 */
   11255 static Bool dis_av_store ( UInt theInstr )
   11256 {
   11257    /* X-Form */
   11258    UChar opc1     = ifieldOPC(theInstr);
   11259    UChar vS_addr  = ifieldRegDS(theInstr);
   11260    UChar rA_addr  = ifieldRegA(theInstr);
   11261    UChar rB_addr  = ifieldRegB(theInstr);
   11262    UInt  opc2     = ifieldOPClo10(theInstr);
   11263    UChar b0       = ifieldBIT0(theInstr);
   11264 
   11265    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   11266    IRTemp EA           = newTemp(ty);
   11267    IRTemp addr_aligned = newTemp(ty);
   11268    IRTemp vS           = newTemp(Ity_V128);
   11269    IRTemp eb           = newTemp(Ity_I8);
   11270    IRTemp idx          = newTemp(Ity_I8);
   11271 
   11272    if (opc1 != 0x1F || b0 != 0) {
   11273       vex_printf("dis_av_store(ppc)(instr)\n");
   11274       return False;
   11275    }
   11276 
   11277    assign( vS, getVReg(vS_addr));
   11278    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   11279 
   11280    switch (opc2) {
   11281    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   11282       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   11283       assign( eb, binop(Iop_And8, mkU8(0xF),
   11284                         unop(Iop_32to8,
   11285                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   11286       assign( idx, binop(Iop_Shl8,
   11287                          binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   11288                          mkU8(3)) );
   11289       storeBE( mkexpr(EA),
   11290                unop(Iop_32to8, unop(Iop_V128to32,
   11291                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   11292       break;
   11293    }
   11294    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   11295       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   11296       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   11297       assign( eb, binop(Iop_And8, mkU8(0xF),
   11298                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   11299       assign( idx, binop(Iop_Shl8,
   11300                          binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   11301                          mkU8(3)) );
   11302       storeBE( mkexpr(addr_aligned),
   11303                unop(Iop_32to16, unop(Iop_V128to32,
   11304                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   11305       break;
   11306    }
   11307    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   11308       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   11309       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   11310       assign( eb, binop(Iop_And8, mkU8(0xF),
   11311                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   11312       assign( idx, binop(Iop_Shl8,
   11313                          binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   11314                          mkU8(3)) );
   11315       storeBE( mkexpr(addr_aligned),
   11316                unop(Iop_V128to32,
   11317                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   11318       break;
   11319    }
   11320 
   11321    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   11322       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   11323       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   11324       break;
   11325 
   11326    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   11327       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   11328       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   11329       break;
   11330 
   11331    default:
   11332       vex_printf("dis_av_store(ppc)(opc2)\n");
   11333       return False;
   11334    }
   11335    return True;
   11336 }
   11337 
   11338 /*
   11339   AltiVec Arithmetic Instructions
   11340 */
   11341 static Bool dis_av_arith ( UInt theInstr )
   11342 {
   11343    /* VX-Form */
   11344    UChar opc1     = ifieldOPC(theInstr);
   11345    UChar vD_addr  = ifieldRegDS(theInstr);
   11346    UChar vA_addr  = ifieldRegA(theInstr);
   11347    UChar vB_addr  = ifieldRegB(theInstr);
   11348    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   11349 
   11350    IRTemp vA = newTemp(Ity_V128);
   11351    IRTemp vB = newTemp(Ity_V128);
   11352    IRTemp z3 = newTemp(Ity_I64);
   11353    IRTemp z2 = newTemp(Ity_I64);
   11354    IRTemp z1 = newTemp(Ity_I64);
   11355    IRTemp z0 = newTemp(Ity_I64);
   11356    IRTemp aEvn, aOdd;
   11357    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   11358    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   11359    IRTemp b3, b2, b1, b0;
   11360 
   11361    aEvn = aOdd = IRTemp_INVALID;
   11362    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   11363    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   11364    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   11365 
   11366    assign( vA, getVReg(vA_addr));
   11367    assign( vB, getVReg(vB_addr));
   11368 
   11369    if (opc1 != 0x4) {
   11370       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   11371       return False;
   11372    }
   11373 
   11374    switch (opc2) {
   11375    /* Add */
   11376    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   11377       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11378       /* unsigned_ov(x+y) = (y >u not(x)) */
   11379       putVReg( vD_addr, binop(Iop_ShrN32x4,
   11380                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   11381                                     unop(Iop_NotV128, mkexpr(vA))),
   11382                               mkU8(31)) );
   11383       break;
   11384    }
   11385    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   11386       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11387       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   11388       break;
   11389 
   11390    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   11391       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11392       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   11393       break;
   11394 
   11395    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   11396       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11397       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   11398       break;
   11399 
   11400    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   11401       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11402       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   11403       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   11404       break;
   11405 
   11406    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   11407       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11408       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   11409       // TODO: set VSCR[SAT]
   11410       break;
   11411 
   11412    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   11413       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11414       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   11415       // TODO: set VSCR[SAT]
   11416       break;
   11417 
   11418    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   11419       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11420       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   11421       // TODO: set VSCR[SAT]
   11422       break;
   11423 
   11424    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   11425       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11426       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   11427       // TODO: set VSCR[SAT]
   11428       break;
   11429 
   11430    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   11431       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11432       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   11433       // TODO: set VSCR[SAT]
   11434       break;
   11435 
   11436 
   11437    /* Subtract */
   11438    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   11439       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11440       /* unsigned_ov(x-y) = (y >u x) */
   11441       putVReg( vD_addr, binop(Iop_ShrN32x4,
   11442                               unop(Iop_NotV128,
   11443                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   11444                                          mkexpr(vA))),
   11445                               mkU8(31)) );
   11446       break;
   11447    }
   11448    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   11449       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11450       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   11451       break;
   11452 
   11453    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   11454       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11455       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   11456       break;
   11457 
   11458    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   11459       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11460       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   11461       break;
   11462 
   11463    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   11464       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11465       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   11466       // TODO: set VSCR[SAT]
   11467       break;
   11468 
   11469    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   11470       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11471       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   11472       // TODO: set VSCR[SAT]
   11473       break;
   11474 
   11475    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   11476       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11477       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   11478       // TODO: set VSCR[SAT]
   11479       break;
   11480 
   11481    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   11482       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11483       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   11484       // TODO: set VSCR[SAT]
   11485       break;
   11486 
   11487    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   11488       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11489       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   11490       // TODO: set VSCR[SAT]
   11491       break;
   11492 
   11493    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   11494       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11495       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   11496       // TODO: set VSCR[SAT]
   11497       break;
   11498 
   11499 
   11500    /* Maximum */
   11501    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   11502       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11503       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   11504       break;
   11505 
   11506    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   11507       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11508       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   11509       break;
   11510 
   11511    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   11512       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11513       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   11514       break;
   11515 
   11516    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   11517       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11518       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   11519       break;
   11520 
   11521    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   11522       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11523       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   11524       break;
   11525 
   11526    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   11527       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11528       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   11529       break;
   11530 
   11531 
   11532    /* Minimum */
   11533    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   11534       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11535       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   11536       break;
   11537 
   11538    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   11539       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11540       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   11541       break;
   11542 
   11543    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   11544       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11545       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   11546       break;
   11547 
   11548    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   11549       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11550       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   11551       break;
   11552 
   11553    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   11554       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11555       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   11556       break;
   11557 
   11558    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   11559       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11560       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   11561       break;
   11562 
   11563 
   11564    /* Average */
   11565    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   11566       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11567       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   11568       break;
   11569 
   11570    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   11571       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11572       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   11573       break;
   11574 
   11575    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   11576       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11577       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   11578       break;
   11579 
   11580    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   11581       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11582       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   11583       break;
   11584 
   11585    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   11586       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11587       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   11588       break;
   11589 
   11590    case 0x582: // vavgsw (Average Signed Word, AV p151)
   11591       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11592       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   11593       break;
   11594 
   11595 
   11596    /* Multiply */
   11597    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   11598       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11599       putVReg( vD_addr,
   11600                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   11601       break;
   11602 
   11603    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   11604       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11605       putVReg( vD_addr,
   11606                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   11607       break;
   11608 
   11609    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   11610       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11611       putVReg( vD_addr,
   11612                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   11613       break;
   11614 
   11615    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   11616       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11617       putVReg( vD_addr,
   11618                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   11619       break;
   11620 
   11621    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   11622       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11623       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   11624       break;
   11625 
   11626    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   11627       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11628       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   11629       break;
   11630 
   11631    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   11632       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11633       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   11634       break;
   11635 
   11636    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   11637       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11638       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   11639       break;
   11640 
   11641 
   11642    /* Sum Across Partial */
   11643    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   11644       IRTemp aEE, aEO, aOE, aOO;
   11645       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   11646       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11647 
   11648       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   11649       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   11650       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   11651       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   11652 
   11653       /* break V128 to 4xI32's, zero-extending to I64's */
   11654       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   11655       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   11656       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   11657       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   11658       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   11659 
   11660       /* add lanes */
   11661       assign( z3, binop(Iop_Add64, mkexpr(b3),
   11662                      binop(Iop_Add64,
   11663                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   11664                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   11665       assign( z2, binop(Iop_Add64, mkexpr(b2),
   11666                      binop(Iop_Add64,
   11667                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   11668                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   11669       assign( z1, binop(Iop_Add64, mkexpr(b1),
   11670                      binop(Iop_Add64,
   11671                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   11672                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   11673       assign( z0, binop(Iop_Add64, mkexpr(b0),
   11674                      binop(Iop_Add64,
   11675                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   11676                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   11677 
   11678       /* saturate-narrow to 32bit, and combine to V128 */
   11679       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   11680                                          mkexpr(z1), mkexpr(z0)) );
   11681       break;
   11682    }
   11683    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   11684       IRTemp aEE, aEO, aOE, aOO;
   11685       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   11686       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11687 
   11688       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   11689       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   11690       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   11691       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   11692 
   11693       /* break V128 to 4xI32's, sign-extending to I64's */
   11694       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   11695       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   11696       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   11697       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   11698       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   11699 
   11700       /* add lanes */
   11701       assign( z3, binop(Iop_Add64, mkexpr(b3),
   11702                      binop(Iop_Add64,
   11703                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   11704                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   11705       assign( z2, binop(Iop_Add64, mkexpr(b2),
   11706                      binop(Iop_Add64,
   11707                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   11708                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   11709       assign( z1, binop(Iop_Add64, mkexpr(b1),
   11710                      binop(Iop_Add64,
   11711                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   11712                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   11713       assign( z0, binop(Iop_Add64, mkexpr(b0),
   11714                      binop(Iop_Add64,
   11715                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   11716                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   11717 
   11718       /* saturate-narrow to 32bit, and combine to V128 */
   11719       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   11720                                          mkexpr(z1), mkexpr(z0)) );
   11721       break;
   11722    }
   11723    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   11724       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11725 
   11726       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   11727       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   11728 
   11729       /* break V128 to 4xI32's, sign-extending to I64's */
   11730       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   11731       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   11732       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   11733 
   11734       /* add lanes */
   11735       assign( z3, binop(Iop_Add64, mkexpr(b3),
   11736                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   11737       assign( z2, binop(Iop_Add64, mkexpr(b2),
   11738                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   11739       assign( z1, binop(Iop_Add64, mkexpr(b1),
   11740                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   11741       assign( z0, binop(Iop_Add64, mkexpr(b0),
   11742                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   11743 
   11744       /* saturate-narrow to 32bit, and combine to V128 */
   11745       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   11746                                          mkexpr(z1), mkexpr(z0)) );
   11747       break;
   11748    }
   11749    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   11750       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11751 
   11752       /* break V128 to 4xI32's, sign-extending to I64's */
   11753       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   11754       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   11755 
   11756       /* add lanes */
   11757       assign( z2, binop(Iop_Add64, mkexpr(b2),
   11758                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   11759       assign( z0, binop(Iop_Add64, mkexpr(b0),
   11760                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   11761 
   11762       /* saturate-narrow to 32bit, and combine to V128 */
   11763       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   11764                                          mkU64(0), mkexpr(z0)) );
   11765       break;
   11766    }
   11767    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   11768       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11769 
   11770       /* break V128 to 4xI32's, sign-extending to I64's */
   11771       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   11772       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   11773 
   11774       /* add lanes */
   11775       assign( z0, binop(Iop_Add64, mkexpr(b0),
   11776                      binop(Iop_Add64,
   11777                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   11778                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   11779 
   11780       /* saturate-narrow to 32bit, and combine to V128 */
   11781       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   11782                                          mkU64(0), mkexpr(z0)) );
   11783       break;
   11784    }
   11785    default:
   11786       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   11787       return False;
   11788    }
   11789    return True;
   11790 }
   11791 
   11792 /*
   11793   AltiVec Logic Instructions
   11794 */
   11795 static Bool dis_av_logic ( UInt theInstr )
   11796 {
   11797    /* VX-Form */
   11798    UChar opc1    = ifieldOPC(theInstr);
   11799    UChar vD_addr = ifieldRegDS(theInstr);
   11800    UChar vA_addr = ifieldRegA(theInstr);
   11801    UChar vB_addr = ifieldRegB(theInstr);
   11802    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   11803 
   11804    IRTemp vA = newTemp(Ity_V128);
   11805    IRTemp vB = newTemp(Ity_V128);
   11806    assign( vA, getVReg(vA_addr));
   11807    assign( vB, getVReg(vB_addr));
   11808 
   11809    if (opc1 != 0x4) {
   11810       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   11811       return False;
   11812    }
   11813 
   11814    switch (opc2) {
   11815    case 0x404: // vand (And, AV p147)
   11816       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11817       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   11818       break;
   11819 
   11820    case 0x444: // vandc (And, AV p148)
   11821       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11822       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   11823                               unop(Iop_NotV128, mkexpr(vB))) );
   11824       break;
   11825 
   11826    case 0x484: // vor (Or, AV p217)
   11827       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11828       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   11829       break;
   11830 
   11831    case 0x4C4: // vxor (Xor, AV p282)
   11832       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11833       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   11834       break;
   11835 
   11836    case 0x504: // vnor (Nor, AV p216)
   11837       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   11838       putVReg( vD_addr,
   11839          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   11840       break;
   11841 
   11842    default:
   11843       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   11844       return False;
   11845    }
   11846    return True;
   11847 }
   11848 
   11849 /*
   11850   AltiVec Compare Instructions
   11851 */
   11852 static Bool dis_av_cmp ( UInt theInstr )
   11853 {
   11854    /* VXR-Form */
   11855    UChar opc1     = ifieldOPC(theInstr);
   11856    UChar vD_addr  = ifieldRegDS(theInstr);
   11857    UChar vA_addr  = ifieldRegA(theInstr);
   11858    UChar vB_addr  = ifieldRegB(theInstr);
   11859    UChar flag_rC  = ifieldBIT10(theInstr);
   11860    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   11861 
   11862    IRTemp vA = newTemp(Ity_V128);
   11863    IRTemp vB = newTemp(Ity_V128);
   11864    IRTemp vD = newTemp(Ity_V128);
   11865    assign( vA, getVReg(vA_addr));
   11866    assign( vB, getVReg(vB_addr));
   11867 
   11868    if (opc1 != 0x4) {
   11869       vex_printf("dis_av_cmp(ppc)(instr)\n");
   11870       return False;
   11871    }
   11872 
   11873    switch (opc2) {
   11874    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   11875       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11876                                       vD_addr, vA_addr, vB_addr);
   11877       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   11878       break;
   11879 
   11880    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   11881       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11882                                       vD_addr, vA_addr, vB_addr);
   11883       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   11884       break;
   11885 
   11886    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   11887       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11888                                       vD_addr, vA_addr, vB_addr);
   11889       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   11890       break;
   11891 
   11892    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   11893       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11894                                       vD_addr, vA_addr, vB_addr);
   11895       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   11896       break;
   11897 
   11898    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   11899       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11900                                       vD_addr, vA_addr, vB_addr);
   11901       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   11902       break;
   11903 
   11904    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   11905       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11906                                        vD_addr, vA_addr, vB_addr);
   11907       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   11908       break;
   11909 
   11910    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   11911       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11912                                        vD_addr, vA_addr, vB_addr);
   11913       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   11914       break;
   11915 
   11916    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   11917       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11918                                       vD_addr, vA_addr, vB_addr);
   11919       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   11920       break;
   11921 
   11922    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   11923       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   11924                                       vD_addr, vA_addr, vB_addr);
   11925       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   11926       break;
   11927 
   11928    default:
   11929       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   11930       return False;
   11931    }
   11932 
   11933    putVReg( vD_addr, mkexpr(vD) );
   11934 
   11935    if (flag_rC) {
   11936       set_AV_CR6( mkexpr(vD), True );
   11937    }
   11938    return True;
   11939 }
   11940 
   11941 /*
   11942   AltiVec Multiply-Sum Instructions
   11943 */
   11944 static Bool dis_av_multarith ( UInt theInstr )
   11945 {
   11946    /* VA-Form */
   11947    UChar opc1     = ifieldOPC(theInstr);
   11948    UChar vD_addr  = ifieldRegDS(theInstr);
   11949    UChar vA_addr  = ifieldRegA(theInstr);
   11950    UChar vB_addr  = ifieldRegB(theInstr);
   11951    UChar vC_addr  = ifieldRegC(theInstr);
   11952    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   11953 
   11954    IRTemp vA    = newTemp(Ity_V128);
   11955    IRTemp vB    = newTemp(Ity_V128);
   11956    IRTemp vC    = newTemp(Ity_V128);
   11957    IRTemp zeros = newTemp(Ity_V128);
   11958    IRTemp aLo   = newTemp(Ity_V128);
   11959    IRTemp bLo   = newTemp(Ity_V128);
   11960    IRTemp cLo   = newTemp(Ity_V128);
   11961    IRTemp zLo   = newTemp(Ity_V128);
   11962    IRTemp aHi   = newTemp(Ity_V128);
   11963    IRTemp bHi   = newTemp(Ity_V128);
   11964    IRTemp cHi   = newTemp(Ity_V128);
   11965    IRTemp zHi   = newTemp(Ity_V128);
   11966    IRTemp abEvn = newTemp(Ity_V128);
   11967    IRTemp abOdd = newTemp(Ity_V128);
   11968    IRTemp z3    = newTemp(Ity_I64);
   11969    IRTemp z2    = newTemp(Ity_I64);
   11970    IRTemp z1    = newTemp(Ity_I64);
   11971    IRTemp z0    = newTemp(Ity_I64);
   11972    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   11973    IRTemp c3, c2, c1, c0;
   11974 
   11975    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   11976    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   11977 
   11978    assign( vA, getVReg(vA_addr));
   11979    assign( vB, getVReg(vB_addr));
   11980    assign( vC, getVReg(vC_addr));
   11981    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   11982 
   11983    if (opc1 != 0x4) {
   11984       vex_printf("dis_av_multarith(ppc)(instr)\n");
   11985       return False;
   11986    }
   11987 
   11988    switch (opc2) {
   11989    /* Multiply-Add */
   11990    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   11991       IRTemp cSigns = newTemp(Ity_V128);
   11992       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   11993           vD_addr, vA_addr, vB_addr, vC_addr);
   11994       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   11995       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   11996       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   11997       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   11998       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   11999       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   12000       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   12001 
   12002       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   12003                          binop(Iop_SarN32x4,
   12004                                binop(Iop_MullEven16Sx8,
   12005                                      mkexpr(aLo), mkexpr(bLo)),
   12006                                mkU8(15))) );
   12007 
   12008       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   12009                          binop(Iop_SarN32x4,
   12010                                binop(Iop_MullEven16Sx8,
   12011                                      mkexpr(aHi), mkexpr(bHi)),
   12012                                mkU8(15))) );
   12013 
   12014       putVReg( vD_addr,
   12015                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   12016       break;
   12017    }
   12018    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   12019       IRTemp zKonst = newTemp(Ity_V128);
   12020       IRTemp cSigns = newTemp(Ity_V128);
   12021       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   12022           vD_addr, vA_addr, vB_addr, vC_addr);
   12023       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   12024       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   12025       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   12026       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   12027       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   12028       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   12029       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   12030 
   12031       /* shifting our const avoids store/load version of Dup */
   12032       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   12033                             mkU8(14)) );
   12034 
   12035       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   12036                          binop(Iop_SarN32x4,
   12037                                binop(Iop_Add32x4, mkexpr(zKonst),
   12038                                      binop(Iop_MullEven16Sx8,
   12039                                            mkexpr(aLo), mkexpr(bLo))),
   12040                                mkU8(15))) );
   12041 
   12042       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   12043                          binop(Iop_SarN32x4,
   12044                                binop(Iop_Add32x4, mkexpr(zKonst),
   12045                                      binop(Iop_MullEven16Sx8,
   12046                                            mkexpr(aHi), mkexpr(bHi))),
   12047                                mkU8(15))) );
   12048 
   12049       putVReg( vD_addr,
   12050                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   12051       break;
   12052    }
   12053    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   12054       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   12055           vD_addr, vA_addr, vB_addr, vC_addr);
   12056       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   12057       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   12058       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   12059       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   12060       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   12061       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   12062       assign(zLo, binop(Iop_Add32x4,
   12063                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   12064                      mkexpr(cLo)) );
   12065       assign(zHi, binop(Iop_Add32x4,
   12066                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   12067                      mkexpr(cHi)));
   12068       putVReg( vD_addr,
   12069                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   12070       break;
   12071    }
   12072 
   12073 
   12074    /* Multiply-Sum */
   12075    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   12076       IRTemp abEE, abEO, abOE, abOO;
   12077       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   12078       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   12079           vD_addr, vA_addr, vB_addr, vC_addr);
   12080 
   12081       /* multiply vA,vB (unsigned, widening) */
   12082       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   12083       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   12084 
   12085       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   12086       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   12087       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   12088 
   12089       putVReg( vD_addr,
   12090          binop(Iop_Add32x4, mkexpr(vC),
   12091                binop(Iop_Add32x4,
   12092                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   12093                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   12094       break;
   12095    }
   12096    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   12097       IRTemp aEvn, aOdd, bEvn, bOdd;
   12098       IRTemp abEE = newTemp(Ity_V128);
   12099       IRTemp abEO = newTemp(Ity_V128);
   12100       IRTemp abOE = newTemp(Ity_V128);
   12101       IRTemp abOO = newTemp(Ity_V128);
   12102       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   12103       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   12104           vD_addr, vA_addr, vB_addr, vC_addr);
   12105 
   12106       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   12107          (separating out adjacent lanes to different vectors) */
   12108       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   12109       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   12110 
   12111       /* multiply vA, vB, again separating adjacent lanes */
   12112       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   12113       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   12114       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   12115       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   12116 
   12117       /* add results together, + vC */
   12118       putVReg( vD_addr,
   12119          binop(Iop_QAdd32Sx4, mkexpr(vC),
   12120                binop(Iop_QAdd32Sx4,
   12121                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   12122                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   12123       break;
   12124    }
   12125    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   12126       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   12127           vD_addr, vA_addr, vB_addr, vC_addr);
   12128       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   12129       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   12130       putVReg( vD_addr,
   12131          binop(Iop_Add32x4, mkexpr(vC),
   12132                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   12133       break;
   12134    }
   12135    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   12136       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   12137           vD_addr, vA_addr, vB_addr, vC_addr);
   12138       /* widening multiply, separating lanes */
   12139       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   12140       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   12141 
   12142       /* break V128 to 4xI32's, zero-extending to I64's */
   12143       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   12144       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   12145       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   12146 
   12147       /* add lanes */
   12148       assign( z3, binop(Iop_Add64, mkexpr(c3),
   12149                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   12150       assign( z2, binop(Iop_Add64, mkexpr(c2),
   12151                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   12152       assign( z1, binop(Iop_Add64, mkexpr(c1),
   12153                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   12154       assign( z0, binop(Iop_Add64, mkexpr(c0),
   12155                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   12156 
   12157       /* saturate-narrow to 32bit, and combine to V128 */
   12158       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   12159                                          mkexpr(z1), mkexpr(z0)) );
   12160 
   12161       break;
   12162    }
   12163    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   12164       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   12165           vD_addr, vA_addr, vB_addr, vC_addr);
   12166       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   12167       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   12168       putVReg( vD_addr,
   12169          binop(Iop_Add32x4, mkexpr(vC),
   12170                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   12171       break;
   12172    }
   12173    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   12174       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   12175           vD_addr, vA_addr, vB_addr, vC_addr);
   12176       /* widening multiply, separating lanes */
   12177       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   12178       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   12179 
   12180       /* break V128 to 4xI32's, sign-extending to I64's */
   12181       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   12182       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   12183       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   12184 
   12185       /* add lanes */
   12186       assign( z3, binop(Iop_Add64, mkexpr(c3),
   12187                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   12188       assign( z2, binop(Iop_Add64, mkexpr(c2),
   12189                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   12190       assign( z1, binop(Iop_Add64, mkexpr(c1),
   12191                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   12192       assign( z0, binop(Iop_Add64, mkexpr(c0),
   12193                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   12194 
   12195       /* saturate-narrow to 32bit, and combine to V128 */
   12196       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   12197                                          mkexpr(z1), mkexpr(z0)) );
   12198       break;
   12199    }
   12200    default:
   12201       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   12202       return False;
   12203    }
   12204    return True;
   12205 }
   12206 
   12207 /*
   12208   AltiVec Shift/Rotate Instructions
   12209 */
   12210 static Bool dis_av_shift ( UInt theInstr )
   12211 {
   12212    /* VX-Form */
   12213    UChar opc1    = ifieldOPC(theInstr);
   12214    UChar vD_addr = ifieldRegDS(theInstr);
   12215    UChar vA_addr = ifieldRegA(theInstr);
   12216    UChar vB_addr = ifieldRegB(theInstr);
   12217    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   12218 
   12219    IRTemp vA = newTemp(Ity_V128);
   12220    IRTemp vB = newTemp(Ity_V128);
   12221    assign( vA, getVReg(vA_addr));
   12222    assign( vB, getVReg(vB_addr));
   12223 
   12224    if (opc1 != 0x4){
   12225       vex_printf("dis_av_shift(ppc)(instr)\n");
   12226       return False;
   12227    }
   12228 
   12229    switch (opc2) {
   12230    /* Rotate */
   12231    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   12232       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12233       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   12234       break;
   12235 
   12236    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   12237       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12238       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   12239       break;
   12240 
   12241    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   12242       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12243       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   12244       break;
   12245 
   12246 
   12247    /* Shift Left */
   12248    case 0x104: // vslb (Shift Left Integer B, AV p240)
   12249       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12250       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   12251       break;
   12252 
   12253    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   12254       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12255       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   12256       break;
   12257 
   12258    case 0x184: // vslw (Shift Left Integer W, AV p244)
   12259       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12260       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   12261       break;
   12262 
   12263    case 0x1C4: { // vsl (Shift Left, AV p239)
   12264       IRTemp sh = newTemp(Ity_I8);
   12265       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12266       assign( sh, binop(Iop_And8, mkU8(0x7),
   12267                         unop(Iop_32to8,
   12268                              unop(Iop_V128to32, mkexpr(vB)))) );
   12269       putVReg( vD_addr,
   12270                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   12271       break;
   12272    }
   12273    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   12274       IRTemp sh = newTemp(Ity_I8);
   12275       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12276       assign( sh, binop(Iop_And8, mkU8(0x78),
   12277                         unop(Iop_32to8,
   12278                              unop(Iop_V128to32, mkexpr(vB)))) );
   12279       putVReg( vD_addr,
   12280                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   12281       break;
   12282    }
   12283 
   12284 
   12285    /* Shift Right */
   12286    case 0x204: // vsrb (Shift Right B, AV p256)
   12287       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12288       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   12289       break;
   12290 
   12291    case 0x244: // vsrh (Shift Right HW, AV p257)
   12292       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12293       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   12294       break;
   12295 
   12296    case 0x284: // vsrw (Shift Right W, AV p259)
   12297       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12298       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   12299       break;
   12300 
   12301    case 0x2C4: { // vsr (Shift Right, AV p251)
   12302       IRTemp sh = newTemp(Ity_I8);
   12303       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12304       assign( sh, binop(Iop_And8, mkU8(0x7),
   12305                         unop(Iop_32to8,
   12306                              unop(Iop_V128to32, mkexpr(vB)))) );
   12307       putVReg( vD_addr,
   12308                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   12309       break;
   12310    }
   12311    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   12312       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12313       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   12314       break;
   12315 
   12316    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   12317       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12318       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   12319       break;
   12320 
   12321    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   12322       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12323       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   12324       break;
   12325 
   12326    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   12327       IRTemp sh = newTemp(Ity_I8);
   12328       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12329       assign( sh, binop(Iop_And8, mkU8(0x78),
   12330                         unop(Iop_32to8,
   12331                              unop(Iop_V128to32, mkexpr(vB)))) );
   12332       putVReg( vD_addr,
   12333                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   12334       break;
   12335    }
   12336 
   12337    default:
   12338       vex_printf("dis_av_shift(ppc)(opc2)\n");
   12339       return False;
   12340    }
   12341    return True;
   12342 }
   12343 
   12344 /*
   12345   AltiVec Permute Instructions
   12346 */
   12347 static Bool dis_av_permute ( UInt theInstr )
   12348 {
   12349    /* VA-Form, VX-Form */
   12350    UChar opc1      = ifieldOPC(theInstr);
   12351    UChar vD_addr   = ifieldRegDS(theInstr);
   12352    UChar vA_addr   = ifieldRegA(theInstr);
   12353    UChar UIMM_5    = vA_addr;
   12354    UChar vB_addr   = ifieldRegB(theInstr);
   12355    UChar vC_addr   = ifieldRegC(theInstr);
   12356    UChar b10       = ifieldBIT10(theInstr);
   12357    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   12358    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   12359 
   12360    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   12361 
   12362    IRTemp vA = newTemp(Ity_V128);
   12363    IRTemp vB = newTemp(Ity_V128);
   12364    IRTemp vC = newTemp(Ity_V128);
   12365    assign( vA, getVReg(vA_addr));
   12366    assign( vB, getVReg(vB_addr));
   12367    assign( vC, getVReg(vC_addr));
   12368 
   12369    if (opc1 != 0x4) {
   12370       vex_printf("dis_av_permute(ppc)(instr)\n");
   12371       return False;
   12372    }
   12373 
   12374    switch (opc2) {
   12375    case 0x2A: // vsel (Conditional Select, AV p238)
   12376       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   12377       /* vD = (vA & ~vC) | (vB & vC) */
   12378       putVReg( vD_addr, binop(Iop_OrV128,
   12379          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   12380          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   12381       return True;
   12382 
   12383    case 0x2B: { // vperm (Permute, AV p218)
   12384       /* limited to two args for IR, so have to play games... */
   12385       IRTemp a_perm  = newTemp(Ity_V128);
   12386       IRTemp b_perm  = newTemp(Ity_V128);
   12387       IRTemp mask    = newTemp(Ity_V128);
   12388       IRTemp vC_andF = newTemp(Ity_V128);
   12389       DIP("vperm v%d,v%d,v%d,v%d\n",
   12390           vD_addr, vA_addr, vB_addr, vC_addr);
   12391       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   12392          IR specifies, and also to hide irrelevant bits from
   12393          memcheck */
   12394       assign( vC_andF,
   12395               binop(Iop_AndV128, mkexpr(vC),
   12396                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   12397       assign( a_perm,
   12398               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   12399       assign( b_perm,
   12400               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   12401       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   12402       assign( mask, binop(Iop_SarN8x16,
   12403                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   12404                           mkU8(7)) );
   12405       // dst = (a & ~mask) | (b & mask)
   12406       putVReg( vD_addr, binop(Iop_OrV128,
   12407                               binop(Iop_AndV128, mkexpr(a_perm),
   12408                                     unop(Iop_NotV128, mkexpr(mask))),
   12409                               binop(Iop_AndV128, mkexpr(b_perm),
   12410                                     mkexpr(mask))) );
   12411       return True;
   12412    }
   12413    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   12414       if (b10 != 0) {
   12415          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   12416          return False;
   12417       }
   12418       DIP("vsldoi v%d,v%d,v%d,%d\n",
   12419           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   12420       if (SHB_uimm4 == 0)
   12421          putVReg( vD_addr, mkexpr(vA) );
   12422       else
   12423          putVReg( vD_addr,
   12424             binop(Iop_OrV128,
   12425                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   12426                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   12427       return True;
   12428 
   12429    default:
   12430      break; // Fall through...
   12431    }
   12432 
   12433    opc2 = IFIELD( theInstr, 0, 11 );
   12434    switch (opc2) {
   12435 
   12436    /* Merge */
   12437    case 0x00C: // vmrghb (Merge High B, AV p195)
   12438       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12439       putVReg( vD_addr,
   12440                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   12441       break;
   12442 
   12443    case 0x04C: // vmrghh (Merge High HW, AV p196)
   12444       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12445       putVReg( vD_addr,
   12446                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   12447       break;
   12448 
   12449    case 0x08C: // vmrghw (Merge High W, AV p197)
   12450       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12451       putVReg( vD_addr,
   12452                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   12453       break;
   12454 
   12455    case 0x10C: // vmrglb (Merge Low B, AV p198)
   12456       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12457       putVReg( vD_addr,
   12458                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   12459       break;
   12460 
   12461    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   12462       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12463       putVReg( vD_addr,
   12464                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   12465       break;
   12466 
   12467    case 0x18C: // vmrglw (Merge Low W, AV p200)
   12468       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12469       putVReg( vD_addr,
   12470                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   12471       break;
   12472 
   12473 
   12474    /* Splat */
   12475    case 0x20C: { // vspltb (Splat Byte, AV p245)
   12476       /* vD = Dup8x16( vB[UIMM_5] ) */
   12477       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   12478       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   12479       putVReg( vD_addr, unop(Iop_Dup8x16,
   12480            unop(Iop_32to8, unop(Iop_V128to32,
   12481                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   12482       break;
   12483    }
   12484    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   12485       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   12486       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   12487       putVReg( vD_addr, unop(Iop_Dup16x8,
   12488            unop(Iop_32to16, unop(Iop_V128to32,
   12489                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   12490       break;
   12491    }
   12492    case 0x28C: { // vspltw (Splat Word, AV p250)
   12493       /* vD = Dup32x4( vB[UIMM_5] ) */
   12494       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   12495       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   12496       putVReg( vD_addr, unop(Iop_Dup32x4,
   12497          unop(Iop_V128to32,
   12498               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   12499       break;
   12500    }
   12501    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   12502       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   12503       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   12504       break;
   12505 
   12506    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   12507       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   12508       putVReg( vD_addr,
   12509                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   12510       break;
   12511 
   12512    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   12513       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   12514       putVReg( vD_addr,
   12515                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   12516       break;
   12517 
   12518    default:
   12519       vex_printf("dis_av_permute(ppc)(opc2)\n");
   12520       return False;
   12521    }
   12522    return True;
   12523 }
   12524 
   12525 /*
   12526   AltiVec Pack/Unpack Instructions
   12527 */
   12528 static Bool dis_av_pack ( UInt theInstr )
   12529 {
   12530    /* VX-Form */
   12531    UChar opc1     = ifieldOPC(theInstr);
   12532    UChar vD_addr  = ifieldRegDS(theInstr);
   12533    UChar vA_addr  = ifieldRegA(theInstr);
   12534    UChar vB_addr  = ifieldRegB(theInstr);
   12535    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   12536 
   12537    IRTemp signs = IRTemp_INVALID;
   12538    IRTemp zeros = IRTemp_INVALID;
   12539    IRTemp vA    = newTemp(Ity_V128);
   12540    IRTemp vB    = newTemp(Ity_V128);
   12541    assign( vA, getVReg(vA_addr));
   12542    assign( vB, getVReg(vB_addr));
   12543 
   12544    if (opc1 != 0x4) {
   12545       vex_printf("dis_av_pack(ppc)(instr)\n");
   12546       return False;
   12547    }
   12548 
   12549    switch (opc2) {
   12550    /* Packing */
   12551    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   12552       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12553       putVReg( vD_addr,
   12554                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   12555       return True;
   12556 
   12557    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   12558       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12559       putVReg( vD_addr,
   12560                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   12561       return True;
   12562 
   12563    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   12564       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12565       putVReg( vD_addr,
   12566                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   12567       // TODO: set VSCR[SAT]
   12568       return True;
   12569 
   12570    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   12571       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12572       putVReg( vD_addr,
   12573                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   12574       // TODO: set VSCR[SAT]
   12575       return True;
   12576 
   12577    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   12578       // This insn does a signed->unsigned saturating conversion.
   12579       // Conversion done here, then uses unsigned->unsigned vpk insn:
   12580       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   12581       IRTemp vA_tmp = newTemp(Ity_V128);
   12582       IRTemp vB_tmp = newTemp(Ity_V128);
   12583       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12584       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   12585                             unop(Iop_NotV128,
   12586                                  binop(Iop_SarN16x8,
   12587                                        mkexpr(vA), mkU8(15)))) );
   12588       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   12589                             unop(Iop_NotV128,
   12590                                  binop(Iop_SarN16x8,
   12591                                        mkexpr(vB), mkU8(15)))) );
   12592       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   12593                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   12594       // TODO: set VSCR[SAT]
   12595       return True;
   12596    }
   12597    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   12598       // This insn does a signed->unsigned saturating conversion.
   12599       // Conversion done here, then uses unsigned->unsigned vpk insn:
   12600       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   12601       IRTemp vA_tmp = newTemp(Ity_V128);
   12602       IRTemp vB_tmp = newTemp(Ity_V128);
   12603       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12604       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   12605                             unop(Iop_NotV128,
   12606                                  binop(Iop_SarN32x4,
   12607                                        mkexpr(vA), mkU8(31)))) );
   12608       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   12609                             unop(Iop_NotV128,
   12610                                  binop(Iop_SarN32x4,
   12611                                        mkexpr(vB), mkU8(31)))) );
   12612       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   12613                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   12614       // TODO: set VSCR[SAT]
   12615       return True;
   12616    }
   12617    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   12618       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12619       putVReg( vD_addr,
   12620                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   12621       // TODO: set VSCR[SAT]
   12622       return True;
   12623 
   12624    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   12625       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12626       putVReg( vD_addr,
   12627                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   12628       // TODO: set VSCR[SAT]
   12629       return True;
   12630 
   12631    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   12632       /* CAB: Worth a new primop? */
   12633       /* Using shifts to compact pixel elements, then packing them */
   12634       IRTemp a1 = newTemp(Ity_V128);
   12635       IRTemp a2 = newTemp(Ity_V128);
   12636       IRTemp a3 = newTemp(Ity_V128);
   12637       IRTemp a_tmp = newTemp(Ity_V128);
   12638       IRTemp b1 = newTemp(Ity_V128);
   12639       IRTemp b2 = newTemp(Ity_V128);
   12640       IRTemp b3 = newTemp(Ity_V128);
   12641       IRTemp b_tmp = newTemp(Ity_V128);
   12642       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12643       assign( a1, binop(Iop_ShlN16x8,
   12644                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   12645                         mkU8(10)) );
   12646       assign( a2, binop(Iop_ShlN16x8,
   12647                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   12648                         mkU8(5)) );
   12649       assign( a3,  binop(Iop_ShrN16x8,
   12650                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   12651                          mkU8(11)) );
   12652       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   12653                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   12654 
   12655       assign( b1, binop(Iop_ShlN16x8,
   12656                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   12657                         mkU8(10)) );
   12658       assign( b2, binop(Iop_ShlN16x8,
   12659                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   12660                         mkU8(5)) );
   12661       assign( b3,  binop(Iop_ShrN16x8,
   12662                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   12663                          mkU8(11)) );
   12664       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   12665                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   12666 
   12667       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   12668                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   12669       return True;
   12670    }
   12671 
   12672    default:
   12673       break; // Fall through...
   12674    }
   12675 
   12676 
   12677    if (vA_addr != 0) {
   12678       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   12679       return False;
   12680    }
   12681 
   12682    signs = newTemp(Ity_V128);
   12683    zeros = newTemp(Ity_V128);
   12684    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   12685 
   12686    switch (opc2) {
   12687    /* Unpacking */
   12688    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   12689       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   12690       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   12691       putVReg( vD_addr,
   12692                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   12693       break;
   12694    }
   12695    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   12696       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   12697       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   12698       putVReg( vD_addr,
   12699                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   12700       break;
   12701    }
   12702    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   12703       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   12704       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   12705       putVReg( vD_addr,
   12706                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   12707       break;
   12708    }
   12709    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   12710       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   12711       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   12712       putVReg( vD_addr,
   12713                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   12714       break;
   12715    }
   12716    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   12717       /* CAB: Worth a new primop? */
   12718       /* Using shifts to isolate pixel elements, then expanding them */
   12719       IRTemp z0  = newTemp(Ity_V128);
   12720       IRTemp z1  = newTemp(Ity_V128);
   12721       IRTemp z01 = newTemp(Ity_V128);
   12722       IRTemp z2  = newTemp(Ity_V128);
   12723       IRTemp z3  = newTemp(Ity_V128);
   12724       IRTemp z23 = newTemp(Ity_V128);
   12725       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   12726       assign( z0,  binop(Iop_ShlN16x8,
   12727                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   12728                          mkU8(8)) );
   12729       assign( z1,  binop(Iop_ShrN16x8,
   12730                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   12731                          mkU8(11)) );
   12732       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   12733                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   12734       assign( z2,  binop(Iop_ShrN16x8,
   12735                          binop(Iop_ShlN16x8,
   12736                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   12737                                mkU8(11)),
   12738                          mkU8(3)) );
   12739       assign( z3,  binop(Iop_ShrN16x8,
   12740                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   12741                          mkU8(11)) );
   12742       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   12743                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   12744       putVReg( vD_addr,
   12745                binop(Iop_OrV128,
   12746                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   12747                      mkexpr(z23)) );
   12748       break;
   12749    }
   12750    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   12751       /* identical to vupkhpx, except interleaving LO */
   12752       IRTemp z0  = newTemp(Ity_V128);
   12753       IRTemp z1  = newTemp(Ity_V128);
   12754       IRTemp z01 = newTemp(Ity_V128);
   12755       IRTemp z2  = newTemp(Ity_V128);
   12756       IRTemp z3  = newTemp(Ity_V128);
   12757       IRTemp z23 = newTemp(Ity_V128);
   12758       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   12759       assign( z0,  binop(Iop_ShlN16x8,
   12760                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   12761                          mkU8(8)) );
   12762       assign( z1,  binop(Iop_ShrN16x8,
   12763                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   12764                          mkU8(11)) );
   12765       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   12766                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   12767       assign( z2,  binop(Iop_ShrN16x8,
   12768                          binop(Iop_ShlN16x8,
   12769                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   12770                                mkU8(11)),
   12771                          mkU8(3)) );
   12772       assign( z3,  binop(Iop_ShrN16x8,
   12773                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   12774                          mkU8(11)) );
   12775       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   12776                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   12777       putVReg( vD_addr,
   12778                binop(Iop_OrV128,
   12779                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   12780                      mkexpr(z23)) );
   12781       break;
   12782    }
   12783    default:
   12784       vex_printf("dis_av_pack(ppc)(opc2)\n");
   12785       return False;
   12786    }
   12787    return True;
   12788 }
   12789 
   12790 
   12791 /*
   12792   AltiVec Floating Point Arithmetic Instructions
   12793 */
   12794 static Bool dis_av_fp_arith ( UInt theInstr )
   12795 {
   12796    /* VA-Form */
   12797    UChar opc1     = ifieldOPC(theInstr);
   12798    UChar vD_addr  = ifieldRegDS(theInstr);
   12799    UChar vA_addr  = ifieldRegA(theInstr);
   12800    UChar vB_addr  = ifieldRegB(theInstr);
   12801    UChar vC_addr  = ifieldRegC(theInstr);
   12802    UInt  opc2=0;
   12803 
   12804    IRTemp vA = newTemp(Ity_V128);
   12805    IRTemp vB = newTemp(Ity_V128);
   12806    IRTemp vC = newTemp(Ity_V128);
   12807    assign( vA, getVReg(vA_addr));
   12808    assign( vB, getVReg(vB_addr));
   12809    assign( vC, getVReg(vC_addr));
   12810 
   12811    if (opc1 != 0x4) {
   12812       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   12813       return False;
   12814    }
   12815 
   12816    opc2 = IFIELD( theInstr, 0, 6 );
   12817    switch (opc2) {
   12818    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   12819       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   12820           vD_addr, vA_addr, vC_addr, vB_addr);
   12821       putVReg( vD_addr,
   12822                binop(Iop_Add32Fx4, mkexpr(vB),
   12823                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   12824       return True;
   12825 
   12826    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   12827       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   12828           vD_addr, vA_addr, vC_addr, vB_addr);
   12829       putVReg( vD_addr,
   12830                binop(Iop_Sub32Fx4,
   12831                      mkexpr(vB),
   12832                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   12833       return True;
   12834    }
   12835 
   12836    default:
   12837      break; // Fall through...
   12838    }
   12839 
   12840    opc2 = IFIELD( theInstr, 0, 11 );
   12841    switch (opc2) {
   12842    case 0x00A: // vaddfp (Add FP, AV p137)
   12843       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12844       putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
   12845       return True;
   12846 
   12847   case 0x04A: // vsubfp (Subtract FP, AV p261)
   12848       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12849       putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
   12850       return True;
   12851 
   12852    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   12853       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12854       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   12855       return True;
   12856 
   12857    case 0x44A: // vminfp (Minimum FP, AV p187)
   12858       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   12859       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   12860       return True;
   12861 
   12862    default:
   12863       break; // Fall through...
   12864    }
   12865 
   12866 
   12867    if (vA_addr != 0) {
   12868       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   12869       return False;
   12870    }
   12871 
   12872    switch (opc2) {
   12873    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   12874       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   12875       putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
   12876       return True;
   12877 
   12878    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   12879       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   12880       putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
   12881       return True;
   12882 
   12883    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   12884       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   12885       DIP(" => not implemented\n");
   12886       return False;
   12887 
   12888    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   12889       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   12890       DIP(" => not implemented\n");
   12891       return False;
   12892 
   12893    default:
   12894       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   12895       return False;
   12896    }
   12897    return True;
   12898 }
   12899 
   12900 /*
   12901   AltiVec Floating Point Compare Instructions
   12902 */
   12903 static Bool dis_av_fp_cmp ( UInt theInstr )
   12904 {
   12905    /* VXR-Form */
   12906    UChar opc1     = ifieldOPC(theInstr);
   12907    UChar vD_addr  = ifieldRegDS(theInstr);
   12908    UChar vA_addr  = ifieldRegA(theInstr);
   12909    UChar vB_addr  = ifieldRegB(theInstr);
   12910    UChar flag_rC  = ifieldBIT10(theInstr);
   12911    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   12912 
   12913    Bool cmp_bounds = False;
   12914 
   12915    IRTemp vA = newTemp(Ity_V128);
   12916    IRTemp vB = newTemp(Ity_V128);
   12917    IRTemp vD = newTemp(Ity_V128);
   12918    assign( vA, getVReg(vA_addr));
   12919    assign( vB, getVReg(vB_addr));
   12920 
   12921    if (opc1 != 0x4) {
   12922       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   12923       return False;
   12924    }
   12925 
   12926    switch (opc2) {
   12927    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   12928       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   12929                                       vD_addr, vA_addr, vB_addr);
   12930       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   12931       break;
   12932 
   12933    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   12934       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   12935                                       vD_addr, vA_addr, vB_addr);
   12936       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   12937       break;
   12938 
   12939    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   12940       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   12941                                       vD_addr, vA_addr, vB_addr);
   12942       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   12943       break;
   12944 
   12945    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   12946       IRTemp gt      = newTemp(Ity_V128);
   12947       IRTemp lt      = newTemp(Ity_V128);
   12948       IRTemp zeros   = newTemp(Ity_V128);
   12949       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   12950                                      vD_addr, vA_addr, vB_addr);
   12951       cmp_bounds = True;
   12952       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   12953 
   12954       /* Note: making use of fact that the ppc backend for compare insns
   12955          return zero'd lanes if either of the corresponding arg lanes is
   12956          a nan.
   12957 
   12958          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   12959          need this for the other compares too (vcmpeqfp etc)...
   12960          Better still, tighten down the spec for compare irops.
   12961        */
   12962       assign( gt, unop(Iop_NotV128,
   12963                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   12964       assign( lt, unop(Iop_NotV128,
   12965                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   12966                              binop(Iop_Sub32Fx4, mkexpr(zeros),
   12967                                                  mkexpr(vB)))) );
   12968 
   12969       // finally, just shift gt,lt to correct position
   12970       assign( vD, binop(Iop_ShlN32x4,
   12971                         binop(Iop_OrV128,
   12972                               binop(Iop_AndV128, mkexpr(gt),
   12973                                     unop(Iop_Dup32x4, mkU32(0x2))),
   12974                               binop(Iop_AndV128, mkexpr(lt),
   12975                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   12976                         mkU8(30)) );
   12977       break;
   12978    }
   12979 
   12980    default:
   12981       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   12982       return False;
   12983    }
   12984 
   12985    putVReg( vD_addr, mkexpr(vD) );
   12986 
   12987    if (flag_rC) {
   12988       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   12989    }
   12990    return True;
   12991 }
   12992 
   12993 /*
   12994   AltiVec Floating Point Convert/Round Instructions
   12995 */
   12996 static Bool dis_av_fp_convert ( UInt theInstr )
   12997 {
   12998    /* VX-Form */
   12999    UChar opc1     = ifieldOPC(theInstr);
   13000    UChar vD_addr  = ifieldRegDS(theInstr);
   13001    UChar UIMM_5   = ifieldRegA(theInstr);
   13002    UChar vB_addr  = ifieldRegB(theInstr);
   13003    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   13004 
   13005    IRTemp vB        = newTemp(Ity_V128);
   13006    IRTemp vScale    = newTemp(Ity_V128);
   13007    IRTemp vInvScale = newTemp(Ity_V128);
   13008 
   13009    float scale, inv_scale;
   13010 
   13011    assign( vB, getVReg(vB_addr));
   13012 
   13013    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   13014    scale = (float)( (unsigned int) 1<<UIMM_5 );
   13015    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   13016    inv_scale = 1/scale;
   13017    assign( vInvScale,
   13018            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   13019 
   13020    if (opc1 != 0x4) {
   13021       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   13022       return False;
   13023    }
   13024 
   13025    switch (opc2) {
   13026    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   13027       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   13028       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   13029                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   13030                               mkexpr(vInvScale)) );
   13031       return True;
   13032 
   13033    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   13034       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   13035 
   13036       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   13037                               unop(Iop_I32StoFx4, mkexpr(vB)),
   13038                               mkexpr(vInvScale)) );
   13039       return True;
   13040 
   13041    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   13042       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   13043       putVReg( vD_addr,
   13044                unop(Iop_QFtoI32Ux4_RZ,
   13045                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   13046       return True;
   13047 
   13048    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   13049       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   13050       putVReg( vD_addr,
   13051                unop(Iop_QFtoI32Sx4_RZ,
   13052                      binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   13053       return True;
   13054 
   13055    default:
   13056      break;    // Fall through...
   13057    }
   13058 
   13059    if (UIMM_5 != 0) {
   13060       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   13061       return False;
   13062    }
   13063 
   13064    switch (opc2) {
   13065    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   13066       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   13067       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   13068       break;
   13069 
   13070    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   13071       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   13072       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   13073       break;
   13074 
   13075    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   13076       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   13077       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   13078       break;
   13079 
   13080    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   13081       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   13082       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   13083       break;
   13084 
   13085    default:
   13086       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   13087       return False;
   13088    }
   13089    return True;
   13090 }
   13091 
   13092 
   13093 /* The 0x3C primary opcode (VSX category) uses several different forms of
   13094  * extended opcodes:
   13095  *   o XX2-form:
   13096  *      - [10:2] (IBM notation [21:29])
   13097  *   o XX3-form variants:
   13098  *       - variant 1: [10:3] (IBM notation [21:28])
   13099  *       - variant 2: [9:3] (IBM notation [22:28])
   13100  *       - variant 3: [7:3] (IBM notation [24:28])
   13101  *   o XX-4 form:
   13102  *      - [10:6] (IBM notation [21:25])
   13103  *
   13104  * The XX2-form needs bit 0 masked from the standard extended opcode
   13105  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   13106  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   13107  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   13108  * front end since their encoding does not begin at bit 21 like the standard
   13109  * format.
   13110  *
   13111  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   13112  * secondary opcode for such VSX instructions.
   13113  *
   13114 */
   13115 
   13116 
   13117 struct vsx_insn {
   13118    UInt opcode;
   13119    Char * name;
   13120 };
   13121 
   13122 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   13123 static struct vsx_insn vsx_all[] = {
   13124       { 0x8, "xxsldwi" },
   13125       { 0x18, "xxsel" },
   13126       { 0x28, "xxpermdi" },
   13127       { 0x48, "xxmrghw" },
   13128       { 0x80, "xsadddp" },
   13129       { 0x84, "xsmaddadp" },
   13130       { 0x8c, "xscmpudp" },
   13131       { 0x90, "xscvdpuxws" },
   13132       { 0x92, "xsrdpi" },
   13133       { 0x94, "xsrsqrtedp" },
   13134       { 0x96, "xssqrtdp" },
   13135       { 0xa0, "xssubdp" },
   13136       { 0xa4, "xsmaddmdp" },
   13137       { 0xac, "xscmpodp" },
   13138       { 0xb0, "xscvdpsxws" },
   13139       { 0xb2, "xsrdpiz" },
   13140       { 0xb4, "xsredp" },
   13141       { 0xc0, "xsmuldp" },
   13142       { 0xc4, "xsmsubadp" },
   13143       { 0xc8, "xxmrglw" },
   13144       { 0xd2, "xsrdpip" },
   13145       { 0xd4, "xstsqrtdp" },
   13146       { 0xd6, "xsrdpic" },
   13147       { 0xe0, "xsdivdp" },
   13148       { 0xe4, "xsmsubmdp" },
   13149       { 0xf2, "xsrdpim" },
   13150       { 0xf4, "xstdivdp" },
   13151       { 0x100, "xvaddsp" },
   13152       { 0x104, "xvmaddasp" },
   13153       { 0x10c, "xvcmpeqsp" },
   13154       { 0x110, "xvcvspuxws" },
   13155       { 0x112, "xvrspi" },
   13156       { 0x114, "xvrsqrtesp" },
   13157       { 0x116, "xvsqrtsp" },
   13158       { 0x120, "xvsubsp" },
   13159       { 0x124, "xvmaddmsp" },
   13160       { 0x12c, "xvcmpgtsp" },
   13161       { 0x130, "xvcvspsxws" },
   13162       { 0x132, "xvrspiz" },
   13163       { 0x134, "xvresp" },
   13164       { 0x140, "xvmulsp" },
   13165       { 0x144, "xvmsubasp" },
   13166       { 0x148, "xxspltw" },
   13167       { 0x14c, "xvcmpgesp" },
   13168       { 0x150, "xvcvuxwsp" },
   13169       { 0x152, "xvrspip" },
   13170       { 0x154, "xvtsqrtsp" },
   13171       { 0x156, "xvrspic" },
   13172       { 0x160, "xvdivsp" },
   13173       { 0x164, "xvmsubmsp" },
   13174       { 0x170, "xvcvsxwsp" },
   13175       { 0x172, "xvrspim" },
   13176       { 0x174, "xvtdivsp" },
   13177       { 0x180, "xvadddp" },
   13178       { 0x184, "xvmaddadp" },
   13179       { 0x18c, "xvcmpeqdp" },
   13180       { 0x190, "xvcvdpuxws" },
   13181       { 0x192, "xvrdpi" },
   13182       { 0x194, "xvrsqrtedp" },
   13183       { 0x196, "xvsqrtdp" },
   13184       { 0x1a0, "xvsubdp" },
   13185       { 0x1a4, "xvmaddmdp" },
   13186       { 0x1ac, "xvcmpgtdp" },
   13187       { 0x1b0, "xvcvdpsxws" },
   13188       { 0x1b2, "xvrdpiz" },
   13189       { 0x1b4, "xvredp" },
   13190       { 0x1c0, "xvmuldp" },
   13191       { 0x1c4, "xvmsubadp" },
   13192       { 0x1cc, "xvcmpgedp" },
   13193       { 0x1d0, "xvcvuxwdp" },
   13194       { 0x1d2, "xvrdpip" },
   13195       { 0x1d4, "xvtsqrtdp" },
   13196       { 0x1d6, "xvrdpic" },
   13197       { 0x1e0, "xvdivdp" },
   13198       { 0x1e4, "xvmsubmdp" },
   13199       { 0x1f0, "xvcvsxwdp" },
   13200       { 0x1f2, "xvrdpim" },
   13201       { 0x1f4, "xvtdivdp" },
   13202       { 0x208, "xxland" },
   13203       { 0x212, "xscvdpsp" },
   13204       { 0x228, "xxlandc" },
   13205       { 0x248 , "xxlor" },
   13206       { 0x268, "xxlxor" },
   13207       { 0x280, "xsmaxdp" },
   13208       { 0x284, "xsnmaddadp" },
   13209       { 0x288, "xxlnor" },
   13210       { 0x290, "xscvdpuxds" },
   13211       { 0x292, "xscvspdp" },
   13212       { 0x2a0, "xsmindp" },
   13213       { 0x2a4, "xsnmaddmdp" },
   13214       { 0x2b0, "xscvdpsxds" },
   13215       { 0x2b2, "xsabsdp" },
   13216       { 0x2c0, "xscpsgndp" },
   13217       { 0x2c4, "xsnmsubadp" },
   13218       { 0x2d0, "xscvuxddp" },
   13219       { 0x2d2, "xsnabsdp" },
   13220       { 0x2e4, "xsnmsubmdp" },
   13221       { 0x2f0, "xscvsxddp" },
   13222       { 0x2f2, "xsnegdp" },
   13223       { 0x300, "xvmaxsp" },
   13224       { 0x304, "xvnmaddasp" },
   13225       { 0x30c, "xvcmpeqsp." },
   13226       { 0x310, "xvcvspuxds" },
   13227       { 0x312, "xvcvdpsp" },
   13228       { 0x320, "xvminsp" },
   13229       { 0x324, "xvnmaddmsp" },
   13230       { 0x32c, "xvcmpgtsp." },
   13231       { 0x330, "xvcvspsxds" },
   13232       { 0x332, "xvabssp" },
   13233       { 0x340, "xvcpsgnsp" },
   13234       { 0x344, "xvnmsubasp" },
   13235       { 0x34c, "xvcmpgesp." },
   13236       { 0x350, "xvcvuxdsp" },
   13237       { 0x352, "xvnabssp" },
   13238       { 0x364, "xvnmsubmsp" },
   13239       { 0x370, "xvcvsxdsp" },
   13240       { 0x372, "xvnegsp" },
   13241       { 0x380, "xvmaxdp" },
   13242       { 0x384, "xvnmaddadp" },
   13243       { 0x38c, "xvcmpeqdp." },
   13244       { 0x390, "xvcvdpuxds" },
   13245       { 0x392, "xvcvspdp" },
   13246       { 0x3a0, "xvmindp" },
   13247       { 0x3a4, "xvnmaddmdp" },
   13248       { 0x3ac, "xvcmpgtdp." },
   13249       { 0x3b0, "xvcvdpsxds" },
   13250       { 0x3b2, "xvabsdp" },
   13251       { 0x3c0, "xvcpsgndp" },
   13252       { 0x3c4, "xvnmsubadp" },
   13253       { 0x3cc, "xvcmpgedp." },
   13254       { 0x3d0, "xvcvuxddp" },
   13255       { 0x3d2, "xvnabsdp" },
   13256       { 0x3e4, "xvnmsubmdp" },
   13257       { 0x3f0, "xvcvsxddp" },
   13258       { 0x3f2, "xvnegdp" }
   13259 };
   13260 #define VSX_ALL_LEN 135
   13261 
   13262 // ATTENTION: This search function assumes vsx_all array is sorted.
   13263 static Int findVSXextOpCode(UInt opcode)
   13264 {
   13265    Int low, mid, high;
   13266    low = 0;
   13267    high = VSX_ALL_LEN - 1;
   13268    while (low <= high) {
   13269       mid = (low + high)/2;
   13270       if (opcode < vsx_all[mid].opcode)
   13271          high = mid - 1;
   13272       else if (opcode > vsx_all[mid].opcode)
   13273          low = mid + 1;
   13274       else
   13275          return mid;
   13276    }
   13277    return -1;
   13278 }
   13279 
   13280 
   13281 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   13282  * passed, and we then try to match it up with one of the VSX forms
   13283  * below.
   13284  */
   13285 static UInt get_VSX60_opc2(UInt opc2_full)
   13286 {
   13287 #define XX2_MASK 0x000003FE
   13288 #define XX3_1_MASK 0x000003FC
   13289 #define XX3_2_MASK 0x000001FC
   13290 #define XX3_3_MASK 0x0000007C
   13291 #define XX4_MASK 0x00000018
   13292    Int ret;
   13293    UInt vsxExtOpcode = 0;
   13294 
   13295    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
   13296       vsxExtOpcode = vsx_all[ret].opcode;
   13297    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
   13298       vsxExtOpcode = vsx_all[ret].opcode;
   13299    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
   13300       vsxExtOpcode = vsx_all[ret].opcode;
   13301    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
   13302       vsxExtOpcode = vsx_all[ret].opcode;
   13303    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
   13304       vsxExtOpcode = vsx_all[ret].opcode;
   13305 
   13306    return vsxExtOpcode;
   13307 }
   13308 
   13309 /*------------------------------------------------------------*/
   13310 /*--- Disassemble a single instruction                     ---*/
   13311 /*------------------------------------------------------------*/
   13312 
   13313 /* Disassemble a single instruction into IR.  The instruction
   13314    is located in host memory at &guest_code[delta]. */
   13315 
   13316 static
   13317 DisResult disInstr_PPC_WRK (
   13318              Bool         put_IP,
   13319              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   13320              Bool         resteerCisOk,
   13321              void*        callback_opaque,
   13322              Long         delta64,
   13323              VexArchInfo* archinfo,
   13324              VexAbiInfo*  abiinfo
   13325           )
   13326 {
   13327    UChar     opc1;
   13328    UInt      opc2;
   13329    DisResult dres;
   13330    UInt      theInstr;
   13331    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   13332    Bool      allow_F  = False;
   13333    Bool      allow_V  = False;
   13334    Bool      allow_FX = False;
   13335    Bool      allow_GX = False;
   13336    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   13337    UInt      hwcaps = archinfo->hwcaps;
   13338    Long      delta;
   13339 
   13340    /* What insn variants are we supporting today? */
   13341    if (mode64) {
   13342       allow_F  = True;
   13343       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   13344       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   13345       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   13346       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   13347    } else {
   13348       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   13349       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   13350       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   13351       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   13352       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   13353    }
   13354 
   13355    /* The running delta */
   13356    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   13357 
   13358    /* Set result defaults. */
   13359    dres.whatNext   = Dis_Continue;
   13360    dres.len        = 0;
   13361    dres.continueAt = 0;
   13362 
   13363    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   13364       4-aligned.  So just fish the whole thing out of memory right now
   13365       and have done. */
   13366    theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
   13367 
   13368    if (0) vex_printf("insn: 0x%x\n", theInstr);
   13369 
   13370    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   13371 
   13372    /* We may be asked to update the guest CIA before going further. */
   13373    if (put_IP)
   13374       putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   13375 
   13376    /* Spot "Special" instructions (see comment at top of file). */
   13377    {
   13378       UChar* code = (UChar*)(guest_code + delta);
   13379       /* Spot the 16-byte preamble:
   13380          32-bit mode:
   13381             54001800  rlwinm 0,0,3,0,0
   13382             54006800  rlwinm 0,0,13,0,0
   13383             5400E800  rlwinm 0,0,29,0,0
   13384             54009800  rlwinm 0,0,19,0,0
   13385          64-bit mode:
   13386             78001800  rotldi 0,0,3
   13387             78006800  rotldi 0,0,13
   13388             7800E802  rotldi 0,0,61
   13389             78009802  rotldi 0,0,51
   13390       */
   13391       UInt word1 = mode64 ? 0x78001800 : 0x54001800;
   13392       UInt word2 = mode64 ? 0x78006800 : 0x54006800;
   13393       UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
   13394       UInt word4 = mode64 ? 0x78009802 : 0x54009800;
   13395       if (getUIntBigendianly(code+ 0) == word1 &&
   13396           getUIntBigendianly(code+ 4) == word2 &&
   13397           getUIntBigendianly(code+ 8) == word3 &&
   13398           getUIntBigendianly(code+12) == word4) {
   13399          /* Got a "Special" instruction preamble.  Which one is it? */
   13400          if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   13401             /* %R3 = client_request ( %R4 ) */
   13402             DIP("r3 = client_request ( %%r4 )\n");
   13403             delta += 20;
   13404             irsb->next     = mkSzImm( ty, guest_CIA_bbstart + delta );
   13405             irsb->jumpkind = Ijk_ClientReq;
   13406             dres.whatNext  = Dis_StopHere;
   13407             goto decode_success;
   13408          }
   13409          else
   13410          if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   13411             /* %R3 = guest_NRADDR */
   13412             DIP("r3 = guest_NRADDR\n");
   13413             delta += 20;
   13414             dres.len = 20;
   13415             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   13416             goto decode_success;
   13417          }
   13418          else
   13419          if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   13420             /*  branch-and-link-to-noredir %R11 */
   13421             DIP("branch-and-link-to-noredir r11\n");
   13422             delta += 20;
   13423             putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   13424             irsb->next     = getIReg(11);
   13425             irsb->jumpkind = Ijk_NoRedir;
   13426             dres.whatNext  = Dis_StopHere;
   13427             goto decode_success;
   13428          }
   13429          else
   13430          if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   13431             /* %R3 = guest_NRADDR_GPR2 */
   13432             DIP("r3 = guest_NRADDR_GPR2\n");
   13433             delta += 20;
   13434             dres.len = 20;
   13435             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   13436             goto decode_success;
   13437          }
   13438          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   13439             can print the insn following the Special-insn preamble. */
   13440          theInstr = getUIntBigendianly(code+16);
   13441          opc1     = ifieldOPC(theInstr);
   13442          opc2     = ifieldOPClo10(theInstr);
   13443          goto decode_failure;
   13444          /*NOTREACHED*/
   13445       }
   13446    }
   13447 
   13448    opc1 = ifieldOPC(theInstr);
   13449    opc2 = ifieldOPClo10(theInstr);
   13450 
   13451    // Note: all 'reserved' bits must be cleared, else invalid
   13452    switch (opc1) {
   13453 
   13454    /* Integer Arithmetic Instructions */
   13455    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   13456    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   13457       if (dis_int_arith( theInstr )) goto decode_success;
   13458       goto decode_failure;
   13459 
   13460    /* Integer Compare Instructions */
   13461    case 0x0B: case 0x0A: // cmpi, cmpli
   13462       if (dis_int_cmp( theInstr )) goto decode_success;
   13463       goto decode_failure;
   13464 
   13465    /* Integer Logical Instructions */
   13466    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   13467    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   13468       if (dis_int_logic( theInstr )) goto decode_success;
   13469       goto decode_failure;
   13470 
   13471    /* Integer Rotate Instructions */
   13472    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   13473       if (dis_int_rot( theInstr )) goto decode_success;
   13474       goto decode_failure;
   13475 
   13476    /* 64bit Integer Rotate Instructions */
   13477    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   13478       if (dis_int_rot( theInstr )) goto decode_success;
   13479       goto decode_failure;
   13480 
   13481    /* Integer Load Instructions */
   13482    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   13483    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   13484    case 0x20: case 0x21:            // lwz,  lwzu
   13485       if (dis_int_load( theInstr )) goto decode_success;
   13486       goto decode_failure;
   13487 
   13488    /* Integer Store Instructions */
   13489    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   13490    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   13491       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   13492       goto decode_failure;
   13493 
   13494    /* Integer Load and Store Multiple Instructions */
   13495    case 0x2E: case 0x2F: // lmw, stmw
   13496       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   13497       goto decode_failure;
   13498 
   13499    /* Branch Instructions */
   13500    case 0x12: case 0x10: // b, bc
   13501       if (dis_branch(theInstr, abiinfo, &dres,
   13502                                resteerOkFn, callback_opaque))
   13503          goto decode_success;
   13504       goto decode_failure;
   13505 
   13506    /* System Linkage Instructions */
   13507    case 0x11: // sc
   13508       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   13509       goto decode_failure;
   13510 
   13511    /* Trap Instructions */
   13512    case 0x02: case 0x03: // tdi, twi
   13513       if (dis_trapi(theInstr, &dres)) goto decode_success;
   13514       goto decode_failure;
   13515 
   13516    /* Floating Point Load Instructions */
   13517    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   13518    case 0x33:                       // lfdu
   13519       if (!allow_F) goto decode_noF;
   13520       if (dis_fp_load( theInstr )) goto decode_success;
   13521       goto decode_failure;
   13522 
   13523    /* Floating Point Store Instructions */
   13524    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   13525    case 0x37:                       // stfdux
   13526       if (!allow_F) goto decode_noF;
   13527       if (dis_fp_store( theInstr )) goto decode_success;
   13528       goto decode_failure;
   13529 
   13530       /* Floating Point Load Double Pair Instructions */
   13531    case 0x39: case 0x3D:
   13532       if (!allow_F) goto decode_noF;
   13533       if (dis_fp_pair( theInstr )) goto decode_success;
   13534       goto decode_failure;
   13535 
   13536    /* 64bit Integer Loads */
   13537    case 0x3A:  // ld, ldu, lwa
   13538       if (!mode64) goto decode_failure;
   13539       if (dis_int_load( theInstr )) goto decode_success;
   13540       goto decode_failure;
   13541 
   13542    case 0x3B:
   13543       if (!allow_F) goto decode_noF;
   13544       opc2 = ifieldOPClo10(theInstr);
   13545       switch (opc2) {
   13546          case 0x3CE: // fcfidus (implemented as native insn)
   13547             if (!allow_VX)
   13548                goto decode_noVX;
   13549             if (dis_fp_round( theInstr ))
   13550                goto decode_success;
   13551             goto decode_failure;
   13552          case 0x34E: // fcfids
   13553             if (dis_fp_round( theInstr ))
   13554                goto decode_success;
   13555             goto decode_failure;
   13556       }
   13557 
   13558       opc2 = IFIELD(theInstr, 1, 5);
   13559       switch (opc2) {
   13560       /* Floating Point Arith Instructions */
   13561       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   13562       case 0x19:                       // fmuls
   13563          if (dis_fp_arith(theInstr)) goto decode_success;
   13564          goto decode_failure;
   13565       case 0x16:                       // fsqrts
   13566          if (!allow_FX) goto decode_noFX;
   13567          if (dis_fp_arith(theInstr)) goto decode_success;
   13568          goto decode_failure;
   13569       case 0x18:                       // fres
   13570          if (!allow_GX) goto decode_noGX;
   13571          if (dis_fp_arith(theInstr)) goto decode_success;
   13572          goto decode_failure;
   13573 
   13574       /* Floating Point Mult-Add Instructions */
   13575       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   13576       case 0x1F:                       // fnmadds
   13577          if (dis_fp_multadd(theInstr)) goto decode_success;
   13578          goto decode_failure;
   13579 
   13580       case 0x1A:                       // frsqrtes
   13581          if (!allow_GX) goto decode_noGX;
   13582          if (dis_fp_arith(theInstr)) goto decode_success;
   13583          goto decode_failure;
   13584 
   13585       default:
   13586          goto decode_failure;
   13587       }
   13588       break;
   13589 
   13590    case 0x3C: // VSX instructions (except load/store)
   13591    {
   13592       UInt vsxOpc2 = get_VSX60_opc2(opc2);
   13593       /* The vsxOpc2 returned is the "normalized" value, representing the
   13594        * instructions secondary opcode as taken from the standard secondary
   13595        * opcode field [21:30] (IBM notatition), even if the actual field
   13596        * is non-standard.  These normalized values are given in the opcode
   13597        * appendices of the ISA 2.06 document.
   13598        */
   13599       if (vsxOpc2 == 0)
   13600          goto decode_failure;
   13601 
   13602       switch (vsxOpc2) {
   13603          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   13604          case 0x018: case 0x148: // xxsel, xxspltw
   13605             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   13606             goto decode_failure;
   13607          case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
   13608             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   13609             goto decode_failure;
   13610          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   13611          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   13612          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   13613          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   13614          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   13615          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   13616          case 0x092: // xsrdpi
   13617             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
   13618             goto decode_failure;
   13619          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   13620             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   13621             goto decode_failure;
   13622          case 0x080: case 0x0E0: // xsadddp, xsdivdp
   13623          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   13624          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   13625          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   13626          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   13627          case 0x0C0: case 0x0A0: // xsmuldp, xssubdp
   13628          case 0x096: case 0x0F4: // xssqrtdp, xstdivdp
   13629          case 0x0D4: // xstsqrtdp
   13630             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   13631             goto decode_failure;
   13632          case 0x180: // xvadddp
   13633          case 0x1E0: // xvdivdp
   13634          case 0x1C0: // xvmuldp
   13635          case 0x1A0: // xvsubdp
   13636          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   13637          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   13638          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   13639          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   13640          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   13641          case 0x196: // xvsqrtdp
   13642             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   13643             goto decode_failure;
   13644          case 0x100: // xvaddsp
   13645          case 0x160: // xvdivsp
   13646          case 0x140: // xvmulsp
   13647          case 0x120: // xvsubsp
   13648          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   13649          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   13650          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   13651          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   13652          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   13653          case 0x116: // xvsqrtsp
   13654             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   13655             goto decode_failure;
   13656 
   13657          case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
   13658          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   13659          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   13660          case 0x212: case 0x090: // xscvdpsp, xscvdpuxws
   13661          case 0x292: case 0x312: // xscvspdp, xvcvdpsp
   13662          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   13663          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   13664          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   13665          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   13666          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   13667          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   13668          case 0x3d0: case 0x350: // xvcvuxddp, xvcvuxdsp
   13669          case 0x1d0: // xvcvuxwdp
   13670             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   13671             goto decode_failure;
   13672 
   13673          case 0x18C: case 0x38C: // xvcmpeqdp[.]
   13674          case 0x10C: case 0x30C: // xvcmpeqsp[.]
   13675          case 0x14C: case 0x34C: // xvcmpgesp[.]
   13676          case 0x12C: case 0x32C: // xvcmpgtsp[.]
   13677          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
   13678          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
   13679              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   13680              goto decode_failure;
   13681 
   13682          case 0x134:  // xvresp
   13683          case 0x1B4:  // xvredp
   13684          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   13685          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   13686          case 0x300: case 0x320: // xvmaxsp, xvminsp
   13687          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   13688          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   13689          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   13690          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   13691          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   13692          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   13693          case 0x112: case 0x156: // xvrspi, xvrspic
   13694          case 0x172: case 0x152: // xvrspim, xvrspip
   13695          case 0x132: // xvrspiz
   13696             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   13697             goto decode_failure;
   13698 
   13699          default:
   13700             goto decode_failure;
   13701       }
   13702       break;
   13703    }
   13704 
   13705    /* 64bit Integer Stores */
   13706    case 0x3E:  // std, stdu
   13707       if (!mode64) goto decode_failure;
   13708       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   13709       goto decode_failure;
   13710 
   13711    case 0x3F:
   13712       if (!allow_F) goto decode_noF;
   13713       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   13714          so we can simply fall through the first switch statement */
   13715 
   13716       opc2 = IFIELD(theInstr, 1, 5);
   13717       switch (opc2) {
   13718       /* Floating Point Arith Instructions */
   13719       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   13720       case 0x19:                       // fmul
   13721          if (dis_fp_arith(theInstr)) goto decode_success;
   13722          goto decode_failure;
   13723       case 0x16:                       // fsqrt
   13724          if (!allow_FX) goto decode_noFX;
   13725          if (dis_fp_arith(theInstr)) goto decode_success;
   13726          goto decode_failure;
   13727       case 0x17: case 0x1A:            // fsel, frsqrte
   13728          if (!allow_GX) goto decode_noGX;
   13729          if (dis_fp_arith(theInstr)) goto decode_success;
   13730          goto decode_failure;
   13731 
   13732       /* Floating Point Mult-Add Instructions */
   13733       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   13734       case 0x1F:                       // fnmadd
   13735          if (dis_fp_multadd(theInstr)) goto decode_success;
   13736          goto decode_failure;
   13737 
   13738       case 0x18:                       // fre
   13739          if (!allow_GX) goto decode_noGX;
   13740          if (dis_fp_arith(theInstr)) goto decode_success;
   13741          goto decode_failure;
   13742 
   13743       default:
   13744          break; // Fall through
   13745       }
   13746 
   13747       opc2 = IFIELD(theInstr, 1, 10);
   13748       switch (opc2) {
   13749       /* Floating Point Compare Instructions */
   13750       case 0x000: // fcmpu
   13751       case 0x020: // fcmpo
   13752          if (dis_fp_cmp(theInstr)) goto decode_success;
   13753          goto decode_failure;
   13754 
   13755       case 0x080: // ftdiv
   13756       case 0x0A0: // ftsqrt
   13757          if (dis_fp_tests(theInstr)) goto decode_success;
   13758          goto decode_failure;
   13759 
   13760       /* Floating Point Rounding/Conversion Instructions */
   13761       case 0x00C: // frsp
   13762       case 0x00E: // fctiw
   13763       case 0x00F: // fctiwz
   13764       case 0x32E: // fctid
   13765       case 0x32F: // fctidz
   13766       case 0x34E: // fcfid
   13767          if (dis_fp_round(theInstr)) goto decode_success;
   13768          goto decode_failure;
   13769       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   13770       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   13771          if (!allow_VX) goto decode_noVX;
   13772          if (dis_fp_round(theInstr)) goto decode_success;
   13773          goto decode_failure;
   13774 
   13775       /* Power6 rounding stuff */
   13776       case 0x1E8: // frim
   13777       case 0x1C8: // frip
   13778       case 0x188: // frin
   13779       case 0x1A8: // friz
   13780          /* A hack to check for P6 capability . . . */
   13781          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   13782              (dis_fp_round(theInstr)))
   13783             goto decode_success;
   13784          goto decode_failure;
   13785 
   13786       /* Floating Point Move Instructions */
   13787       case 0x008: // fcpsgn
   13788       case 0x028: // fneg
   13789       case 0x048: // fmr
   13790       case 0x088: // fnabs
   13791       case 0x108: // fabs
   13792          if (dis_fp_move( theInstr )) goto decode_success;
   13793          goto decode_failure;
   13794 
   13795       /* Floating Point Status/Control Register Instructions */
   13796       case 0x026: // mtfsb1
   13797       case 0x040: // mcrfs
   13798       case 0x046: // mtfsb0
   13799       case 0x086: // mtfsfi
   13800       case 0x247: // mffs
   13801       case 0x2C7: // mtfsf
   13802          if (dis_fp_scr( theInstr )) goto decode_success;
   13803          goto decode_failure;
   13804 
   13805       default:
   13806          goto decode_failure;
   13807       }
   13808       break;
   13809 
   13810    case 0x13:
   13811       switch (opc2) {
   13812 
   13813       /* Condition Register Logical Instructions */
   13814       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   13815       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   13816       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   13817          if (dis_cond_logic( theInstr )) goto decode_success;
   13818          goto decode_failure;
   13819 
   13820       /* Branch Instructions */
   13821       case 0x210: case 0x010: // bcctr, bclr
   13822          if (dis_branch(theInstr, abiinfo, &dres,
   13823                                   resteerOkFn, callback_opaque))
   13824             goto decode_success;
   13825          goto decode_failure;
   13826 
   13827       /* Memory Synchronization Instructions */
   13828       case 0x096: // isync
   13829          if (dis_memsync( theInstr )) goto decode_success;
   13830          goto decode_failure;
   13831 
   13832       default:
   13833          goto decode_failure;
   13834       }
   13835       break;
   13836 
   13837 
   13838    case 0x1F:
   13839 
   13840       /* For arith instns, bit10 is the OE flag (overflow enable) */
   13841 
   13842       opc2 = IFIELD(theInstr, 1, 9);
   13843       switch (opc2) {
   13844       /* Integer Arithmetic Instructions */
   13845       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   13846       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   13847       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   13848       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   13849       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   13850       case 0x0C8: // subfze
   13851          if (dis_int_arith( theInstr )) goto decode_success;
   13852          goto decode_failure;
   13853 
   13854       case 0x18B: // divweu (implemented as native insn)
   13855       case 0x1AB: // divwe (implemented as native insn)
   13856          if (!allow_VX) goto decode_noVX;
   13857          if (dis_int_arith( theInstr )) goto decode_success;
   13858          goto decode_failure;
   13859 
   13860       /* 64bit Integer Arithmetic */
   13861       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   13862       case 0x1C9: case 0x1E9: // divdu, divd
   13863          if (!mode64) goto decode_failure;
   13864          if (dis_int_arith( theInstr )) goto decode_success;
   13865          goto decode_failure;
   13866 
   13867       case 0x1A9: //  divde (implemented as native insn)
   13868       case 0x189: //  divdeuo (implemented as native insn)
   13869          if (!allow_VX) goto decode_noVX;
   13870          if (!mode64) goto decode_failure;
   13871          if (dis_int_arith( theInstr )) goto decode_success;
   13872          goto decode_failure;
   13873 
   13874       case 0x1FC:                         // cmpb
   13875          if (dis_int_logic( theInstr )) goto decode_success;
   13876          goto decode_failure;
   13877 
   13878       default:
   13879          break;  // Fall through...
   13880       }
   13881 
   13882       /* All remaining opcodes use full 10 bits. */
   13883 
   13884       opc2 = IFIELD(theInstr, 1, 10);
   13885       switch (opc2) {
   13886       /* Integer Compare Instructions  */
   13887       case 0x000: case 0x020: // cmp, cmpl
   13888          if (dis_int_cmp( theInstr )) goto decode_success;
   13889          goto decode_failure;
   13890 
   13891       /* Integer Logical Instructions */
   13892       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   13893       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   13894       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   13895       case 0x19C: case 0x13C:             // orc,  xor
   13896       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   13897          if (dis_int_logic( theInstr )) goto decode_success;
   13898          goto decode_failure;
   13899 
   13900       /* 64bit Integer Logical Instructions */
   13901       case 0x3DA: case 0x03A: // extsw, cntlzd
   13902          if (!mode64) goto decode_failure;
   13903          if (dis_int_logic( theInstr )) goto decode_success;
   13904          goto decode_failure;
   13905 
   13906          /* 64bit Integer Parity Instructions */
   13907       case 0xba: case 0x9a: // prtyd, prtyw
   13908          if (dis_int_parity( theInstr )) goto decode_success;
   13909          goto decode_failure;
   13910 
   13911       /* Integer Shift Instructions */
   13912       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   13913       case 0x218:                         // srw
   13914          if (dis_int_shift( theInstr )) goto decode_success;
   13915          goto decode_failure;
   13916 
   13917       /* 64bit Integer Shift Instructions */
   13918       case 0x01B: case 0x31A: // sld, srad
   13919       case 0x33A: case 0x33B: // sradi
   13920       case 0x21B:             // srd
   13921          if (!mode64) goto decode_failure;
   13922          if (dis_int_shift( theInstr )) goto decode_success;
   13923          goto decode_failure;
   13924 
   13925       /* Integer Load Instructions */
   13926       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   13927       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   13928       case 0x017: case 0x037:             // lwzx,  lwzux
   13929          if (dis_int_load( theInstr )) goto decode_success;
   13930          goto decode_failure;
   13931 
   13932       /* 64bit Integer Load Instructions */
   13933       case 0x035: case 0x015:             // ldux,  ldx
   13934       case 0x175: case 0x155:             // lwaux, lwax
   13935          if (!mode64) goto decode_failure;
   13936          if (dis_int_load( theInstr )) goto decode_success;
   13937          goto decode_failure;
   13938 
   13939       /* Integer Store Instructions */
   13940       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   13941       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   13942          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   13943          goto decode_failure;
   13944 
   13945       /* 64bit Integer Store Instructions */
   13946       case 0x0B5: case 0x095: // stdux, stdx
   13947          if (!mode64) goto decode_failure;
   13948          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   13949          goto decode_failure;
   13950 
   13951       /* Integer Load and Store with Byte Reverse Instructions */
   13952       case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
   13953       case 0x296: case 0x214:             // stwbrx, ldbrx
   13954       case 0x294:                         // stdbrx
   13955          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   13956          goto decode_failure;
   13957 
   13958       /* Integer Load and Store String Instructions */
   13959       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   13960       case 0x295: {                       // stswx
   13961          Bool stopHere = False;
   13962          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   13963          if (!ok) goto decode_failure;
   13964          if (stopHere) {
   13965             irsb->next     = mkSzImm(ty, nextInsnAddr());
   13966             irsb->jumpkind = Ijk_Boring;
   13967             dres.whatNext  = Dis_StopHere;
   13968          }
   13969          goto decode_success;
   13970       }
   13971 
   13972       /* Memory Synchronization Instructions */
   13973       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   13974       case 0x256:                         // sync
   13975          if (dis_memsync( theInstr )) goto decode_success;
   13976          goto decode_failure;
   13977 
   13978       /* 64bit Memory Synchronization Instructions */
   13979       case 0x054: case 0x0D6: // ldarx, stdcx.
   13980          if (!mode64) goto decode_failure;
   13981          if (dis_memsync( theInstr )) goto decode_success;
   13982          goto decode_failure;
   13983 
   13984       /* Processor Control Instructions */
   13985       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   13986       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   13987          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   13988          goto decode_failure;
   13989 
   13990       /* Cache Management Instructions */
   13991       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   13992       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   13993       case 0x3D6:                         // icbi
   13994          if (dis_cache_manage( theInstr, &dres, archinfo ))
   13995             goto decode_success;
   13996          goto decode_failure;
   13997 
   13998 //zz       /* External Control Instructions */
   13999 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   14000 //zz          DIP("external control op => not implemented\n");
   14001 //zz          goto decode_failure;
   14002 
   14003       /* Trap Instructions */
   14004       case 0x004: case 0x044:             // tw,   td
   14005          if (dis_trap(theInstr, &dres)) goto decode_success;
   14006          goto decode_failure;
   14007 
   14008       /* Floating Point Load Instructions */
   14009       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   14010       case 0x277:                         // lfdux
   14011          if (!allow_F) goto decode_noF;
   14012          if (dis_fp_load( theInstr )) goto decode_success;
   14013          goto decode_failure;
   14014 
   14015       /* Floating Point Store Instructions */
   14016       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   14017       case 0x2F7:                         // stfdu, stfiwx
   14018          if (!allow_F) goto decode_noF;
   14019          if (dis_fp_store( theInstr )) goto decode_success;
   14020          goto decode_failure;
   14021       case 0x3D7:                         // stfiwx
   14022          if (!allow_F) goto decode_noF;
   14023          if (!allow_GX) goto decode_noGX;
   14024          if (dis_fp_store( theInstr )) goto decode_success;
   14025          goto decode_failure;
   14026 
   14027          /* Floating Point Double Pair Indexed Instructions */
   14028       case 0x317: // lfdpx (Power6)
   14029       case 0x397: // stfdpx (Power6)
   14030          if (!allow_F) goto decode_noF;
   14031          if (dis_fp_pair(theInstr)) goto decode_success;
   14032          goto decode_failure;
   14033 
   14034       case 0x357:                         // lfiwax
   14035          if (!allow_F) goto decode_noF;
   14036          if (dis_fp_load( theInstr )) goto decode_success;
   14037          goto decode_failure;
   14038 
   14039       case 0x377:                         // lfiwzx
   14040          if (!allow_F) goto decode_noF;
   14041          if (dis_fp_load( theInstr )) goto decode_success;
   14042          goto decode_failure;
   14043 
   14044       /* AltiVec instructions */
   14045 
   14046       /* AV Cache Control - Data streams */
   14047       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   14048          if (!allow_V) goto decode_noV;
   14049          if (dis_av_datastream( theInstr )) goto decode_success;
   14050          goto decode_failure;
   14051 
   14052       /* AV Load */
   14053       case 0x006: case 0x026:             // lvsl, lvsr
   14054       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   14055       case 0x067: case 0x167:             // lvx, lvxl
   14056          if (!allow_V) goto decode_noV;
   14057          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   14058          goto decode_failure;
   14059 
   14060       /* AV Store */
   14061       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   14062       case 0x0E7: case 0x1E7:             // stvx, stvxl
   14063          if (!allow_V) goto decode_noV;
   14064          if (dis_av_store( theInstr )) goto decode_success;
   14065          goto decode_failure;
   14066 
   14067       /* VSX Load */
   14068       case 0x24C: // lxsdx
   14069       case 0x34C: // lxvd2x
   14070       case 0x14C: // lxvdsx
   14071       case 0x30C: // lxvw4x
   14072     	  if (dis_vx_load( theInstr )) goto decode_success;
   14073           goto decode_failure;
   14074 
   14075       /* VSX Store */
   14076       case 0x2CC: // stxsdx
   14077       case 0x3CC: // stxvd2x
   14078       case 0x38C: // stxvw4x
   14079     	  if (dis_vx_store( theInstr )) goto decode_success;
   14080     	  goto decode_failure;
   14081 
   14082       /* Miscellaneous ISA 2.06 instructions */
   14083       case 0x1FA: // popcntd
   14084       case 0x17A: // popcntw
   14085     	  if (dis_int_logic( theInstr )) goto decode_success;
   14086     	  goto decode_failure;
   14087 
   14088       case 0x0FC: // bpermd
   14089          if (dis_int_logic( theInstr )) goto decode_success;
   14090          goto decode_failure;
   14091 
   14092       default:
   14093          /* Deal with some other cases that we would otherwise have
   14094             punted on. */
   14095          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   14096          /* only decode this insn when reserved bit 0 (31 in IBM's
   14097             notation) is zero */
   14098          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   14099             UInt rT = ifieldRegDS( theInstr );
   14100             UInt rA = ifieldRegA( theInstr );
   14101             UInt rB = ifieldRegB( theInstr );
   14102             UInt bi = ifieldRegC( theInstr );
   14103             putIReg(
   14104                rT,
   14105                IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
   14106                              getIReg(rB),
   14107                              rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   14108                                      : getIReg(rA) )
   14109             );
   14110             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   14111             goto decode_success;
   14112          }
   14113          goto decode_failure;
   14114       }
   14115       break;
   14116 
   14117 
   14118    case 0x04:
   14119       /* AltiVec instructions */
   14120 
   14121       opc2 = IFIELD(theInstr, 0, 6);
   14122       switch (opc2) {
   14123       /* AV Mult-Add, Mult-Sum */
   14124       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   14125       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   14126       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   14127          if (!allow_V) goto decode_noV;
   14128          if (dis_av_multarith( theInstr )) goto decode_success;
   14129          goto decode_failure;
   14130 
   14131       /* AV Permutations */
   14132       case 0x2A:                       // vsel
   14133       case 0x2B:                       // vperm
   14134       case 0x2C:                       // vsldoi
   14135          if (!allow_V) goto decode_noV;
   14136          if (dis_av_permute( theInstr )) goto decode_success;
   14137          goto decode_failure;
   14138 
   14139       /* AV Floating Point Mult-Add/Sub */
   14140       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   14141          if (!allow_V) goto decode_noV;
   14142          if (dis_av_fp_arith( theInstr )) goto decode_success;
   14143          goto decode_failure;
   14144 
   14145       default:
   14146          break;  // Fall through...
   14147       }
   14148 
   14149       opc2 = IFIELD(theInstr, 0, 11);
   14150       switch (opc2) {
   14151       /* AV Arithmetic */
   14152       case 0x180:                         // vaddcuw
   14153       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   14154       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   14155       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   14156       case 0x580:                         // vsubcuw
   14157       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   14158       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   14159       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   14160       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   14161       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   14162       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   14163       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   14164       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   14165       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   14166       case 0x008: case 0x048:             // vmuloub, vmulouh
   14167       case 0x108: case 0x148:             // vmulosb, vmulosh
   14168       case 0x208: case 0x248:             // vmuleub, vmuleuh
   14169       case 0x308: case 0x348:             // vmulesb, vmulesh
   14170       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   14171       case 0x688: case 0x788:             // vsum2sws, vsumsws
   14172          if (!allow_V) goto decode_noV;
   14173          if (dis_av_arith( theInstr )) goto decode_success;
   14174          goto decode_failure;
   14175 
   14176       /* AV Rotate, Shift */
   14177       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   14178       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   14179       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   14180       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   14181       case 0x1C4: case 0x2C4:             // vsl, vsr
   14182       case 0x40C: case 0x44C:             // vslo, vsro
   14183          if (!allow_V) goto decode_noV;
   14184          if (dis_av_shift( theInstr )) goto decode_success;
   14185          goto decode_failure;
   14186 
   14187       /* AV Logic */
   14188       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   14189       case 0x4C4: case 0x504:             // vxor, vnor
   14190          if (!allow_V) goto decode_noV;
   14191          if (dis_av_logic( theInstr )) goto decode_success;
   14192          goto decode_failure;
   14193 
   14194       /* AV Processor Control */
   14195       case 0x604: case 0x644:             // mfvscr, mtvscr
   14196          if (!allow_V) goto decode_noV;
   14197          if (dis_av_procctl( theInstr )) goto decode_success;
   14198          goto decode_failure;
   14199 
   14200       /* AV Floating Point Arithmetic */
   14201       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   14202       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   14203       case 0x1CA:                         // vlogefp
   14204       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   14205          if (!allow_V) goto decode_noV;
   14206          if (dis_av_fp_arith( theInstr )) goto decode_success;
   14207          goto decode_failure;
   14208 
   14209       /* AV Floating Point Round/Convert */
   14210       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   14211       case 0x2CA:                         // vrfim
   14212       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   14213       case 0x3CA:                         // vctsxs
   14214          if (!allow_V) goto decode_noV;
   14215          if (dis_av_fp_convert( theInstr )) goto decode_success;
   14216          goto decode_failure;
   14217 
   14218       /* AV Merge, Splat */
   14219       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   14220       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   14221       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   14222       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   14223          if (!allow_V) goto decode_noV;
   14224          if (dis_av_permute( theInstr )) goto decode_success;
   14225          goto decode_failure;
   14226 
   14227       /* AV Pack, Unpack */
   14228       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   14229       case 0x0CE:                         // vpkuwus
   14230       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   14231       case 0x1CE:                         // vpkswss
   14232       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   14233       case 0x2CE:                         // vupklsh
   14234       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   14235          if (!allow_V) goto decode_noV;
   14236          if (dis_av_pack( theInstr )) goto decode_success;
   14237          goto decode_failure;
   14238 
   14239       default:
   14240          break;  // Fall through...
   14241       }
   14242 
   14243       opc2 = IFIELD(theInstr, 0, 10);
   14244       switch (opc2) {
   14245 
   14246       /* AV Compare */
   14247       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   14248       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   14249       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   14250          if (!allow_V) goto decode_noV;
   14251          if (dis_av_cmp( theInstr )) goto decode_success;
   14252          goto decode_failure;
   14253 
   14254       /* AV Floating Point Compare */
   14255       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   14256       case 0x3C6:                         // vcmpbfp
   14257          if (!allow_V) goto decode_noV;
   14258          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   14259          goto decode_failure;
   14260 
   14261       default:
   14262          goto decode_failure;
   14263       }
   14264       break;
   14265 
   14266    default:
   14267       goto decode_failure;
   14268 
   14269    decode_noF:
   14270       vassert(!allow_F);
   14271       vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
   14272       goto decode_failure;
   14273    decode_noV:
   14274       vassert(!allow_V);
   14275       vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
   14276       goto decode_failure;
   14277    decode_noVX:
   14278       vassert(!allow_VX);
   14279       vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
   14280       goto decode_failure;
   14281    decode_noFX:
   14282       vassert(!allow_FX);
   14283       vex_printf("disInstr(ppc): "
   14284                  "declined to decode a GeneralPurpose-Optional insn.\n");
   14285       goto decode_failure;
   14286    decode_noGX:
   14287       vassert(!allow_GX);
   14288       vex_printf("disInstr(ppc): "
   14289                  "declined to decode a Graphics-Optional insn.\n");
   14290       goto decode_failure;
   14291 
   14292    decode_failure:
   14293    /* All decode failures end up here. */
   14294    opc2 = (theInstr) & 0x7FF;
   14295    vex_printf("disInstr(ppc): unhandled instruction: "
   14296               "0x%x\n", theInstr);
   14297    vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   14298               opc1, opc1, opc2, opc2);
   14299 
   14300    /* Tell the dispatcher that this insn cannot be decoded, and so has
   14301       not been executed, and (is currently) the next to be executed.
   14302       CIA should be up-to-date since it made so at the start of each
   14303       insn, but nevertheless be paranoid and update it again right
   14304       now. */
   14305    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   14306    irsb->next     = mkSzImm(ty, guest_CIA_curr_instr);
   14307    irsb->jumpkind = Ijk_NoDecode;
   14308    dres.whatNext  = Dis_StopHere;
   14309    dres.len       = 0;
   14310    return dres;
   14311 
   14312    } /* switch (opc) for the main (primary) opcode switch. */
   14313 
   14314   decode_success:
   14315    /* All decode successes end up here. */
   14316    DIP("\n");
   14317 
   14318    if (dres.len == 0) {
   14319       dres.len = 4;
   14320    } else {
   14321       vassert(dres.len == 20);
   14322    }
   14323    return dres;
   14324 }
   14325 
   14326 #undef DIP
   14327 #undef DIS
   14328 
   14329 
   14330 /*------------------------------------------------------------*/
   14331 /*--- Top-level fn                                         ---*/
   14332 /*------------------------------------------------------------*/
   14333 
   14334 /* Disassemble a single instruction into IR.  The instruction
   14335    is located in host memory at &guest_code[delta]. */
   14336 
   14337 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   14338                          Bool         put_IP,
   14339                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   14340                          Bool         resteerCisOk,
   14341                          void*        callback_opaque,
   14342                          UChar*       guest_code_IN,
   14343                          Long         delta,
   14344                          Addr64       guest_IP,
   14345                          VexArch      guest_arch,
   14346                          VexArchInfo* archinfo,
   14347                          VexAbiInfo*  abiinfo,
   14348                          Bool         host_bigendian_IN )
   14349 {
   14350    IRType     ty;
   14351    DisResult  dres;
   14352    UInt       mask32, mask64;
   14353    UInt hwcaps_guest = archinfo->hwcaps;
   14354 
   14355    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   14356 
   14357    /* global -- ick */
   14358    mode64 = guest_arch == VexArchPPC64;
   14359    ty = mode64 ? Ity_I64 : Ity_I32;
   14360 
   14361    /* do some sanity checks */
   14362    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   14363             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
   14364 
   14365    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   14366 		   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
   14367 
   14368    if (mode64) {
   14369       vassert((hwcaps_guest & mask32) == 0);
   14370    } else {
   14371       vassert((hwcaps_guest & mask64) == 0);
   14372    }
   14373 
   14374    /* Set globals (see top of this file) */
   14375    guest_code           = guest_code_IN;
   14376    irsb                 = irsb_IN;
   14377    host_is_bigendian    = host_bigendian_IN;
   14378 
   14379    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   14380    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   14381 
   14382    dres = disInstr_PPC_WRK ( put_IP,
   14383                              resteerOkFn, resteerCisOk, callback_opaque,
   14384                              delta, archinfo, abiinfo );
   14385 
   14386    return dres;
   14387 }
   14388 
   14389 
   14390 /*------------------------------------------------------------*/
   14391 /*--- Unused stuff                                         ---*/
   14392 /*------------------------------------------------------------*/
   14393 
   14394 ///* A potentially more memcheck-friendly implementation of Clz32, with
   14395 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   14396 //
   14397 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   14398 //{
   14399 //   /* Welcome ... to SSA R Us. */
   14400 //   IRTemp n1  = newTemp(Ity_I32);
   14401 //   IRTemp n2  = newTemp(Ity_I32);
   14402 //   IRTemp n3  = newTemp(Ity_I32);
   14403 //   IRTemp n4  = newTemp(Ity_I32);
   14404 //   IRTemp n5  = newTemp(Ity_I32);
   14405 //   IRTemp n6  = newTemp(Ity_I32);
   14406 //   IRTemp n7  = newTemp(Ity_I32);
   14407 //   IRTemp n8  = newTemp(Ity_I32);
   14408 //   IRTemp n9  = newTemp(Ity_I32);
   14409 //   IRTemp n10 = newTemp(Ity_I32);
   14410 //   IRTemp n11 = newTemp(Ity_I32);
   14411 //   IRTemp n12 = newTemp(Ity_I32);
   14412 //
   14413 //   /* First, propagate the most significant 1-bit into all lower
   14414 //      positions in the word. */
   14415 //   /* unsigned int clz ( unsigned int n )
   14416 //      {
   14417 //         n |= (n >> 1);
   14418 //         n |= (n >> 2);
   14419 //         n |= (n >> 4);
   14420 //         n |= (n >> 8);
   14421 //         n |= (n >> 16);
   14422 //         return bitcount(~n);
   14423 //      }
   14424 //   */
   14425 //   assign(n1, mkexpr(arg));
   14426 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   14427 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   14428 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   14429 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   14430 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   14431 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   14432 //      a word of the form 1---10---0, then do a population-count idiom
   14433 //      (to count the 1s, which is the number of leading zeroes, or 32
   14434 //      if the original word was 0. */
   14435 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   14436 //
   14437 //   /* unsigned int bitcount ( unsigned int n )
   14438 //      {
   14439 //         n = n - ((n >> 1) & 0x55555555);
   14440 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   14441 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   14442 //         n = n + (n >> 8);
   14443 //         n = (n + (n >> 16)) & 0x3F;
   14444 //         return n;
   14445 //      }
   14446 //   */
   14447 //   assign(n8,
   14448 //          binop(Iop_Sub32,
   14449 //                mkexpr(n7),
   14450 //                binop(Iop_And32,
   14451 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   14452 //                      mkU32(0x55555555))));
   14453 //   assign(n9,
   14454 //          binop(Iop_Add32,
   14455 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   14456 //                binop(Iop_And32,
   14457 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   14458 //                      mkU32(0x33333333))));
   14459 //   assign(n10,
   14460 //          binop(Iop_And32,
   14461 //                binop(Iop_Add32,
   14462 //                      mkexpr(n9),
   14463 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   14464 //                mkU32(0x0F0F0F0F)));
   14465 //   assign(n11,
   14466 //          binop(Iop_Add32,
   14467 //                mkexpr(n10),
   14468 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   14469 //   assign(n12,
   14470 //          binop(Iop_Add32,
   14471 //                mkexpr(n11),
   14472 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   14473 //   return
   14474 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   14475 //}
   14476 
   14477 /*--------------------------------------------------------------------*/
   14478 /*--- end                                         guest_ppc_toIR.c ---*/
   14479 /*--------------------------------------------------------------------*/
   14480