Home | History | Annotate | Download | only in priv
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- begin                                       guest_ppc_toIR.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2004-2010 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 
     30    Neither the names of the U.S. Department of Energy nor the
     31    University of California nor the names of its contributors may be
     32    used to endorse or promote products derived from this software
     33    without prior written permission.
     34 */
     35 
     36 /* TODO 18/Nov/05:
     37 
     38    Spot rld... cases which are simply left/right shifts and emit
     39    Shl64/Shr64 accordingly.
     40 
     41    Altivec
     42    - datastream insns
     43    - lvxl,stvxl: load/store with 'least recently used' hint
     44    - vexptefp, vlogefp
     45 
     46    LIMITATIONS:
     47 
     48    Various, including:
     49 
     50    - Some invalid forms of lswi and lswx are accepted when they should
     51      not be.
     52 
     53    - Floating Point:
     54      - All exceptions disabled in FPSCR
     55      - condition codes not set in FPSCR
     56 
     57    - Altivec floating point:
     58      - vmaddfp, vnmsubfp
     59        Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
     60        system default of Non-Java mode, we get some small errors
     61        (lowest bit only).
     62        This is because Non-Java mode brutally hacks denormalised results
     63        to zero, whereas we keep maximum accuracy.  However, using
     64        Non-Java mode would give us more inaccuracy, as our intermediate
     65        results would then be zeroed, too.
     66 
     67    - AbiHints for the stack red zone are only emitted for
     68        unconditional calls and returns (bl, blr).  They should also be
     69        emitted for conditional calls and returns, but we don't have a
     70        way to express that right now.  Ah well.
     71 */
     72 
     73 /* "Special" instructions.
     74 
     75    This instruction decoder can decode four special instructions
     76    which mean nothing natively (are no-ops as far as regs/mem are
     77    concerned) but have meaning for supporting Valgrind.  A special
     78    instruction is flagged by a 16-byte preamble:
     79 
     80       32-bit mode: 54001800 54006800 5400E800 54009800
     81                    (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0;
     82                     rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
     83 
     84       64-bit mode: 78001800 78006800 7800E802 78009802
     85                    (rotldi 0,0,3; rotldi 0,0,13;
     86                     rotldi 0,0,61; rotldi 0,0,51)
     87 
     88    Following that, one of the following 3 are allowed
     89    (standard interpretation in parentheses):
     90 
     91       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
     92       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
     93       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
     94       7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
     95 
     96    Any other bytes following the 16-byte preamble are illegal and
     97    constitute a failure in instruction decoding.  This all assumes
     98    that the preamble will never occur except in specific code
     99    fragments designed for Valgrind to catch.
    100 */
    101 
    102 
    103 /* Translates PPC32/64 code to IR. */
    104 
    105 /* References
    106 
    107 #define PPC32
    108    "PowerPC Microprocessor Family:
    109     The Programming Environments Manual for 32-Bit Microprocessors"
    110     02/21/2000
    111     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
    112 
    113 #define PPC64
    114    "PowerPC Microprocessor Family:
    115     Programming Environments Manual for 64-Bit Microprocessors"
    116     06/10/2003
    117    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
    118 
    119 #define AV
    120    "PowerPC Microprocessor Family:
    121     AltiVec(TM) Technology Programming Environments Manual"
    122     07/10/2003
    123    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
    124 */
    125 
    126 #include "libvex_basictypes.h"
    127 #include "libvex_ir.h"
    128 #include "libvex.h"
    129 #include "libvex_guest_ppc32.h"
    130 #include "libvex_guest_ppc64.h"
    131 
    132 #include "main_util.h"
    133 #include "main_globals.h"
    134 #include "guest_generic_bb_to_IR.h"
    135 #include "guest_ppc_defs.h"
    136 
    137 
    138 /*------------------------------------------------------------*/
    139 /*--- Globals                                              ---*/
    140 /*------------------------------------------------------------*/
    141 
    142 /* These are set at the start of the translation of an insn, right
    143    down in disInstr_PPC, so that we don't have to pass them around
    144    endlessly.  They are all constant during the translation of any
    145    given insn. */
    146 
    147 /* We need to know this to do sub-register accesses correctly. */
    148 static Bool host_is_bigendian;
    149 
    150 /* Pointer to the guest code area. */
    151 static UChar* guest_code;
    152 
    153 /* The guest address corresponding to guest_code[0]. */
    154 static Addr64 guest_CIA_bbstart;
    155 
    156 /* The guest address for the instruction currently being
    157    translated. */
    158 static Addr64 guest_CIA_curr_instr;
    159 
    160 /* The IRSB* into which we're generating code. */
    161 static IRSB* irsb;
    162 
    163 /* Is our guest binary 32 or 64bit?  Set at each call to
    164    disInstr_PPC below. */
    165 static Bool mode64 = False;
    166 
    167 // Given a pointer to a function as obtained by "& functionname" in C,
    168 // produce a pointer to the actual entry point for the function.  For
    169 // most platforms it's the identity function.  Unfortunately, on
    170 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
    171 // ppc64-aix5.
    172 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
    173 {
    174    if (vbi->host_ppc_calls_use_fndescrs) {
    175       /* f is a pointer to a 3-word function descriptor, of which the
    176          first word is the entry address. */
    177       /* note, this is correct even with cross-jitting, since this is
    178          purely a host issue, not a guest one. */
    179       HWord* fdescr = (HWord*)f;
    180       return (void*)(fdescr[0]);
    181    } else {
    182       /* Simple; "& f" points directly at the code for f. */
    183       return f;
    184    }
    185 }
    186 
    187 
    188 /*------------------------------------------------------------*/
    189 /*--- Debugging output                                     ---*/
    190 /*------------------------------------------------------------*/
    191 
    192 #define DIP(format, args...)           \
    193    if (vex_traceflags & VEX_TRACE_FE)  \
    194       vex_printf(format, ## args)
    195 
    196 #define DIS(buf, format, args...)      \
    197    if (vex_traceflags & VEX_TRACE_FE)  \
    198       vex_sprintf(buf, format, ## args)
    199 
    200 
    201 /*------------------------------------------------------------*/
    202 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
    203 /*------------------------------------------------------------*/
    204 
    205 #define offsetofPPCGuestState(_x) \
    206    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
    207              offsetof(VexGuestPPC32State, _x))
    208 
    209 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
    210 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
    211 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
    212 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
    213 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
    214 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
    215 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
    216 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
    217 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
    218 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
    219 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
    220 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
    221 #define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
    222 #define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
    223 #define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
    224 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
    225 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
    226 
    227 
    228 /*------------------------------------------------------------*/
    229 /*--- Extract instruction fields                          --- */
    230 /*------------------------------------------------------------*/
    231 
    232 /* Extract field from insn, given idx (zero = lsb) and field length */
    233 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    234 
    235 /* Extract primary opcode, instr[31:26] */
    236 static UChar ifieldOPC( UInt instr ) {
    237    return toUChar( IFIELD( instr, 26, 6 ) );
    238 }
    239 
    240 /* Extract 10-bit secondary opcode, instr[10:1] */
    241 static UInt ifieldOPClo10 ( UInt instr) {
    242    return IFIELD( instr, 1, 10 );
    243 }
    244 
    245 /* Extract 9-bit secondary opcode, instr[9:1] */
    246 static UInt ifieldOPClo9 ( UInt instr) {
    247    return IFIELD( instr, 1, 9 );
    248 }
    249 
    250 /* Extract 5-bit secondary opcode, instr[5:1] */
    251 static UInt ifieldOPClo5 ( UInt instr) {
    252    return IFIELD( instr, 1, 5 );
    253 }
    254 
    255 /* Extract RD (destination register) field, instr[25:21] */
    256 static UChar ifieldRegDS( UInt instr ) {
    257    return toUChar( IFIELD( instr, 21, 5 ) );
    258 }
    259 
    260 /* Extract RA (1st source register) field, instr[20:16] */
    261 static UChar ifieldRegA ( UInt instr ) {
    262    return toUChar( IFIELD( instr, 16, 5 ) );
    263 }
    264 
    265 /* Extract RB (2nd source register) field, instr[15:11] */
    266 static UChar ifieldRegB ( UInt instr ) {
    267    return toUChar( IFIELD( instr, 11, 5 ) );
    268 }
    269 
    270 /* Extract RC (3rd source register) field, instr[10:6] */
    271 static UChar ifieldRegC ( UInt instr ) {
    272    return toUChar( IFIELD( instr, 6, 5 ) );
    273 }
    274 
    275 /* Extract 2nd lowest bit, instr[1] */
    276 static UChar ifieldBIT10 ( UInt instr ) {
    277    return toUChar( IFIELD( instr, 10, 1 ) );
    278 }
    279 
    280 /* Extract 2nd lowest bit, instr[1] */
    281 static UChar ifieldBIT1 ( UInt instr ) {
    282    return toUChar( IFIELD( instr, 1, 1 ) );
    283 }
    284 
    285 /* Extract lowest bit, instr[0] */
    286 static UChar ifieldBIT0 ( UInt instr ) {
    287    return toUChar( instr & 0x1 );
    288 }
    289 
    290 /* Extract unsigned bottom half, instr[15:0] */
    291 static UInt ifieldUIMM16 ( UInt instr ) {
    292    return instr & 0xFFFF;
    293 }
    294 
    295 /* Extract unsigned bottom 26 bits, instr[25:0] */
    296 static UInt ifieldUIMM26 ( UInt instr ) {
    297    return instr & 0x3FFFFFF;
    298 }
    299 
    300 
    301 /*------------------------------------------------------------*/
    302 /*--- Guest-state identifiers                              ---*/
    303 /*------------------------------------------------------------*/
    304 
    305 typedef enum {
    306     PPC_GST_CIA,    // Current Instruction Address
    307     PPC_GST_LR,     // Link Register
    308     PPC_GST_CTR,    // Count Register
    309     PPC_GST_XER,    // Overflow, carry flags, byte count
    310     PPC_GST_CR,     // Condition Register
    311     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    312     PPC_GST_VRSAVE, // Vector Save/Restore Register
    313     PPC_GST_VSCR,   // Vector Status and Control Register
    314     PPC_GST_EMWARN, // Emulation warnings
    315     PPC_GST_TISTART,// For icbi: start of area to invalidate
    316     PPC_GST_TILEN,  // For icbi: length of area to invalidate
    317     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    318     PPC_GST_SPRG3_RO, // SPRG3
    319     PPC_GST_MAX
    320 } PPC_GST;
    321 
    322 #define MASK_FPSCR_RN   0x3
    323 #define MASK_FPSCR_FPRF 0x1F000
    324 #define MASK_VSCR_VALID 0x00010001
    325 
    326 
    327 /*------------------------------------------------------------*/
    328 /*---  FP Helpers                                          ---*/
    329 /*------------------------------------------------------------*/
    330 
    331 /* Produce the 32-bit pattern corresponding to the supplied
    332    float. */
    333 static UInt float_to_bits ( Float f )
    334 {
    335    union { UInt i; Float f; } u;
    336    vassert(4 == sizeof(UInt));
    337    vassert(4 == sizeof(Float));
    338    vassert(4 == sizeof(u));
    339    u.f = f;
    340    return u.i;
    341 }
    342 
    343 
    344 /*------------------------------------------------------------*/
    345 /*--- Misc Helpers                                         ---*/
    346 /*------------------------------------------------------------*/
    347 
    348 /* Generate mask with 1's from 'begin' through 'end',
    349    wrapping if begin > end.
    350    begin->end works from right to left, 0=lsb
    351 */
    352 static UInt MASK32( UInt begin, UInt end )
    353 {
    354    UInt m1, m2, mask;
    355    vassert(begin < 32);
    356    vassert(end < 32);
    357    m1   = ((UInt)(-1)) << begin;
    358    m2   = ((UInt)(-1)) << end << 1;
    359    mask = m1 ^ m2;
    360    if (begin > end) mask = ~mask;  // wrap mask
    361    return mask;
    362 }
    363 
    364 /* ditto for 64bit mask */
    365 static ULong MASK64( UInt begin, UInt end )
    366 {
    367    ULong m1, m2, mask;
    368    vassert(begin < 64);
    369    vassert(end < 64);
    370    m1   = ((ULong)(-1)) << begin;
    371    m2   = ((ULong)(-1)) << end << 1;
    372    mask = m1 ^ m2;
    373    if (begin > end) mask = ~mask;  // wrap mask
    374    return mask;
    375 }
    376 
    377 static Addr64 nextInsnAddr( void )
    378 {
    379    return guest_CIA_curr_instr + 4;
    380 }
    381 
    382 
    383 /*------------------------------------------------------------*/
    384 /*--- Helper bits and pieces for deconstructing the        ---*/
    385 /*--- ppc32/64 insn stream.                                ---*/
    386 /*------------------------------------------------------------*/
    387 
    388 /* Add a statement to the list held by "irsb". */
    389 static void stmt ( IRStmt* st )
    390 {
    391    addStmtToIRSB( irsb, st );
    392 }
    393 
    394 /* Generate a new temporary of the given type. */
    395 static IRTemp newTemp ( IRType ty )
    396 {
    397    vassert(isPlausibleIRType(ty));
    398    return newIRTemp( irsb->tyenv, ty );
    399 }
    400 
    401 /* Various simple conversions */
    402 
    403 static UChar extend_s_5to8 ( UChar x )
    404 {
    405    return toUChar((((Int)x) << 27) >> 27);
    406 }
    407 
    408 static UInt extend_s_8to32( UChar x )
    409 {
    410    return (UInt)((((Int)x) << 24) >> 24);
    411 }
    412 
    413 static UInt extend_s_16to32 ( UInt x )
    414 {
    415    return (UInt)((((Int)x) << 16) >> 16);
    416 }
    417 
    418 static ULong extend_s_16to64 ( UInt x )
    419 {
    420    return (ULong)((((Long)x) << 48) >> 48);
    421 }
    422 
    423 static ULong extend_s_26to64 ( UInt x )
    424 {
    425    return (ULong)((((Long)x) << 38) >> 38);
    426 }
    427 
    428 static ULong extend_s_32to64 ( UInt x )
    429 {
    430    return (ULong)((((Long)x) << 32) >> 32);
    431 }
    432 
    433 /* Do a big-endian load of a 32-bit word, regardless of the endianness
    434    of the underlying host. */
    435 static UInt getUIntBigendianly ( UChar* p )
    436 {
    437    UInt w = 0;
    438    w = (w << 8) | p[0];
    439    w = (w << 8) | p[1];
    440    w = (w << 8) | p[2];
    441    w = (w << 8) | p[3];
    442    return w;
    443 }
    444 
    445 
    446 /*------------------------------------------------------------*/
    447 /*--- Helpers for constructing IR.                         ---*/
    448 /*------------------------------------------------------------*/
    449 
    450 static void assign ( IRTemp dst, IRExpr* e )
    451 {
    452    stmt( IRStmt_WrTmp(dst, e) );
    453 }
    454 
    455 /* This generates a normal (non store-conditional) store. */
    456 static void storeBE ( IRExpr* addr, IRExpr* data )
    457 {
    458    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    459    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    460    stmt( IRStmt_Store(Iend_BE, addr, data) );
    461 }
    462 
    463 static IRExpr* unop ( IROp op, IRExpr* a )
    464 {
    465    return IRExpr_Unop(op, a);
    466 }
    467 
    468 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    469 {
    470    return IRExpr_Binop(op, a1, a2);
    471 }
    472 
    473 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    474 {
    475    return IRExpr_Triop(op, a1, a2, a3);
    476 }
    477 
    478 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    479                               IRExpr* a3, IRExpr* a4 )
    480 {
    481    return IRExpr_Qop(op, a1, a2, a3, a4);
    482 }
    483 
    484 static IRExpr* mkexpr ( IRTemp tmp )
    485 {
    486    return IRExpr_RdTmp(tmp);
    487 }
    488 
    489 static IRExpr* mkU8 ( UChar i )
    490 {
    491    return IRExpr_Const(IRConst_U8(i));
    492 }
    493 
    494 static IRExpr* mkU16 ( UInt i )
    495 {
    496    return IRExpr_Const(IRConst_U16(i));
    497 }
    498 
    499 static IRExpr* mkU32 ( UInt i )
    500 {
    501    return IRExpr_Const(IRConst_U32(i));
    502 }
    503 
    504 static IRExpr* mkU64 ( ULong i )
    505 {
    506    return IRExpr_Const(IRConst_U64(i));
    507 }
    508 
    509 /* This generates a normal (non load-linked) load. */
    510 static IRExpr* loadBE ( IRType ty, IRExpr* addr )
    511 {
    512    return IRExpr_Load(Iend_BE, ty, addr);
    513 }
    514 
    515 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    516 {
    517    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    518    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    519    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    520                                           unop(Iop_1Uto32, arg2)));
    521 }
    522 
    523 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    524 {
    525    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    526    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    527    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    528                                            unop(Iop_1Uto32, arg2)));
    529 }
    530 
    531 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    532 static void expand8Ux16( IRExpr* vIn,
    533                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    534 {
    535    IRTemp ones8x16 = newTemp(Ity_V128);
    536 
    537    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    538    vassert(vEvn && *vEvn == IRTemp_INVALID);
    539    vassert(vOdd && *vOdd == IRTemp_INVALID);
    540    *vEvn = newTemp(Ity_V128);
    541    *vOdd = newTemp(Ity_V128);
    542 
    543    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    544    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    545    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    546                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    547 }
    548 
    549 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    550 static void expand8Sx16( IRExpr* vIn,
    551                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    552 {
    553    IRTemp ones8x16 = newTemp(Ity_V128);
    554 
    555    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    556    vassert(vEvn && *vEvn == IRTemp_INVALID);
    557    vassert(vOdd && *vOdd == IRTemp_INVALID);
    558    *vEvn = newTemp(Ity_V128);
    559    *vOdd = newTemp(Ity_V128);
    560 
    561    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    562    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    563    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    564                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    565 }
    566 
    567 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    568 static void expand16Ux8( IRExpr* vIn,
    569                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    570 {
    571    IRTemp ones16x8 = newTemp(Ity_V128);
    572 
    573    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    574    vassert(vEvn && *vEvn == IRTemp_INVALID);
    575    vassert(vOdd && *vOdd == IRTemp_INVALID);
    576    *vEvn = newTemp(Ity_V128);
    577    *vOdd = newTemp(Ity_V128);
    578 
    579    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    580    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    581    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    582                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    583 }
    584 
    585 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    586 static void expand16Sx8( IRExpr* vIn,
    587                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    588 {
    589    IRTemp ones16x8 = newTemp(Ity_V128);
    590 
    591    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    592    vassert(vEvn && *vEvn == IRTemp_INVALID);
    593    vassert(vOdd && *vOdd == IRTemp_INVALID);
    594    *vEvn = newTemp(Ity_V128);
    595    *vOdd = newTemp(Ity_V128);
    596 
    597    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    598    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    599    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    600                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    601 }
    602 
    603 /* break V128 to 4xI32's, then sign-extend to I64's */
    604 static void breakV128to4x64S( IRExpr* t128,
    605                               /*OUTs*/
    606                               IRTemp* t3, IRTemp* t2,
    607                               IRTemp* t1, IRTemp* t0 )
    608 {
    609    IRTemp hi64 = newTemp(Ity_I64);
    610    IRTemp lo64 = newTemp(Ity_I64);
    611 
    612    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    613    vassert(t0 && *t0 == IRTemp_INVALID);
    614    vassert(t1 && *t1 == IRTemp_INVALID);
    615    vassert(t2 && *t2 == IRTemp_INVALID);
    616    vassert(t3 && *t3 == IRTemp_INVALID);
    617    *t0 = newTemp(Ity_I64);
    618    *t1 = newTemp(Ity_I64);
    619    *t2 = newTemp(Ity_I64);
    620    *t3 = newTemp(Ity_I64);
    621 
    622    assign( hi64, unop(Iop_V128HIto64, t128) );
    623    assign( lo64, unop(Iop_V128to64,   t128) );
    624    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    625    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    626    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    627    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    628 }
    629 
    630 /* break V128 to 4xI32's, then zero-extend to I64's */
    631 static void breakV128to4x64U ( IRExpr* t128,
    632                                /*OUTs*/
    633                                IRTemp* t3, IRTemp* t2,
    634                                IRTemp* t1, IRTemp* t0 )
    635 {
    636    IRTemp hi64 = newTemp(Ity_I64);
    637    IRTemp lo64 = newTemp(Ity_I64);
    638 
    639    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    640    vassert(t0 && *t0 == IRTemp_INVALID);
    641    vassert(t1 && *t1 == IRTemp_INVALID);
    642    vassert(t2 && *t2 == IRTemp_INVALID);
    643    vassert(t3 && *t3 == IRTemp_INVALID);
    644    *t0 = newTemp(Ity_I64);
    645    *t1 = newTemp(Ity_I64);
    646    *t2 = newTemp(Ity_I64);
    647    *t3 = newTemp(Ity_I64);
    648 
    649    assign( hi64, unop(Iop_V128HIto64, t128) );
    650    assign( lo64, unop(Iop_V128to64,   t128) );
    651    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    652    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    653    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    654    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    655 }
    656 
    657 /* Signed saturating narrow 64S to 32 */
    658 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    659 {
    660    IRTemp hi32 = newTemp(Ity_I32);
    661    IRTemp lo32 = newTemp(Ity_I32);
    662 
    663    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    664 
    665    assign( hi32, unop(Iop_64HIto32, t64));
    666    assign( lo32, unop(Iop_64to32,   t64));
    667 
    668    return IRExpr_Mux0X(
    669              /* if (hi32 == (lo32 >>s 31)) */
    670              unop(Iop_1Uto8,
    671                   binop(Iop_CmpEQ32, mkexpr(hi32),
    672                         binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
    673              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    674              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    675                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
    676              /* then: within signed-32 range: lo half good enough */
    677              mkexpr(lo32) );
    678 }
    679 
    680 /* Unsigned saturating narrow 64S to 32 */
    681 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    682 {
    683    IRTemp hi32 = newTemp(Ity_I32);
    684    IRTemp lo32 = newTemp(Ity_I32);
    685 
    686    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    687 
    688    assign( hi32, unop(Iop_64HIto32, t64));
    689    assign( lo32, unop(Iop_64to32,   t64));
    690 
    691    return IRExpr_Mux0X(
    692             /* if (top 32 bits of t64 are 0) */
    693             unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
    694             /* else: positive saturate -> 0xFFFFFFFF */
    695             mkU32(0xFFFFFFFF),
    696             /* then: within unsigned-32 range: lo half good enough */
    697             mkexpr(lo32) );
    698 }
    699 
    700 /* Signed saturate narrow 64->32, combining to V128 */
    701 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    702                                  IRExpr* t1, IRExpr* t0 )
    703 {
    704    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    705    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    706    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    707    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    708    return binop(Iop_64HLtoV128,
    709                 binop(Iop_32HLto64,
    710                       mkQNarrow64Sto32( t3 ),
    711                       mkQNarrow64Sto32( t2 )),
    712                 binop(Iop_32HLto64,
    713                       mkQNarrow64Sto32( t1 ),
    714                       mkQNarrow64Sto32( t0 )));
    715 }
    716 
    717 /* Unsigned saturate narrow 64->32, combining to V128 */
    718 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    719                                  IRExpr* t1, IRExpr* t0 )
    720 {
    721    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    722    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    723    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    724    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    725    return binop(Iop_64HLtoV128,
    726                 binop(Iop_32HLto64,
    727                       mkQNarrow64Uto32( t3 ),
    728                       mkQNarrow64Uto32( t2 )),
    729                 binop(Iop_32HLto64,
    730                       mkQNarrow64Uto32( t1 ),
    731                       mkQNarrow64Uto32( t0 )));
    732 }
    733 
    734 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    735 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    736       binop(Iop_MullEven8Ux16, \
    737             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    738             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    739 
    740 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    741       binop(Iop_MullEven8Sx16, \
    742             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    743             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    744 
    745 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    746       binop(Iop_MullEven16Ux8, \
    747             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    748             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    749 
    750 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    751       binop(Iop_MullEven16Sx8, \
    752             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    753             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    754 
    755 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
    756 {
    757    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    758    return unop(Iop_32Sto64, unop(Iop_64to32, src));
    759 }
    760 
    761 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
    762 {
    763    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
    764    return unop(Iop_32Uto64, unop(Iop_64to32, src));
    765 }
    766 
    767 static IROp mkSzOp ( IRType ty, IROp op8 )
    768 {
    769    Int adj;
    770    vassert(ty == Ity_I8  || ty == Ity_I16 ||
    771            ty == Ity_I32 || ty == Ity_I64);
    772    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
    773            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
    774            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
    775            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
    776            op8 == Iop_Not8 );
    777    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
    778    return adj + op8;
    779 }
    780 
    781 /* Make sure we get valid 32 and 64bit addresses */
    782 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
    783 {
    784    vassert(ty == Ity_I32 || ty == Ity_I64);
    785    return ( ty == Ity_I64 ?
    786             (Addr64)addr :
    787             (Addr64)extend_s_32to64( toUInt(addr) ) );
    788 }
    789 
    790 /* sz, ULong -> IRExpr */
    791 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
    792 {
    793    vassert(ty == Ity_I32 || ty == Ity_I64);
    794    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
    795 }
    796 
    797 /* sz, ULong -> IRConst */
    798 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
    799 {
    800    vassert(ty == Ity_I32 || ty == Ity_I64);
    801    return ( ty == Ity_I64 ?
    802             IRConst_U64(imm64) :
    803             IRConst_U32((UInt)imm64) );
    804 }
    805 
    806 /* Sign extend imm16 -> IRExpr* */
    807 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
    808 {
    809    vassert(ty == Ity_I32 || ty == Ity_I64);
    810    return ( ty == Ity_I64 ?
    811             mkU64(extend_s_16to64(imm16)) :
    812             mkU32(extend_s_16to32(imm16)) );
    813 }
    814 
    815 /* Sign extend imm32 -> IRExpr* */
    816 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
    817 {
    818    vassert(ty == Ity_I32 || ty == Ity_I64);
    819    return ( ty == Ity_I64 ?
    820             mkU64(extend_s_32to64(imm32)) :
    821             mkU32(imm32) );
    822 }
    823 
    824 /* IR narrows I32/I64 -> I8/I16/I32 */
    825 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
    826 {
    827    vassert(ty == Ity_I32 || ty == Ity_I64);
    828    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
    829 }
    830 
    831 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
    832 {
    833    vassert(ty == Ity_I32 || ty == Ity_I64);
    834    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
    835 }
    836 
    837 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
    838 {
    839    vassert(ty == Ity_I32 || ty == Ity_I64);
    840    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
    841 }
    842 
    843 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
    844 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
    845 {
    846    IROp op;
    847    vassert(ty == Ity_I32 || ty == Ity_I64);
    848    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
    849    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
    850    return unop(op, src);
    851 }
    852 
    853 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
    854 {
    855    IROp op;
    856    vassert(ty == Ity_I32 || ty == Ity_I64);
    857    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
    858    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
    859    return unop(op, src);
    860 }
    861 
    862 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
    863 {
    864    vassert(ty == Ity_I32 || ty == Ity_I64);
    865    if (ty == Ity_I32)
    866       return src;
    867    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
    868 }
    869 
    870 
    871 static Int integerGuestRegOffset ( UInt archreg )
    872 {
    873    vassert(archreg < 32);
    874 
    875    // jrs: probably not necessary; only matters if we reference sub-parts
    876    // of the ppc registers, but that isn't the case
    877    // later: this might affect Altivec though?
    878    vassert(host_is_bigendian);
    879 
    880    switch (archreg) {
    881    case  0: return offsetofPPCGuestState(guest_GPR0);
    882    case  1: return offsetofPPCGuestState(guest_GPR1);
    883    case  2: return offsetofPPCGuestState(guest_GPR2);
    884    case  3: return offsetofPPCGuestState(guest_GPR3);
    885    case  4: return offsetofPPCGuestState(guest_GPR4);
    886    case  5: return offsetofPPCGuestState(guest_GPR5);
    887    case  6: return offsetofPPCGuestState(guest_GPR6);
    888    case  7: return offsetofPPCGuestState(guest_GPR7);
    889    case  8: return offsetofPPCGuestState(guest_GPR8);
    890    case  9: return offsetofPPCGuestState(guest_GPR9);
    891    case 10: return offsetofPPCGuestState(guest_GPR10);
    892    case 11: return offsetofPPCGuestState(guest_GPR11);
    893    case 12: return offsetofPPCGuestState(guest_GPR12);
    894    case 13: return offsetofPPCGuestState(guest_GPR13);
    895    case 14: return offsetofPPCGuestState(guest_GPR14);
    896    case 15: return offsetofPPCGuestState(guest_GPR15);
    897    case 16: return offsetofPPCGuestState(guest_GPR16);
    898    case 17: return offsetofPPCGuestState(guest_GPR17);
    899    case 18: return offsetofPPCGuestState(guest_GPR18);
    900    case 19: return offsetofPPCGuestState(guest_GPR19);
    901    case 20: return offsetofPPCGuestState(guest_GPR20);
    902    case 21: return offsetofPPCGuestState(guest_GPR21);
    903    case 22: return offsetofPPCGuestState(guest_GPR22);
    904    case 23: return offsetofPPCGuestState(guest_GPR23);
    905    case 24: return offsetofPPCGuestState(guest_GPR24);
    906    case 25: return offsetofPPCGuestState(guest_GPR25);
    907    case 26: return offsetofPPCGuestState(guest_GPR26);
    908    case 27: return offsetofPPCGuestState(guest_GPR27);
    909    case 28: return offsetofPPCGuestState(guest_GPR28);
    910    case 29: return offsetofPPCGuestState(guest_GPR29);
    911    case 30: return offsetofPPCGuestState(guest_GPR30);
    912    case 31: return offsetofPPCGuestState(guest_GPR31);
    913    default: break;
    914    }
    915    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
    916 }
    917 
    918 static IRExpr* getIReg ( UInt archreg )
    919 {
    920    IRType ty = mode64 ? Ity_I64 : Ity_I32;
    921    vassert(archreg < 32);
    922    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
    923 }
    924 
    925 /* Ditto, but write to a reg instead. */
    926 static void putIReg ( UInt archreg, IRExpr* e )
    927 {
    928    IRType ty = mode64 ? Ity_I64 : Ity_I32;
    929    vassert(archreg < 32);
    930    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
    931    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
    932 }
    933 
    934 
    935 static Int floatGuestRegOffset ( UInt archreg )
    936 {
    937    vassert(archreg < 32);
    938 
    939    switch (archreg) {
    940    case  0: return offsetofPPCGuestState(guest_FPR0);
    941    case  1: return offsetofPPCGuestState(guest_FPR1);
    942    case  2: return offsetofPPCGuestState(guest_FPR2);
    943    case  3: return offsetofPPCGuestState(guest_FPR3);
    944    case  4: return offsetofPPCGuestState(guest_FPR4);
    945    case  5: return offsetofPPCGuestState(guest_FPR5);
    946    case  6: return offsetofPPCGuestState(guest_FPR6);
    947    case  7: return offsetofPPCGuestState(guest_FPR7);
    948    case  8: return offsetofPPCGuestState(guest_FPR8);
    949    case  9: return offsetofPPCGuestState(guest_FPR9);
    950    case 10: return offsetofPPCGuestState(guest_FPR10);
    951    case 11: return offsetofPPCGuestState(guest_FPR11);
    952    case 12: return offsetofPPCGuestState(guest_FPR12);
    953    case 13: return offsetofPPCGuestState(guest_FPR13);
    954    case 14: return offsetofPPCGuestState(guest_FPR14);
    955    case 15: return offsetofPPCGuestState(guest_FPR15);
    956    case 16: return offsetofPPCGuestState(guest_FPR16);
    957    case 17: return offsetofPPCGuestState(guest_FPR17);
    958    case 18: return offsetofPPCGuestState(guest_FPR18);
    959    case 19: return offsetofPPCGuestState(guest_FPR19);
    960    case 20: return offsetofPPCGuestState(guest_FPR20);
    961    case 21: return offsetofPPCGuestState(guest_FPR21);
    962    case 22: return offsetofPPCGuestState(guest_FPR22);
    963    case 23: return offsetofPPCGuestState(guest_FPR23);
    964    case 24: return offsetofPPCGuestState(guest_FPR24);
    965    case 25: return offsetofPPCGuestState(guest_FPR25);
    966    case 26: return offsetofPPCGuestState(guest_FPR26);
    967    case 27: return offsetofPPCGuestState(guest_FPR27);
    968    case 28: return offsetofPPCGuestState(guest_FPR28);
    969    case 29: return offsetofPPCGuestState(guest_FPR29);
    970    case 30: return offsetofPPCGuestState(guest_FPR30);
    971    case 31: return offsetofPPCGuestState(guest_FPR31);
    972    default: break;
    973    }
    974    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
    975 }
    976 
    977 static IRExpr* getFReg ( UInt archreg )
    978 {
    979    vassert(archreg < 32);
    980    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
    981 }
    982 
    983 /* Ditto, but write to a reg instead. */
    984 static void putFReg ( UInt archreg, IRExpr* e )
    985 {
    986    vassert(archreg < 32);
    987    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
    988    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
    989 }
    990 
    991 
    992 static Int vectorGuestRegOffset ( UInt archreg )
    993 {
    994    vassert(archreg < 32);
    995 
    996    switch (archreg) {
    997    case  0: return offsetofPPCGuestState(guest_VR0);
    998    case  1: return offsetofPPCGuestState(guest_VR1);
    999    case  2: return offsetofPPCGuestState(guest_VR2);
   1000    case  3: return offsetofPPCGuestState(guest_VR3);
   1001    case  4: return offsetofPPCGuestState(guest_VR4);
   1002    case  5: return offsetofPPCGuestState(guest_VR5);
   1003    case  6: return offsetofPPCGuestState(guest_VR6);
   1004    case  7: return offsetofPPCGuestState(guest_VR7);
   1005    case  8: return offsetofPPCGuestState(guest_VR8);
   1006    case  9: return offsetofPPCGuestState(guest_VR9);
   1007    case 10: return offsetofPPCGuestState(guest_VR10);
   1008    case 11: return offsetofPPCGuestState(guest_VR11);
   1009    case 12: return offsetofPPCGuestState(guest_VR12);
   1010    case 13: return offsetofPPCGuestState(guest_VR13);
   1011    case 14: return offsetofPPCGuestState(guest_VR14);
   1012    case 15: return offsetofPPCGuestState(guest_VR15);
   1013    case 16: return offsetofPPCGuestState(guest_VR16);
   1014    case 17: return offsetofPPCGuestState(guest_VR17);
   1015    case 18: return offsetofPPCGuestState(guest_VR18);
   1016    case 19: return offsetofPPCGuestState(guest_VR19);
   1017    case 20: return offsetofPPCGuestState(guest_VR20);
   1018    case 21: return offsetofPPCGuestState(guest_VR21);
   1019    case 22: return offsetofPPCGuestState(guest_VR22);
   1020    case 23: return offsetofPPCGuestState(guest_VR23);
   1021    case 24: return offsetofPPCGuestState(guest_VR24);
   1022    case 25: return offsetofPPCGuestState(guest_VR25);
   1023    case 26: return offsetofPPCGuestState(guest_VR26);
   1024    case 27: return offsetofPPCGuestState(guest_VR27);
   1025    case 28: return offsetofPPCGuestState(guest_VR28);
   1026    case 29: return offsetofPPCGuestState(guest_VR29);
   1027    case 30: return offsetofPPCGuestState(guest_VR30);
   1028    case 31: return offsetofPPCGuestState(guest_VR31);
   1029    default: break;
   1030    }
   1031    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1032 }
   1033 
   1034 static IRExpr* getVReg ( UInt archreg )
   1035 {
   1036    vassert(archreg < 32);
   1037    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1038 }
   1039 
   1040 /* Ditto, but write to a reg instead. */
   1041 static void putVReg ( UInt archreg, IRExpr* e )
   1042 {
   1043    vassert(archreg < 32);
   1044    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1045    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1046 }
   1047 
   1048 static Int guestCR321offset ( UInt cr )
   1049 {
   1050    switch (cr) {
   1051    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1052    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1053    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1054    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1055    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1056    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1057    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1058    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1059    default: vpanic("guestCR321offset(ppc)");
   1060    }
   1061 }
   1062 
   1063 static Int guestCR0offset ( UInt cr )
   1064 {
   1065    switch (cr) {
   1066    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1067    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1068    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1069    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1070    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1071    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1072    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1073    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1074    default: vpanic("guestCR3offset(ppc)");
   1075    }
   1076 }
   1077 
   1078 // ROTL(src32/64, rot_amt5/6)
   1079 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1080                                           IRExpr* rot_amt )
   1081 {
   1082    IRExpr *mask, *rot;
   1083    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1084 
   1085    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1086       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1087       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1088       rot  = binop(Iop_Or64,
   1089                 binop(Iop_Shl64, src, mask),
   1090                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1091    } else {
   1092       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1093       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1094       rot  = binop(Iop_Or32,
   1095                 binop(Iop_Shl32, src, mask),
   1096                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1097    }
   1098    /* Note: the MuxOX is not merely an optimisation; it's needed
   1099       because otherwise the Shr is a shift by the word size when
   1100       mask denotes zero.  For rotates by immediates, a lot of
   1101       this junk gets folded out. */
   1102    return IRExpr_Mux0X( mask, /*     zero rotate */ src,
   1103                               /* non-zero rotate */ rot );
   1104 }
   1105 
   1106 /* Standard effective address calc: (rA + rB) */
   1107 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1108 {
   1109    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1110    vassert(rA < 32);
   1111    vassert(rB < 32);
   1112    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1113 }
   1114 
   1115 /* Standard effective address calc: (rA + simm) */
   1116 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1117 {
   1118    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1119    vassert(rA < 32);
   1120    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1121                 mkSzExtendS16(ty, simm16));
   1122 }
   1123 
   1124 /* Standard effective address calc: (rA|0) */
   1125 static IRExpr* ea_rAor0 ( UInt rA )
   1126 {
   1127    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1128    vassert(rA < 32);
   1129    if (rA == 0) {
   1130       return mkSzImm(ty, 0);
   1131    } else {
   1132       return getIReg(rA);
   1133    }
   1134 }
   1135 
   1136 /* Standard effective address calc: (rA|0) + rB */
   1137 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1138 {
   1139    vassert(rA < 32);
   1140    vassert(rB < 32);
   1141    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1142 }
   1143 
   1144 /* Standard effective address calc: (rA|0) + simm16 */
   1145 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1146 {
   1147    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1148    vassert(rA < 32);
   1149    if (rA == 0) {
   1150       return mkSzExtendS16(ty, simm16);
   1151    } else {
   1152       return ea_rA_simm( rA, simm16 );
   1153    }
   1154 }
   1155 
   1156 
   1157 /* Align effective address */
   1158 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1159 {
   1160    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1161    Long mask;
   1162    switch (align) {
   1163    case 1:  return addr;                    // byte aligned
   1164    case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
   1165    case 4:  mask = ((Long)-1) << 2; break;  // word aligned
   1166    case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
   1167    default:
   1168       vex_printf("addr_align: align = %u\n", align);
   1169       vpanic("addr_align(ppc)");
   1170    }
   1171 
   1172    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1173    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1174 }
   1175 
   1176 
   1177 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1178    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1179    restart of the current insn. */
   1180 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1181 {
   1182    vassert(align == 4 || align == 8);
   1183    if (mode64) {
   1184       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1185       stmt(
   1186          IRStmt_Exit(
   1187             binop(Iop_CmpNE64,
   1188                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1189                   mkU64(0)),
   1190             Ijk_SigBUS,
   1191             IRConst_U64( guest_CIA_curr_instr )
   1192          )
   1193       );
   1194    } else {
   1195       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1196       stmt(
   1197          IRStmt_Exit(
   1198             binop(Iop_CmpNE32,
   1199                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1200                   mkU32(0)),
   1201             Ijk_SigBUS,
   1202             IRConst_U32( guest_CIA_curr_instr )
   1203          )
   1204       );
   1205    }
   1206 }
   1207 
   1208 
   1209 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1210    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1211    N) becomes undefined.  That is at function calls and returns.  ELF
   1212    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1213    the address of the next instruction to be executed.
   1214 */
   1215 static void make_redzone_AbiHint ( VexAbiInfo* vbi,
   1216                                    IRTemp nia, HChar* who )
   1217 {
   1218    Int szB = vbi->guest_stack_redzone_size;
   1219    if (0) vex_printf("AbiHint: %s\n", who);
   1220    vassert(szB >= 0);
   1221    if (szB > 0) {
   1222       if (mode64) {
   1223          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1224          stmt( IRStmt_AbiHint(
   1225                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1226                   szB,
   1227                   mkexpr(nia)
   1228          ));
   1229       } else {
   1230          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1231          stmt( IRStmt_AbiHint(
   1232                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1233                   szB,
   1234                   mkexpr(nia)
   1235          ));
   1236       }
   1237    }
   1238 }
   1239 
   1240 
   1241 /*------------------------------------------------------------*/
   1242 /*--- Helpers for condition codes.                         ---*/
   1243 /*------------------------------------------------------------*/
   1244 
   1245 /* Condition register layout.
   1246 
   1247    In the hardware, CR is laid out like this.  The leftmost end is the
   1248    most significant bit in the register; however the IBM documentation
   1249    numbers the bits backwards for some reason.
   1250 
   1251    CR0      CR1    ..........   CR6       CR7
   1252    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1253    31  28                             3    0     (normal bit numbering)
   1254 
   1255    Each CR field is 4 bits:  [<,>,==,SO]
   1256 
   1257    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1258 
   1259    Indexing from BI to guest state:
   1260 
   1261      let    n = BI / 4
   1262           off = BI % 4
   1263      this references CR n:
   1264 
   1265         off==0   ->  guest_CRn_321 >> 3
   1266         off==1   ->  guest_CRn_321 >> 2
   1267         off==2   ->  guest_CRn_321 >> 1
   1268         off==3   ->  guest_CRn_SO
   1269 
   1270    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1271    (normal notation) and in guest_CRn_321 the significant bits are
   1272    3, 2 and 1 (normal notation).
   1273 */
   1274 
   1275 static void putCR321 ( UInt cr, IRExpr* e )
   1276 {
   1277    vassert(cr < 8);
   1278    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1279    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1280 }
   1281 
   1282 static void putCR0 ( UInt cr, IRExpr* e )
   1283 {
   1284    vassert(cr < 8);
   1285    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1286    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1287 }
   1288 
   1289 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1290 {
   1291    vassert(cr < 8);
   1292    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1293 }
   1294 
   1295 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1296 {
   1297    vassert(cr < 8);
   1298    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1299 }
   1300 
   1301 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1302    return it at the bottom of an I32; the top 31 bits are guaranteed
   1303    to be zero. */
   1304 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1305 {
   1306    UInt n   = bi / 4;
   1307    UInt off = bi % 4;
   1308    vassert(bi < 32);
   1309    if (off == 3) {
   1310       /* Fetch the SO bit for this CR field */
   1311       /* Note: And32 is redundant paranoia iff guest state only has 0
   1312          or 1 in that slot. */
   1313       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1314    } else {
   1315       /* Fetch the <, > or == bit for this CR field */
   1316       return binop( Iop_And32,
   1317                     binop( Iop_Shr32,
   1318                            unop(Iop_8Uto32, getCR321(n)),
   1319                            mkU8(toUChar(3-off)) ),
   1320                     mkU32(1) );
   1321    }
   1322 }
   1323 
   1324 /* Dually, write the least significant bit of BIT to the specified CR
   1325    bit.  Indexing as per getCRbit. */
   1326 static void putCRbit ( UInt bi, IRExpr* bit )
   1327 {
   1328    UInt    n, off;
   1329    IRExpr* safe;
   1330    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1331    safe = binop(Iop_And32, bit, mkU32(1));
   1332    n   = bi / 4;
   1333    off = bi % 4;
   1334    vassert(bi < 32);
   1335    if (off == 3) {
   1336       /* This is the SO bit for this CR field */
   1337       putCR0(n, unop(Iop_32to8, safe));
   1338    } else {
   1339       off = 3 - off;
   1340       vassert(off == 1 || off == 2 || off == 3);
   1341       putCR321(
   1342          n,
   1343          unop( Iop_32to8,
   1344                binop( Iop_Or32,
   1345                       /* old value with field masked out */
   1346                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1347                                        mkU32(~(1 << off))),
   1348                       /* new value in the right place */
   1349                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1350                )
   1351          )
   1352       );
   1353    }
   1354 }
   1355 
   1356 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1357    return it somewhere in an I32; it does not matter where, but
   1358    whichever bit it is, all other bits are guaranteed to be zero.  In
   1359    other words, the I32-typed expression will be zero if the bit is
   1360    zero and nonzero if the bit is 1.  Write into *where the index
   1361    of where the bit will be. */
   1362 
   1363 static
   1364 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   1365 {
   1366    UInt n   = bi / 4;
   1367    UInt off = bi % 4;
   1368    vassert(bi < 32);
   1369    if (off == 3) {
   1370       /* Fetch the SO bit for this CR field */
   1371       /* Note: And32 is redundant paranoia iff guest state only has 0
   1372          or 1 in that slot. */
   1373       *where = 0;
   1374       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1375    } else {
   1376       /* Fetch the <, > or == bit for this CR field */
   1377       *where = 3-off;
   1378       return binop( Iop_And32,
   1379                     unop(Iop_8Uto32, getCR321(n)),
   1380                     mkU32(1 << (3-off)) );
   1381    }
   1382 }
   1383 
   1384 /* Set the CR0 flags following an arithmetic operation.
   1385    (Condition Register CR0 Field Definition, PPC32 p60)
   1386 */
   1387 static IRExpr* getXER_SO ( void );
   1388 static void set_CR0 ( IRExpr* result )
   1389 {
   1390    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1391            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1392    if (mode64) {
   1393       putCR321( 0, unop(Iop_64to8,
   1394                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1395    } else {
   1396       putCR321( 0, unop(Iop_32to8,
   1397                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1398    }
   1399    putCR0( 0, getXER_SO() );
   1400 }
   1401 
   1402 
   1403 /* Set the CR6 flags following an AltiVec compare operation. */
   1404 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1405 {
   1406    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1407       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1408       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1409    */
   1410    IRTemp v0 = newTemp(Ity_V128);
   1411    IRTemp v1 = newTemp(Ity_V128);
   1412    IRTemp v2 = newTemp(Ity_V128);
   1413    IRTemp v3 = newTemp(Ity_V128);
   1414    IRTemp rOnes  = newTemp(Ity_I8);
   1415    IRTemp rZeros = newTemp(Ity_I8);
   1416 
   1417    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1418 
   1419    assign( v0, result );
   1420    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1421    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1422    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1423 
   1424    assign( rZeros, unop(Iop_1Uto8,
   1425        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1426              unop(Iop_Not32,
   1427                   unop(Iop_V128to32,
   1428                        binop(Iop_OrV128,
   1429                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1430                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1431                   ))) );
   1432 
   1433    if (test_all_ones) {
   1434       assign( rOnes, unop(Iop_1Uto8,
   1435          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1436                unop(Iop_V128to32,
   1437                     binop(Iop_AndV128,
   1438                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   1439                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   1440                     ))) );
   1441       putCR321( 6, binop(Iop_Or8,
   1442                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   1443                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   1444    } else {
   1445       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   1446    }
   1447    putCR0( 6, mkU8(0) );
   1448 }
   1449 
   1450 
   1451 
   1452 /*------------------------------------------------------------*/
   1453 /*--- Helpers for XER flags.                               ---*/
   1454 /*------------------------------------------------------------*/
   1455 
   1456 static void putXER_SO ( IRExpr* e )
   1457 {
   1458    IRExpr* so;
   1459    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1460    so = binop(Iop_And8, e, mkU8(1));
   1461    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   1462 }
   1463 
   1464 static void putXER_OV ( IRExpr* e )
   1465 {
   1466    IRExpr* ov;
   1467    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1468    ov = binop(Iop_And8, e, mkU8(1));
   1469    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   1470 }
   1471 
   1472 static void putXER_CA ( IRExpr* e )
   1473 {
   1474    IRExpr* ca;
   1475    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1476    ca = binop(Iop_And8, e, mkU8(1));
   1477    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   1478 }
   1479 
   1480 static void putXER_BC ( IRExpr* e )
   1481 {
   1482    IRExpr* bc;
   1483    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1484    bc = binop(Iop_And8, e, mkU8(0x7F));
   1485    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   1486 }
   1487 
   1488 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   1489 {
   1490    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   1491 }
   1492 
   1493 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   1494 {
   1495    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   1496 }
   1497 
   1498 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   1499 {
   1500    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   1501 }
   1502 
   1503 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   1504 {
   1505    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   1506 }
   1507 
   1508 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   1509 {
   1510    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   1511    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   1512 }
   1513 
   1514 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   1515 {
   1516    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1517 }
   1518 
   1519 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   1520 {
   1521    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   1522    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   1523 }
   1524 
   1525 
   1526 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   1527    %XER.SO accordingly. */
   1528 
   1529 static void set_XER_OV_32( UInt op, IRExpr* res,
   1530                            IRExpr* argL, IRExpr* argR )
   1531 {
   1532    IRTemp  t64;
   1533    IRExpr* xer_ov;
   1534    vassert(op < PPCG_FLAG_OP_NUMBER);
   1535    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   1536    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   1537    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   1538 
   1539 #  define INT32_MIN 0x80000000
   1540 
   1541 #  define XOR2(_aa,_bb) \
   1542       binop(Iop_Xor32,(_aa),(_bb))
   1543 
   1544 #  define XOR3(_cc,_dd,_ee) \
   1545       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   1546 
   1547 #  define AND3(_ff,_gg,_hh) \
   1548       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   1549 
   1550 #define NOT(_jj) \
   1551       unop(Iop_Not32, (_jj))
   1552 
   1553    switch (op) {
   1554    case /* 0  */ PPCG_FLAG_OP_ADD:
   1555    case /* 1  */ PPCG_FLAG_OP_ADDE:
   1556       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   1557       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   1558       xer_ov
   1559          = AND3( XOR3(argL,argR,mkU32(-1)),
   1560                  XOR2(argL,res),
   1561                  mkU32(INT32_MIN) );
   1562       /* xer_ov can only be 0 or 1<<31 */
   1563       xer_ov
   1564          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1565       break;
   1566 
   1567    case /* 2  */ PPCG_FLAG_OP_DIVW:
   1568       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   1569       xer_ov
   1570          = mkOR1(
   1571               mkAND1(
   1572                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   1573                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   1574               ),
   1575               binop(Iop_CmpEQ32, argR, mkU32(0) )
   1576            );
   1577       xer_ov
   1578          = unop(Iop_1Uto32, xer_ov);
   1579       break;
   1580 
   1581    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   1582       /* argR == 0 */
   1583       xer_ov
   1584          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   1585       break;
   1586 
   1587    case /* 4  */ PPCG_FLAG_OP_MULLW:
   1588       /* OV true if result can't be represented in 32 bits
   1589          i.e sHi != sign extension of sLo */
   1590       t64 = newTemp(Ity_I64);
   1591       assign( t64, binop(Iop_MullS32, argL, argR) );
   1592       xer_ov
   1593          = binop( Iop_CmpNE32,
   1594                   unop(Iop_64HIto32, mkexpr(t64)),
   1595                   binop( Iop_Sar32,
   1596                          unop(Iop_64to32, mkexpr(t64)),
   1597                          mkU8(31))
   1598                   );
   1599       xer_ov
   1600          = unop(Iop_1Uto32, xer_ov);
   1601       break;
   1602 
   1603    case /* 5  */ PPCG_FLAG_OP_NEG:
   1604       /* argL == INT32_MIN */
   1605       xer_ov
   1606          = unop( Iop_1Uto32,
   1607                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   1608       break;
   1609 
   1610    case /* 6  */ PPCG_FLAG_OP_SUBF:
   1611    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   1612    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   1613       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   1614       xer_ov
   1615          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   1616                  XOR2(NOT(argL),res),
   1617                  mkU32(INT32_MIN) );
   1618       /* xer_ov can only be 0 or 1<<31 */
   1619       xer_ov
   1620          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   1621       break;
   1622 
   1623    default:
   1624       vex_printf("set_XER_OV: op = %u\n", op);
   1625       vpanic("set_XER_OV(ppc)");
   1626    }
   1627 
   1628    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   1629    putXER_OV( unop(Iop_32to8, xer_ov) );
   1630 
   1631    /* Update the summary overflow */
   1632    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   1633 
   1634 #  undef INT32_MIN
   1635 #  undef AND3
   1636 #  undef XOR3
   1637 #  undef XOR2
   1638 #  undef NOT
   1639 }
   1640 
   1641 static void set_XER_OV_64( UInt op, IRExpr* res,
   1642                            IRExpr* argL, IRExpr* argR )
   1643 {
   1644    IRExpr* xer_ov;
   1645    vassert(op < PPCG_FLAG_OP_NUMBER);
   1646    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   1647    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   1648    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   1649 
   1650 #  define INT64_MIN 0x8000000000000000ULL
   1651 
   1652 #  define XOR2(_aa,_bb) \
   1653       binop(Iop_Xor64,(_aa),(_bb))
   1654 
   1655 #  define XOR3(_cc,_dd,_ee) \
   1656       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   1657 
   1658 #  define AND3(_ff,_gg,_hh) \
   1659       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   1660 
   1661 #define NOT(_jj) \
   1662       unop(Iop_Not64, (_jj))
   1663 
   1664    switch (op) {
   1665    case /* 0  */ PPCG_FLAG_OP_ADD:
   1666    case /* 1  */ PPCG_FLAG_OP_ADDE:
   1667       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   1668       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   1669       xer_ov
   1670          = AND3( XOR3(argL,argR,mkU64(-1)),
   1671                  XOR2(argL,res),
   1672                  mkU64(INT64_MIN) );
   1673       /* xer_ov can only be 0 or 1<<63 */
   1674       xer_ov
   1675          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   1676       break;
   1677 
   1678    case /* 2  */ PPCG_FLAG_OP_DIVW:
   1679       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   1680       xer_ov
   1681          = mkOR1(
   1682               mkAND1(
   1683                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   1684                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   1685               ),
   1686               binop(Iop_CmpEQ64, argR, mkU64(0) )
   1687            );
   1688       break;
   1689 
   1690    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   1691       /* argR == 0 */
   1692       xer_ov
   1693          = binop(Iop_CmpEQ64, argR, mkU64(0));
   1694       break;
   1695 
   1696    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   1697       /* OV true if result can't be represented in 64 bits
   1698          i.e sHi != sign extension of sLo */
   1699       xer_ov
   1700          = binop( Iop_CmpNE32,
   1701                   unop(Iop_64HIto32, res),
   1702                   binop( Iop_Sar32,
   1703                          unop(Iop_64to32, res),
   1704                          mkU8(31))
   1705                   );
   1706       break;
   1707    }
   1708 
   1709    case /* 5  */ PPCG_FLAG_OP_NEG:
   1710       /* argL == INT64_MIN */
   1711       xer_ov
   1712          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   1713       break;
   1714 
   1715    case /* 6  */ PPCG_FLAG_OP_SUBF:
   1716    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   1717    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   1718       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   1719       xer_ov
   1720          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   1721                  XOR2(NOT(argL),res),
   1722                  mkU64(INT64_MIN) );
   1723       /* xer_ov can only be 0 or 1<<63 */
   1724       xer_ov
   1725          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   1726       break;
   1727 
   1728    default:
   1729       vex_printf("set_XER_OV: op = %u\n", op);
   1730       vpanic("set_XER_OV(ppc64)");
   1731    }
   1732 
   1733    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   1734    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   1735 
   1736    /* Update the summary overflow */
   1737    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   1738 
   1739 #  undef INT64_MIN
   1740 #  undef AND3
   1741 #  undef XOR3
   1742 #  undef XOR2
   1743 #  undef NOT
   1744 }
   1745 
   1746 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   1747                          IRExpr* argL, IRExpr* argR )
   1748 {
   1749    if (ty == Ity_I32)
   1750       set_XER_OV_32( op, res, argL, argR );
   1751    else
   1752       set_XER_OV_64( op, res, argL, argR );
   1753 }
   1754 
   1755 
   1756 
   1757 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   1758    value being OLDCA.  Set %XER.CA accordingly. */
   1759 
   1760 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   1761                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   1762 {
   1763    IRExpr* xer_ca;
   1764    vassert(op < PPCG_FLAG_OP_NUMBER);
   1765    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   1766    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   1767    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   1768    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   1769 
   1770    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   1771       seems reasonable given that it's always generated by
   1772       getXER_CA32(), which masks it accordingly.  In any case it being
   1773       0 or 1 is an invariant of the ppc guest state representation;
   1774       if it has any other value, that invariant has been violated. */
   1775 
   1776    switch (op) {
   1777    case /* 0 */ PPCG_FLAG_OP_ADD:
   1778       /* res <u argL */
   1779       xer_ca
   1780          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   1781       break;
   1782 
   1783    case /* 1 */ PPCG_FLAG_OP_ADDE:
   1784       /* res <u argL || (old_ca==1 && res==argL) */
   1785       xer_ca
   1786          = mkOR1(
   1787               binop(Iop_CmpLT32U, res, argL),
   1788               mkAND1(
   1789                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   1790                  binop(Iop_CmpEQ32, res, argL)
   1791               )
   1792            );
   1793       xer_ca
   1794          = unop(Iop_1Uto32, xer_ca);
   1795       break;
   1796 
   1797    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   1798       /* res <u argR || (old_ca==1 && res==argR) */
   1799       xer_ca
   1800          = mkOR1(
   1801               binop(Iop_CmpLT32U, res, argR),
   1802               mkAND1(
   1803                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   1804                  binop(Iop_CmpEQ32, res, argR)
   1805               )
   1806            );
   1807       xer_ca
   1808          = unop(Iop_1Uto32, xer_ca);
   1809       break;
   1810 
   1811    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   1812    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   1813       /* res <=u argR */
   1814       xer_ca
   1815          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   1816       break;
   1817 
   1818    case /* 10 */ PPCG_FLAG_OP_SRAW:
   1819       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   1820          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   1821          bit of argL. */
   1822       /* This term valid for shift amount < 32 only */
   1823       xer_ca
   1824          = binop(
   1825               Iop_And32,
   1826               binop(Iop_Sar32, argL, mkU8(31)),
   1827               binop( Iop_And32,
   1828                      argL,
   1829                      binop( Iop_Sub32,
   1830                             binop(Iop_Shl32, mkU32(1),
   1831                                              unop(Iop_32to8,argR)),
   1832                             mkU32(1) )
   1833                      )
   1834               );
   1835       xer_ca
   1836          = IRExpr_Mux0X(
   1837               /* shift amt > 31 ? */
   1838               unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
   1839               /* no -- be like srawi */
   1840               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
   1841               /* yes -- get sign bit of argL */
   1842               binop(Iop_Shr32, argL, mkU8(31))
   1843            );
   1844       break;
   1845 
   1846    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   1847       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   1848          0.  Since the shift amount is known to be in the range
   1849          0 .. 31 inclusive the following seems viable:
   1850          xer.ca == 1 iff the following is nonzero:
   1851          (argL >>s 31)           -- either all 0s or all 1s
   1852          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   1853       xer_ca
   1854          = binop(
   1855               Iop_And32,
   1856               binop(Iop_Sar32, argL, mkU8(31)),
   1857               binop( Iop_And32,
   1858                      argL,
   1859                      binop( Iop_Sub32,
   1860                             binop(Iop_Shl32, mkU32(1),
   1861                                              unop(Iop_32to8,argR)),
   1862                             mkU32(1) )
   1863                      )
   1864               );
   1865       xer_ca
   1866          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   1867       break;
   1868 
   1869    default:
   1870       vex_printf("set_XER_CA: op = %u\n", op);
   1871       vpanic("set_XER_CA(ppc)");
   1872    }
   1873 
   1874    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   1875    putXER_CA( unop(Iop_32to8, xer_ca) );
   1876 }
   1877 
   1878 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   1879                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   1880 {
   1881    IRExpr* xer_ca;
   1882    vassert(op < PPCG_FLAG_OP_NUMBER);
   1883    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   1884    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   1885    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   1886    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   1887 
   1888    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   1889       seems reasonable given that it's always generated by
   1890       getXER_CA32(), which masks it accordingly.  In any case it being
   1891       0 or 1 is an invariant of the ppc guest state representation;
   1892       if it has any other value, that invariant has been violated. */
   1893 
   1894    switch (op) {
   1895    case /* 0 */ PPCG_FLAG_OP_ADD:
   1896       /* res <u argL */
   1897       xer_ca
   1898          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   1899       break;
   1900 
   1901    case /* 1 */ PPCG_FLAG_OP_ADDE:
   1902       /* res <u argL || (old_ca==1 && res==argL) */
   1903       xer_ca
   1904          = mkOR1(
   1905               binop(Iop_CmpLT64U, res, argL),
   1906               mkAND1(
   1907                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   1908                  binop(Iop_CmpEQ64, res, argL)
   1909                  )
   1910               );
   1911       xer_ca
   1912          = unop(Iop_1Uto32, xer_ca);
   1913       break;
   1914 
   1915    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   1916       /* res <u argR || (old_ca==1 && res==argR) */
   1917       xer_ca
   1918          = mkOR1(
   1919               binop(Iop_CmpLT64U, res, argR),
   1920               mkAND1(
   1921                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   1922                  binop(Iop_CmpEQ64, res, argR)
   1923               )
   1924            );
   1925       xer_ca
   1926          = unop(Iop_1Uto32, xer_ca);
   1927       break;
   1928 
   1929    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   1930    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   1931       /* res <=u argR */
   1932       xer_ca
   1933          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   1934       break;
   1935 
   1936 
   1937    case /* 10 */ PPCG_FLAG_OP_SRAW:
   1938       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   1939          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   1940          bit of argL. */
   1941          /* This term valid for shift amount < 31 only */
   1942 
   1943       xer_ca
   1944          = binop(
   1945               Iop_And64,
   1946               binop(Iop_Sar64, argL, mkU8(31)),
   1947               binop( Iop_And64,
   1948                      argL,
   1949                      binop( Iop_Sub64,
   1950                             binop(Iop_Shl64, mkU64(1),
   1951                                              unop(Iop_64to8,argR)),
   1952                             mkU64(1) )
   1953               )
   1954            );
   1955       xer_ca
   1956          = IRExpr_Mux0X(
   1957               /* shift amt > 31 ? */
   1958               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
   1959               /* no -- be like srawi */
   1960               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   1961               /* yes -- get sign bit of argL */
   1962               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   1963            );
   1964       break;
   1965 
   1966    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   1967       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   1968          Since the shift amount is known to be in the range 0 .. 31
   1969          inclusive the following seems viable:
   1970          xer.ca == 1 iff the following is nonzero:
   1971          (argL >>s 31)           -- either all 0s or all 1s
   1972          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   1973 
   1974       xer_ca
   1975          = binop(
   1976               Iop_And64,
   1977               binop(Iop_Sar64, argL, mkU8(31)),
   1978               binop( Iop_And64,
   1979                      argL,
   1980                      binop( Iop_Sub64,
   1981                             binop(Iop_Shl64, mkU64(1),
   1982                                              unop(Iop_64to8,argR)),
   1983                             mkU64(1) )
   1984               )
   1985            );
   1986       xer_ca
   1987          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   1988       break;
   1989 
   1990 
   1991    case /* 12 */ PPCG_FLAG_OP_SRAD:
   1992       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   1993          If it is <= 63, behave like SRADI; else XER.CA is the sign
   1994          bit of argL. */
   1995          /* This term valid for shift amount < 63 only */
   1996 
   1997       xer_ca
   1998          = binop(
   1999               Iop_And64,
   2000               binop(Iop_Sar64, argL, mkU8(63)),
   2001               binop( Iop_And64,
   2002                      argL,
   2003                      binop( Iop_Sub64,
   2004                             binop(Iop_Shl64, mkU64(1),
   2005                                              unop(Iop_64to8,argR)),
   2006                             mkU64(1) )
   2007               )
   2008            );
   2009       xer_ca
   2010          = IRExpr_Mux0X(
   2011               /* shift amt > 63 ? */
   2012               unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
   2013               /* no -- be like sradi */
   2014               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
   2015               /* yes -- get sign bit of argL */
   2016               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
   2017            );
   2018       break;
   2019 
   2020 
   2021    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2022       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2023          Since the shift amount is known to be in the range 0 .. 63
   2024          inclusive, the following seems viable:
   2025          xer.ca == 1 iff the following is nonzero:
   2026          (argL >>s 63)           -- either all 0s or all 1s
   2027          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2028 
   2029       xer_ca
   2030          = binop(
   2031               Iop_And64,
   2032               binop(Iop_Sar64, argL, mkU8(63)),
   2033               binop( Iop_And64,
   2034                      argL,
   2035                      binop( Iop_Sub64,
   2036                             binop(Iop_Shl64, mkU64(1),
   2037                                              unop(Iop_64to8,argR)),
   2038                             mkU64(1) )
   2039               )
   2040            );
   2041       xer_ca
   2042          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2043       break;
   2044 
   2045    default:
   2046       vex_printf("set_XER_CA: op = %u\n", op);
   2047       vpanic("set_XER_CA(ppc64)");
   2048    }
   2049 
   2050    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2051    putXER_CA( unop(Iop_32to8, xer_ca) );
   2052 }
   2053 
   2054 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2055                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2056 {
   2057    if (ty == Ity_I32)
   2058       set_XER_CA_32( op, res, argL, argR, oldca );
   2059    else
   2060       set_XER_CA_64( op, res, argL, argR, oldca );
   2061 }
   2062 
   2063 
   2064 
   2065 /*------------------------------------------------------------*/
   2066 /*--- Read/write to guest-state                           --- */
   2067 /*------------------------------------------------------------*/
   2068 
   2069 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2070 {
   2071    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2072    switch (reg) {
   2073    case PPC_GST_SPRG3_RO:
   2074       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2075 
   2076    case PPC_GST_CIA:
   2077       return IRExpr_Get( OFFB_CIA, ty );
   2078 
   2079    case PPC_GST_LR:
   2080       return IRExpr_Get( OFFB_LR, ty );
   2081 
   2082    case PPC_GST_CTR:
   2083       return IRExpr_Get( OFFB_CTR, ty );
   2084 
   2085    case PPC_GST_VRSAVE:
   2086       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2087 
   2088    case PPC_GST_VSCR:
   2089       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2090                               mkU32(MASK_VSCR_VALID));
   2091 
   2092    case PPC_GST_CR: {
   2093       /* Synthesise the entire CR into a single word.  Expensive. */
   2094 #     define FIELD(_n)                                               \
   2095          binop(Iop_Shl32,                                            \
   2096                unop(Iop_8Uto32,                                      \
   2097                     binop(Iop_Or8,                                   \
   2098                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2099                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2100                     )                                                \
   2101                ),                                                    \
   2102                mkU8(4 * (7-(_n)))                                    \
   2103          )
   2104       return binop(Iop_Or32,
   2105                    binop(Iop_Or32,
   2106                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2107                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2108                          ),
   2109                    binop(Iop_Or32,
   2110                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2111                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2112                          )
   2113                    );
   2114 #     undef FIELD
   2115    }
   2116 
   2117    case PPC_GST_XER:
   2118       return binop(Iop_Or32,
   2119                    binop(Iop_Or32,
   2120                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2121                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2122                    binop(Iop_Or32,
   2123                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2124                          getXER_BC32()));
   2125 
   2126    default:
   2127       vex_printf("getGST(ppc): reg = %u", reg);
   2128       vpanic("getGST(ppc)");
   2129    }
   2130 }
   2131 
   2132 /* Get a masked word from the given reg */
   2133 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2134 {
   2135    IRTemp val = newTemp(Ity_I32);
   2136    vassert( reg < PPC_GST_MAX );
   2137 
   2138    switch (reg) {
   2139 
   2140    case PPC_GST_FPSCR: {
   2141       /* Vex-generated code expects the FPSCR to be set as follows:
   2142          all exceptions masked, round-to-nearest.
   2143          This corresponds to a FPSCR value of 0x0. */
   2144 
   2145       /* We're only keeping track of the rounding mode,
   2146          so if the mask isn't asking for this, just return 0x0 */
   2147       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
   2148          assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
   2149       } else {
   2150          assign( val, mkU32(0x0) );
   2151       }
   2152       break;
   2153    }
   2154 
   2155    default:
   2156       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2157       vpanic("getGST_masked(ppc)");
   2158    }
   2159 
   2160    if (mask != 0xFFFFFFFF) {
   2161       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2162    } else {
   2163       return mkexpr(val);
   2164    }
   2165 }
   2166 
   2167 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2168    and return it at the bottom of an I32; the top 27 bits are
   2169    guaranteed to be zero. */
   2170 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2171 {
   2172    UInt shft, mask;
   2173 
   2174    vassert( fld < 8 );
   2175    vassert( reg < PPC_GST_MAX );
   2176 
   2177    shft = 4*(7-fld);
   2178    mask = 0xF<<shft;
   2179 
   2180    switch (reg) {
   2181    case PPC_GST_XER:
   2182       vassert(fld ==7);
   2183       return binop(Iop_Or32,
   2184                    binop(Iop_Or32,
   2185                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2186                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2187                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2188       break;
   2189 
   2190    default:
   2191       if (shft == 0)
   2192          return getGST_masked( reg, mask );
   2193       else
   2194          return binop(Iop_Shr32,
   2195                       getGST_masked( reg, mask ),
   2196                       mkU8(toUChar( shft )));
   2197    }
   2198 }
   2199 
   2200 static void putGST ( PPC_GST reg, IRExpr* src )
   2201 {
   2202    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2203    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2204    vassert( reg < PPC_GST_MAX );
   2205    switch (reg) {
   2206    case PPC_GST_IP_AT_SYSCALL:
   2207       vassert( ty_src == ty );
   2208       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2209       break;
   2210    case PPC_GST_CIA:
   2211       vassert( ty_src == ty );
   2212       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2213       break;
   2214    case PPC_GST_LR:
   2215       vassert( ty_src == ty );
   2216       stmt( IRStmt_Put( OFFB_LR, src ) );
   2217       break;
   2218    case PPC_GST_CTR:
   2219       vassert( ty_src == ty );
   2220       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2221       break;
   2222    case PPC_GST_VRSAVE:
   2223       vassert( ty_src == Ity_I32 );
   2224       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2225       break;
   2226    case PPC_GST_VSCR:
   2227       vassert( ty_src == Ity_I32 );
   2228       stmt( IRStmt_Put( OFFB_VSCR,
   2229                         binop(Iop_And32, src,
   2230                               mkU32(MASK_VSCR_VALID)) ) );
   2231       break;
   2232    case PPC_GST_XER:
   2233       vassert( ty_src == Ity_I32 );
   2234       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2235       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2236       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2237       putXER_BC( unop(Iop_32to8, src) );
   2238       break;
   2239 
   2240    case PPC_GST_EMWARN:
   2241       vassert( ty_src == Ity_I32 );
   2242       stmt( IRStmt_Put( OFFB_EMWARN,src) );
   2243       break;
   2244 
   2245    case PPC_GST_TISTART:
   2246       vassert( ty_src == ty );
   2247       stmt( IRStmt_Put( OFFB_TISTART, src) );
   2248       break;
   2249 
   2250    case PPC_GST_TILEN:
   2251       vassert( ty_src == ty );
   2252       stmt( IRStmt_Put( OFFB_TILEN, src) );
   2253       break;
   2254 
   2255    default:
   2256       vex_printf("putGST(ppc): reg = %u", reg);
   2257       vpanic("putGST(ppc)");
   2258    }
   2259 }
   2260 
   2261 /* Write masked src to the given reg */
   2262 static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
   2263 {
   2264    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2265    vassert( reg < PPC_GST_MAX );
   2266    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2267 
   2268    switch (reg) {
   2269    case PPC_GST_FPSCR: {
   2270       /* Allow writes to Rounding Mode */
   2271       if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
   2272          /* construct new fpround from new and old values as per mask:
   2273             new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
   2274          stmt(
   2275             IRStmt_Put(
   2276                OFFB_FPROUND,
   2277                binop(
   2278                   Iop_Or32,
   2279                   binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
   2280                   binop(
   2281                      Iop_And32,
   2282                      IRExpr_Get(OFFB_FPROUND,Ity_I32),
   2283                      mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
   2284                   )
   2285                )
   2286             )
   2287          );
   2288       }
   2289 
   2290       /* Give EmWarn for attempted writes to:
   2291          - Exception Controls
   2292          - Non-IEEE Mode
   2293       */
   2294       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   2295          VexEmWarn ew = EmWarn_PPCexns;
   2296 
   2297          /* If any of the src::exception_control bits are actually set,
   2298             side-exit to the next insn, reporting the warning,
   2299             so that Valgrind's dispatcher sees the warning. */
   2300          putGST( PPC_GST_EMWARN, mkU32(ew) );
   2301          stmt(
   2302             IRStmt_Exit(
   2303                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
   2304                Ijk_EmWarn,
   2305                mkSzConst( ty, nextInsnAddr()) ));
   2306       }
   2307 
   2308       /* Ignore all other writes */
   2309       break;
   2310    }
   2311 
   2312    default:
   2313       vex_printf("putGST_masked(ppc): reg = %u", reg);
   2314       vpanic("putGST_masked(ppc)");
   2315    }
   2316 }
   2317 
   2318 /* Write the least significant nibble of src to the specified
   2319    REG[FLD] (as per IBM/hardware notation). */
   2320 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   2321 {
   2322    UInt shft, mask;
   2323 
   2324    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   2325    vassert( fld < 8 );
   2326    vassert( reg < PPC_GST_MAX );
   2327 
   2328    shft = 4*(7-fld);
   2329    mask = 0xF<<shft;
   2330 
   2331    switch (reg) {
   2332    case PPC_GST_CR:
   2333       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   2334       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   2335       break;
   2336 
   2337    default:
   2338       if (shft == 0) {
   2339          putGST_masked( reg, src, mask );
   2340       } else {
   2341          putGST_masked( reg,
   2342                         binop(Iop_Shl32, src, mkU8(toUChar(shft))),
   2343                         mask );
   2344       }
   2345    }
   2346 }
   2347 
   2348 
   2349 
   2350 /*------------------------------------------------------------*/
   2351 /*--- Integer Instruction Translation                     --- */
   2352 /*------------------------------------------------------------*/
   2353 
   2354 /*
   2355   Integer Arithmetic Instructions
   2356 */
   2357 static Bool dis_int_arith ( UInt theInstr )
   2358 {
   2359    /* D-Form, XO-Form */
   2360    UChar opc1    = ifieldOPC(theInstr);
   2361    UChar rD_addr = ifieldRegDS(theInstr);
   2362    UChar rA_addr = ifieldRegA(theInstr);
   2363    UInt  uimm16  = ifieldUIMM16(theInstr);
   2364    UChar rB_addr = ifieldRegB(theInstr);
   2365    UChar flag_OE = ifieldBIT10(theInstr);
   2366    UInt  opc2    = ifieldOPClo9(theInstr);
   2367    UChar flag_rC = ifieldBIT0(theInstr);
   2368 
   2369    Long   simm16 = extend_s_16to64(uimm16);
   2370    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2371    IRTemp rA     = newTemp(ty);
   2372    IRTemp rB     = newTemp(ty);
   2373    IRTemp rD     = newTemp(ty);
   2374 
   2375    Bool do_rc = False;
   2376 
   2377    assign( rA, getIReg(rA_addr) );
   2378    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   2379 
   2380    switch (opc1) {
   2381    /* D-Form */
   2382    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   2383       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2384       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2385                          mkSzExtendS16(ty, uimm16) ) );
   2386       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   2387                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2388                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2389       break;
   2390 
   2391    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   2392       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2393       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2394                          mkSzExtendS16(ty, uimm16) ) );
   2395       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   2396                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2397                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2398       do_rc = True;  // Always record to CR
   2399       flag_rC = 1;
   2400       break;
   2401 
   2402    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   2403       // li rD,val   == addi rD,0,val
   2404       // la disp(rA) == addi rD,rA,disp
   2405       if ( rA_addr == 0 ) {
   2406          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   2407          assign( rD, mkSzExtendS16(ty, uimm16) );
   2408       } else {
   2409          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2410          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2411                             mkSzExtendS16(ty, uimm16) ) );
   2412       }
   2413       break;
   2414 
   2415    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   2416       // lis rD,val == addis rD,0,val
   2417       if ( rA_addr == 0 ) {
   2418          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   2419          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   2420       } else {
   2421          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
   2422          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2423                             mkSzExtendS32(ty, uimm16 << 16) ) );
   2424       }
   2425       break;
   2426 
   2427    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   2428       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2429       if (mode64)
   2430          assign( rD, unop(Iop_128to64,
   2431                           binop(Iop_MullS64, mkexpr(rA),
   2432                                 mkSzExtendS16(ty, uimm16))) );
   2433       else
   2434          assign( rD, unop(Iop_64to32,
   2435                           binop(Iop_MullS32, mkexpr(rA),
   2436                                 mkSzExtendS16(ty, uimm16))) );
   2437       break;
   2438 
   2439    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   2440       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   2441       // rD = simm16 - rA
   2442       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   2443                          mkSzExtendS16(ty, uimm16),
   2444                          mkexpr(rA)) );
   2445       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   2446                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   2447                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2448       break;
   2449 
   2450    /* XO-Form */
   2451    case 0x1F:
   2452       do_rc = True;    // All below record to CR
   2453 
   2454       switch (opc2) {
   2455       case 0x10A: // add  (Add, PPC32 p347)
   2456          DIP("add%s%s r%u,r%u,r%u\n",
   2457              flag_OE ? "o" : "", flag_rC ? ".":"",
   2458              rD_addr, rA_addr, rB_addr);
   2459          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2460                             mkexpr(rA), mkexpr(rB) ) );
   2461          if (flag_OE) {
   2462             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   2463                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2464          }
   2465          break;
   2466 
   2467       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   2468          DIP("addc%s%s r%u,r%u,r%u\n",
   2469              flag_OE ? "o" : "", flag_rC ? ".":"",
   2470              rD_addr, rA_addr, rB_addr);
   2471          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2472                             mkexpr(rA), mkexpr(rB)) );
   2473          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   2474                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   2475                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2476          if (flag_OE) {
   2477             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   2478                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2479          }
   2480          break;
   2481 
   2482       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   2483          IRTemp old_xer_ca = newTemp(ty);
   2484          DIP("adde%s%s r%u,r%u,r%u\n",
   2485              flag_OE ? "o" : "", flag_rC ? ".":"",
   2486              rD_addr, rA_addr, rB_addr);
   2487          // rD = rA + rB + XER[CA]
   2488          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2489          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2490                             binop( mkSzOp(ty, Iop_Add8),
   2491                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   2492          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   2493                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   2494                      mkexpr(old_xer_ca) );
   2495          if (flag_OE) {
   2496             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   2497                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2498          }
   2499          break;
   2500       }
   2501 
   2502       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   2503          IRTemp old_xer_ca = newTemp(ty);
   2504          IRExpr *min_one;
   2505          if (rB_addr != 0) {
   2506             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   2507             return False;
   2508          }
   2509          DIP("addme%s%s r%u,r%u,r%u\n",
   2510              flag_OE ? "o" : "", flag_rC ? ".":"",
   2511              rD_addr, rA_addr, rB_addr);
   2512          // rD = rA + (-1) + XER[CA]
   2513          // => Just another form of adde
   2514          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2515          min_one = mkSzImm(ty, (Long)-1);
   2516          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   2517                             binop( mkSzOp(ty, Iop_Add8),
   2518                                    min_one, mkexpr(old_xer_ca)) ));
   2519          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   2520                      mkexpr(rD), mkexpr(rA), min_one,
   2521                      mkexpr(old_xer_ca) );
   2522          if (flag_OE) {
   2523             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   2524                         mkexpr(rD), mkexpr(rA), min_one );
   2525          }
   2526          break;
   2527       }
   2528 
   2529       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   2530          IRTemp old_xer_ca = newTemp(ty);
   2531          if (rB_addr != 0) {
   2532             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   2533             return False;
   2534          }
   2535          DIP("addze%s%s r%u,r%u,r%u\n",
   2536              flag_OE ? "o" : "", flag_rC ? ".":"",
   2537              rD_addr, rA_addr, rB_addr);
   2538          // rD = rA + (0) + XER[CA]
   2539          // => Just another form of adde
   2540          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2541          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2542                             mkexpr(rA), mkexpr(old_xer_ca)) );
   2543          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   2544                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   2545                      mkexpr(old_xer_ca) );
   2546          if (flag_OE) {
   2547             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   2548                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   2549          }
   2550          break;
   2551       }
   2552 
   2553       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   2554          DIP("divw%s%s r%u,r%u,r%u\n",
   2555              flag_OE ? "o" : "", flag_rC ? ".":"",
   2556              rD_addr, rA_addr, rB_addr);
   2557          if (mode64) {
   2558             /* Note:
   2559                XER settings are mode independent, and reflect the
   2560                overflow of the low-order 32bit result
   2561                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   2562             */
   2563             /* rD[hi32] are undefined: setting them to sign of lo32
   2564                 - makes set_CR0 happy */
   2565             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   2566             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   2567             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   2568                                                          divisor) ) );
   2569             if (flag_OE) {
   2570                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   2571                            mkexpr(rD), dividend, divisor );
   2572             }
   2573          } else {
   2574             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   2575             if (flag_OE) {
   2576                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   2577                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2578             }
   2579          }
   2580          /* Note:
   2581             if (0x8000_0000 / -1) or (x / 0)
   2582             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   2583             => But _no_ exception raised. */
   2584          break;
   2585 
   2586       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   2587          DIP("divwu%s%s r%u,r%u,r%u\n",
   2588              flag_OE ? "o" : "", flag_rC ? ".":"",
   2589              rD_addr, rA_addr, rB_addr);
   2590          if (mode64) {
   2591             /* Note:
   2592                XER settings are mode independent, and reflect the
   2593                overflow of the low-order 32bit result
   2594                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   2595             */
   2596             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   2597             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   2598             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   2599                                                          divisor) ) );
   2600             if (flag_OE) {
   2601                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   2602                            mkexpr(rD), dividend, divisor );
   2603             }
   2604          } else {
   2605             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   2606             if (flag_OE) {
   2607                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   2608                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2609             }
   2610          }
   2611          /* Note: ditto comment divw, for (x / 0) */
   2612          break;
   2613 
   2614       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   2615          if (flag_OE != 0) {
   2616             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   2617             return False;
   2618          }
   2619          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   2620              rD_addr, rA_addr, rB_addr);
   2621          if (mode64) {
   2622             /* rD[hi32] are undefined: setting them to sign of lo32
   2623                 - makes set_CR0 happy */
   2624             assign( rD, binop(Iop_Sar64,
   2625                            binop(Iop_Mul64,
   2626                                  mk64lo32Sto64( mkexpr(rA) ),
   2627                                  mk64lo32Sto64( mkexpr(rB) )),
   2628                               mkU8(32)) );
   2629          } else {
   2630             assign( rD, unop(Iop_64HIto32,
   2631                              binop(Iop_MullS32,
   2632                                    mkexpr(rA), mkexpr(rB))) );
   2633          }
   2634          break;
   2635 
   2636       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   2637          if (flag_OE != 0) {
   2638             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   2639             return False;
   2640          }
   2641          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   2642              rD_addr, rA_addr, rB_addr);
   2643          if (mode64) {
   2644             /* rD[hi32] are undefined: setting them to sign of lo32
   2645                 - makes set_CR0 happy */
   2646             assign( rD, binop(Iop_Sar64,
   2647                            binop(Iop_Mul64,
   2648                                  mk64lo32Uto64( mkexpr(rA) ),
   2649                                  mk64lo32Uto64( mkexpr(rB) ) ),
   2650                               mkU8(32)) );
   2651          } else {
   2652             assign( rD, unop(Iop_64HIto32,
   2653                              binop(Iop_MullU32,
   2654                                    mkexpr(rA), mkexpr(rB))) );
   2655          }
   2656          break;
   2657 
   2658       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   2659          DIP("mullw%s%s r%u,r%u,r%u\n",
   2660              flag_OE ? "o" : "", flag_rC ? ".":"",
   2661              rD_addr, rA_addr, rB_addr);
   2662          if (mode64) {
   2663             /* rD[hi32] are undefined: setting them to sign of lo32
   2664                 - set_XER_OV() and set_CR0() depend on this */
   2665             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   2666             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   2667             assign( rD, binop(Iop_MullS32, a, b) );
   2668             if (flag_OE) {
   2669                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   2670                            mkexpr(rD),
   2671                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   2672             }
   2673          } else {
   2674             assign( rD, unop(Iop_64to32,
   2675                              binop(Iop_MullU32,
   2676                                    mkexpr(rA), mkexpr(rB))) );
   2677             if (flag_OE) {
   2678                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   2679                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2680             }
   2681          }
   2682          break;
   2683 
   2684       case 0x068: // neg        (Negate, PPC32 p493)
   2685          if (rB_addr != 0) {
   2686             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   2687             return False;
   2688          }
   2689          DIP("neg%s%s r%u,r%u\n",
   2690              flag_OE ? "o" : "", flag_rC ? ".":"",
   2691              rD_addr, rA_addr);
   2692          // rD = (~rA) + 1
   2693          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2694                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   2695                             mkSzImm(ty, 1)) );
   2696          if (flag_OE) {
   2697             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   2698                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2699          }
   2700          break;
   2701 
   2702       case 0x028: // subf       (Subtract From, PPC32 p537)
   2703          DIP("subf%s%s r%u,r%u,r%u\n",
   2704              flag_OE ? "o" : "", flag_rC ? ".":"",
   2705              rD_addr, rA_addr, rB_addr);
   2706          // rD = rB - rA
   2707          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   2708                             mkexpr(rB), mkexpr(rA)) );
   2709          if (flag_OE) {
   2710             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   2711                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2712          }
   2713          break;
   2714 
   2715       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   2716          DIP("subfc%s%s r%u,r%u,r%u\n",
   2717              flag_OE ? "o" : "", flag_rC ? ".":"",
   2718              rD_addr, rA_addr, rB_addr);
   2719          // rD = rB - rA
   2720          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   2721                             mkexpr(rB), mkexpr(rA)) );
   2722          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   2723                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   2724                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   2725          if (flag_OE) {
   2726             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   2727                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2728          }
   2729          break;
   2730 
   2731       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   2732          IRTemp old_xer_ca = newTemp(ty);
   2733          DIP("subfe%s%s r%u,r%u,r%u\n",
   2734              flag_OE ? "o" : "", flag_rC ? ".":"",
   2735              rD_addr, rA_addr, rB_addr);
   2736          // rD = (log not)rA + rB + XER[CA]
   2737          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2738          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2739                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   2740                             binop( mkSzOp(ty, Iop_Add8),
   2741                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   2742          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   2743                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   2744                      mkexpr(old_xer_ca) );
   2745          if (flag_OE) {
   2746             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   2747                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2748          }
   2749          break;
   2750       }
   2751 
   2752       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   2753          IRTemp old_xer_ca = newTemp(ty);
   2754          IRExpr *min_one;
   2755          if (rB_addr != 0) {
   2756             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   2757             return False;
   2758          }
   2759          DIP("subfme%s%s r%u,r%u\n",
   2760              flag_OE ? "o" : "", flag_rC ? ".":"",
   2761              rD_addr, rA_addr);
   2762          // rD = (log not)rA + (-1) + XER[CA]
   2763          // => Just another form of subfe
   2764          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2765          min_one = mkSzImm(ty, (Long)-1);
   2766          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2767                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   2768                             binop( mkSzOp(ty, Iop_Add8),
   2769                                    min_one, mkexpr(old_xer_ca))) );
   2770          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   2771                      mkexpr(rD), mkexpr(rA), min_one,
   2772                      mkexpr(old_xer_ca) );
   2773          if (flag_OE) {
   2774             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   2775                         mkexpr(rD), mkexpr(rA), min_one );
   2776          }
   2777          break;
   2778       }
   2779 
   2780       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   2781          IRTemp old_xer_ca = newTemp(ty);
   2782          if (rB_addr != 0) {
   2783             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   2784             return False;
   2785          }
   2786          DIP("subfze%s%s r%u,r%u\n",
   2787              flag_OE ? "o" : "", flag_rC ? ".":"",
   2788              rD_addr, rA_addr);
   2789          // rD = (log not)rA + (0) + XER[CA]
   2790          // => Just another form of subfe
   2791          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   2792          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   2793                            unop( mkSzOp(ty, Iop_Not8),
   2794                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   2795          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   2796                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   2797                      mkexpr(old_xer_ca) );
   2798          if (flag_OE) {
   2799             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   2800                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   2801          }
   2802          break;
   2803       }
   2804 
   2805 
   2806       /* 64bit Arithmetic */
   2807       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   2808          if (flag_OE != 0) {
   2809             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   2810             return False;
   2811          }
   2812          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   2813              rD_addr, rA_addr, rB_addr);
   2814          assign( rD, unop(Iop_128HIto64,
   2815                           binop(Iop_MullS64,
   2816                                 mkexpr(rA), mkexpr(rB))) );
   2817 
   2818          break;
   2819 
   2820       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   2821          if (flag_OE != 0) {
   2822             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   2823             return False;
   2824          }
   2825          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   2826              rD_addr, rA_addr, rB_addr);
   2827          assign( rD, unop(Iop_128HIto64,
   2828                           binop(Iop_MullU64,
   2829                                 mkexpr(rA), mkexpr(rB))) );
   2830          break;
   2831 
   2832       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   2833          DIP("mulld%s%s r%u,r%u,r%u\n",
   2834              flag_OE ? "o" : "", flag_rC ? ".":"",
   2835              rD_addr, rA_addr, rB_addr);
   2836          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   2837          if (flag_OE) {
   2838             set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   2839                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2840          }
   2841          break;
   2842 
   2843       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   2844          DIP("divd%s%s r%u,r%u,r%u\n",
   2845              flag_OE ? "o" : "", flag_rC ? ".":"",
   2846              rD_addr, rA_addr, rB_addr);
   2847          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   2848          if (flag_OE) {
   2849             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   2850                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2851          }
   2852          break;
   2853          /* Note:
   2854             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   2855             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   2856             => But _no_ exception raised. */
   2857 
   2858       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   2859          DIP("divdu%s%s r%u,r%u,r%u\n",
   2860              flag_OE ? "o" : "", flag_rC ? ".":"",
   2861              rD_addr, rA_addr, rB_addr);
   2862          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   2863          if (flag_OE) {
   2864             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   2865                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   2866          }
   2867          break;
   2868          /* Note: ditto comment divd, for (x / 0) */
   2869 
   2870       default:
   2871          vex_printf("dis_int_arith(ppc)(opc2)\n");
   2872          return False;
   2873       }
   2874       break;
   2875 
   2876    default:
   2877       vex_printf("dis_int_arith(ppc)(opc1)\n");
   2878       return False;
   2879    }
   2880 
   2881    putIReg( rD_addr, mkexpr(rD) );
   2882 
   2883    if (do_rc && flag_rC) {
   2884       set_CR0( mkexpr(rD) );
   2885    }
   2886    return True;
   2887 }
   2888 
   2889 
   2890 
   2891 /*
   2892   Integer Compare Instructions
   2893 */
   2894 static Bool dis_int_cmp ( UInt theInstr )
   2895 {
   2896    /* D-Form, X-Form */
   2897    UChar opc1    = ifieldOPC(theInstr);
   2898    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   2899    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   2900    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   2901    UChar rA_addr = ifieldRegA(theInstr);
   2902    UInt  uimm16  = ifieldUIMM16(theInstr);
   2903    UChar rB_addr = ifieldRegB(theInstr);
   2904    UInt  opc2    = ifieldOPClo10(theInstr);
   2905    UChar b0      = ifieldBIT0(theInstr);
   2906 
   2907    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2908    IRExpr *a = getIReg(rA_addr);
   2909    IRExpr *b;
   2910 
   2911    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   2912       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   2913       return False;
   2914    }
   2915 
   2916    if (b22 != 0) {
   2917       vex_printf("dis_int_cmp(ppc)(b22)\n");
   2918       return False;
   2919    }
   2920 
   2921    switch (opc1) {
   2922    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   2923       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   2924           (Int)extend_s_16to32(uimm16));
   2925       b = mkSzExtendS16( ty, uimm16 );
   2926       if (flag_L == 1) {
   2927          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   2928       } else {
   2929          a = mkNarrowTo32( ty, a );
   2930          b = mkNarrowTo32( ty, b );
   2931          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   2932       }
   2933       putCR0( crfD, getXER_SO() );
   2934       break;
   2935 
   2936    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   2937       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   2938       b = mkSzImm( ty, uimm16 );
   2939       if (flag_L == 1) {
   2940          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   2941       } else {
   2942          a = mkNarrowTo32( ty, a );
   2943          b = mkNarrowTo32( ty, b );
   2944          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   2945       }
   2946       putCR0( crfD, getXER_SO() );
   2947       break;
   2948 
   2949    /* X Form */
   2950    case 0x1F:
   2951       if (b0 != 0) {
   2952          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   2953          return False;
   2954       }
   2955       b = getIReg(rB_addr);
   2956 
   2957       switch (opc2) {
   2958       case 0x000: // cmp (Compare, PPC32 p367)
   2959          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   2960          /* Comparing a reg with itself produces a result which
   2961             doesn't depend on the contents of the reg.  Therefore
   2962             remove the false dependency, which has been known to cause
   2963             memcheck to produce false errors. */
   2964          if (rA_addr == rB_addr)
   2965             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   2966                     ? mkU64(0)  : mkU32(0);
   2967          if (flag_L == 1) {
   2968             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   2969          } else {
   2970             a = mkNarrowTo32( ty, a );
   2971             b = mkNarrowTo32( ty, b );
   2972             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   2973          }
   2974          putCR0( crfD, getXER_SO() );
   2975          break;
   2976 
   2977       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   2978          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   2979          /* Comparing a reg with itself produces a result which
   2980             doesn't depend on the contents of the reg.  Therefore
   2981             remove the false dependency, which has been known to cause
   2982             memcheck to produce false errors. */
   2983          if (rA_addr == rB_addr)
   2984             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   2985                     ? mkU64(0)  : mkU32(0);
   2986          if (flag_L == 1) {
   2987             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   2988          } else {
   2989             a = mkNarrowTo32( ty, a );
   2990             b = mkNarrowTo32( ty, b );
   2991             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   2992          }
   2993          putCR0( crfD, getXER_SO() );
   2994          break;
   2995 
   2996       default:
   2997          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   2998          return False;
   2999       }
   3000       break;
   3001 
   3002    default:
   3003       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   3004       return False;
   3005    }
   3006 
   3007    return True;
   3008 }
   3009 
   3010 
   3011 /*
   3012   Integer Logical Instructions
   3013 */
   3014 static Bool dis_int_logic ( UInt theInstr )
   3015 {
   3016    /* D-Form, X-Form */
   3017    UChar opc1    = ifieldOPC(theInstr);
   3018    UChar rS_addr = ifieldRegDS(theInstr);
   3019    UChar rA_addr = ifieldRegA(theInstr);
   3020    UInt  uimm16  = ifieldUIMM16(theInstr);
   3021    UChar rB_addr = ifieldRegB(theInstr);
   3022    UInt  opc2    = ifieldOPClo10(theInstr);
   3023    UChar flag_rC = ifieldBIT0(theInstr);
   3024 
   3025    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3026    IRTemp rS     = newTemp(ty);
   3027    IRTemp rA     = newTemp(ty);
   3028    IRTemp rB     = newTemp(ty);
   3029    IRExpr* irx;
   3030    Bool do_rc    = False;
   3031 
   3032    assign( rS, getIReg(rS_addr) );
   3033    assign( rB, getIReg(rB_addr) );
   3034 
   3035    switch (opc1) {
   3036    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   3037       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3038       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3039                          mkSzImm(ty, uimm16)) );
   3040       do_rc = True;  // Always record to CR
   3041       flag_rC = 1;
   3042       break;
   3043 
   3044    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   3045       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3046       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3047                          mkSzImm(ty, uimm16 << 16)) );
   3048       do_rc = True;  // Always record to CR
   3049       flag_rC = 1;
   3050       break;
   3051 
   3052    case 0x18: // ori (OR Immediate, PPC32 p497)
   3053       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3054       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3055                          mkSzImm(ty, uimm16)) );
   3056       break;
   3057 
   3058    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   3059       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3060       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3061                          mkSzImm(ty, uimm16 << 16)) );
   3062       break;
   3063 
   3064    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   3065       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3066       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3067                          mkSzImm(ty, uimm16)) );
   3068       break;
   3069 
   3070    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   3071       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   3072       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   3073                          mkSzImm(ty, uimm16 << 16)) );
   3074       break;
   3075 
   3076    /* X Form */
   3077    case 0x1F:
   3078       do_rc = True;    // All below record to CR
   3079 
   3080       switch (opc2) {
   3081       case 0x01C: // and (AND, PPC32 p356)
   3082          DIP("and%s r%u,r%u,r%u\n",
   3083              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3084          assign(rA, binop( mkSzOp(ty, Iop_And8),
   3085                            mkexpr(rS), mkexpr(rB)));
   3086          break;
   3087 
   3088       case 0x03C: // andc (AND with Complement, PPC32 p357)
   3089          DIP("andc%s r%u,r%u,r%u\n",
   3090              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3091          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   3092                            unop( mkSzOp(ty, Iop_Not8),
   3093                                  mkexpr(rB))));
   3094          break;
   3095 
   3096       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   3097          IRExpr* lo32;
   3098          if (rB_addr!=0) {
   3099             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   3100             return False;
   3101          }
   3102          DIP("cntlzw%s r%u,r%u\n",
   3103              flag_rC ? ".":"", rA_addr, rS_addr);
   3104 
   3105          // mode64: count in low word only
   3106          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   3107 
   3108          // Iop_Clz32 undefined for arg==0, so deal with that case:
   3109          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   3110          assign(rA, mkWidenFrom32(ty,
   3111                          IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3112                                        mkU32(32),
   3113                                        unop(Iop_Clz32, lo32)),
   3114                          False));
   3115 
   3116          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   3117          break;
   3118       }
   3119 
   3120       case 0x11C: // eqv (Equivalent, PPC32 p396)
   3121          DIP("eqv%s r%u,r%u,r%u\n",
   3122              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3123          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3124                            binop( mkSzOp(ty, Iop_Xor8),
   3125                                   mkexpr(rS), mkexpr(rB))) );
   3126          break;
   3127 
   3128       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   3129          if (rB_addr!=0) {
   3130             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   3131             return False;
   3132          }
   3133          DIP("extsb%s r%u,r%u\n",
   3134              flag_rC ? ".":"", rA_addr, rS_addr);
   3135          if (mode64)
   3136             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   3137          else
   3138             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   3139          break;
   3140 
   3141       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   3142          if (rB_addr!=0) {
   3143             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   3144             return False;
   3145          }
   3146          DIP("extsh%s r%u,r%u\n",
   3147              flag_rC ? ".":"", rA_addr, rS_addr);
   3148          if (mode64)
   3149             assign( rA, unop(Iop_16Sto64,
   3150                              unop(Iop_64to16, mkexpr(rS))) );
   3151          else
   3152             assign( rA, unop(Iop_16Sto32,
   3153                              unop(Iop_32to16, mkexpr(rS))) );
   3154          break;
   3155 
   3156       case 0x1DC: // nand (NAND, PPC32 p492)
   3157          DIP("nand%s r%u,r%u,r%u\n",
   3158              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3159          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3160                            binop( mkSzOp(ty, Iop_And8),
   3161                                   mkexpr(rS), mkexpr(rB))) );
   3162          break;
   3163 
   3164       case 0x07C: // nor (NOR, PPC32 p494)
   3165          DIP("nor%s r%u,r%u,r%u\n",
   3166              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3167          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   3168                            binop( mkSzOp(ty, Iop_Or8),
   3169                                   mkexpr(rS), mkexpr(rB))) );
   3170          break;
   3171 
   3172       case 0x1BC: // or (OR, PPC32 p495)
   3173          if ((!flag_rC) && rS_addr == rB_addr) {
   3174             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   3175             assign( rA, mkexpr(rS) );
   3176          } else {
   3177             DIP("or%s r%u,r%u,r%u\n",
   3178                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3179             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   3180                                mkexpr(rS), mkexpr(rB)) );
   3181          }
   3182          break;
   3183 
   3184       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   3185          DIP("orc%s r%u,r%u,r%u\n",
   3186              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3187          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   3188                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   3189          break;
   3190 
   3191       case 0x13C: // xor (XOR, PPC32 p549)
   3192          DIP("xor%s r%u,r%u,r%u\n",
   3193              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   3194          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   3195                             mkexpr(rS), mkexpr(rB)) );
   3196          break;
   3197 
   3198 
   3199       /* 64bit Integer Logical Instructions */
   3200       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   3201          if (rB_addr!=0) {
   3202             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   3203             return False;
   3204          }
   3205          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   3206          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   3207          break;
   3208 
   3209       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   3210          if (rB_addr!=0) {
   3211             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   3212             return False;
   3213          }
   3214          DIP("cntlzd%s r%u,r%u\n",
   3215              flag_rC ? ".":"", rA_addr, rS_addr);
   3216          // Iop_Clz64 undefined for arg==0, so deal with that case:
   3217          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   3218          assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
   3219                                   mkU64(64),
   3220                                   unop(Iop_Clz64, mkexpr(rS)) ));
   3221          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   3222          break;
   3223 
   3224       case 0x1FC: // cmpb (Power6: compare bytes)
   3225          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   3226 
   3227          if (mode64)
   3228             assign( rA, unop( Iop_V128to64,
   3229                               binop( Iop_CmpEQ8x16,
   3230                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   3231                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   3232                                      )) );
   3233          else
   3234             assign( rA, unop( Iop_V128to32,
   3235                               binop( Iop_CmpEQ8x16,
   3236                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   3237                                      unop( Iop_32UtoV128, mkexpr(rB) )
   3238                                      )) );
   3239          break;
   3240 
   3241       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   3242          IRTemp frB = newTemp(Ity_F64);
   3243          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   3244 
   3245          assign( frB, getFReg(rB_addr));  // always F64
   3246          if (mode64)
   3247             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   3248          else
   3249             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   3250 
   3251          putIReg( rS_addr, mkexpr(rA));
   3252          return True;
   3253       }
   3254 
   3255       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   3256          IRTemp frA = newTemp(Ity_F64);
   3257          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   3258 
   3259          if (mode64)
   3260             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   3261          else
   3262             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   3263 
   3264          putFReg( rS_addr, mkexpr(frA));
   3265          return True;
   3266       }
   3267 
   3268       default:
   3269          vex_printf("dis_int_logic(ppc)(opc2)\n");
   3270          return False;
   3271       }
   3272       break;
   3273 
   3274    default:
   3275       vex_printf("dis_int_logic(ppc)(opc1)\n");
   3276       return False;
   3277    }
   3278 
   3279    putIReg( rA_addr, mkexpr(rA) );
   3280 
   3281    if (do_rc && flag_rC) {
   3282       set_CR0( mkexpr(rA) );
   3283    }
   3284    return True;
   3285 }
   3286 
   3287 /*
   3288   Integer Parity Instructions
   3289 */
   3290 static Bool dis_int_parity ( UInt theInstr )
   3291 {
   3292    /* X-Form */
   3293    UChar opc1    = ifieldOPC(theInstr);
   3294    UChar rS_addr = ifieldRegDS(theInstr);
   3295    UChar rA_addr = ifieldRegA(theInstr);
   3296    UChar rB_addr = ifieldRegB(theInstr);
   3297    UInt  opc2    = ifieldOPClo10(theInstr);
   3298    UChar b0      = ifieldBIT0(theInstr);
   3299    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3300 
   3301    IRTemp rS     = newTemp(ty);
   3302    IRTemp rA     = newTemp(ty);
   3303    IRTemp iTot1  = newTemp(Ity_I32);
   3304    IRTemp iTot2  = newTemp(Ity_I32);
   3305    IRTemp iTot3  = newTemp(Ity_I32);
   3306    IRTemp iTot4  = newTemp(Ity_I32);
   3307    IRTemp iTot5  = newTemp(Ity_I32);
   3308    IRTemp iTot6  = newTemp(Ity_I32);
   3309    IRTemp iTot7  = newTemp(Ity_I32);
   3310    IRTemp iTot8  = newTemp(Ity_I32);
   3311    IRTemp rS1    = newTemp(ty);
   3312    IRTemp rS2    = newTemp(ty);
   3313    IRTemp rS3    = newTemp(ty);
   3314    IRTemp rS4    = newTemp(ty);
   3315    IRTemp rS5    = newTemp(ty);
   3316    IRTemp rS6    = newTemp(ty);
   3317    IRTemp rS7    = newTemp(ty);
   3318    IRTemp iHi    = newTemp(Ity_I32);
   3319    IRTemp iLo    = newTemp(Ity_I32);
   3320    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   3321    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   3322 
   3323    if (opc1 != 0x1f || rB_addr || b0) {
   3324       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   3325       return False;
   3326    }
   3327 
   3328    assign( rS, getIReg(rS_addr) );
   3329 
   3330    switch (opc2) {
   3331    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   3332       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   3333       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   3334       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   3335       assign( iTot2, binop(Iop_Add32,
   3336                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   3337                            mkexpr(iTot1)) );
   3338       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   3339       assign( iTot3, binop(Iop_Add32,
   3340                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   3341                            mkexpr(iTot2)) );
   3342       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   3343       assign( iTot4, binop(Iop_Add32,
   3344                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   3345                            mkexpr(iTot3)) );
   3346       if (mode64) {
   3347          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   3348          assign( iTot5, binop(Iop_Add32,
   3349                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   3350                               mkexpr(iTot4)) );
   3351          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   3352          assign( iTot6, binop(Iop_Add32,
   3353                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   3354                               mkexpr(iTot5)) );
   3355          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   3356          assign( iTot7, binop(Iop_Add32,
   3357                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   3358                               mkexpr(iTot6)) );
   3359          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   3360          assign( iTot8, binop(Iop_Add32,
   3361                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   3362                               mkexpr(iTot7)) );
   3363          assign( rA, unop(Iop_32Uto64,
   3364                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   3365       } else
   3366          assign( rA, mkexpr(iTot4) );
   3367 
   3368       break;
   3369    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   3370       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   3371       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   3372       assign( iTot2, binop(Iop_Add32,
   3373                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   3374                            mkexpr(iTot1)) );
   3375       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   3376       assign( iTot3, binop(Iop_Add32,
   3377                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   3378                            mkexpr(iTot2)) );
   3379       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   3380       assign( iTot4, binop(Iop_Add32,
   3381                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   3382                            mkexpr(iTot3)) );
   3383       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   3384 
   3385       if (mode64) {
   3386          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   3387          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   3388          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   3389          assign( iTot6, binop(Iop_Add32,
   3390                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   3391                               mkexpr(iTot5)) );
   3392          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   3393          assign( iTot7, binop(Iop_Add32,
   3394                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   3395                               mkexpr(iTot6)) );
   3396          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   3397          assign( iTot8, binop(Iop_Add32,
   3398                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   3399                               mkexpr(iTot7)) );
   3400          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   3401             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   3402       } else
   3403          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   3404       break;
   3405    default:
   3406       vex_printf("dis_int_parity(ppc)(opc2)\n");
   3407       return False;
   3408    }
   3409 
   3410    putIReg( rA_addr, mkexpr(rA) );
   3411 
   3412    return True;
   3413 }
   3414 
   3415 
   3416 /*
   3417   Integer Rotate Instructions
   3418 */
   3419 static Bool dis_int_rot ( UInt theInstr )
   3420 {
   3421    /* M-Form, MDS-Form */
   3422    UChar opc1    = ifieldOPC(theInstr);
   3423    UChar rS_addr = ifieldRegDS(theInstr);
   3424    UChar rA_addr = ifieldRegA(theInstr);
   3425    UChar rB_addr = ifieldRegB(theInstr);
   3426    UChar sh_imm  = rB_addr;
   3427    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   3428    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   3429    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   3430    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   3431    UChar b1      = ifieldBIT1(theInstr);
   3432    UChar flag_rC = ifieldBIT0(theInstr);
   3433 
   3434    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3435    IRTemp rS     = newTemp(ty);
   3436    IRTemp rA     = newTemp(ty);
   3437    IRTemp rB     = newTemp(ty);
   3438    IRTemp rot    = newTemp(ty);
   3439    IRExpr *r;
   3440    UInt   mask32;
   3441    ULong  mask64;
   3442 
   3443    assign( rS, getIReg(rS_addr) );
   3444    assign( rB, getIReg(rB_addr) );
   3445 
   3446    switch (opc1) {
   3447    case 0x14: {
   3448       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   3449       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   3450           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   3451       if (mode64) {
   3452          // tmp32 = (ROTL(rS_Lo32, Imm)
   3453          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   3454          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   3455          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   3456          r = unop(Iop_32Uto64, r);
   3457          assign( rot, binop(Iop_Or64, r,
   3458                             binop(Iop_Shl64, r, mkU8(32))) );
   3459          assign( rA,
   3460             binop(Iop_Or64,
   3461                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   3462                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   3463       }
   3464       else {
   3465          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   3466          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   3467          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   3468          assign( rA,
   3469             binop(Iop_Or32,
   3470                   binop(Iop_And32, mkU32(mask32), r),
   3471                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   3472       }
   3473       break;
   3474    }
   3475 
   3476    case 0x15: {
   3477       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   3478       vassert(MaskBeg < 32);
   3479       vassert(MaskEnd < 32);
   3480       vassert(sh_imm  < 32);
   3481 
   3482       if (mode64) {
   3483          IRTemp rTmp = newTemp(Ity_I64);
   3484          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   3485          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   3486              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   3487          // tmp32 = (ROTL(rS_Lo32, Imm)
   3488          // rA = ((tmp32 || tmp32) & mask64)
   3489          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   3490          r = unop(Iop_32Uto64, r);
   3491          assign( rTmp, r );
   3492          r = NULL;
   3493          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   3494                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   3495          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   3496       }
   3497       else {
   3498          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   3499             /* Special-case the ,n,0,31-n form as that is just n-bit
   3500                shift left, PPC32 p501 */
   3501             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   3502                 rA_addr, rS_addr, sh_imm);
   3503             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   3504          }
   3505          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   3506             /* Special-case the ,32-n,n,31 form as that is just n-bit
   3507                unsigned shift right, PPC32 p501 */
   3508             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   3509                 rA_addr, rS_addr, MaskBeg);
   3510             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   3511          }
   3512          else {
   3513             /* General case. */
   3514             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   3515             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   3516                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   3517             // rA = ROTL(rS, Imm) & mask
   3518             assign( rA, binop(Iop_And32,
   3519                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   3520                               mkU32(mask32)) );
   3521          }
   3522       }
   3523       break;
   3524    }
   3525 
   3526    case 0x17: {
   3527       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   3528       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   3529           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   3530       if (mode64) {
   3531          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   3532          /* weird insn alert!
   3533             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   3534             rA = ((tmp32 || tmp32) & mask64)
   3535          */
   3536          // note, ROTL does the masking, so we don't do it here
   3537          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   3538                    unop(Iop_64to8, mkexpr(rB)) );
   3539          r = unop(Iop_32Uto64, r);
   3540          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   3541          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   3542       } else {
   3543          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   3544          // rA = ROTL(rS, rB[0-4]) & mask
   3545          // note, ROTL does the masking, so we don't do it here
   3546          assign( rA, binop(Iop_And32,
   3547                            ROTL(mkexpr(rS),
   3548                                 unop(Iop_32to8, mkexpr(rB))),
   3549                            mkU32(mask32)) );
   3550       }
   3551       break;
   3552    }
   3553 
   3554    /* 64bit Integer Rotates */
   3555    case 0x1E: {
   3556       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   3557       sh_imm |= b1 << 5;
   3558 
   3559       vassert( msk_imm < 64 );
   3560       vassert( sh_imm < 64 );
   3561 
   3562       switch (opc2) {
   3563       case 0x4: {
   3564          /* r = ROTL64( rS, rB_lo6) */
   3565          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   3566 
   3567          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   3568             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   3569                 rA_addr, rS_addr, rB_addr, msk_imm);
   3570             // note, ROTL does the masking, so we don't do it here
   3571             mask64 = MASK64(0, 63-msk_imm);
   3572             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   3573             break;
   3574          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   3575             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   3576                 rA_addr, rS_addr, rB_addr, msk_imm);
   3577             mask64 = MASK64(63-msk_imm, 63);
   3578             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   3579             break;
   3580          }
   3581          break;
   3582       }
   3583       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   3584          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   3585              rA_addr, rS_addr, sh_imm, msk_imm);
   3586          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   3587          mask64 = MASK64(sh_imm, 63-msk_imm);
   3588          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   3589          break;
   3590          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   3591          /*
   3592            Hmm... looks like this'll do the job more simply:
   3593            r = SHL(rS, sh_imm)
   3594            m = ~(1 << (63-msk_imm))
   3595            assign(rA, r & m);
   3596          */
   3597 
   3598       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   3599          if (mode64
   3600              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   3601             /* special-case the ,64-n,n form as that is just
   3602                unsigned shift-right by n */
   3603             DIP("srdi%s r%u,r%u,%u\n",
   3604                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   3605             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   3606          } else {
   3607             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   3608                 rA_addr, rS_addr, sh_imm, msk_imm);
   3609             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   3610             mask64 = MASK64(0, 63-msk_imm);
   3611             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   3612          }
   3613          break;
   3614 
   3615       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   3616          if (mode64
   3617              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   3618             /* special-case the ,n,63-n form as that is just
   3619                shift-left by n */
   3620             DIP("sldi%s r%u,r%u,%u\n",
   3621                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   3622             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   3623          } else {
   3624             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   3625                 rA_addr, rS_addr, sh_imm, msk_imm);
   3626             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   3627             mask64 = MASK64(63-msk_imm, 63);
   3628             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   3629          }
   3630          break;
   3631 
   3632       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   3633          IRTemp rA_orig = newTemp(ty);
   3634          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   3635              rA_addr, rS_addr, sh_imm, msk_imm);
   3636          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   3637          mask64 = MASK64(sh_imm, 63-msk_imm);
   3638          assign( rA_orig, getIReg(rA_addr) );
   3639          assign( rA, binop(Iop_Or64,
   3640                            binop(Iop_And64, mkU64(mask64),  r),
   3641                            binop(Iop_And64, mkU64(~mask64),
   3642                                             mkexpr(rA_orig))) );
   3643          break;
   3644       }
   3645       default:
   3646          vex_printf("dis_int_rot(ppc)(opc2)\n");
   3647          return False;
   3648       }
   3649       break;
   3650    }
   3651 
   3652    default:
   3653       vex_printf("dis_int_rot(ppc)(opc1)\n");
   3654       return False;
   3655    }
   3656 
   3657    putIReg( rA_addr, mkexpr(rA) );
   3658 
   3659    if (flag_rC) {
   3660       set_CR0( mkexpr(rA) );
   3661    }
   3662    return True;
   3663 }
   3664 
   3665 
   3666 /*
   3667   Integer Load Instructions
   3668 */
   3669 static Bool dis_int_load ( UInt theInstr )
   3670 {
   3671    /* D-Form, X-Form, DS-Form */
   3672    UChar opc1     = ifieldOPC(theInstr);
   3673    UChar rD_addr  = ifieldRegDS(theInstr);
   3674    UChar rA_addr  = ifieldRegA(theInstr);
   3675    UInt  uimm16   = ifieldUIMM16(theInstr);
   3676    UChar rB_addr  = ifieldRegB(theInstr);
   3677    UInt  opc2     = ifieldOPClo10(theInstr);
   3678    UChar b1       = ifieldBIT1(theInstr);
   3679    UChar b0       = ifieldBIT0(theInstr);
   3680 
   3681    Int     simm16 = extend_s_16to32(uimm16);
   3682    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   3683    IRTemp  EA     = newTemp(ty);
   3684    IRExpr* val;
   3685 
   3686    switch (opc1) {
   3687    case 0x1F: // register offset
   3688       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   3689       break;
   3690    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   3691               // lowest 2 bits of immediate before forming EA
   3692       simm16 = simm16 & 0xFFFFFFFC;
   3693    default:   // immediate offset
   3694       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   3695       break;
   3696    }
   3697 
   3698    switch (opc1) {
   3699    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   3700       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3701       val = loadBE(Ity_I8, mkexpr(EA));
   3702       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   3703       break;
   3704 
   3705    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   3706       if (rA_addr == 0 || rA_addr == rD_addr) {
   3707          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   3708          return False;
   3709       }
   3710       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3711       val = loadBE(Ity_I8, mkexpr(EA));
   3712       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   3713       putIReg( rA_addr, mkexpr(EA) );
   3714       break;
   3715 
   3716    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   3717       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3718       val = loadBE(Ity_I16, mkexpr(EA));
   3719       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   3720       break;
   3721 
   3722    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   3723       if (rA_addr == 0 || rA_addr == rD_addr) {
   3724          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   3725          return False;
   3726       }
   3727       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3728       val = loadBE(Ity_I16, mkexpr(EA));
   3729       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   3730       putIReg( rA_addr, mkexpr(EA) );
   3731       break;
   3732 
   3733    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   3734       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3735       val = loadBE(Ity_I16, mkexpr(EA));
   3736       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   3737       break;
   3738 
   3739    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   3740       if (rA_addr == 0 || rA_addr == rD_addr) {
   3741          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   3742          return False;
   3743       }
   3744       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3745       val = loadBE(Ity_I16, mkexpr(EA));
   3746       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   3747       putIReg( rA_addr, mkexpr(EA) );
   3748       break;
   3749 
   3750    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   3751       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3752       val = loadBE(Ity_I32, mkexpr(EA));
   3753       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   3754       break;
   3755 
   3756    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   3757       if (rA_addr == 0 || rA_addr == rD_addr) {
   3758          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   3759          return False;
   3760       }
   3761       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   3762       val = loadBE(Ity_I32, mkexpr(EA));
   3763       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   3764       putIReg( rA_addr, mkexpr(EA) );
   3765       break;
   3766 
   3767    /* X Form */
   3768    case 0x1F:
   3769       if (b0 != 0) {
   3770          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   3771          return False;
   3772       }
   3773 
   3774       switch (opc2) {
   3775       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   3776          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3777          if (rA_addr == 0 || rA_addr == rD_addr) {
   3778             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   3779             return False;
   3780          }
   3781          val = loadBE(Ity_I8, mkexpr(EA));
   3782          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   3783          putIReg( rA_addr, mkexpr(EA) );
   3784          break;
   3785 
   3786       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   3787          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3788          val = loadBE(Ity_I8, mkexpr(EA));
   3789          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   3790          break;
   3791 
   3792       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   3793          if (rA_addr == 0 || rA_addr == rD_addr) {
   3794             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   3795             return False;
   3796          }
   3797          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3798          val = loadBE(Ity_I16, mkexpr(EA));
   3799          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   3800          putIReg( rA_addr, mkexpr(EA) );
   3801          break;
   3802 
   3803       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   3804          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3805          val = loadBE(Ity_I16, mkexpr(EA));
   3806          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   3807          break;
   3808 
   3809       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   3810          if (rA_addr == 0 || rA_addr == rD_addr) {
   3811             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   3812             return False;
   3813          }
   3814          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3815          val = loadBE(Ity_I16, mkexpr(EA));
   3816          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   3817          putIReg( rA_addr, mkexpr(EA) );
   3818          break;
   3819 
   3820       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   3821          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3822          val = loadBE(Ity_I16, mkexpr(EA));
   3823          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   3824          break;
   3825 
   3826       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   3827          if (rA_addr == 0 || rA_addr == rD_addr) {
   3828             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   3829             return False;
   3830          }
   3831          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3832          val = loadBE(Ity_I32, mkexpr(EA));
   3833          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   3834          putIReg( rA_addr, mkexpr(EA) );
   3835          break;
   3836 
   3837       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   3838          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3839          val = loadBE(Ity_I32, mkexpr(EA));
   3840          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   3841          break;
   3842 
   3843 
   3844       /* 64bit Loads */
   3845       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   3846          if (rA_addr == 0 || rA_addr == rD_addr) {
   3847             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   3848             return False;
   3849          }
   3850          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3851          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   3852          putIReg( rA_addr, mkexpr(EA) );
   3853          break;
   3854 
   3855       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   3856          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3857          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   3858          break;
   3859 
   3860       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   3861          if (rA_addr == 0 || rA_addr == rD_addr) {
   3862             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   3863             return False;
   3864          }
   3865          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3866          putIReg( rD_addr,
   3867                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   3868          putIReg( rA_addr, mkexpr(EA) );
   3869          break;
   3870 
   3871       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   3872          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   3873          putIReg( rD_addr,
   3874                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   3875          break;
   3876 
   3877       default:
   3878          vex_printf("dis_int_load(ppc)(opc2)\n");
   3879          return False;
   3880       }
   3881       break;
   3882 
   3883    /* DS Form - 64bit Loads.  In each case EA will have been formed
   3884       with the lowest 2 bits masked off the immediate offset. */
   3885    case 0x3A:
   3886       switch ((b1<<1) | b0) {
   3887       case 0x0: // ld (Load DWord, PPC64 p472)
   3888          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   3889          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   3890          break;
   3891 
   3892       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   3893          if (rA_addr == 0 || rA_addr == rD_addr) {
   3894             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   3895             return False;
   3896          }
   3897          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   3898          putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
   3899          putIReg( rA_addr, mkexpr(EA) );
   3900          break;
   3901 
   3902       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   3903          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   3904          putIReg( rD_addr,
   3905                   unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
   3906          break;
   3907 
   3908       default:
   3909          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   3910          return False;
   3911       }
   3912       break;
   3913 
   3914    default:
   3915       vex_printf("dis_int_load(ppc)(opc1)\n");
   3916       return False;
   3917    }
   3918    return True;
   3919 }
   3920 
   3921 
   3922 
   3923 /*
   3924   Integer Store Instructions
   3925 */
   3926 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
   3927 {
   3928    /* D-Form, X-Form, DS-Form */
   3929    UChar opc1    = ifieldOPC(theInstr);
   3930    UInt  rS_addr = ifieldRegDS(theInstr);
   3931    UInt  rA_addr = ifieldRegA(theInstr);
   3932    UInt  uimm16  = ifieldUIMM16(theInstr);
   3933    UInt  rB_addr = ifieldRegB(theInstr);
   3934    UInt  opc2    = ifieldOPClo10(theInstr);
   3935    UChar b1      = ifieldBIT1(theInstr);
   3936    UChar b0      = ifieldBIT0(theInstr);
   3937 
   3938    Int    simm16 = extend_s_16to32(uimm16);
   3939    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3940    IRTemp rS     = newTemp(ty);
   3941    IRTemp rB     = newTemp(ty);
   3942    IRTemp EA     = newTemp(ty);
   3943 
   3944    assign( rB, getIReg(rB_addr) );
   3945    assign( rS, getIReg(rS_addr) );
   3946 
   3947    switch (opc1) {
   3948    case 0x1F: // register offset
   3949       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   3950       break;
   3951    case 0x3E: // immediate offset: 64bit: std/stdu: mask off
   3952               // lowest 2 bits of immediate before forming EA
   3953       simm16 = simm16 & 0xFFFFFFFC;
   3954    default:   // immediate offset
   3955       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   3956       break;
   3957    }
   3958 
   3959    switch (opc1) {
   3960    case 0x26: // stb (Store B, PPC32 p509)
   3961       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   3962       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   3963       break;
   3964 
   3965    case 0x27: // stbu (Store B, Update, PPC32 p510)
   3966       if (rA_addr == 0 ) {
   3967          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   3968          return False;
   3969       }
   3970       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   3971       putIReg( rA_addr, mkexpr(EA) );
   3972       storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   3973       break;
   3974 
   3975    case 0x2C: // sth (Store HW, PPC32 p522)
   3976       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   3977       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   3978       break;
   3979 
   3980    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   3981       if (rA_addr == 0) {
   3982          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   3983          return False;
   3984       }
   3985       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   3986       putIReg( rA_addr, mkexpr(EA) );
   3987       storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   3988       break;
   3989 
   3990    case 0x24: // stw (Store W, PPC32 p530)
   3991       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   3992       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   3993       break;
   3994 
   3995    case 0x25: // stwu (Store W, Update, PPC32 p534)
   3996       if (rA_addr == 0) {
   3997          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   3998          return False;
   3999       }
   4000       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4001       putIReg( rA_addr, mkexpr(EA) );
   4002       storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4003       break;
   4004 
   4005    /* X Form : all these use EA_indexed */
   4006    case 0x1F:
   4007       if (b0 != 0) {
   4008          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   4009          return False;
   4010       }
   4011 
   4012       switch (opc2) {
   4013       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   4014          if (rA_addr == 0) {
   4015             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   4016             return False;
   4017          }
   4018          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4019          putIReg( rA_addr, mkexpr(EA) );
   4020          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4021          break;
   4022 
   4023       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   4024          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4025          storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   4026          break;
   4027 
   4028       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   4029          if (rA_addr == 0) {
   4030             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   4031             return False;
   4032          }
   4033          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4034          putIReg( rA_addr, mkexpr(EA) );
   4035          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4036          break;
   4037 
   4038       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   4039          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4040          storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   4041          break;
   4042 
   4043       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   4044          if (rA_addr == 0) {
   4045             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   4046             return False;
   4047          }
   4048          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4049          putIReg( rA_addr, mkexpr(EA) );
   4050          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4051          break;
   4052 
   4053       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   4054          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4055          storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   4056          break;
   4057 
   4058 
   4059       /* 64bit Stores */
   4060       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   4061          if (rA_addr == 0) {
   4062             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   4063             return False;
   4064          }
   4065          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4066          putIReg( rA_addr, mkexpr(EA) );
   4067          storeBE( mkexpr(EA), mkexpr(rS) );
   4068          break;
   4069 
   4070       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   4071          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4072          storeBE( mkexpr(EA), mkexpr(rS) );
   4073          break;
   4074 
   4075       default:
   4076          vex_printf("dis_int_store(ppc)(opc2)\n");
   4077          return False;
   4078       }
   4079       break;
   4080 
   4081    /* DS Form - 64bit Stores.  In each case EA will have been formed
   4082       with the lowest 2 bits masked off the immediate offset. */
   4083    case 0x3E:
   4084       switch ((b1<<1) | b0) {
   4085       case 0x0: // std (Store DWord, PPC64 p580)
   4086          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4087          storeBE( mkexpr(EA), mkexpr(rS) );
   4088          break;
   4089 
   4090       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   4091          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4092          putIReg( rA_addr, mkexpr(EA) );
   4093          storeBE( mkexpr(EA), mkexpr(rS) );
   4094          break;
   4095 
   4096       default:
   4097          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   4098          return False;
   4099       }
   4100       break;
   4101 
   4102    default:
   4103       vex_printf("dis_int_store(ppc)(opc1)\n");
   4104       return False;
   4105    }
   4106    return True;
   4107 }
   4108 
   4109 
   4110 
   4111 /*
   4112   Integer Load/Store Multiple Instructions
   4113 */
   4114 static Bool dis_int_ldst_mult ( UInt theInstr )
   4115 {
   4116    /* D-Form */
   4117    UChar opc1     = ifieldOPC(theInstr);
   4118    UChar rD_addr  = ifieldRegDS(theInstr);
   4119    UChar rS_addr  = rD_addr;
   4120    UChar rA_addr  = ifieldRegA(theInstr);
   4121    UInt  uimm16   = ifieldUIMM16(theInstr);
   4122 
   4123    Int     simm16 = extend_s_16to32(uimm16);
   4124    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   4125    IRTemp  EA     = newTemp(ty);
   4126    UInt    r      = 0;
   4127    UInt    ea_off = 0;
   4128    IRExpr* irx_addr;
   4129 
   4130    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   4131 
   4132    switch (opc1) {
   4133    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   4134       if (rA_addr >= rD_addr) {
   4135          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   4136          return False;
   4137       }
   4138       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   4139       for (r = rD_addr; r <= 31; r++) {
   4140          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4141          putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
   4142                                        False) );
   4143          ea_off += 4;
   4144       }
   4145       break;
   4146 
   4147    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   4148       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   4149       for (r = rS_addr; r <= 31; r++) {
   4150          irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
   4151          storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   4152          ea_off += 4;
   4153       }
   4154       break;
   4155 
   4156    default:
   4157       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   4158       return False;
   4159    }
   4160    return True;
   4161 }
   4162 
   4163 
   4164 
   4165 /*
   4166   Integer Load/Store String Instructions
   4167 */
   4168 static
   4169 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   4170                              IRTemp EA,        // EA
   4171                              Int    rD,        // first dst register
   4172                              Int    maxBytes ) // 32 or 128
   4173 {
   4174    Int     i, shift = 24;
   4175    IRExpr* e_nbytes = mkexpr(tNBytes);
   4176    IRExpr* e_EA     = mkexpr(EA);
   4177    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   4178 
   4179    vassert(rD >= 0 && rD < 32);
   4180    rD--; if (rD < 0) rD = 31;
   4181 
   4182    for (i = 0; i < maxBytes; i++) {
   4183       /* if (nBytes < (i+1)) goto NIA; */
   4184       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   4185                          Ijk_Boring,
   4186                          mkSzConst( ty, nextInsnAddr()) ));
   4187       /* when crossing into a new dest register, set it to zero. */
   4188       if ((i % 4) == 0) {
   4189          rD++; if (rD == 32) rD = 0;
   4190          putIReg(rD, mkSzImm(ty, 0));
   4191          shift = 24;
   4192       }
   4193       /* rD |=  (8Uto32(*(EA+i))) << shift */
   4194       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   4195       putIReg(
   4196          rD,
   4197          mkWidenFrom32(
   4198             ty,
   4199             binop(
   4200                Iop_Or32,
   4201                mkNarrowTo32(ty, getIReg(rD)),
   4202                binop(
   4203                   Iop_Shl32,
   4204                   unop(
   4205                      Iop_8Uto32,
   4206                      loadBE(Ity_I8,
   4207                             binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
   4208                   ),
   4209                   mkU8(toUChar(shift))
   4210                )
   4211             ),
   4212             /*Signed*/False
   4213 	 )
   4214       );
   4215       shift -= 8;
   4216    }
   4217 }
   4218 
   4219 static
   4220 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   4221                               IRTemp EA,        // EA
   4222                               Int    rS,        // first src register
   4223                               Int    maxBytes ) // 32 or 128
   4224 {
   4225    Int     i, shift = 24;
   4226    IRExpr* e_nbytes = mkexpr(tNBytes);
   4227    IRExpr* e_EA     = mkexpr(EA);
   4228    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   4229 
   4230    vassert(rS >= 0 && rS < 32);
   4231    rS--; if (rS < 0) rS = 31;
   4232 
   4233    for (i = 0; i < maxBytes; i++) {
   4234       /* if (nBytes < (i+1)) goto NIA; */
   4235       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   4236                          Ijk_Boring,
   4237                          mkSzConst( ty, nextInsnAddr() ) ));
   4238       /* check for crossing into a new src register. */
   4239       if ((i % 4) == 0) {
   4240          rS++; if (rS == 32) rS = 0;
   4241          shift = 24;
   4242       }
   4243       /* *(EA+i) = 32to8(rS >> shift) */
   4244       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   4245       storeBE(
   4246          binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   4247          unop(Iop_32to8,
   4248               binop(Iop_Shr32,
   4249                     mkNarrowTo32(ty, getIReg(rS)),
   4250                     mkU8(toUChar(shift))))
   4251       );
   4252       shift -= 8;
   4253    }
   4254 }
   4255 
   4256 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   4257 {
   4258    /* X-Form */
   4259    UChar opc1     = ifieldOPC(theInstr);
   4260    UChar rD_addr  = ifieldRegDS(theInstr);
   4261    UChar rS_addr  = rD_addr;
   4262    UChar rA_addr  = ifieldRegA(theInstr);
   4263    UChar rB_addr  = ifieldRegB(theInstr);
   4264    UChar NumBytes = rB_addr;
   4265    UInt  opc2     = ifieldOPClo10(theInstr);
   4266    UChar b0       = ifieldBIT0(theInstr);
   4267 
   4268    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   4269    IRTemp t_EA    = newTemp(ty);
   4270    IRTemp t_nbytes = IRTemp_INVALID;
   4271 
   4272    *stopHere = False;
   4273 
   4274    if (opc1 != 0x1F || b0 != 0) {
   4275       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   4276       return False;
   4277    }
   4278 
   4279    switch (opc2) {
   4280    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   4281       /* NB: does not reject the case where RA is in the range of
   4282          registers to be loaded.  It should. */
   4283       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   4284       assign( t_EA, ea_rAor0(rA_addr) );
   4285       if (NumBytes == 8 && !mode64) {
   4286          /* Special case hack */
   4287          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   4288          putIReg( rD_addr,
   4289                   loadBE(Ity_I32, mkexpr(t_EA)) );
   4290          putIReg( (rD_addr+1) % 32,
   4291                   loadBE(Ity_I32,
   4292                          binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   4293       } else {
   4294          t_nbytes = newTemp(Ity_I32);
   4295          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   4296          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   4297          *stopHere = True;
   4298       }
   4299       return True;
   4300 
   4301    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   4302       /* NB: does not reject the case where RA is in the range of
   4303          registers to be loaded.  It should.  Although considering
   4304          that that can only be detected at run time, it's not easy to
   4305          do so. */
   4306       if (rD_addr == rA_addr || rD_addr == rB_addr)
   4307          return False;
   4308       if (rD_addr == 0 && rA_addr == 0)
   4309          return False;
   4310       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   4311       t_nbytes = newTemp(Ity_I32);
   4312       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   4313       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   4314       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   4315       *stopHere = True;
   4316       return True;
   4317 
   4318    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   4319       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   4320       assign( t_EA, ea_rAor0(rA_addr) );
   4321       if (NumBytes == 8 && !mode64) {
   4322          /* Special case hack */
   4323          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   4324          storeBE( mkexpr(t_EA),
   4325                   getIReg(rD_addr) );
   4326          storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   4327                   getIReg((rD_addr+1) % 32) );
   4328       } else {
   4329          t_nbytes = newTemp(Ity_I32);
   4330          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   4331          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   4332          *stopHere = True;
   4333       }
   4334       return True;
   4335 
   4336    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   4337       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   4338       t_nbytes = newTemp(Ity_I32);
   4339       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   4340       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   4341       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   4342       *stopHere = True;
   4343       return True;
   4344 
   4345    default:
   4346       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   4347       return False;
   4348    }
   4349    return True;
   4350 }
   4351 
   4352 
   4353 /* ------------------------------------------------------------------
   4354    Integer Branch Instructions
   4355    ------------------------------------------------------------------ */
   4356 
   4357 /*
   4358   Branch helper function
   4359   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   4360   Returns an I32 which is 0x00000000 if the ctr condition failed
   4361   and 0xFFFFFFFF otherwise.
   4362 */
   4363 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   4364 {
   4365    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   4366    IRTemp ok = newTemp(Ity_I32);
   4367 
   4368    if ((BO >> 2) & 1) {     // independent of ctr
   4369       assign( ok, mkU32(0xFFFFFFFF) );
   4370    } else {
   4371       if ((BO >> 1) & 1) {  // ctr == 0 ?
   4372          assign( ok, unop( Iop_1Sto32,
   4373                            binop( mkSzOp(ty, Iop_CmpEQ8),
   4374                                   getGST( PPC_GST_CTR ),
   4375                                   mkSzImm(ty,0))) );
   4376       } else {              // ctr != 0 ?
   4377          assign( ok, unop( Iop_1Sto32,
   4378                            binop( mkSzOp(ty, Iop_CmpNE8),
   4379                                   getGST( PPC_GST_CTR ),
   4380                                   mkSzImm(ty,0))) );
   4381       }
   4382    }
   4383    return mkexpr(ok);
   4384 }
   4385 
   4386 
   4387 /*
   4388   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   4389   Returns an I32 which is either 0 if the condition failed or
   4390   some arbitrary nonzero value otherwise. */
   4391 
   4392 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   4393 {
   4394    Int where;
   4395    IRTemp res   = newTemp(Ity_I32);
   4396    IRTemp cr_bi = newTemp(Ity_I32);
   4397 
   4398    if ((BO >> 4) & 1) {
   4399       assign( res, mkU32(1) );
   4400    } else {
   4401       // ok = (CR[BI] == BO[3]) Note, the following relies on
   4402       // getCRbit_anywhere returning a value which
   4403       // is either zero or has exactly 1 bit set.
   4404       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   4405 
   4406       if ((BO >> 3) & 1) {
   4407          /* We can use cr_bi as-is. */
   4408          assign( res, mkexpr(cr_bi) );
   4409       } else {
   4410          /* We have to invert the sense of the information held in
   4411             cr_bi.  For that we need to know which bit
   4412             getCRbit_anywhere regards as significant. */
   4413          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   4414                                        mkU32(1<<where)) );
   4415       }
   4416    }
   4417    return mkexpr(res);
   4418 }
   4419 
   4420 
   4421 /*
   4422   Integer Branch Instructions
   4423 */
   4424 static Bool dis_branch ( UInt theInstr,
   4425                          VexAbiInfo* vbi,
   4426                          /*OUT*/DisResult* dres,
   4427                          Bool (*resteerOkFn)(void*,Addr64),
   4428                          void* callback_opaque )
   4429 {
   4430    UChar opc1    = ifieldOPC(theInstr);
   4431    UChar BO      = ifieldRegDS(theInstr);
   4432    UChar BI      = ifieldRegA(theInstr);
   4433    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   4434    UChar b11to15 = ifieldRegB(theInstr);
   4435    UInt  opc2    = ifieldOPClo10(theInstr);
   4436    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   4437    UChar flag_AA = ifieldBIT1(theInstr);
   4438    UChar flag_LK = ifieldBIT0(theInstr);
   4439 
   4440    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   4441    Addr64   tgt       = 0;
   4442    Int      BD        = extend_s_16to32(BD_u16);
   4443    IRTemp   do_branch = newTemp(Ity_I32);
   4444    IRTemp   ctr_ok    = newTemp(Ity_I32);
   4445    IRTemp   cond_ok   = newTemp(Ity_I32);
   4446    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   4447    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   4448    IRTemp   lr_old    = newTemp(ty);
   4449 
   4450    /* Hack to pass through code that just wants to read the PC */
   4451    if (theInstr == 0x429F0005) {
   4452       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   4453       putGST( PPC_GST_LR, e_nia );
   4454       return True;
   4455    }
   4456 
   4457    /* The default what-next.  Individual cases can override it. */
   4458    dres->whatNext = Dis_StopHere;
   4459 
   4460    switch (opc1) {
   4461    case 0x12: // b     (Branch, PPC32 p360)
   4462       if (flag_AA) {
   4463          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   4464       } else {
   4465          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   4466                              (Long)extend_s_26to64(LI_u26) );
   4467       }
   4468       if (mode64) {
   4469          DIP("b%s%s 0x%llx\n",
   4470              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   4471       } else {
   4472          DIP("b%s%s 0x%x\n",
   4473              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   4474       }
   4475 
   4476       if (flag_LK) {
   4477          putGST( PPC_GST_LR, e_nia );
   4478          if (vbi->guest_ppc_zap_RZ_at_bl
   4479              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   4480             IRTemp t_tgt = newTemp(ty);
   4481             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   4482             make_redzone_AbiHint( vbi, t_tgt,
   4483                                   "branch-and-link (unconditional call)" );
   4484          }
   4485       }
   4486 
   4487       if (resteerOkFn( callback_opaque, tgt )) {
   4488          dres->whatNext   = Dis_ResteerU;
   4489          dres->continueAt = tgt;
   4490       } else {
   4491          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
   4492          irsb->next     = mkSzImm(ty, tgt);
   4493       }
   4494       break;
   4495 
   4496    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   4497       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   4498           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   4499 
   4500       if (!(BO & 0x4)) {
   4501          putGST( PPC_GST_CTR,
   4502                  binop(mkSzOp(ty, Iop_Sub8),
   4503                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   4504       }
   4505 
   4506       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   4507          cond_ok is either zero or nonzero, since that's the cheapest
   4508          way to compute it.  Anding them together gives a value which
   4509          is either zero or non zero and so that's what we must test
   4510          for in the IRStmt_Exit. */
   4511       assign( ctr_ok,  branch_ctr_ok( BO ) );
   4512       assign( cond_ok, branch_cond_ok( BO, BI ) );
   4513       assign( do_branch,
   4514               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   4515 
   4516       if (flag_AA) {
   4517          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   4518       } else {
   4519          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   4520                             (Long)extend_s_16to64(BD_u16));
   4521       }
   4522       if (flag_LK)
   4523          putGST( PPC_GST_LR, e_nia );
   4524 
   4525       stmt( IRStmt_Exit(
   4526                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   4527                flag_LK ? Ijk_Call : Ijk_Boring,
   4528                mkSzConst(ty, tgt) ) );
   4529 
   4530       irsb->jumpkind = Ijk_Boring;
   4531       irsb->next     = e_nia;
   4532       break;
   4533 
   4534    case 0x13:
   4535       /* For bclr and bcctr, it appears that the lowest two bits of
   4536          b11to15 are a branch hint, and so we only need to ensure it's
   4537          of the form 000XX. */
   4538       if ((b11to15 & ~3) != 0) {
   4539          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
   4540          return False;
   4541       }
   4542 
   4543       switch (opc2) {
   4544       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   4545          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   4546             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   4547             return False;
   4548          }
   4549          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   4550 
   4551          assign( cond_ok, branch_cond_ok( BO, BI ) );
   4552 
   4553          /* FIXME: this is confusing.  lr_old holds the old value
   4554             of ctr, not lr :-) */
   4555          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   4556 
   4557          if (flag_LK)
   4558             putGST( PPC_GST_LR, e_nia );
   4559 
   4560          stmt( IRStmt_Exit(
   4561                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   4562                   Ijk_Boring,
   4563                   c_nia ));
   4564 
   4565          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   4566             make_redzone_AbiHint( vbi, lr_old,
   4567                                   "b-ctr-l (indirect call)" );
   4568 	 }
   4569 
   4570          irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
   4571          irsb->next     = mkexpr(lr_old);
   4572          break;
   4573 
   4574       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   4575          Bool vanilla_return = False;
   4576          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   4577             DIP("blr\n");
   4578             vanilla_return = True;
   4579          } else {
   4580             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   4581          }
   4582 
   4583          if (!(BO & 0x4)) {
   4584             putGST( PPC_GST_CTR,
   4585                     binop(mkSzOp(ty, Iop_Sub8),
   4586                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   4587          }
   4588 
   4589          /* See comments above for 'bc' about this */
   4590          assign( ctr_ok,  branch_ctr_ok( BO ) );
   4591          assign( cond_ok, branch_cond_ok( BO, BI ) );
   4592          assign( do_branch,
   4593                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   4594 
   4595          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   4596 
   4597          if (flag_LK)
   4598             putGST( PPC_GST_LR,  e_nia );
   4599 
   4600          stmt( IRStmt_Exit(
   4601                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   4602                   Ijk_Boring,
   4603                   c_nia ));
   4604 
   4605          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   4606             make_redzone_AbiHint( vbi, lr_old,
   4607                                   "branch-to-lr (unconditional return)" );
   4608          }
   4609 
   4610          /* blrl is pretty strange; it's like a return that sets the
   4611             return address of its caller to the insn following this
   4612             one.  Mark it as a return. */
   4613          irsb->jumpkind = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   4614          irsb->next     = mkexpr(lr_old);
   4615          break;
   4616       }
   4617       default:
   4618          vex_printf("dis_int_branch(ppc)(opc2)\n");
   4619          return False;
   4620       }
   4621       break;
   4622 
   4623    default:
   4624       vex_printf("dis_int_branch(ppc)(opc1)\n");
   4625       return False;
   4626    }
   4627 
   4628    return True;
   4629 }
   4630 
   4631 
   4632 
   4633 /*
   4634   Condition Register Logical Instructions
   4635 */
   4636 static Bool dis_cond_logic ( UInt theInstr )
   4637 {
   4638    /* XL-Form */
   4639    UChar opc1      = ifieldOPC(theInstr);
   4640    UChar crbD_addr = ifieldRegDS(theInstr);
   4641    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   4642    UChar crbA_addr = ifieldRegA(theInstr);
   4643    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   4644    UChar crbB_addr = ifieldRegB(theInstr);
   4645    UInt  opc2      = ifieldOPClo10(theInstr);
   4646    UChar b0        = ifieldBIT0(theInstr);
   4647 
   4648    IRTemp crbD     = newTemp(Ity_I32);
   4649    IRTemp crbA     = newTemp(Ity_I32);
   4650    IRTemp crbB     = newTemp(Ity_I32);
   4651 
   4652    if (opc1 != 19 || b0 != 0) {
   4653       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   4654       return False;
   4655    }
   4656 
   4657    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   4658       if (((crbD_addr & 0x3) != 0) ||
   4659           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   4660          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   4661          return False;
   4662       }
   4663       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   4664       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   4665       putCR321( crfD_addr, getCR321(crfS_addr) );
   4666    } else {
   4667       assign( crbA, getCRbit(crbA_addr) );
   4668       if (crbA_addr == crbB_addr)
   4669          crbB = crbA;
   4670       else
   4671          assign( crbB, getCRbit(crbB_addr) );
   4672 
   4673       switch (opc2) {
   4674       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   4675          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4676          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   4677          break;
   4678       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   4679          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4680          assign( crbD, binop(Iop_And32,
   4681                              mkexpr(crbA),
   4682                              unop(Iop_Not32, mkexpr(crbB))) );
   4683          break;
   4684       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   4685          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4686          assign( crbD, unop(Iop_Not32,
   4687                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   4688          break;
   4689       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   4690          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4691          assign( crbD, unop(Iop_Not32,
   4692                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   4693          break;
   4694       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   4695          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4696          assign( crbD, unop(Iop_Not32,
   4697                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   4698          break;
   4699       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   4700          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4701          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   4702          break;
   4703       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   4704          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4705          assign( crbD, binop(Iop_Or32,
   4706                              mkexpr(crbA),
   4707                              unop(Iop_Not32, mkexpr(crbB))) );
   4708          break;
   4709       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   4710          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   4711          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   4712          break;
   4713       default:
   4714          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   4715          return False;
   4716       }
   4717 
   4718       putCRbit( crbD_addr, mkexpr(crbD) );
   4719    }
   4720    return True;
   4721 }
   4722 
   4723 
   4724 /*
   4725   Trap instructions
   4726 */
   4727 
   4728 /* Do the code generation for a trap.  Returned Bool is true iff
   4729    this is an unconditional trap.  If the two arg IRExpr*s are
   4730    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   4731    then they are 64-bit, and we must be disassembling 64-bit
   4732    instructions. */
   4733 static Bool do_trap ( UChar TO,
   4734                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   4735 {
   4736    IRTemp argL, argR;
   4737    IRExpr *argLe, *argRe, *cond, *tmp;
   4738 
   4739    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   4740 
   4741    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   4742    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   4743    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   4744    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   4745    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   4746    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   4747    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   4748    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   4749    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   4750    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   4751 
   4752    const UChar b11100 = 0x1C;
   4753    const UChar b00111 = 0x07;
   4754 
   4755    if (is32bit) {
   4756       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   4757       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   4758    } else {
   4759       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   4760       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   4761       vassert( mode64 );
   4762    }
   4763 
   4764    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   4765       /* Unconditional trap.  Just do the exit without
   4766          testing the arguments. */
   4767       stmt( IRStmt_Exit(
   4768                binop(opCMPEQ, const0, const0),
   4769                Ijk_SigTRAP,
   4770                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
   4771       ));
   4772       return True; /* unconditional trap */
   4773    }
   4774 
   4775    if (is32bit) {
   4776       argL = newTemp(Ity_I32);
   4777       argR = newTemp(Ity_I32);
   4778    } else {
   4779       argL = newTemp(Ity_I64);
   4780       argR = newTemp(Ity_I64);
   4781    }
   4782 
   4783    assign( argL, argL0 );
   4784    assign( argR, argR0 );
   4785 
   4786    argLe = mkexpr(argL);
   4787    argRe = mkexpr(argR);
   4788 
   4789    cond = const0;
   4790    if (TO & 16) { // L <s R
   4791       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   4792       cond = binop(opOR, tmp, cond);
   4793    }
   4794    if (TO & 8) { // L >s R
   4795       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   4796       cond = binop(opOR, tmp, cond);
   4797    }
   4798    if (TO & 4) { // L == R
   4799       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   4800       cond = binop(opOR, tmp, cond);
   4801    }
   4802    if (TO & 2) { // L <u R
   4803       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   4804       cond = binop(opOR, tmp, cond);
   4805    }
   4806    if (TO & 1) { // L >u R
   4807       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   4808       cond = binop(opOR, tmp, cond);
   4809    }
   4810    stmt( IRStmt_Exit(
   4811             binop(opCMPNE, cond, const0),
   4812             Ijk_SigTRAP,
   4813             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
   4814    ));
   4815    return False; /* not an unconditional trap */
   4816 }
   4817 
   4818 static Bool dis_trapi ( UInt theInstr,
   4819                         /*OUT*/DisResult* dres )
   4820 {
   4821    /* D-Form */
   4822    UChar  opc1    = ifieldOPC(theInstr);
   4823    UChar  TO      = ifieldRegDS(theInstr);
   4824    UChar  rA_addr = ifieldRegA(theInstr);
   4825    UInt   uimm16  = ifieldUIMM16(theInstr);
   4826    ULong  simm16  = extend_s_16to64(uimm16);
   4827    Addr64 cia     = guest_CIA_curr_instr;
   4828    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   4829    Bool   uncond  = False;
   4830 
   4831    switch (opc1) {
   4832    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   4833       uncond = do_trap( TO,
   4834                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   4835                                : getIReg(rA_addr),
   4836                         mkU32( (UInt)simm16 ),
   4837                         cia );
   4838       if (TO == 4) {
   4839          DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   4840       } else {
   4841          DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   4842       }
   4843       break;
   4844    case 0x02: // tdi
   4845       if (!mode64)
   4846          return False;
   4847       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   4848       if (TO == 4) {
   4849          DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
   4850       } else {
   4851          DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
   4852       }
   4853       break;
   4854    default:
   4855       return False;
   4856    }
   4857 
   4858    if (uncond) {
   4859       /* If the trap shows signs of being unconditional, don't
   4860          continue decoding past it. */
   4861       irsb->next     = mkSzImm( ty, nextInsnAddr() );
   4862       irsb->jumpkind = Ijk_Boring;
   4863       dres->whatNext = Dis_StopHere;
   4864    }
   4865 
   4866    return True;
   4867 }
   4868 
   4869 static Bool dis_trap ( UInt theInstr,
   4870                         /*OUT*/DisResult* dres )
   4871 {
   4872    /* X-Form */
   4873    UInt   opc2    = ifieldOPClo10(theInstr);
   4874    UChar  TO      = ifieldRegDS(theInstr);
   4875    UChar  rA_addr = ifieldRegA(theInstr);
   4876    UChar  rB_addr = ifieldRegB(theInstr);
   4877    Addr64 cia     = guest_CIA_curr_instr;
   4878    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   4879    Bool   uncond  = False;
   4880 
   4881    if (ifieldBIT0(theInstr) != 0)
   4882       return False;
   4883 
   4884    switch (opc2) {
   4885    case 0x004: // tw  (Trap Word, PPC64 p540)
   4886       uncond = do_trap( TO,
   4887                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   4888                                : getIReg(rA_addr),
   4889                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   4890                                : getIReg(rB_addr),
   4891                         cia );
   4892       if (TO == 4) {
   4893          DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   4894       } else {
   4895          DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   4896       }
   4897       break;
   4898    case 0x044: // td (Trap Doubleword, PPC64 p534)
   4899       if (!mode64)
   4900          return False;
   4901       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   4902       if (TO == 4) {
   4903          DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
   4904       } else {
   4905          DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
   4906       }
   4907       break;
   4908    default:
   4909       return False;
   4910    }
   4911 
   4912    if (uncond) {
   4913       /* If the trap shows signs of being unconditional, don't
   4914          continue decoding past it. */
   4915       irsb->next     = mkSzImm( ty, nextInsnAddr() );
   4916       irsb->jumpkind = Ijk_Boring;
   4917       dres->whatNext = Dis_StopHere;
   4918    }
   4919 
   4920    return True;
   4921 }
   4922 
   4923 
   4924 /*
   4925   System Linkage Instructions
   4926 */
   4927 static Bool dis_syslink ( UInt theInstr,
   4928                           VexAbiInfo* abiinfo, DisResult* dres )
   4929 {
   4930    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   4931 
   4932    if (theInstr != 0x44000002) {
   4933       vex_printf("dis_syslink(ppc)(theInstr)\n");
   4934       return False;
   4935    }
   4936 
   4937    // sc  (System Call, PPC32 p504)
   4938    DIP("sc\n");
   4939 
   4940    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
   4941       Valgrind can back the guest up to this instruction if it needs
   4942       to restart the syscall. */
   4943    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   4944 
   4945    /* It's important that all ArchRegs carry their up-to-date value
   4946       at this point.  So we declare an end-of-block here, which
   4947       forces any TempRegs caching ArchRegs to be flushed. */
   4948    irsb->next     = abiinfo->guest_ppc_sc_continues_at_LR
   4949                        ? getGST( PPC_GST_LR )
   4950                        : mkSzImm( ty, nextInsnAddr() );
   4951    irsb->jumpkind = Ijk_Sys_syscall;
   4952 
   4953    dres->whatNext = Dis_StopHere;
   4954    return True;
   4955 }
   4956 
   4957 
   4958 /*
   4959   Memory Synchronization Instructions
   4960 
   4961   Note on Reservations:
   4962   We rely on the assumption that V will in fact only allow one thread at
   4963   once to run.  In effect, a thread can make a reservation, but we don't
   4964   check any stores it does.  Instead, the reservation is cancelled when
   4965   the scheduler switches to another thread (run_thread_for_a_while()).
   4966 */
   4967 static Bool dis_memsync ( UInt theInstr )
   4968 {
   4969    /* X-Form, XL-Form */
   4970    UChar opc1    = ifieldOPC(theInstr);
   4971    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   4972    UChar flag_L  = ifieldRegDS(theInstr);
   4973    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   4974    UChar rD_addr = ifieldRegDS(theInstr);
   4975    UChar rS_addr = rD_addr;
   4976    UChar rA_addr = ifieldRegA(theInstr);
   4977    UChar rB_addr = ifieldRegB(theInstr);
   4978    UInt  opc2    = ifieldOPClo10(theInstr);
   4979    UChar b0      = ifieldBIT0(theInstr);
   4980 
   4981    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4982    IRTemp EA     = newTemp(ty);
   4983 
   4984    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   4985 
   4986    switch (opc1) {
   4987    /* XL-Form */
   4988    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   4989       if (opc2 != 0x096) {
   4990          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   4991          return False;
   4992       }
   4993       if (b11to25 != 0 || b0 != 0) {
   4994          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   4995          return False;
   4996       }
   4997       DIP("isync\n");
   4998       stmt( IRStmt_MBE(Imbe_Fence) );
   4999       break;
   5000 
   5001    /* X-Form */
   5002    case 0x1F:
   5003       switch (opc2) {
   5004       case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
   5005          if (b11to25 != 0 || b0 != 0) {
   5006             vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
   5007             return False;
   5008          }
   5009          DIP("eieio\n");
   5010          /* Insert a memory fence, just to be on the safe side. */
   5011          stmt( IRStmt_MBE(Imbe_Fence) );
   5012          break;
   5013 
   5014       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   5015          IRTemp res;
   5016          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5017             in the documentation) is merely a hint bit to the
   5018             hardware, I think as to whether or not contention is
   5019             likely.  So we can just ignore it. */
   5020          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5021 
   5022          // trap if misaligned
   5023          gen_SIGBUS_if_misaligned( EA, 4 );
   5024 
   5025          // and actually do the load
   5026          res = newTemp(Ity_I32);
   5027          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5028 
   5029          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   5030          break;
   5031       }
   5032 
   5033       case 0x096: {
   5034          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   5035          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   5036          // so isn't quite as straightforward as it might otherwise be.
   5037          IRTemp rS = newTemp(Ity_I32);
   5038          IRTemp resSC;
   5039          if (b0 != 1) {
   5040             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   5041             return False;
   5042          }
   5043          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5044 
   5045          // trap if misaligned
   5046          gen_SIGBUS_if_misaligned( EA, 4 );
   5047 
   5048          // Get the data to be stored, and narrow to 32 bits if necessary
   5049          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   5050 
   5051          // Do the store, and get success/failure bit into resSC
   5052          resSC = newTemp(Ity_I1);
   5053          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5054 
   5055          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5056          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5057          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5058          putCR0(0, getXER_SO());
   5059 
   5060          /* Note:
   5061             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5062             whether rS is stored is dependent on that value. */
   5063          /* So I guess we can just ignore this case? */
   5064          break;
   5065       }
   5066 
   5067       case 0x256: // sync (Synchronize, PPC32 p543),
   5068                   // also lwsync (L==1), ptesync (L==2)
   5069          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   5070 
   5071             The PowerPC architecture used in IBM chips has expanded
   5072             the sync instruction into two variants: lightweight sync
   5073             and heavyweight sync.  The original sync instruction is
   5074             the new heavyweight sync and lightweight sync is a strict
   5075             subset of the heavyweight sync functionality. This allows
   5076             the programmer to specify a less expensive operation on
   5077             high-end systems when the full sync functionality is not
   5078             necessary.
   5079 
   5080             The basic "sync" mnemonic now utilizes an operand. "sync"
   5081             without an operand now becomes a extended mnemonic for
   5082             heavyweight sync.  Processors without the lwsync
   5083             instruction will not decode the L field and will perform a
   5084             heavyweight sync.  Everything is backward compatible.
   5085 
   5086             sync    =       sync 0
   5087             lwsync  =       sync 1
   5088             ptesync =       sync 2    *** TODO - not implemented ***
   5089          */
   5090          if (b11to20 != 0 || b0 != 0) {
   5091             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   5092             return False;
   5093          }
   5094          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   5095             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   5096             return False;
   5097          }
   5098          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   5099          /* Insert a memory fence.  It's sometimes important that these
   5100             are carried through to the generated code. */
   5101          stmt( IRStmt_MBE(Imbe_Fence) );
   5102          break;
   5103 
   5104       /* 64bit Memsync */
   5105       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   5106          IRTemp res;
   5107          /* According to the PowerPC ISA version 2.05, b0 (called EH
   5108             in the documentation) is merely a hint bit to the
   5109             hardware, I think as to whether or not contention is
   5110             likely.  So we can just ignore it. */
   5111          if (!mode64)
   5112             return False;
   5113          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
   5114 
   5115          // trap if misaligned
   5116          gen_SIGBUS_if_misaligned( EA, 8 );
   5117 
   5118          // and actually do the load
   5119          res = newTemp(Ity_I64);
   5120          stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
   5121 
   5122          putIReg( rD_addr, mkexpr(res) );
   5123          break;
   5124       }
   5125 
   5126       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   5127          // A marginally simplified version of the stwcx. case
   5128          IRTemp rS = newTemp(Ity_I64);
   5129          IRTemp resSC;
   5130          if (b0 != 1) {
   5131             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   5132             return False;
   5133          }
   5134          if (!mode64)
   5135             return False;
   5136          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5137 
   5138          // trap if misaligned
   5139          gen_SIGBUS_if_misaligned( EA, 8 );
   5140 
   5141          // Get the data to be stored
   5142          assign( rS, getIReg(rS_addr) );
   5143 
   5144          // Do the store, and get success/failure bit into resSC
   5145          resSC = newTemp(Ity_I1);
   5146          stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
   5147 
   5148          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   5149          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   5150          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   5151          putCR0(0, getXER_SO());
   5152 
   5153          /* Note:
   5154             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   5155             whether rS is stored is dependent on that value. */
   5156          /* So I guess we can just ignore this case? */
   5157          break;
   5158       }
   5159 
   5160       default:
   5161          vex_printf("dis_memsync(ppc)(opc2)\n");
   5162          return False;
   5163       }
   5164       break;
   5165 
   5166    default:
   5167       vex_printf("dis_memsync(ppc)(opc1)\n");
   5168       return False;
   5169    }
   5170    return True;
   5171 }
   5172 
   5173 
   5174 
   5175 /*
   5176   Integer Shift Instructions
   5177 */
   5178 static Bool dis_int_shift ( UInt theInstr )
   5179 {
   5180    /* X-Form, XS-Form */
   5181    UChar opc1    = ifieldOPC(theInstr);
   5182    UChar rS_addr = ifieldRegDS(theInstr);
   5183    UChar rA_addr = ifieldRegA(theInstr);
   5184    UChar rB_addr = ifieldRegB(theInstr);
   5185    UChar sh_imm  = rB_addr;
   5186    UInt  opc2    = ifieldOPClo10(theInstr);
   5187    UChar b1      = ifieldBIT1(theInstr);
   5188    UChar flag_rC = ifieldBIT0(theInstr);
   5189 
   5190    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   5191    IRTemp  rA         = newTemp(ty);
   5192    IRTemp  rS         = newTemp(ty);
   5193    IRTemp  rB         = newTemp(ty);
   5194    IRTemp  outofrange = newTemp(Ity_I8);
   5195    IRTemp  rS_lo32    = newTemp(Ity_I32);
   5196    IRTemp  rB_lo32    = newTemp(Ity_I32);
   5197    IRExpr* e_tmp;
   5198 
   5199    assign( rS, getIReg(rS_addr) );
   5200    assign( rB, getIReg(rB_addr) );
   5201    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   5202    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   5203 
   5204    if (opc1 == 0x1F) {
   5205       switch (opc2) {
   5206       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   5207          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   5208              rA_addr, rS_addr, rB_addr);
   5209          /* rA = rS << rB */
   5210          /* ppc32 semantics are:
   5211             slw(x,y) = (x << (y & 31))         -- primary result
   5212                        & ~((y << 26) >>s 31)   -- make result 0
   5213                                                   for y in 32 .. 63
   5214          */
   5215          e_tmp =
   5216             binop( Iop_And32,
   5217                binop( Iop_Shl32,
   5218                       mkexpr(rS_lo32),
   5219                       unop( Iop_32to8,
   5220                             binop(Iop_And32,
   5221                                   mkexpr(rB_lo32), mkU32(31)))),
   5222                unop( Iop_Not32,
   5223                      binop( Iop_Sar32,
   5224                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   5225                             mkU8(31))) );
   5226          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   5227          break;
   5228       }
   5229 
   5230       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   5231          IRTemp sh_amt = newTemp(Ity_I32);
   5232          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   5233              rA_addr, rS_addr, rB_addr);
   5234          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   5235             amt = rB & 63
   5236             rA = Sar32( rS, amt > 31 ? 31 : amt )
   5237             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   5238          */
   5239          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   5240                                           mkexpr(rB_lo32)) );
   5241          assign( outofrange,
   5242                  unop( Iop_1Uto8,
   5243                        binop(Iop_CmpLT32U, mkU32(31),
   5244                                            mkexpr(sh_amt)) ));
   5245          e_tmp = binop( Iop_Sar32,
   5246                         mkexpr(rS_lo32),
   5247                         unop( Iop_32to8,
   5248                               IRExpr_Mux0X( mkexpr(outofrange),
   5249                                             mkexpr(sh_amt),
   5250                                             mkU32(31)) ) );
   5251          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   5252 
   5253          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   5254                      mkexpr(rA),
   5255                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   5256                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   5257                      mkWidenFrom32(ty, getXER_CA32(), True) );
   5258          break;
   5259       }
   5260 
   5261       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   5262          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   5263              rA_addr, rS_addr, sh_imm);
   5264          vassert(sh_imm < 32);
   5265          if (mode64) {
   5266             assign( rA, binop(Iop_Sar64,
   5267                               binop(Iop_Shl64, getIReg(rS_addr),
   5268                                                mkU8(32)),
   5269                               mkU8(32 + sh_imm)) );
   5270          } else {
   5271             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   5272                                          mkU8(sh_imm)) );
   5273          }
   5274 
   5275          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   5276                      mkexpr(rA),
   5277                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   5278                      mkSzImm(ty, sh_imm),
   5279                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   5280          break;
   5281 
   5282       case 0x218: // srw (Shift Right Word, PPC32 p508)
   5283          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   5284              rA_addr, rS_addr, rB_addr);
   5285          /* rA = rS >>u rB */
   5286          /* ppc32 semantics are:
   5287             srw(x,y) = (x >>u (y & 31))        -- primary result
   5288                        & ~((y << 26) >>s 31)   -- make result 0
   5289                                                   for y in 32 .. 63
   5290          */
   5291          e_tmp =
   5292             binop(
   5293                Iop_And32,
   5294                binop( Iop_Shr32,
   5295                       mkexpr(rS_lo32),
   5296                       unop( Iop_32to8,
   5297                             binop(Iop_And32, mkexpr(rB_lo32),
   5298                                              mkU32(31)))),
   5299                unop( Iop_Not32,
   5300                      binop( Iop_Sar32,
   5301                             binop(Iop_Shl32, mkexpr(rB_lo32),
   5302                                              mkU8(26)),
   5303                             mkU8(31))));
   5304          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   5305          break;
   5306 
   5307 
   5308       /* 64bit Shifts */
   5309       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   5310          DIP("sld%s r%u,r%u,r%u\n",
   5311              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   5312          /* rA = rS << rB */
   5313          /* ppc64 semantics are:
   5314             slw(x,y) = (x << (y & 63))         -- primary result
   5315                        & ~((y << 57) >>s 63)   -- make result 0
   5316                                                   for y in 64 ..
   5317          */
   5318          assign( rA,
   5319             binop(
   5320                Iop_And64,
   5321                binop( Iop_Shl64,
   5322                       mkexpr(rS),
   5323                       unop( Iop_64to8,
   5324                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   5325                unop( Iop_Not64,
   5326                      binop( Iop_Sar64,
   5327                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   5328                             mkU8(63)))) );
   5329          break;
   5330 
   5331       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   5332          IRTemp sh_amt = newTemp(Ity_I64);
   5333          DIP("srad%s r%u,r%u,r%u\n",
   5334              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   5335          /* amt = rB & 127
   5336             rA = Sar64( rS, amt > 63 ? 63 : amt )
   5337             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   5338          */
   5339          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   5340          assign( outofrange,
   5341                  unop( Iop_1Uto8,
   5342                        binop(Iop_CmpLT64U, mkU64(63),
   5343                                            mkexpr(sh_amt)) ));
   5344          assign( rA,
   5345                  binop( Iop_Sar64,
   5346                         mkexpr(rS),
   5347                         unop( Iop_64to8,
   5348                               IRExpr_Mux0X( mkexpr(outofrange),
   5349                                             mkexpr(sh_amt),
   5350                                             mkU64(63)) ))
   5351                );
   5352          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   5353                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   5354                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   5355          break;
   5356       }
   5357 
   5358       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   5359          sh_imm |= b1<<5;
   5360          vassert(sh_imm < 64);
   5361          DIP("sradi%s r%u,r%u,%u\n",
   5362              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   5363          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   5364 
   5365          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   5366                      mkexpr(rA),
   5367                      getIReg(rS_addr),
   5368                      mkU64(sh_imm),
   5369                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   5370          break;
   5371 
   5372       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   5373          DIP("srd%s r%u,r%u,r%u\n",
   5374              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   5375          /* rA = rS >>u rB */
   5376          /* ppc semantics are:
   5377             srw(x,y) = (x >>u (y & 63))        -- primary result
   5378                        & ~((y << 57) >>s 63)   -- make result 0
   5379                                                   for y in 64 .. 127
   5380          */
   5381          assign( rA,
   5382             binop(
   5383                Iop_And64,
   5384                binop( Iop_Shr64,
   5385                       mkexpr(rS),
   5386                       unop( Iop_64to8,
   5387                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   5388                unop( Iop_Not64,
   5389                      binop( Iop_Sar64,
   5390                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   5391                             mkU8(63)))) );
   5392          break;
   5393 
   5394       default:
   5395          vex_printf("dis_int_shift(ppc)(opc2)\n");
   5396          return False;
   5397       }
   5398    } else {
   5399       vex_printf("dis_int_shift(ppc)(opc1)\n");
   5400       return False;
   5401    }
   5402 
   5403    putIReg( rA_addr, mkexpr(rA) );
   5404 
   5405    if (flag_rC) {
   5406       set_CR0( mkexpr(rA) );
   5407    }
   5408    return True;
   5409 }
   5410 
   5411 
   5412 
   5413 /*
   5414   Integer Load/Store Reverse Instructions
   5415 */
   5416 /* Generates code to swap the byte order in an Ity_I32. */
   5417 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   5418 {
   5419    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   5420    return
   5421       binop(Iop_Or32,
   5422          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   5423       binop(Iop_Or32,
   5424          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   5425                           mkU32(0x00FF0000)),
   5426       binop(Iop_Or32,
   5427          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   5428                           mkU32(0x0000FF00)),
   5429          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   5430                           mkU32(0x000000FF) )
   5431       )));
   5432 }
   5433 
   5434 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   5435    and zeroes the upper half. */
   5436 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   5437 {
   5438    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   5439    return
   5440       binop(Iop_Or32,
   5441          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   5442                           mkU32(0x0000FF00)),
   5443          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   5444                           mkU32(0x000000FF))
   5445       );
   5446 }
   5447 
   5448 static Bool dis_int_ldst_rev ( UInt theInstr )
   5449 {
   5450    /* X-Form */
   5451    UChar opc1    = ifieldOPC(theInstr);
   5452    UChar rD_addr = ifieldRegDS(theInstr);
   5453    UChar rS_addr = rD_addr;
   5454    UChar rA_addr = ifieldRegA(theInstr);
   5455    UChar rB_addr = ifieldRegB(theInstr);
   5456    UInt  opc2    = ifieldOPClo10(theInstr);
   5457    UChar b0      = ifieldBIT0(theInstr);
   5458 
   5459    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5460    IRTemp EA = newTemp(ty);
   5461    IRTemp w1 = newTemp(Ity_I32);
   5462    IRTemp w2 = newTemp(Ity_I32);
   5463 
   5464    if (opc1 != 0x1F || b0 != 0) {
   5465       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   5466       return False;
   5467    }
   5468 
   5469    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5470 
   5471    switch (opc2) {
   5472 
   5473       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   5474          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5475          assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
   5476          assign( w2, gen_byterev16(w1) );
   5477          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   5478                                          /* Signed */False) );
   5479          break;
   5480 
   5481       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   5482          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5483          assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
   5484          assign( w2, gen_byterev32(w1) );
   5485          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   5486                                          /* Signed */False) );
   5487          break;
   5488 
   5489       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   5490          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5491          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   5492          storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   5493          break;
   5494 
   5495       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   5496          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5497          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   5498          storeBE( mkexpr(EA), gen_byterev32(w1) );
   5499          break;
   5500 
   5501       default:
   5502          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   5503          return False;
   5504    }
   5505    return True;
   5506 }
   5507 
   5508 
   5509 
   5510 /*
   5511   Processor Control Instructions
   5512 */
   5513 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
   5514 {
   5515    UChar opc1     = ifieldOPC(theInstr);
   5516 
   5517    /* X-Form */
   5518    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   5519    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   5520    UChar rD_addr  = ifieldRegDS(theInstr);
   5521    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   5522 
   5523    /* XFX-Form */
   5524    UChar rS_addr  = rD_addr;
   5525    UInt  SPR      = b11to20;
   5526    UInt  TBR      = b11to20;
   5527    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   5528    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   5529    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   5530 
   5531    UInt  opc2     = ifieldOPClo10(theInstr);
   5532    UChar b0       = ifieldBIT0(theInstr);
   5533 
   5534    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5535    IRTemp rS = newTemp(ty);
   5536    assign( rS, getIReg(rS_addr) );
   5537 
   5538    /* Reorder SPR field as per PPC32 p470 */
   5539    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   5540    /* Reorder TBR field as per PPC32 p475 */
   5541    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   5542 
   5543    if (opc1 != 0x1F || b0 != 0) {
   5544       vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
   5545       return False;
   5546    }
   5547 
   5548    switch (opc2) {
   5549    /* X-Form */
   5550    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   5551       if (b21to22 != 0 || b11to20 != 0) {
   5552          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   5553          return False;
   5554       }
   5555       DIP("mcrxr crf%d\n", crfD);
   5556       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   5557       putGST_field( PPC_GST_CR,
   5558                     getGST_field( PPC_GST_XER, 7 ),
   5559                     crfD );
   5560 
   5561       // Clear XER[0-3]
   5562       putXER_SO( mkU8(0) );
   5563       putXER_OV( mkU8(0) );
   5564       putXER_CA( mkU8(0) );
   5565       break;
   5566    }
   5567 
   5568    case 0x013:
   5569       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   5570       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   5571       // However it seems that the 'mfcr' behaviour is an acceptable
   5572       // implementation of mfocr (from the 2.02 arch spec)
   5573       if (b11to20 == 0) {
   5574          DIP("mfcr r%u\n", rD_addr);
   5575          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   5576                                          /* Signed */False) );
   5577          break;
   5578       }
   5579       if (b20 == 1 && b11 == 0) {
   5580          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   5581          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   5582                                          /* Signed */False) );
   5583          break;
   5584       }
   5585       /* not decodable */
   5586       return False;
   5587 
   5588    /* XFX-Form */
   5589    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   5590 
   5591       switch (SPR) {  // Choose a register...
   5592       case 0x1:
   5593          DIP("mfxer r%u\n", rD_addr);
   5594          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   5595                                          /* Signed */False) );
   5596          break;
   5597       case 0x8:
   5598          DIP("mflr r%u\n", rD_addr);
   5599          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   5600          break;
   5601       case 0x9:
   5602          DIP("mfctr r%u\n", rD_addr);
   5603          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   5604          break;
   5605       case 0x100:
   5606          DIP("mfvrsave r%u\n", rD_addr);
   5607          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   5608                                          /* Signed */False) );
   5609          break;
   5610 
   5611       case 0x103:
   5612          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   5613          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   5614          break;
   5615 
   5616       /* Even a lowly PPC7400 can run the associated helper, so no
   5617          obvious need for feature testing at this point. */
   5618       case 268 /* 0x10C */:
   5619       case 269 /* 0x10D */: {
   5620          UInt     arg  = SPR==268 ? 0 : 1;
   5621          IRTemp   val  = newTemp(Ity_I32);
   5622          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   5623          IRDirty* d    = unsafeIRDirty_1_N(
   5624                             val,
   5625                             0/*regparms*/,
   5626                             "ppc32g_dirtyhelper_MFSPR_268_269",
   5627                             fnptr_to_fnentry
   5628                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   5629                             args
   5630                          );
   5631          /* execute the dirty call, dumping the result in val. */
   5632          stmt( IRStmt_Dirty(d) );
   5633          putIReg( rD_addr,
   5634                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   5635          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   5636          break;
   5637       }
   5638 
   5639       /* Again, runs natively on PPC7400 (7447, really).  Not
   5640          bothering with a feature test. */
   5641       case 287: /* 0x11F */ {
   5642          IRTemp   val  = newTemp(Ity_I32);
   5643          IRExpr** args = mkIRExprVec_0();
   5644          IRDirty* d    = unsafeIRDirty_1_N(
   5645                             val,
   5646                             0/*regparms*/,
   5647                             "ppc32g_dirtyhelper_MFSPR_287",
   5648                             fnptr_to_fnentry
   5649                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   5650                             args
   5651                          );
   5652          /* execute the dirty call, dumping the result in val. */
   5653          stmt( IRStmt_Dirty(d) );
   5654          putIReg( rD_addr,
   5655                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   5656          DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
   5657          break;
   5658       }
   5659 
   5660       default:
   5661          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   5662          return False;
   5663       }
   5664       break;
   5665 
   5666    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   5667       IRTemp   val  = newTemp(Ity_I64);
   5668       IRExpr** args = mkIRExprVec_0();
   5669       IRDirty* d    = unsafeIRDirty_1_N(
   5670                               val,
   5671                               0/*regparms*/,
   5672                               "ppcg_dirtyhelper_MFTB",
   5673                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   5674                               args );
   5675       /* execute the dirty call, dumping the result in val. */
   5676       stmt( IRStmt_Dirty(d) );
   5677 
   5678       switch (TBR) {
   5679       case 269:
   5680          DIP("mftbu r%u", rD_addr);
   5681          putIReg( rD_addr,
   5682                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   5683                                 /* Signed */False) );
   5684          break;
   5685       case 268:
   5686          DIP("mftb r%u", rD_addr);
   5687          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   5688                                       unop(Iop_64to32, mkexpr(val)) );
   5689          break;
   5690       default:
   5691          return False; /* illegal instruction */
   5692       }
   5693       break;
   5694    }
   5695 
   5696    case 0x090: {
   5697       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   5698       // b20==1: mtocrf (Move to One Cond Reg Field)
   5699       Int   cr;
   5700       UChar shft;
   5701       if (b11 != 0)
   5702          return False;
   5703       if (b20 == 1) {
   5704          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   5705             1 field is written.  It seems more robust to decline to
   5706             decode the insn if so. */
   5707          switch (CRM) {
   5708             case 0x01: case 0x02: case 0x04: case 0x08:
   5709             case 0x10: case 0x20: case 0x40: case 0x80:
   5710                break;
   5711             default:
   5712                return False;
   5713          }
   5714       }
   5715       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   5716                            CRM, rS_addr);
   5717       /* Write to each field specified by CRM */
   5718       for (cr = 0; cr < 8; cr++) {
   5719          if ((CRM & (1 << (7-cr))) == 0)
   5720             continue;
   5721          shft = 4*(7-cr);
   5722          putGST_field( PPC_GST_CR,
   5723                        binop(Iop_Shr32,
   5724                              mkNarrowTo32(ty, mkexpr(rS)),
   5725                              mkU8(shft)), cr );
   5726       }
   5727       break;
   5728    }
   5729 
   5730    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   5731 
   5732       switch (SPR) {  // Choose a register...
   5733       case 0x1:
   5734          DIP("mtxer r%u\n", rS_addr);
   5735          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   5736          break;
   5737       case 0x8:
   5738          DIP("mtlr r%u\n", rS_addr);
   5739          putGST( PPC_GST_LR, mkexpr(rS) );
   5740          break;
   5741       case 0x9:
   5742          DIP("mtctr r%u\n", rS_addr);
   5743          putGST( PPC_GST_CTR, mkexpr(rS) );
   5744          break;
   5745       case 0x100:
   5746          DIP("mtvrsave r%u\n", rS_addr);
   5747          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   5748          break;
   5749 
   5750       default:
   5751          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   5752          return False;
   5753       }
   5754       break;
   5755 
   5756    default:
   5757       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   5758       return False;
   5759    }
   5760    return True;
   5761 }
   5762 
   5763 
   5764 /*
   5765   Cache Management Instructions
   5766 */
   5767 static Bool dis_cache_manage ( UInt         theInstr,
   5768                                DisResult*   dres,
   5769                                VexArchInfo* guest_archinfo )
   5770 {
   5771    /* X-Form */
   5772    UChar opc1    = ifieldOPC(theInstr);
   5773    UChar b21to25 = ifieldRegDS(theInstr);
   5774    UChar rA_addr = ifieldRegA(theInstr);
   5775    UChar rB_addr = ifieldRegB(theInstr);
   5776    UInt  opc2    = ifieldOPClo10(theInstr);
   5777    UChar b0      = ifieldBIT0(theInstr);
   5778    UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
   5779    Bool  is_dcbzl = False;
   5780 
   5781    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5782 
   5783    /* For dcbt, the lowest two bits of b21to25 encode an
   5784       access-direction hint (TH field) which we ignore.  Well, that's
   5785       what the PowerPC documentation says.  In fact xlc -O4 on POWER5
   5786       seems to generate values of 8 and 10 for b21to25. */
   5787    if (opc1 == 0x1F && opc2 == 0x116) {
   5788      /* b21to25 &= ~3; */ /* if the docs were true */
   5789      b21to25 = 0; /* blunt instrument */
   5790    }
   5791    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   5792       if (b21to25 == 1) {
   5793          is_dcbzl = True;
   5794          b21to25 = 0;
   5795          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   5796             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   5797             return False;
   5798          }
   5799       }
   5800    }
   5801 
   5802    if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
   5803       if (0) vex_printf("dis_cache_manage %d %d %d\n",
   5804                         (Int)opc1, (Int)b21to25, (Int)b0);
   5805       vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
   5806       return False;
   5807    }
   5808 
   5809    /* stay sane .. */
   5810    vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
   5811 
   5812    switch (opc2) {
   5813 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   5814 //zz       vassert(0); /* AWAITING TEST CASE */
   5815 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   5816 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   5817 //zz       break;
   5818 
   5819    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   5820       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   5821       /* nop as far as vex is concerned */
   5822       break;
   5823 
   5824    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   5825       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   5826       /* nop as far as vex is concerned */
   5827       break;
   5828 
   5829    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   5830       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   5831       /* nop as far as vex is concerned */
   5832       break;
   5833 
   5834    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   5835       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   5836       /* nop as far as vex is concerned */
   5837       break;
   5838 
   5839    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   5840                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   5841       /* Clear all bytes in cache block at (rA|0) + rB. */
   5842       IRTemp  EA   = newTemp(ty);
   5843       IRTemp  addr = newTemp(ty);
   5844       IRExpr* irx_addr;
   5845       UInt    i;
   5846       UInt clearszB;
   5847       if (is_dcbzl) {
   5848           clearszB = guest_archinfo->ppc_dcbzl_szB;
   5849           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   5850       }
   5851       else {
   5852           clearszB = guest_archinfo->ppc_dcbz_szB;
   5853           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   5854       }
   5855 
   5856       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   5857 
   5858       if (mode64) {
   5859          /* Round EA down to the start of the containing block. */
   5860          assign( addr, binop( Iop_And64,
   5861                               mkexpr(EA),
   5862                               mkU64( ~((ULong)clearszB-1) )) );
   5863 
   5864          for (i = 0; i < clearszB / 8; i++) {
   5865             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   5866             storeBE( irx_addr, mkU64(0) );
   5867          }
   5868       } else {
   5869          /* Round EA down to the start of the containing block. */
   5870          assign( addr, binop( Iop_And32,
   5871                               mkexpr(EA),
   5872                               mkU32( ~(clearszB-1) )) );
   5873 
   5874          for (i = 0; i < clearszB / 4; i++) {
   5875             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   5876             storeBE( irx_addr, mkU32(0) );
   5877          }
   5878       }
   5879       break;
   5880    }
   5881 
   5882    case 0x3D6: {
   5883       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   5884       /* Invalidate all translations containing code from the cache
   5885          block at (rA|0) + rB. */
   5886       IRTemp EA   = newTemp(ty);
   5887       IRTemp addr = newTemp(ty);
   5888       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   5889       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   5890 
   5891       /* Round EA down to the start of the containing block. */
   5892       assign( addr, binop( mkSzOp(ty, Iop_And8),
   5893                            mkexpr(EA),
   5894                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   5895       putGST( PPC_GST_TISTART, mkexpr(addr) );
   5896       putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
   5897 
   5898       /* be paranoid ... */
   5899       stmt( IRStmt_MBE(Imbe_Fence) );
   5900 
   5901       irsb->jumpkind = Ijk_TInval;
   5902       irsb->next     = mkSzImm(ty, nextInsnAddr());
   5903       dres->whatNext = Dis_StopHere;
   5904       break;
   5905    }
   5906 
   5907    default:
   5908       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   5909       return False;
   5910    }
   5911    return True;
   5912 }
   5913 
   5914 
   5915 /*------------------------------------------------------------*/
   5916 /*--- Floating Point Helpers                               ---*/
   5917 /*------------------------------------------------------------*/
   5918 
   5919 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   5920 /* Produces a value in 0 .. 3, which is encoded as per the type
   5921    IRRoundingMode.  PPCRoundingMode encoding is different to
   5922    IRRoundingMode, so need to map it.
   5923 */
   5924 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   5925 {
   5926 /*
   5927    rounding mode | PPC | IR
   5928    ------------------------
   5929    to nearest    | 00  | 00
   5930    to zero       | 01  | 11
   5931    to +infinity  | 10  | 10
   5932    to -infinity  | 11  | 01
   5933 */
   5934    IRTemp rm_PPC32 = newTemp(Ity_I32);
   5935    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   5936 
   5937    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   5938    return binop( Iop_Xor32,
   5939                  mkexpr(rm_PPC32),
   5940                  binop( Iop_And32,
   5941                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   5942                         mkU32(2) ));
   5943 }
   5944 
   5945 
   5946 /*------------------------------------------------------------*/
   5947 /*--- Floating Point Instruction Translation               ---*/
   5948 /*------------------------------------------------------------*/
   5949 
   5950 /*
   5951   Floating Point Load Instructions
   5952 */
   5953 static Bool dis_fp_load ( UInt theInstr )
   5954 {
   5955    /* X-Form, D-Form */
   5956    UChar opc1      = ifieldOPC(theInstr);
   5957    UChar frD_addr  = ifieldRegDS(theInstr);
   5958    UChar rA_addr   = ifieldRegA(theInstr);
   5959    UChar rB_addr   = ifieldRegB(theInstr);
   5960    UInt  opc2      = ifieldOPClo10(theInstr);
   5961    UChar b0        = ifieldBIT0(theInstr);
   5962    UInt  uimm16    = ifieldUIMM16(theInstr);
   5963 
   5964    Int    simm16 = extend_s_16to32(uimm16);
   5965    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5966    IRTemp EA     = newTemp(ty);
   5967    IRTemp rA     = newTemp(ty);
   5968    IRTemp rB     = newTemp(ty);
   5969    IRTemp iHi    = newTemp(Ity_I32);
   5970    IRTemp iLo    = newTemp(Ity_I32);
   5971 
   5972    assign( rA, getIReg(rA_addr) );
   5973    assign( rB, getIReg(rB_addr) );
   5974 
   5975    /* These are completely straightforward from a rounding and status
   5976       bits perspective: no rounding involved and no funny status or CR
   5977       bits affected. */
   5978 
   5979    switch (opc1) {
   5980    case 0x30: // lfs (Load Float Single, PPC32 p441)
   5981       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   5982       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   5983       putFReg( frD_addr,
   5984                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   5985       break;
   5986 
   5987    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   5988       if (rA_addr == 0)
   5989          return False;
   5990       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   5991       assign( EA, ea_rA_simm(rA_addr, simm16) );
   5992       putFReg( frD_addr,
   5993                unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   5994       putIReg( rA_addr, mkexpr(EA) );
   5995       break;
   5996 
   5997    case 0x32: // lfd (Load Float Double, PPC32 p437)
   5998       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   5999       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6000       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6001       break;
   6002 
   6003    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   6004       if (rA_addr == 0)
   6005          return False;
   6006       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   6007       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6008       putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6009       putIReg( rA_addr, mkexpr(EA) );
   6010       break;
   6011 
   6012    case 0x1F:
   6013       if (b0 != 0) {
   6014          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   6015          return False;
   6016       }
   6017 
   6018       switch(opc2) {
   6019       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   6020          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6021          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6022          putFReg( frD_addr, unop( Iop_F32toF64,
   6023                                   loadBE(Ity_F32, mkexpr(EA))) );
   6024          break;
   6025 
   6026       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   6027          if (rA_addr == 0)
   6028             return False;
   6029          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6030          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6031          putFReg( frD_addr,
   6032                   unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
   6033          putIReg( rA_addr, mkexpr(EA) );
   6034          break;
   6035 
   6036       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   6037          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6038          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6039          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6040          break;
   6041 
   6042       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   6043          if (rA_addr == 0)
   6044             return False;
   6045          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6046          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6047          putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
   6048          putIReg( rA_addr, mkexpr(EA) );
   6049          break;
   6050 
   6051       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   6052          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   6053          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6054          assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
   6055          assign( iHi, binop(Iop_Sub32,
   6056                             mkU32(0),
   6057                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   6058          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   6059                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   6060          break;
   6061 
   6062       default:
   6063          vex_printf("dis_fp_load(ppc)(opc2)\n");
   6064          return False;
   6065       }
   6066       break;
   6067 
   6068    default:
   6069       vex_printf("dis_fp_load(ppc)(opc1)\n");
   6070       return False;
   6071    }
   6072    return True;
   6073 }
   6074 
   6075 
   6076 
   6077 /*
   6078   Floating Point Store Instructions
   6079 */
   6080 static Bool dis_fp_store ( UInt theInstr )
   6081 {
   6082    /* X-Form, D-Form */
   6083    UChar opc1      = ifieldOPC(theInstr);
   6084    UChar frS_addr  = ifieldRegDS(theInstr);
   6085    UChar rA_addr   = ifieldRegA(theInstr);
   6086    UChar rB_addr   = ifieldRegB(theInstr);
   6087    UInt  opc2      = ifieldOPClo10(theInstr);
   6088    UChar b0        = ifieldBIT0(theInstr);
   6089    Int   uimm16    = ifieldUIMM16(theInstr);
   6090 
   6091    Int    simm16 = extend_s_16to32(uimm16);
   6092    IRTemp frS    = newTemp(Ity_F64);
   6093    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6094    IRTemp EA     = newTemp(ty);
   6095    IRTemp rA     = newTemp(ty);
   6096    IRTemp rB     = newTemp(ty);
   6097 
   6098    assign( frS, getFReg(frS_addr) );
   6099    assign( rA,  getIReg(rA_addr) );
   6100    assign( rB,  getIReg(rB_addr) );
   6101 
   6102    /* These are straightforward from a status bits perspective: no
   6103       funny status or CR bits affected.  For single precision stores,
   6104       the values are truncated and denormalised (not rounded) to turn
   6105       them into single precision values. */
   6106 
   6107    switch (opc1) {
   6108 
   6109    case 0x34: // stfs (Store Float Single, PPC32 p518)
   6110       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6111       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6112       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   6113          the value to be stored in the correct way, without any
   6114          rounding. */
   6115       storeBE( mkexpr(EA),
   6116                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6117       break;
   6118 
   6119    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   6120       if (rA_addr == 0)
   6121          return False;
   6122       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6123       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6124       /* See comment for stfs */
   6125       storeBE( mkexpr(EA),
   6126                unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6127       putIReg( rA_addr, mkexpr(EA) );
   6128       break;
   6129 
   6130    case 0x36: // stfd (Store Float Double, PPC32 p513)
   6131       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6132       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   6133       storeBE( mkexpr(EA), mkexpr(frS) );
   6134       break;
   6135 
   6136    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   6137       if (rA_addr == 0)
   6138          return False;
   6139       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   6140       assign( EA, ea_rA_simm(rA_addr, simm16) );
   6141       storeBE( mkexpr(EA), mkexpr(frS) );
   6142       putIReg( rA_addr, mkexpr(EA) );
   6143       break;
   6144 
   6145    case 0x1F:
   6146       if (b0 != 0) {
   6147          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   6148          return False;
   6149       }
   6150       switch(opc2) {
   6151       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   6152          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6153          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6154          /* See note for stfs */
   6155          storeBE( mkexpr(EA),
   6156                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6157          break;
   6158 
   6159       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   6160          if (rA_addr == 0)
   6161             return False;
   6162          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6163          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6164          /* See note for stfs */
   6165          storeBE( mkexpr(EA),
   6166                   unop(Iop_TruncF64asF32, mkexpr(frS)) );
   6167          putIReg( rA_addr, mkexpr(EA) );
   6168          break;
   6169 
   6170       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   6171          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6172          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6173          storeBE( mkexpr(EA), mkexpr(frS) );
   6174          break;
   6175 
   6176       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   6177          if (rA_addr == 0)
   6178             return False;
   6179          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6180          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   6181          storeBE( mkexpr(EA), mkexpr(frS) );
   6182          putIReg( rA_addr, mkexpr(EA) );
   6183          break;
   6184 
   6185       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   6186          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6187          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   6188          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   6189          storeBE( mkexpr(EA),
   6190                   unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   6191          break;
   6192 
   6193       default:
   6194          vex_printf("dis_fp_store(ppc)(opc2)\n");
   6195          return False;
   6196       }
   6197       break;
   6198 
   6199    default:
   6200       vex_printf("dis_fp_store(ppc)(opc1)\n");
   6201       return False;
   6202    }
   6203    return True;
   6204 }
   6205 
   6206 
   6207 
   6208 /*
   6209   Floating Point Arith Instructions
   6210 */
   6211 static Bool dis_fp_arith ( UInt theInstr )
   6212 {
   6213    /* A-Form */
   6214    UChar opc1     = ifieldOPC(theInstr);
   6215    UChar frD_addr = ifieldRegDS(theInstr);
   6216    UChar frA_addr = ifieldRegA(theInstr);
   6217    UChar frB_addr = ifieldRegB(theInstr);
   6218    UChar frC_addr = ifieldRegC(theInstr);
   6219    UChar opc2     = ifieldOPClo5(theInstr);
   6220    UChar flag_rC  = ifieldBIT0(theInstr);
   6221 
   6222    IRTemp  frD = newTemp(Ity_F64);
   6223    IRTemp  frA = newTemp(Ity_F64);
   6224    IRTemp  frB = newTemp(Ity_F64);
   6225    IRTemp  frC = newTemp(Ity_F64);
   6226    IRExpr* rm  = get_IR_roundingmode();
   6227 
   6228    /* By default, we will examine the results of the operation and set
   6229       fpscr[FPRF] accordingly. */
   6230    Bool set_FPRF = True;
   6231 
   6232    /* By default, if flag_RC is set, we will clear cr1 after the
   6233       operation.  In reality we should set cr1 to indicate the
   6234       exception status of the operation, but since we're not
   6235       simulating exceptions, the exception status will appear to be
   6236       zero.  Hence cr1 should be cleared if this is a . form insn. */
   6237    Bool clear_CR1 = True;
   6238 
   6239    assign( frA, getFReg(frA_addr));
   6240    assign( frB, getFReg(frB_addr));
   6241    assign( frC, getFReg(frC_addr));
   6242 
   6243    switch (opc1) {
   6244    case 0x3B:
   6245       switch (opc2) {
   6246       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   6247          if (frC_addr != 0)
   6248             return False;
   6249          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6250              frD_addr, frA_addr, frB_addr);
   6251          assign( frD, triop( Iop_DivF64r32,
   6252                              rm, mkexpr(frA), mkexpr(frB) ));
   6253          break;
   6254 
   6255       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   6256          if (frC_addr != 0)
   6257             return False;
   6258          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6259              frD_addr, frA_addr, frB_addr);
   6260          assign( frD, triop( Iop_SubF64r32,
   6261                              rm, mkexpr(frA), mkexpr(frB) ));
   6262          break;
   6263 
   6264       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   6265          if (frC_addr != 0)
   6266             return False;
   6267          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6268              frD_addr, frA_addr, frB_addr);
   6269          assign( frD, triop( Iop_AddF64r32,
   6270                              rm, mkexpr(frA), mkexpr(frB) ));
   6271          break;
   6272 
   6273       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   6274          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   6275          if (frA_addr != 0 || frC_addr != 0)
   6276             return False;
   6277          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   6278              frD_addr, frB_addr);
   6279          // however illogically, on ppc970 this insn behaves identically
   6280          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   6281          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   6282          break;
   6283 
   6284       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   6285          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6286          if (frA_addr != 0 || frC_addr != 0)
   6287             return False;
   6288          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   6289              frD_addr, frB_addr);
   6290          { IRExpr* ieee_one
   6291               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   6292            assign( frD, triop( Iop_DivF64r32,
   6293                                rm,
   6294                                ieee_one, mkexpr(frB) ));
   6295          }
   6296          break;
   6297 
   6298       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   6299          if (frB_addr != 0)
   6300             return False;
   6301          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6302              frD_addr, frA_addr, frC_addr);
   6303          assign( frD, triop( Iop_MulF64r32,
   6304                              rm, mkexpr(frA), mkexpr(frC) ));
   6305          break;
   6306 
   6307       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   6308          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6309          // Undocumented instruction?
   6310          if (frA_addr != 0 || frC_addr != 0)
   6311             return False;
   6312          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   6313              frD_addr, frB_addr);
   6314          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   6315          break;
   6316 
   6317       default:
   6318          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   6319          return False;
   6320       }
   6321       break;
   6322 
   6323    case 0x3F:
   6324       switch (opc2) {
   6325       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   6326          if (frC_addr != 0)
   6327             return False;
   6328          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6329              frD_addr, frA_addr, frB_addr);
   6330          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   6331          break;
   6332 
   6333       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   6334          if (frC_addr != 0)
   6335             return False;
   6336          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6337              frD_addr, frA_addr, frB_addr);
   6338          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   6339          break;
   6340 
   6341       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   6342          if (frC_addr != 0)
   6343             return False;
   6344          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6345              frD_addr, frA_addr, frB_addr);
   6346          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   6347          break;
   6348 
   6349       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   6350          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   6351          if (frA_addr != 0 || frC_addr != 0)
   6352             return False;
   6353          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   6354              frD_addr, frB_addr);
   6355          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   6356          break;
   6357 
   6358       case 0x17: { // fsel (Floating Select, PPC32 p426)
   6359          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6360          IRTemp cc    = newTemp(Ity_I32);
   6361          IRTemp cc_b0 = newTemp(Ity_I32);
   6362 
   6363          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6364              frD_addr, frA_addr, frC_addr, frB_addr);
   6365 
   6366          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   6367          // => GT|EQ == (cc & 0x1 == 0)
   6368          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   6369                                        IRExpr_Const(IRConst_F64(0))) );
   6370          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   6371 
   6372          // frD = (frA >= 0.0) ? frC : frB
   6373          //     = (cc_b0 == 0) ? frC : frB
   6374          assign( frD,
   6375                  IRExpr_Mux0X(
   6376                     unop(Iop_1Uto8,
   6377                          binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
   6378                     mkexpr(frB),
   6379                     mkexpr(frC) ));
   6380 
   6381          /* One of the rare ones which don't mess with FPRF */
   6382          set_FPRF = False;
   6383          break;
   6384       }
   6385 
   6386       case 0x18: // fre (Floating Reciprocal Estimate)
   6387          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6388          // Note: unclear whether this insn really exists or not
   6389          // ppc970 doesn't have it, but POWER5 does
   6390          if (frA_addr != 0 || frC_addr != 0)
   6391             return False;
   6392          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   6393              frD_addr, frB_addr);
   6394          { IRExpr* ieee_one
   6395               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   6396            assign( frD, triop( Iop_DivF64,
   6397                                rm,
   6398                                ieee_one, mkexpr(frB) ));
   6399          }
   6400          break;
   6401 
   6402       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   6403          if (frB_addr != 0)
   6404             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   6405          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6406              frD_addr, frA_addr, frC_addr);
   6407          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   6408          break;
   6409 
   6410       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   6411          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   6412          if (frA_addr != 0 || frC_addr != 0)
   6413             return False;
   6414          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   6415              frD_addr, frB_addr);
   6416          assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
   6417          break;
   6418 
   6419       default:
   6420          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   6421          return False;
   6422       }
   6423       break;
   6424 
   6425    default:
   6426       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   6427       return False;
   6428    }
   6429 
   6430    putFReg( frD_addr, mkexpr(frD) );
   6431 
   6432    if (set_FPRF) {
   6433       // XXX XXX XXX FIXME
   6434       // set FPRF from frD
   6435    }
   6436 
   6437    if (flag_rC && clear_CR1) {
   6438       putCR321( 1, mkU8(0) );
   6439       putCR0( 1, mkU8(0) );
   6440    }
   6441 
   6442    return True;
   6443 }
   6444 
   6445 
   6446 
   6447 /*
   6448   Floating Point Mult-Add Instructions
   6449 */
   6450 static Bool dis_fp_multadd ( UInt theInstr )
   6451 {
   6452    /* A-Form */
   6453    UChar opc1     = ifieldOPC(theInstr);
   6454    UChar frD_addr = ifieldRegDS(theInstr);
   6455    UChar frA_addr = ifieldRegA(theInstr);
   6456    UChar frB_addr = ifieldRegB(theInstr);
   6457    UChar frC_addr = ifieldRegC(theInstr);
   6458    UChar opc2     = ifieldOPClo5(theInstr);
   6459    UChar flag_rC  = ifieldBIT0(theInstr);
   6460 
   6461    IRTemp  frD = newTemp(Ity_F64);
   6462    IRTemp  frA = newTemp(Ity_F64);
   6463    IRTemp  frB = newTemp(Ity_F64);
   6464    IRTemp  frC = newTemp(Ity_F64);
   6465    IRTemp  rmt = newTemp(Ity_I32);
   6466    IRExpr* rm;
   6467 
   6468    /* By default, we will examine the results of the operation and set
   6469       fpscr[FPRF] accordingly. */
   6470    Bool set_FPRF = True;
   6471 
   6472    /* By default, if flag_RC is set, we will clear cr1 after the
   6473       operation.  In reality we should set cr1 to indicate the
   6474       exception status of the operation, but since we're not
   6475       simulating exceptions, the exception status will appear to be
   6476       zero.  Hence cr1 should be cleared if this is a . form insn. */
   6477    Bool clear_CR1 = True;
   6478 
   6479    /* Bind the rounding mode expression to a temp; there's no
   6480       point in creating gratuitous CSEs, as we know we'll need
   6481       to use it twice. */
   6482    assign( rmt, get_IR_roundingmode() );
   6483    rm = mkexpr(rmt);
   6484 
   6485    assign( frA, getFReg(frA_addr));
   6486    assign( frB, getFReg(frB_addr));
   6487    assign( frC, getFReg(frC_addr));
   6488 
   6489    /* The rounding in this is all a bit dodgy.  The idea is to only do
   6490       one rounding.  That clearly isn't achieveable without dedicated
   6491       four-input IR primops, although in the single precision case we
   6492       can sort-of simulate it by doing the inner multiply in double
   6493       precision.
   6494 
   6495       In the negated cases, the negation happens after rounding. */
   6496 
   6497    switch (opc1) {
   6498    case 0x3B:
   6499       switch (opc2) {
   6500       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   6501          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6502              frD_addr, frA_addr, frC_addr, frB_addr);
   6503          assign( frD, qop( Iop_MSubF64r32, rm,
   6504                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   6505          break;
   6506 
   6507       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   6508          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6509              frD_addr, frA_addr, frC_addr, frB_addr);
   6510          assign( frD, qop( Iop_MAddF64r32, rm,
   6511                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   6512          break;
   6513 
   6514       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   6515          DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6516              frD_addr, frA_addr, frC_addr, frB_addr);
   6517          assign( frD, unop( Iop_NegF64,
   6518                       qop( Iop_MSubF64r32, rm,
   6519                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   6520          break;
   6521 
   6522       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   6523          DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6524              frD_addr, frA_addr, frC_addr, frB_addr);
   6525          assign( frD, unop( Iop_NegF64,
   6526                       qop( Iop_MAddF64r32, rm,
   6527                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   6528          break;
   6529 
   6530       default:
   6531          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   6532          return False;
   6533       }
   6534       break;
   6535 
   6536    case 0x3F:
   6537       switch (opc2) {
   6538       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   6539          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6540              frD_addr, frA_addr, frC_addr, frB_addr);
   6541          assign( frD, qop( Iop_MSubF64, rm,
   6542                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   6543          break;
   6544 
   6545       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   6546          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6547              frD_addr, frA_addr, frC_addr, frB_addr);
   6548          assign( frD, qop( Iop_MAddF64, rm,
   6549                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   6550          break;
   6551 
   6552       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   6553          DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6554              frD_addr, frA_addr, frC_addr, frB_addr);
   6555          assign( frD, unop( Iop_NegF64,
   6556                       qop( Iop_MSubF64, rm,
   6557                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   6558          break;
   6559 
   6560       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   6561          DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   6562              frD_addr, frA_addr, frC_addr, frB_addr);
   6563          assign( frD, unop( Iop_NegF64,
   6564                       qop( Iop_MAddF64, rm,
   6565                            mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
   6566          break;
   6567 
   6568       default:
   6569          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   6570          return False;
   6571       }
   6572       break;
   6573 
   6574    default:
   6575       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   6576       return False;
   6577    }
   6578 
   6579    putFReg( frD_addr, mkexpr(frD) );
   6580 
   6581    if (set_FPRF) {
   6582       // XXX XXX XXX FIXME
   6583       // set FPRF from frD
   6584    }
   6585 
   6586    if (flag_rC && clear_CR1) {
   6587       putCR321( 1, mkU8(0) );
   6588       putCR0( 1, mkU8(0) );
   6589    }
   6590 
   6591    return True;
   6592 }
   6593 
   6594 
   6595 
   6596 /*
   6597   Floating Point Compare Instructions
   6598 */
   6599 static Bool dis_fp_cmp ( UInt theInstr )
   6600 {
   6601    /* X-Form */
   6602    UChar opc1     = ifieldOPC(theInstr);
   6603    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   6604    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   6605    UChar frA_addr = ifieldRegA(theInstr);
   6606    UChar frB_addr = ifieldRegB(theInstr);
   6607    UInt  opc2     = ifieldOPClo10(theInstr);
   6608    UChar b0       = ifieldBIT0(theInstr);
   6609 
   6610    IRTemp ccIR    = newTemp(Ity_I32);
   6611    IRTemp ccPPC32 = newTemp(Ity_I32);
   6612 
   6613    IRTemp frA     = newTemp(Ity_F64);
   6614    IRTemp frB     = newTemp(Ity_F64);
   6615 
   6616    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   6617       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   6618       return False;
   6619    }
   6620 
   6621    assign( frA, getFReg(frA_addr));
   6622    assign( frB, getFReg(frB_addr));
   6623 
   6624    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   6625 
   6626    /* Map compare result from IR to PPC32 */
   6627    /*
   6628      FP cmp result | PPC | IR
   6629      --------------------------
   6630      UN            | 0x1 | 0x45
   6631      EQ            | 0x2 | 0x40
   6632      GT            | 0x4 | 0x00
   6633      LT            | 0x8 | 0x01
   6634    */
   6635 
   6636    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   6637    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   6638    assign(
   6639       ccPPC32,
   6640       binop(
   6641          Iop_Shl32,
   6642          mkU32(1),
   6643          unop(
   6644             Iop_32to8,
   6645             binop(
   6646                Iop_Or32,
   6647                binop(
   6648                   Iop_And32,
   6649                   unop(
   6650                      Iop_Not32,
   6651                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   6652                   ),
   6653                   mkU32(2)
   6654                ),
   6655                binop(
   6656                   Iop_And32,
   6657                   binop(
   6658                      Iop_Xor32,
   6659                      mkexpr(ccIR),
   6660                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   6661                   ),
   6662                   mkU32(1)
   6663                )
   6664             )
   6665          )
   6666       )
   6667    );
   6668 
   6669    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   6670 
   6671    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   6672       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   6673    */
   6674    // XXX XXX XXX FIXME
   6675    // Also write the result into FPRF (it's not entirely clear how)
   6676 
   6677    /* Note: Differences between fcmpu and fcmpo are only in exception
   6678       flag settings, which aren't supported anyway. */
   6679    switch (opc2) {
   6680    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   6681       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   6682       break;
   6683    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   6684       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   6685       break;
   6686    default:
   6687       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   6688       return False;
   6689    }
   6690    return True;
   6691 }
   6692 
   6693 
   6694 
   6695 /*
   6696   Floating Point Rounding/Conversion Instructions
   6697 */
   6698 static Bool dis_fp_round ( UInt theInstr )
   6699 {
   6700    /* X-Form */
   6701    UChar opc1     = ifieldOPC(theInstr);
   6702    UChar b16to20  = ifieldRegA(theInstr);
   6703    UChar frD_addr = ifieldRegDS(theInstr);
   6704    UChar frB_addr = ifieldRegB(theInstr);
   6705    UInt  opc2     = ifieldOPClo10(theInstr);
   6706    UChar flag_rC  = ifieldBIT0(theInstr);
   6707 
   6708    IRTemp  frD     = newTemp(Ity_F64);
   6709    IRTemp  frB     = newTemp(Ity_F64);
   6710    IRTemp  r_tmp32 = newTemp(Ity_I32);
   6711    IRTemp  r_tmp64 = newTemp(Ity_I64);
   6712    IRExpr* rm      = get_IR_roundingmode();
   6713 
   6714    /* By default, we will examine the results of the operation and set
   6715       fpscr[FPRF] accordingly. */
   6716    Bool set_FPRF = True;
   6717 
   6718    /* By default, if flag_RC is set, we will clear cr1 after the
   6719       operation.  In reality we should set cr1 to indicate the
   6720       exception status of the operation, but since we're not
   6721       simulating exceptions, the exception status will appear to be
   6722       zero.  Hence cr1 should be cleared if this is a . form insn. */
   6723    Bool clear_CR1 = True;
   6724 
   6725    if (opc1 != 0x3F || b16to20 != 0) {
   6726       vex_printf("dis_fp_round(ppc)(instr)\n");
   6727       return False;
   6728    }
   6729 
   6730    assign( frB, getFReg(frB_addr));
   6731 
   6732    switch (opc2) {
   6733    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   6734       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6735       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   6736       break;
   6737 
   6738    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   6739       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6740       assign( r_tmp32,
   6741               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   6742       assign( frD, unop( Iop_ReinterpI64asF64,
   6743                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   6744       /* FPRF is undefined after fctiw.  Leave unchanged. */
   6745       set_FPRF = False;
   6746       break;
   6747 
   6748    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   6749       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6750       assign( r_tmp32,
   6751               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   6752       assign( frD, unop( Iop_ReinterpI64asF64,
   6753                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   6754       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   6755       set_FPRF = False;
   6756       break;
   6757 
   6758    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   6759       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6760       assign( r_tmp64,
   6761               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   6762       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   6763       /* FPRF is undefined after fctid.  Leave unchanged. */
   6764       set_FPRF = False;
   6765       break;
   6766 
   6767    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   6768       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6769       assign( r_tmp64,
   6770               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   6771       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   6772       /* FPRF is undefined after fctidz.  Leave unchanged. */
   6773       set_FPRF = False;
   6774       break;
   6775 
   6776    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   6777       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6778       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   6779       assign( frD,
   6780               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   6781       break;
   6782 
   6783    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   6784       switch(opc2) {
   6785       case 0x188: // frin (Floating Round to Integer Nearest)
   6786          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6787          assign( r_tmp64,
   6788                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   6789          break;
   6790       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   6791          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6792          assign( r_tmp64,
   6793                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   6794          break;
   6795       case 0x1C8: // frip (Floating Round to Integer Plus)
   6796          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6797          assign( r_tmp64,
   6798                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   6799          break;
   6800       case 0x1E8: // frim (Floating Round to Integer Minus)
   6801          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6802          assign( r_tmp64,
   6803                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   6804          break;
   6805       }
   6806 
   6807       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   6808       /* F64 has only log10(2**52) significant digits anyway */
   6809       /* need to preserve sign of zero */
   6810       /*   frD = (fabs(frB) > 9e18) ? frB :
   6811                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   6812       assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
   6813                                      binop(Iop_CmpF64,
   6814                                            IRExpr_Const(IRConst_F64(9e18)),
   6815                                            unop(Iop_AbsF64, mkexpr(frB)))),
   6816                                 IRExpr_Mux0X(unop(Iop_32to8,
   6817                                                   binop(Iop_Shr32,
   6818                                                         unop(Iop_64HIto32,
   6819                                                              unop(Iop_ReinterpF64asI64,
   6820                                                                   mkexpr(frB))), mkU8(31))),
   6821                                              binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
   6822                                              unop(Iop_NegF64,
   6823                                                   unop( Iop_AbsF64,
   6824                                                         binop(Iop_I64StoF64, mkU32(0),
   6825                                                               mkexpr(r_tmp64)) )) ),
   6826                                 mkexpr(frB)));
   6827       break;
   6828 
   6829    default:
   6830       vex_printf("dis_fp_round(ppc)(opc2)\n");
   6831       return False;
   6832    }
   6833 
   6834    putFReg( frD_addr, mkexpr(frD) );
   6835 
   6836    if (set_FPRF) {
   6837       // XXX XXX XXX FIXME
   6838       // set FPRF from frD
   6839    }
   6840 
   6841    if (flag_rC && clear_CR1) {
   6842       putCR321( 1, mkU8(0) );
   6843       putCR0( 1, mkU8(0) );
   6844    }
   6845 
   6846    return True;
   6847 }
   6848 
   6849 /*
   6850   Floating Point Pair Instructions
   6851 */
   6852 static Bool dis_fp_pair ( UInt theInstr )
   6853 {
   6854    /* X-Form/DS-Form */
   6855    UChar  opc1         = ifieldOPC(theInstr);
   6856    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   6857    UChar  frT_lo_addr  = frT_hi_addr + 1;
   6858    UChar  rA_addr      = ifieldRegA(theInstr);
   6859    UChar  rB_addr      = ifieldRegB(theInstr);
   6860    UInt  uimm16        = ifieldUIMM16(theInstr);
   6861    Int    simm16       = extend_s_16to32(uimm16);
   6862    UInt   opc2         = ifieldOPClo10(theInstr);
   6863    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   6864    IRTemp EA_hi        = newTemp(ty);
   6865    IRTemp EA_lo        = newTemp(ty);
   6866    IRTemp frT_hi       = newTemp(Ity_F64);
   6867    IRTemp frT_lo       = newTemp(Ity_F64);
   6868    UChar b0            = ifieldBIT0(theInstr);
   6869    Bool is_load        = 0;
   6870 
   6871    if ((frT_hi_addr %2) != 0) {
   6872       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   6873       return False;
   6874    }
   6875 
   6876    switch (opc1) {
   6877    case 0x1F: // register offset
   6878       switch(opc2) {
   6879       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   6880          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   6881          is_load = 1;
   6882          break;
   6883       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   6884          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   6885          break;
   6886       default:
   6887          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   6888          return False;
   6889       }
   6890 
   6891       if (b0 != 0) {
   6892          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   6893          return False;
   6894       }
   6895       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6896       break;
   6897    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   6898       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   6899       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   6900       is_load = 1;
   6901       break;
   6902    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   6903       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   6904       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   6905       break;
   6906    default:   // immediate offset
   6907       vex_printf("dis_fp_pair(ppc)(instr)\n");
   6908       return False;
   6909    }
   6910 
   6911    if (mode64)
   6912       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   6913    else
   6914       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   6915 
   6916    assign( frT_hi, getFReg(frT_hi_addr) );
   6917    assign( frT_lo, getFReg(frT_lo_addr) );
   6918 
   6919    if (is_load) {
   6920       putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
   6921       putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
   6922    } else {
   6923       storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
   6924       storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
   6925    }
   6926 
   6927    return True;
   6928 }
   6929 
   6930 
   6931 /*
   6932   Floating Point Move Instructions
   6933 */
   6934 static Bool dis_fp_move ( UInt theInstr )
   6935 {
   6936    /* X-Form */
   6937    UChar opc1     = ifieldOPC(theInstr);
   6938    UChar frD_addr = ifieldRegDS(theInstr);
   6939    UChar frA_addr = ifieldRegA(theInstr);
   6940    UChar frB_addr = ifieldRegB(theInstr);
   6941    UInt  opc2     = ifieldOPClo10(theInstr);
   6942    UChar flag_rC  = ifieldBIT0(theInstr);
   6943 
   6944    IRTemp frD = newTemp(Ity_F64);
   6945    IRTemp frB = newTemp(Ity_F64);
   6946    IRTemp itmpB = newTemp(Ity_F64);
   6947    IRTemp frA;
   6948    IRTemp signA;
   6949    IRTemp hiD;
   6950 
   6951    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   6952       vex_printf("dis_fp_move(ppc)(instr)\n");
   6953       return False;
   6954    }
   6955 
   6956    assign( frB, getFReg(frB_addr));
   6957 
   6958    switch (opc2) {
   6959    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   6960       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   6961           frB_addr);
   6962       signA = newTemp(Ity_I32);
   6963       hiD = newTemp(Ity_I32);
   6964       itmpB = newTemp(Ity_I64);
   6965       frA = newTemp(Ity_F64);
   6966       assign( frA, getFReg(frA_addr) );
   6967 
   6968       /* get A's sign bit */
   6969       assign(signA, binop(Iop_And32,
   6970                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   6971                                                   mkexpr(frA))),
   6972                           mkU32(0x80000000)) );
   6973 
   6974       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   6975 
   6976       /* mask off B's sign bit and or in A's sign bit */
   6977       assign(hiD, binop(Iop_Or32,
   6978                         binop(Iop_And32,
   6979                               unop(Iop_64HIto32,
   6980                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   6981                               mkU32(0x7fffffff)),
   6982                         mkexpr(signA)) );
   6983 
   6984       /* combine hiD/loB into frD */
   6985       assign( frD, unop(Iop_ReinterpI64asF64,
   6986                         binop(Iop_32HLto64,
   6987                               mkexpr(hiD),
   6988                               unop(Iop_64to32,
   6989                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   6990       break;
   6991 
   6992    case 0x028: // fneg (Floating Negate, PPC32 p416)
   6993       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6994       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   6995       break;
   6996 
   6997    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   6998       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   6999       assign( frD, mkexpr(frB) );
   7000       break;
   7001 
   7002    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   7003       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7004       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   7005       break;
   7006 
   7007    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   7008       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   7009       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   7010       break;
   7011 
   7012    default:
   7013       vex_printf("dis_fp_move(ppc)(opc2)\n");
   7014       return False;
   7015    }
   7016 
   7017    putFReg( frD_addr, mkexpr(frD) );
   7018 
   7019    /* None of these change FPRF.  cr1 is set in the usual way though,
   7020       if flag_rC is set. */
   7021 
   7022    if (flag_rC) {
   7023       putCR321( 1, mkU8(0) );
   7024       putCR0( 1, mkU8(0) );
   7025    }
   7026 
   7027    return True;
   7028 }
   7029 
   7030 
   7031 
   7032 /*
   7033   Floating Point Status/Control Register Instructions
   7034 */
   7035 static Bool dis_fp_scr ( UInt theInstr )
   7036 {
   7037    /* Many forms - see each switch case */
   7038    UChar opc1    = ifieldOPC(theInstr);
   7039    UInt  opc2    = ifieldOPClo10(theInstr);
   7040    UChar flag_rC = ifieldBIT0(theInstr);
   7041 
   7042    if (opc1 != 0x3F) {
   7043       vex_printf("dis_fp_scr(ppc)(instr)\n");
   7044       return False;
   7045    }
   7046 
   7047    switch (opc2) {
   7048    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   7049       // Bit crbD of the FPSCR is set.
   7050       UChar crbD    = ifieldRegDS(theInstr);
   7051       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   7052 
   7053       if (b11to20 != 0) {
   7054          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   7055          return False;
   7056       }
   7057       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   7058       putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
   7059       break;
   7060    }
   7061 
   7062    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   7063       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   7064       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   7065       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   7066       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   7067       IRTemp  tmp     = newTemp(Ity_I32);
   7068       IRExpr* fpscr_all;
   7069       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   7070          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   7071          return False;
   7072       }
   7073       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   7074       vassert(crfD < 8);
   7075       vassert(crfS < 8);
   7076       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   7077       assign( tmp, binop(Iop_And32,
   7078                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   7079                         mkU32(0xF)) );
   7080       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   7081       break;
   7082    }
   7083 
   7084    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   7085       // Bit crbD of the FPSCR is cleared.
   7086       UChar crbD    = ifieldRegDS(theInstr);
   7087       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   7088 
   7089       if (b11to20 != 0) {
   7090          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   7091          return False;
   7092       }
   7093       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   7094       putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
   7095       break;
   7096    }
   7097 
   7098    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   7099       UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   7100       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   7101       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   7102       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   7103 
   7104       if (b16to22 != 0 || b11 != 0) {
   7105          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   7106          return False;
   7107       }
   7108       DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
   7109       putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
   7110       break;
   7111    }
   7112 
   7113    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   7114       UChar   frD_addr  = ifieldRegDS(theInstr);
   7115       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   7116       IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   7117 
   7118       if (b11to20 != 0) {
   7119          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   7120          return False;
   7121       }
   7122       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   7123       putFReg( frD_addr,
   7124           unop( Iop_ReinterpI64asF64,
   7125                 unop( Iop_32Uto64, fpscr_all )));
   7126       break;
   7127    }
   7128 
   7129    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   7130       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   7131       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   7132       UChar frB_addr = ifieldRegB(theInstr);
   7133       IRTemp frB   = newTemp(Ity_F64);
   7134       IRTemp rB_32 = newTemp(Ity_I32);
   7135       Int i, mask;
   7136 
   7137       if (b25 == 1) {
   7138          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   7139           * a one do a full 64 bit move.  Note, the FPSCR is not really
   7140           * properly modeled.  This instruciton only changes the value of
   7141           * the rounding mode.  The HW exception bits do not get set in
   7142           * the simulator.  1/12/09
   7143           */
   7144          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   7145          mask = 0xFF;
   7146 
   7147       } else {
   7148          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   7149          // Build 32bit mask from FM:
   7150          mask = 0;
   7151          for (i=0; i<8; i++) {
   7152             if ((FM & (1<<(7-i))) == 1) {
   7153                mask |= 0xF << (7-i);
   7154             }
   7155          }
   7156       }
   7157       assign( frB, getFReg(frB_addr));
   7158       assign( rB_32, unop( Iop_64to32,
   7159                            unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
   7160       putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
   7161       break;
   7162    }
   7163 
   7164    default:
   7165       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   7166       return False;
   7167    }
   7168    return True;
   7169 }
   7170 
   7171 
   7172 
   7173 /*------------------------------------------------------------*/
   7174 /*--- AltiVec Instruction Translation                      ---*/
   7175 /*------------------------------------------------------------*/
   7176 
   7177 /*
   7178   Altivec Cache Control Instructions (Data Streams)
   7179 */
   7180 static Bool dis_av_datastream ( UInt theInstr )
   7181 {
   7182    /* X-Form */
   7183    UChar opc1     = ifieldOPC(theInstr);
   7184    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   7185    UChar flag_A   = flag_T;
   7186    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   7187    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   7188    UChar rA_addr  = ifieldRegA(theInstr);
   7189    UChar rB_addr  = ifieldRegB(theInstr);
   7190    UInt  opc2     = ifieldOPClo10(theInstr);
   7191    UChar b0       = ifieldBIT0(theInstr);
   7192 
   7193    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   7194       vex_printf("dis_av_datastream(ppc)(instr)\n");
   7195       return False;
   7196    }
   7197 
   7198    switch (opc2) {
   7199    case 0x156: // dst (Data Stream Touch, AV p115)
   7200       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   7201                                 rA_addr, rB_addr, STRM);
   7202       break;
   7203 
   7204    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   7205       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   7206                                   rA_addr, rB_addr, STRM);
   7207       break;
   7208 
   7209    case 0x336: // dss (Data Stream Stop, AV p114)
   7210       if (rA_addr != 0 || rB_addr != 0) {
   7211          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   7212          return False;
   7213       }
   7214       if (flag_A == 0) {
   7215          DIP("dss %d\n", STRM);
   7216       } else {
   7217          DIP("dssall\n");
   7218       }
   7219       break;
   7220 
   7221    default:
   7222       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   7223       return False;
   7224    }
   7225    return True;
   7226 }
   7227 
   7228 /*
   7229   AltiVec Processor Control Instructions
   7230 */
   7231 static Bool dis_av_procctl ( UInt theInstr )
   7232 {
   7233    /* VX-Form */
   7234    UChar opc1    = ifieldOPC(theInstr);
   7235    UChar vD_addr = ifieldRegDS(theInstr);
   7236    UChar vA_addr = ifieldRegA(theInstr);
   7237    UChar vB_addr = ifieldRegB(theInstr);
   7238    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   7239 
   7240    if (opc1 != 0x4) {
   7241       vex_printf("dis_av_procctl(ppc)(instr)\n");
   7242       return False;
   7243    }
   7244 
   7245    switch (opc2) {
   7246    case 0x604: // mfvscr (Move from VSCR, AV p129)
   7247       if (vA_addr != 0 || vB_addr != 0) {
   7248          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   7249          return False;
   7250       }
   7251       DIP("mfvscr v%d\n", vD_addr);
   7252       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   7253       break;
   7254 
   7255    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   7256       IRTemp vB = newTemp(Ity_V128);
   7257       if (vD_addr != 0 || vA_addr != 0) {
   7258          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   7259          return False;
   7260       }
   7261       DIP("mtvscr v%d\n", vB_addr);
   7262       assign( vB, getVReg(vB_addr));
   7263       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   7264       break;
   7265    }
   7266    default:
   7267       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   7268       return False;
   7269    }
   7270    return True;
   7271 }
   7272 
   7273 /*
   7274   AltiVec Load Instructions
   7275 */
   7276 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
   7277 {
   7278    /* X-Form */
   7279    UChar opc1     = ifieldOPC(theInstr);
   7280    UChar vD_addr  = ifieldRegDS(theInstr);
   7281    UChar rA_addr  = ifieldRegA(theInstr);
   7282    UChar rB_addr  = ifieldRegB(theInstr);
   7283    UInt  opc2     = ifieldOPClo10(theInstr);
   7284    UChar b0       = ifieldBIT0(theInstr);
   7285 
   7286    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   7287    IRTemp EA         = newTemp(ty);
   7288    IRTemp EA_align16 = newTemp(ty);
   7289 
   7290    if (opc1 != 0x1F || b0 != 0) {
   7291       vex_printf("dis_av_load(ppc)(instr)\n");
   7292       return False;
   7293    }
   7294 
   7295    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7296    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   7297 
   7298    switch (opc2) {
   7299 
   7300    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   7301       IRDirty* d;
   7302       UInt vD_off = vectorGuestRegOffset(vD_addr);
   7303       IRExpr** args = mkIRExprVec_3(
   7304                          mkU32(vD_off),
   7305                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   7306                                           mkU32(0xF)),
   7307                          mkU32(0)/*left*/ );
   7308       if (!mode64) {
   7309          d = unsafeIRDirty_0_N (
   7310                         0/*regparms*/,
   7311                         "ppc32g_dirtyhelper_LVS",
   7312                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   7313                         args );
   7314       } else {
   7315          d = unsafeIRDirty_0_N (
   7316                         0/*regparms*/,
   7317                         "ppc64g_dirtyhelper_LVS",
   7318                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   7319                         args );
   7320       }
   7321       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7322       /* declare guest state effects */
   7323       d->needsBBP = True;
   7324       d->nFxState = 1;
   7325       d->fxState[0].fx     = Ifx_Write;
   7326       d->fxState[0].offset = vD_off;
   7327       d->fxState[0].size   = sizeof(U128);
   7328 
   7329       /* execute the dirty call, side-effecting guest state */
   7330       stmt( IRStmt_Dirty(d) );
   7331       break;
   7332    }
   7333    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   7334       IRDirty* d;
   7335       UInt vD_off = vectorGuestRegOffset(vD_addr);
   7336       IRExpr** args = mkIRExprVec_3(
   7337                          mkU32(vD_off),
   7338                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   7339                                           mkU32(0xF)),
   7340                          mkU32(1)/*right*/ );
   7341       if (!mode64) {
   7342          d = unsafeIRDirty_0_N (
   7343                         0/*regparms*/,
   7344                         "ppc32g_dirtyhelper_LVS",
   7345                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   7346                         args );
   7347       } else {
   7348          d = unsafeIRDirty_0_N (
   7349                         0/*regparms*/,
   7350                         "ppc64g_dirtyhelper_LVS",
   7351                         fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   7352                         args );
   7353       }
   7354       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7355       /* declare guest state effects */
   7356       d->needsBBP = True;
   7357       d->nFxState = 1;
   7358       d->fxState[0].fx     = Ifx_Write;
   7359       d->fxState[0].offset = vD_off;
   7360       d->fxState[0].size   = sizeof(U128);
   7361 
   7362       /* execute the dirty call, side-effecting guest state */
   7363       stmt( IRStmt_Dirty(d) );
   7364       break;
   7365    }
   7366    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   7367       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7368       /* loads addressed byte into vector[EA[0:3]
   7369          since all other destination bytes are undefined,
   7370          can simply load entire vector from 16-aligned EA */
   7371       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   7372       break;
   7373 
   7374    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   7375       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7376       /* see note for lvebx */
   7377       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   7378       break;
   7379 
   7380    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   7381       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7382       /* see note for lvebx */
   7383       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   7384       break;
   7385 
   7386    case 0x067: // lvx (Load Vector Indexed, AV p127)
   7387       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7388       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   7389       break;
   7390 
   7391    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   7392       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   7393       putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
   7394       break;
   7395 
   7396    default:
   7397       vex_printf("dis_av_load(ppc)(opc2)\n");
   7398       return False;
   7399    }
   7400    return True;
   7401 }
   7402 
   7403 
   7404 /*
   7405   AltiVec Store Instructions
   7406 */
   7407 static Bool dis_av_store ( UInt theInstr )
   7408 {
   7409    /* X-Form */
   7410    UChar opc1     = ifieldOPC(theInstr);
   7411    UChar vS_addr  = ifieldRegDS(theInstr);
   7412    UChar rA_addr  = ifieldRegA(theInstr);
   7413    UChar rB_addr  = ifieldRegB(theInstr);
   7414    UInt  opc2     = ifieldOPClo10(theInstr);
   7415    UChar b0       = ifieldBIT0(theInstr);
   7416 
   7417    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   7418    IRTemp EA           = newTemp(ty);
   7419    IRTemp addr_aligned = newTemp(ty);
   7420    IRTemp vS           = newTemp(Ity_V128);
   7421    IRTemp eb           = newTemp(Ity_I8);
   7422    IRTemp idx          = newTemp(Ity_I8);
   7423 
   7424    if (opc1 != 0x1F || b0 != 0) {
   7425       vex_printf("dis_av_store(ppc)(instr)\n");
   7426       return False;
   7427    }
   7428 
   7429    assign( vS, getVReg(vS_addr));
   7430    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7431 
   7432    switch (opc2) {
   7433    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   7434       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   7435       assign( eb, binop(Iop_And8, mkU8(0xF),
   7436                         unop(Iop_32to8,
   7437                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   7438       assign( idx, binop(Iop_Shl8,
   7439                          binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   7440                          mkU8(3)) );
   7441       storeBE( mkexpr(EA),
   7442                unop(Iop_32to8, unop(Iop_V128to32,
   7443                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   7444       break;
   7445    }
   7446    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   7447       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   7448       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   7449       assign( eb, binop(Iop_And8, mkU8(0xF),
   7450                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   7451       assign( idx, binop(Iop_Shl8,
   7452                          binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   7453                          mkU8(3)) );
   7454       storeBE( mkexpr(addr_aligned),
   7455                unop(Iop_32to16, unop(Iop_V128to32,
   7456                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   7457       break;
   7458    }
   7459    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   7460       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   7461       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   7462       assign( eb, binop(Iop_And8, mkU8(0xF),
   7463                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   7464       assign( idx, binop(Iop_Shl8,
   7465                          binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   7466                          mkU8(3)) );
   7467       storeBE( mkexpr(addr_aligned),
   7468                unop(Iop_V128to32,
   7469                     binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   7470       break;
   7471    }
   7472 
   7473    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   7474       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   7475       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   7476       break;
   7477 
   7478    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   7479       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   7480       storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   7481       break;
   7482 
   7483    default:
   7484       vex_printf("dis_av_store(ppc)(opc2)\n");
   7485       return False;
   7486    }
   7487    return True;
   7488 }
   7489 
   7490 /*
   7491   AltiVec Arithmetic Instructions
   7492 */
   7493 static Bool dis_av_arith ( UInt theInstr )
   7494 {
   7495    /* VX-Form */
   7496    UChar opc1     = ifieldOPC(theInstr);
   7497    UChar vD_addr  = ifieldRegDS(theInstr);
   7498    UChar vA_addr  = ifieldRegA(theInstr);
   7499    UChar vB_addr  = ifieldRegB(theInstr);
   7500    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   7501 
   7502    IRTemp vA = newTemp(Ity_V128);
   7503    IRTemp vB = newTemp(Ity_V128);
   7504    IRTemp z3 = newTemp(Ity_I64);
   7505    IRTemp z2 = newTemp(Ity_I64);
   7506    IRTemp z1 = newTemp(Ity_I64);
   7507    IRTemp z0 = newTemp(Ity_I64);
   7508    IRTemp aEvn, aOdd;
   7509    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   7510    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   7511    IRTemp b3, b2, b1, b0;
   7512 
   7513    aEvn = aOdd = IRTemp_INVALID;
   7514    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   7515    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   7516    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   7517 
   7518    assign( vA, getVReg(vA_addr));
   7519    assign( vB, getVReg(vB_addr));
   7520 
   7521    if (opc1 != 0x4) {
   7522       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   7523       return False;
   7524    }
   7525 
   7526    switch (opc2) {
   7527    /* Add */
   7528    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   7529       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7530       /* unsigned_ov(x+y) = (y >u not(x)) */
   7531       putVReg( vD_addr, binop(Iop_ShrN32x4,
   7532                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   7533                                     unop(Iop_NotV128, mkexpr(vA))),
   7534                               mkU8(31)) );
   7535       break;
   7536    }
   7537    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   7538       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7539       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   7540       break;
   7541 
   7542    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   7543       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7544       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   7545       break;
   7546 
   7547    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   7548       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7549       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   7550       break;
   7551 
   7552    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   7553       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7554       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   7555       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   7556       break;
   7557 
   7558    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   7559       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7560       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   7561       // TODO: set VSCR[SAT]
   7562       break;
   7563 
   7564    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   7565       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7566       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   7567       // TODO: set VSCR[SAT]
   7568       break;
   7569 
   7570    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   7571       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7572       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   7573       // TODO: set VSCR[SAT]
   7574       break;
   7575 
   7576    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   7577       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7578       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   7579       // TODO: set VSCR[SAT]
   7580       break;
   7581 
   7582    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   7583       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7584       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   7585       // TODO: set VSCR[SAT]
   7586       break;
   7587 
   7588 
   7589    /* Subtract */
   7590    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   7591       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7592       /* unsigned_ov(x-y) = (y >u x) */
   7593       putVReg( vD_addr, binop(Iop_ShrN32x4,
   7594                               unop(Iop_NotV128,
   7595                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   7596                                          mkexpr(vA))),
   7597                               mkU8(31)) );
   7598       break;
   7599    }
   7600    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   7601       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7602       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   7603       break;
   7604 
   7605    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   7606       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7607       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   7608       break;
   7609 
   7610    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   7611       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7612       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   7613       break;
   7614 
   7615    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   7616       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7617       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   7618       // TODO: set VSCR[SAT]
   7619       break;
   7620 
   7621    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   7622       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7623       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   7624       // TODO: set VSCR[SAT]
   7625       break;
   7626 
   7627    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   7628       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7629       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   7630       // TODO: set VSCR[SAT]
   7631       break;
   7632 
   7633    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   7634       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7635       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   7636       // TODO: set VSCR[SAT]
   7637       break;
   7638 
   7639    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   7640       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7641       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   7642       // TODO: set VSCR[SAT]
   7643       break;
   7644 
   7645    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   7646       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7647       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   7648       // TODO: set VSCR[SAT]
   7649       break;
   7650 
   7651 
   7652    /* Maximum */
   7653    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   7654       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7655       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   7656       break;
   7657 
   7658    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   7659       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7660       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   7661       break;
   7662 
   7663    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   7664       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7665       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   7666       break;
   7667 
   7668    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   7669       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7670       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   7671       break;
   7672 
   7673    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   7674       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7675       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   7676       break;
   7677 
   7678    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   7679       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7680       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   7681       break;
   7682 
   7683 
   7684    /* Minimum */
   7685    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   7686       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7687       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   7688       break;
   7689 
   7690    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   7691       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7692       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   7693       break;
   7694 
   7695    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   7696       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7697       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   7698       break;
   7699 
   7700    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   7701       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7702       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   7703       break;
   7704 
   7705    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   7706       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7707       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   7708       break;
   7709 
   7710    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   7711       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7712       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   7713       break;
   7714 
   7715 
   7716    /* Average */
   7717    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   7718       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7719       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   7720       break;
   7721 
   7722    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   7723       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7724       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   7725       break;
   7726 
   7727    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   7728       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7729       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   7730       break;
   7731 
   7732    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   7733       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7734       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   7735       break;
   7736 
   7737    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   7738       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7739       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   7740       break;
   7741 
   7742    case 0x582: // vavgsw (Average Signed Word, AV p151)
   7743       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7744       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   7745       break;
   7746 
   7747 
   7748    /* Multiply */
   7749    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   7750       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7751       putVReg( vD_addr,
   7752                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   7753       break;
   7754 
   7755    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   7756       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7757       putVReg( vD_addr,
   7758                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   7759       break;
   7760 
   7761    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   7762       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7763       putVReg( vD_addr,
   7764                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   7765       break;
   7766 
   7767    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   7768       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7769       putVReg( vD_addr,
   7770                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   7771       break;
   7772 
   7773    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   7774       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7775       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   7776       break;
   7777 
   7778    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   7779       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7780       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   7781       break;
   7782 
   7783    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   7784       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7785       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   7786       break;
   7787 
   7788    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   7789       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7790       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   7791       break;
   7792 
   7793 
   7794    /* Sum Across Partial */
   7795    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   7796       IRTemp aEE, aEO, aOE, aOO;
   7797       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   7798       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7799 
   7800       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   7801       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   7802       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   7803       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   7804 
   7805       /* break V128 to 4xI32's, zero-extending to I64's */
   7806       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   7807       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   7808       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   7809       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   7810       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   7811 
   7812       /* add lanes */
   7813       assign( z3, binop(Iop_Add64, mkexpr(b3),
   7814                      binop(Iop_Add64,
   7815                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   7816                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   7817       assign( z2, binop(Iop_Add64, mkexpr(b2),
   7818                      binop(Iop_Add64,
   7819                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   7820                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   7821       assign( z1, binop(Iop_Add64, mkexpr(b1),
   7822                      binop(Iop_Add64,
   7823                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   7824                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   7825       assign( z0, binop(Iop_Add64, mkexpr(b0),
   7826                      binop(Iop_Add64,
   7827                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   7828                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   7829 
   7830       /* saturate-narrow to 32bit, and combine to V128 */
   7831       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   7832                                          mkexpr(z1), mkexpr(z0)) );
   7833       break;
   7834    }
   7835    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   7836       IRTemp aEE, aEO, aOE, aOO;
   7837       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   7838       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7839 
   7840       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   7841       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   7842       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   7843       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   7844 
   7845       /* break V128 to 4xI32's, sign-extending to I64's */
   7846       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   7847       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   7848       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   7849       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   7850       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   7851 
   7852       /* add lanes */
   7853       assign( z3, binop(Iop_Add64, mkexpr(b3),
   7854                      binop(Iop_Add64,
   7855                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   7856                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   7857       assign( z2, binop(Iop_Add64, mkexpr(b2),
   7858                      binop(Iop_Add64,
   7859                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   7860                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   7861       assign( z1, binop(Iop_Add64, mkexpr(b1),
   7862                      binop(Iop_Add64,
   7863                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   7864                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   7865       assign( z0, binop(Iop_Add64, mkexpr(b0),
   7866                      binop(Iop_Add64,
   7867                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   7868                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   7869 
   7870       /* saturate-narrow to 32bit, and combine to V128 */
   7871       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   7872                                          mkexpr(z1), mkexpr(z0)) );
   7873       break;
   7874    }
   7875    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   7876       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7877 
   7878       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   7879       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   7880 
   7881       /* break V128 to 4xI32's, sign-extending to I64's */
   7882       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   7883       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   7884       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   7885 
   7886       /* add lanes */
   7887       assign( z3, binop(Iop_Add64, mkexpr(b3),
   7888                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   7889       assign( z2, binop(Iop_Add64, mkexpr(b2),
   7890                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   7891       assign( z1, binop(Iop_Add64, mkexpr(b1),
   7892                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   7893       assign( z0, binop(Iop_Add64, mkexpr(b0),
   7894                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   7895 
   7896       /* saturate-narrow to 32bit, and combine to V128 */
   7897       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   7898                                          mkexpr(z1), mkexpr(z0)) );
   7899       break;
   7900    }
   7901    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   7902       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7903 
   7904       /* break V128 to 4xI32's, sign-extending to I64's */
   7905       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   7906       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   7907 
   7908       /* add lanes */
   7909       assign( z2, binop(Iop_Add64, mkexpr(b2),
   7910                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   7911       assign( z0, binop(Iop_Add64, mkexpr(b0),
   7912                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   7913 
   7914       /* saturate-narrow to 32bit, and combine to V128 */
   7915       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   7916                                          mkU64(0), mkexpr(z0)) );
   7917       break;
   7918    }
   7919    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   7920       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7921 
   7922       /* break V128 to 4xI32's, sign-extending to I64's */
   7923       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   7924       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   7925 
   7926       /* add lanes */
   7927       assign( z0, binop(Iop_Add64, mkexpr(b0),
   7928                      binop(Iop_Add64,
   7929                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   7930                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   7931 
   7932       /* saturate-narrow to 32bit, and combine to V128 */
   7933       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   7934                                          mkU64(0), mkexpr(z0)) );
   7935       break;
   7936    }
   7937    default:
   7938       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   7939       return False;
   7940    }
   7941    return True;
   7942 }
   7943 
   7944 /*
   7945   AltiVec Logic Instructions
   7946 */
   7947 static Bool dis_av_logic ( UInt theInstr )
   7948 {
   7949    /* VX-Form */
   7950    UChar opc1    = ifieldOPC(theInstr);
   7951    UChar vD_addr = ifieldRegDS(theInstr);
   7952    UChar vA_addr = ifieldRegA(theInstr);
   7953    UChar vB_addr = ifieldRegB(theInstr);
   7954    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   7955 
   7956    IRTemp vA = newTemp(Ity_V128);
   7957    IRTemp vB = newTemp(Ity_V128);
   7958    assign( vA, getVReg(vA_addr));
   7959    assign( vB, getVReg(vB_addr));
   7960 
   7961    if (opc1 != 0x4) {
   7962       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   7963       return False;
   7964    }
   7965 
   7966    switch (opc2) {
   7967    case 0x404: // vand (And, AV p147)
   7968       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7969       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   7970       break;
   7971 
   7972    case 0x444: // vandc (And, AV p148)
   7973       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7974       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   7975                               unop(Iop_NotV128, mkexpr(vB))) );
   7976       break;
   7977 
   7978    case 0x484: // vor (Or, AV p217)
   7979       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7980       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   7981       break;
   7982 
   7983    case 0x4C4: // vxor (Xor, AV p282)
   7984       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7985       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   7986       break;
   7987 
   7988    case 0x504: // vnor (Nor, AV p216)
   7989       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   7990       putVReg( vD_addr,
   7991          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   7992       break;
   7993 
   7994    default:
   7995       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   7996       return False;
   7997    }
   7998    return True;
   7999 }
   8000 
   8001 /*
   8002   AltiVec Compare Instructions
   8003 */
   8004 static Bool dis_av_cmp ( UInt theInstr )
   8005 {
   8006    /* VXR-Form */
   8007    UChar opc1     = ifieldOPC(theInstr);
   8008    UChar vD_addr  = ifieldRegDS(theInstr);
   8009    UChar vA_addr  = ifieldRegA(theInstr);
   8010    UChar vB_addr  = ifieldRegB(theInstr);
   8011    UChar flag_rC  = ifieldBIT10(theInstr);
   8012    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   8013 
   8014    IRTemp vA = newTemp(Ity_V128);
   8015    IRTemp vB = newTemp(Ity_V128);
   8016    IRTemp vD = newTemp(Ity_V128);
   8017    assign( vA, getVReg(vA_addr));
   8018    assign( vB, getVReg(vB_addr));
   8019 
   8020    if (opc1 != 0x4) {
   8021       vex_printf("dis_av_cmp(ppc)(instr)\n");
   8022       return False;
   8023    }
   8024 
   8025    switch (opc2) {
   8026    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   8027       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8028                                       vD_addr, vA_addr, vB_addr);
   8029       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   8030       break;
   8031 
   8032    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   8033       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8034                                       vD_addr, vA_addr, vB_addr);
   8035       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   8036       break;
   8037 
   8038    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   8039       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8040                                       vD_addr, vA_addr, vB_addr);
   8041       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   8042       break;
   8043 
   8044    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   8045       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8046                                       vD_addr, vA_addr, vB_addr);
   8047       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   8048       break;
   8049 
   8050    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   8051       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8052                                       vD_addr, vA_addr, vB_addr);
   8053       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   8054       break;
   8055 
   8056    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   8057       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8058                                        vD_addr, vA_addr, vB_addr);
   8059       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   8060       break;
   8061 
   8062    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   8063       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8064                                        vD_addr, vA_addr, vB_addr);
   8065       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   8066       break;
   8067 
   8068    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   8069       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8070                                       vD_addr, vA_addr, vB_addr);
   8071       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   8072       break;
   8073 
   8074    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   8075       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   8076                                       vD_addr, vA_addr, vB_addr);
   8077       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   8078       break;
   8079 
   8080    default:
   8081       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   8082       return False;
   8083    }
   8084 
   8085    putVReg( vD_addr, mkexpr(vD) );
   8086 
   8087    if (flag_rC) {
   8088       set_AV_CR6( mkexpr(vD), True );
   8089    }
   8090    return True;
   8091 }
   8092 
   8093 /*
   8094   AltiVec Multiply-Sum Instructions
   8095 */
   8096 static Bool dis_av_multarith ( UInt theInstr )
   8097 {
   8098    /* VA-Form */
   8099    UChar opc1     = ifieldOPC(theInstr);
   8100    UChar vD_addr  = ifieldRegDS(theInstr);
   8101    UChar vA_addr  = ifieldRegA(theInstr);
   8102    UChar vB_addr  = ifieldRegB(theInstr);
   8103    UChar vC_addr  = ifieldRegC(theInstr);
   8104    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   8105 
   8106    IRTemp vA    = newTemp(Ity_V128);
   8107    IRTemp vB    = newTemp(Ity_V128);
   8108    IRTemp vC    = newTemp(Ity_V128);
   8109    IRTemp zeros = newTemp(Ity_V128);
   8110    IRTemp aLo   = newTemp(Ity_V128);
   8111    IRTemp bLo   = newTemp(Ity_V128);
   8112    IRTemp cLo   = newTemp(Ity_V128);
   8113    IRTemp zLo   = newTemp(Ity_V128);
   8114    IRTemp aHi   = newTemp(Ity_V128);
   8115    IRTemp bHi   = newTemp(Ity_V128);
   8116    IRTemp cHi   = newTemp(Ity_V128);
   8117    IRTemp zHi   = newTemp(Ity_V128);
   8118    IRTemp abEvn = newTemp(Ity_V128);
   8119    IRTemp abOdd = newTemp(Ity_V128);
   8120    IRTemp z3    = newTemp(Ity_I64);
   8121    IRTemp z2    = newTemp(Ity_I64);
   8122    IRTemp z1    = newTemp(Ity_I64);
   8123    IRTemp z0    = newTemp(Ity_I64);
   8124    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   8125    IRTemp c3, c2, c1, c0;
   8126 
   8127    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   8128    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   8129 
   8130    assign( vA, getVReg(vA_addr));
   8131    assign( vB, getVReg(vB_addr));
   8132    assign( vC, getVReg(vC_addr));
   8133    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   8134 
   8135    if (opc1 != 0x4) {
   8136       vex_printf("dis_av_multarith(ppc)(instr)\n");
   8137       return False;
   8138    }
   8139 
   8140    switch (opc2) {
   8141    /* Multiply-Add */
   8142    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   8143       IRTemp cSigns = newTemp(Ity_V128);
   8144       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   8145           vD_addr, vA_addr, vB_addr, vC_addr);
   8146       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   8147       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   8148       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   8149       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   8150       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   8151       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   8152       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   8153 
   8154       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   8155                          binop(Iop_SarN32x4,
   8156                                binop(Iop_MullEven16Sx8,
   8157                                      mkexpr(aLo), mkexpr(bLo)),
   8158                                mkU8(15))) );
   8159 
   8160       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   8161                          binop(Iop_SarN32x4,
   8162                                binop(Iop_MullEven16Sx8,
   8163                                      mkexpr(aHi), mkexpr(bHi)),
   8164                                mkU8(15))) );
   8165 
   8166       putVReg( vD_addr,
   8167                binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
   8168       break;
   8169    }
   8170    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   8171       IRTemp zKonst = newTemp(Ity_V128);
   8172       IRTemp cSigns = newTemp(Ity_V128);
   8173       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   8174           vD_addr, vA_addr, vB_addr, vC_addr);
   8175       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   8176       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   8177       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   8178       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   8179       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   8180       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   8181       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   8182 
   8183       /* shifting our const avoids store/load version of Dup */
   8184       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   8185                             mkU8(14)) );
   8186 
   8187       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   8188                          binop(Iop_SarN32x4,
   8189                                binop(Iop_Add32x4, mkexpr(zKonst),
   8190                                      binop(Iop_MullEven16Sx8,
   8191                                            mkexpr(aLo), mkexpr(bLo))),
   8192                                mkU8(15))) );
   8193 
   8194       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   8195                          binop(Iop_SarN32x4,
   8196                                binop(Iop_Add32x4, mkexpr(zKonst),
   8197                                      binop(Iop_MullEven16Sx8,
   8198                                            mkexpr(aHi), mkexpr(bHi))),
   8199                                mkU8(15))) );
   8200 
   8201       putVReg( vD_addr, binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) );
   8202       break;
   8203    }
   8204    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   8205       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   8206           vD_addr, vA_addr, vB_addr, vC_addr);
   8207       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   8208       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   8209       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   8210       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   8211       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   8212       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   8213       assign(zLo, binop(Iop_Add32x4,
   8214                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   8215                      mkexpr(cLo)) );
   8216       assign(zHi, binop(Iop_Add32x4,
   8217                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   8218                      mkexpr(cHi)));
   8219       putVReg(vD_addr, binop(Iop_Narrow32x4, mkexpr(zHi), mkexpr(zLo)));
   8220       break;
   8221    }
   8222 
   8223 
   8224    /* Multiply-Sum */
   8225    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   8226       IRTemp abEE, abEO, abOE, abOO;
   8227       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   8228       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   8229           vD_addr, vA_addr, vB_addr, vC_addr);
   8230 
   8231       /* multiply vA,vB (unsigned, widening) */
   8232       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   8233       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   8234 
   8235       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   8236       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   8237       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   8238 
   8239       putVReg( vD_addr,
   8240          binop(Iop_Add32x4, mkexpr(vC),
   8241                binop(Iop_Add32x4,
   8242                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   8243                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   8244       break;
   8245    }
   8246    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   8247       IRTemp aEvn, aOdd, bEvn, bOdd;
   8248       IRTemp abEE = newTemp(Ity_V128);
   8249       IRTemp abEO = newTemp(Ity_V128);
   8250       IRTemp abOE = newTemp(Ity_V128);
   8251       IRTemp abOO = newTemp(Ity_V128);
   8252       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   8253       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   8254           vD_addr, vA_addr, vB_addr, vC_addr);
   8255 
   8256       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   8257          (separating out adjacent lanes to different vectors) */
   8258       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   8259       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   8260 
   8261       /* multiply vA, vB, again separating adjacent lanes */
   8262       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   8263       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   8264       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   8265       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   8266 
   8267       /* add results together, + vC */
   8268       putVReg( vD_addr,
   8269          binop(Iop_QAdd32Sx4, mkexpr(vC),
   8270                binop(Iop_QAdd32Sx4,
   8271                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   8272                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   8273       break;
   8274    }
   8275    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   8276       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   8277           vD_addr, vA_addr, vB_addr, vC_addr);
   8278       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   8279       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   8280       putVReg( vD_addr,
   8281          binop(Iop_Add32x4, mkexpr(vC),
   8282                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   8283       break;
   8284    }
   8285    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   8286       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   8287           vD_addr, vA_addr, vB_addr, vC_addr);
   8288       /* widening multiply, separating lanes */
   8289       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   8290       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   8291 
   8292       /* break V128 to 4xI32's, zero-extending to I64's */
   8293       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   8294       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   8295       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   8296 
   8297       /* add lanes */
   8298       assign( z3, binop(Iop_Add64, mkexpr(c3),
   8299                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   8300       assign( z2, binop(Iop_Add64, mkexpr(c2),
   8301                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   8302       assign( z1, binop(Iop_Add64, mkexpr(c1),
   8303                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   8304       assign( z0, binop(Iop_Add64, mkexpr(c0),
   8305                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   8306 
   8307       /* saturate-narrow to 32bit, and combine to V128 */
   8308       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   8309                                          mkexpr(z1), mkexpr(z0)) );
   8310 
   8311       break;
   8312    }
   8313    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   8314       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   8315           vD_addr, vA_addr, vB_addr, vC_addr);
   8316       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   8317       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   8318       putVReg( vD_addr,
   8319          binop(Iop_Add32x4, mkexpr(vC),
   8320                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   8321       break;
   8322    }
   8323    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   8324       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   8325           vD_addr, vA_addr, vB_addr, vC_addr);
   8326       /* widening multiply, separating lanes */
   8327       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   8328       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   8329 
   8330       /* break V128 to 4xI32's, sign-extending to I64's */
   8331       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   8332       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   8333       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   8334 
   8335       /* add lanes */
   8336       assign( z3, binop(Iop_Add64, mkexpr(c3),
   8337                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   8338       assign( z2, binop(Iop_Add64, mkexpr(c2),
   8339                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   8340       assign( z1, binop(Iop_Add64, mkexpr(c1),
   8341                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   8342       assign( z0, binop(Iop_Add64, mkexpr(c0),
   8343                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   8344 
   8345       /* saturate-narrow to 32bit, and combine to V128 */
   8346       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   8347                                          mkexpr(z1), mkexpr(z0)) );
   8348       break;
   8349    }
   8350    default:
   8351       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   8352       return False;
   8353    }
   8354    return True;
   8355 }
   8356 
   8357 /*
   8358   AltiVec Shift/Rotate Instructions
   8359 */
   8360 static Bool dis_av_shift ( UInt theInstr )
   8361 {
   8362    /* VX-Form */
   8363    UChar opc1    = ifieldOPC(theInstr);
   8364    UChar vD_addr = ifieldRegDS(theInstr);
   8365    UChar vA_addr = ifieldRegA(theInstr);
   8366    UChar vB_addr = ifieldRegB(theInstr);
   8367    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   8368 
   8369    IRTemp vA = newTemp(Ity_V128);
   8370    IRTemp vB = newTemp(Ity_V128);
   8371    assign( vA, getVReg(vA_addr));
   8372    assign( vB, getVReg(vB_addr));
   8373 
   8374    if (opc1 != 0x4){
   8375       vex_printf("dis_av_shift(ppc)(instr)\n");
   8376       return False;
   8377    }
   8378 
   8379    switch (opc2) {
   8380    /* Rotate */
   8381    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   8382       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8383       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   8384       break;
   8385 
   8386    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   8387       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8388       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   8389       break;
   8390 
   8391    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   8392       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8393       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   8394       break;
   8395 
   8396 
   8397    /* Shift Left */
   8398    case 0x104: // vslb (Shift Left Integer B, AV p240)
   8399       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8400       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   8401       break;
   8402 
   8403    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   8404       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8405       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   8406       break;
   8407 
   8408    case 0x184: // vslw (Shift Left Integer W, AV p244)
   8409       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8410       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   8411       break;
   8412 
   8413    case 0x1C4: { // vsl (Shift Left, AV p239)
   8414       IRTemp sh = newTemp(Ity_I8);
   8415       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8416       assign( sh, binop(Iop_And8, mkU8(0x7),
   8417                         unop(Iop_32to8,
   8418                              unop(Iop_V128to32, mkexpr(vB)))) );
   8419       putVReg( vD_addr,
   8420                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   8421       break;
   8422    }
   8423    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   8424       IRTemp sh = newTemp(Ity_I8);
   8425       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8426       assign( sh, binop(Iop_And8, mkU8(0x78),
   8427                         unop(Iop_32to8,
   8428                              unop(Iop_V128to32, mkexpr(vB)))) );
   8429       putVReg( vD_addr,
   8430                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   8431       break;
   8432    }
   8433 
   8434 
   8435    /* Shift Right */
   8436    case 0x204: // vsrb (Shift Right B, AV p256)
   8437       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8438       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   8439       break;
   8440 
   8441    case 0x244: // vsrh (Shift Right HW, AV p257)
   8442       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8443       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   8444       break;
   8445 
   8446    case 0x284: // vsrw (Shift Right W, AV p259)
   8447       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8448       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   8449       break;
   8450 
   8451    case 0x2C4: { // vsr (Shift Right, AV p251)
   8452       IRTemp sh = newTemp(Ity_I8);
   8453       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8454       assign( sh, binop(Iop_And8, mkU8(0x7),
   8455                         unop(Iop_32to8,
   8456                              unop(Iop_V128to32, mkexpr(vB)))) );
   8457       putVReg( vD_addr,
   8458                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   8459       break;
   8460    }
   8461    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   8462       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8463       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   8464       break;
   8465 
   8466    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   8467       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8468       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   8469       break;
   8470 
   8471    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   8472       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8473       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   8474       break;
   8475 
   8476    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   8477       IRTemp sh = newTemp(Ity_I8);
   8478       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8479       assign( sh, binop(Iop_And8, mkU8(0x78),
   8480                         unop(Iop_32to8,
   8481                              unop(Iop_V128to32, mkexpr(vB)))) );
   8482       putVReg( vD_addr,
   8483                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   8484       break;
   8485    }
   8486 
   8487    default:
   8488       vex_printf("dis_av_shift(ppc)(opc2)\n");
   8489       return False;
   8490    }
   8491    return True;
   8492 }
   8493 
   8494 /*
   8495   AltiVec Permute Instructions
   8496 */
   8497 static Bool dis_av_permute ( UInt theInstr )
   8498 {
   8499    /* VA-Form, VX-Form */
   8500    UChar opc1      = ifieldOPC(theInstr);
   8501    UChar vD_addr   = ifieldRegDS(theInstr);
   8502    UChar vA_addr   = ifieldRegA(theInstr);
   8503    UChar UIMM_5    = vA_addr;
   8504    UChar vB_addr   = ifieldRegB(theInstr);
   8505    UChar vC_addr   = ifieldRegC(theInstr);
   8506    UChar b10       = ifieldBIT10(theInstr);
   8507    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   8508    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   8509 
   8510    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   8511 
   8512    IRTemp vA = newTemp(Ity_V128);
   8513    IRTemp vB = newTemp(Ity_V128);
   8514    IRTemp vC = newTemp(Ity_V128);
   8515    assign( vA, getVReg(vA_addr));
   8516    assign( vB, getVReg(vB_addr));
   8517    assign( vC, getVReg(vC_addr));
   8518 
   8519    if (opc1 != 0x4) {
   8520       vex_printf("dis_av_permute(ppc)(instr)\n");
   8521       return False;
   8522    }
   8523 
   8524    switch (opc2) {
   8525    case 0x2A: // vsel (Conditional Select, AV p238)
   8526       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   8527       /* vD = (vA & ~vC) | (vB & vC) */
   8528       putVReg( vD_addr, binop(Iop_OrV128,
   8529          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   8530          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   8531       return True;
   8532 
   8533    case 0x2B: { // vperm (Permute, AV p218)
   8534       /* limited to two args for IR, so have to play games... */
   8535       IRTemp a_perm  = newTemp(Ity_V128);
   8536       IRTemp b_perm  = newTemp(Ity_V128);
   8537       IRTemp mask    = newTemp(Ity_V128);
   8538       IRTemp vC_andF = newTemp(Ity_V128);
   8539       DIP("vperm v%d,v%d,v%d,v%d\n",
   8540           vD_addr, vA_addr, vB_addr, vC_addr);
   8541       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   8542          IR specifies, and also to hide irrelevant bits from
   8543          memcheck */
   8544       assign( vC_andF,
   8545               binop(Iop_AndV128, mkexpr(vC),
   8546                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   8547       assign( a_perm,
   8548               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   8549       assign( b_perm,
   8550               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   8551       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   8552       assign( mask, binop(Iop_SarN8x16,
   8553                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   8554                           mkU8(7)) );
   8555       // dst = (a & ~mask) | (b & mask)
   8556       putVReg( vD_addr, binop(Iop_OrV128,
   8557                               binop(Iop_AndV128, mkexpr(a_perm),
   8558                                     unop(Iop_NotV128, mkexpr(mask))),
   8559                               binop(Iop_AndV128, mkexpr(b_perm),
   8560                                     mkexpr(mask))) );
   8561       return True;
   8562    }
   8563    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   8564       if (b10 != 0) {
   8565          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   8566          return False;
   8567       }
   8568       DIP("vsldoi v%d,v%d,v%d,%d\n",
   8569           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   8570       if (SHB_uimm4 == 0)
   8571          putVReg( vD_addr, mkexpr(vA) );
   8572       else
   8573          putVReg( vD_addr,
   8574             binop(Iop_OrV128,
   8575                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   8576                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   8577       return True;
   8578 
   8579    default:
   8580      break; // Fall through...
   8581    }
   8582 
   8583    opc2 = IFIELD( theInstr, 0, 11 );
   8584    switch (opc2) {
   8585 
   8586    /* Merge */
   8587    case 0x00C: // vmrghb (Merge High B, AV p195)
   8588       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8589       putVReg( vD_addr,
   8590                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   8591       break;
   8592 
   8593    case 0x04C: // vmrghh (Merge High HW, AV p196)
   8594       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8595       putVReg( vD_addr,
   8596                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   8597       break;
   8598 
   8599    case 0x08C: // vmrghw (Merge High W, AV p197)
   8600       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8601       putVReg( vD_addr,
   8602                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   8603       break;
   8604 
   8605    case 0x10C: // vmrglb (Merge Low B, AV p198)
   8606       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8607       putVReg( vD_addr,
   8608                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   8609       break;
   8610 
   8611    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   8612       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8613       putVReg( vD_addr,
   8614                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   8615       break;
   8616 
   8617    case 0x18C: // vmrglw (Merge Low W, AV p200)
   8618       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8619       putVReg( vD_addr,
   8620                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   8621       break;
   8622 
   8623 
   8624    /* Splat */
   8625    case 0x20C: { // vspltb (Splat Byte, AV p245)
   8626       /* vD = Dup8x16( vB[UIMM_5] ) */
   8627       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   8628       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   8629       putVReg( vD_addr, unop(Iop_Dup8x16,
   8630            unop(Iop_32to8, unop(Iop_V128to32,
   8631                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   8632       break;
   8633    }
   8634    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   8635       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   8636       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   8637       putVReg( vD_addr, unop(Iop_Dup16x8,
   8638            unop(Iop_32to16, unop(Iop_V128to32,
   8639                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   8640       break;
   8641    }
   8642    case 0x28C: { // vspltw (Splat Word, AV p250)
   8643       /* vD = Dup32x4( vB[UIMM_5] ) */
   8644       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   8645       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   8646       putVReg( vD_addr, unop(Iop_Dup32x4,
   8647          unop(Iop_V128to32,
   8648               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   8649       break;
   8650    }
   8651    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   8652       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   8653       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   8654       break;
   8655 
   8656    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   8657       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   8658       putVReg( vD_addr,
   8659                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   8660       break;
   8661 
   8662    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   8663       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   8664       putVReg( vD_addr,
   8665                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   8666       break;
   8667 
   8668    default:
   8669       vex_printf("dis_av_permute(ppc)(opc2)\n");
   8670       return False;
   8671    }
   8672    return True;
   8673 }
   8674 
   8675 /*
   8676   AltiVec Pack/Unpack Instructions
   8677 */
   8678 static Bool dis_av_pack ( UInt theInstr )
   8679 {
   8680    /* VX-Form */
   8681    UChar opc1     = ifieldOPC(theInstr);
   8682    UChar vD_addr  = ifieldRegDS(theInstr);
   8683    UChar vA_addr  = ifieldRegA(theInstr);
   8684    UChar vB_addr  = ifieldRegB(theInstr);
   8685    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   8686 
   8687    IRTemp signs = IRTemp_INVALID;
   8688    IRTemp zeros = IRTemp_INVALID;
   8689    IRTemp vA    = newTemp(Ity_V128);
   8690    IRTemp vB    = newTemp(Ity_V128);
   8691    assign( vA, getVReg(vA_addr));
   8692    assign( vB, getVReg(vB_addr));
   8693 
   8694    if (opc1 != 0x4) {
   8695       vex_printf("dis_av_pack(ppc)(instr)\n");
   8696       return False;
   8697    }
   8698 
   8699    switch (opc2) {
   8700    /* Packing */
   8701    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   8702       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8703       putVReg( vD_addr, binop(Iop_Narrow16x8, mkexpr(vA), mkexpr(vB)) );
   8704       return True;
   8705 
   8706    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   8707       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8708       putVReg( vD_addr, binop(Iop_Narrow32x4, mkexpr(vA), mkexpr(vB)) );
   8709       return True;
   8710 
   8711    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   8712       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8713       putVReg( vD_addr,
   8714                binop(Iop_QNarrow16Ux8, mkexpr(vA), mkexpr(vB)) );
   8715       // TODO: set VSCR[SAT]
   8716       return True;
   8717 
   8718    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   8719       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8720       putVReg( vD_addr,
   8721                binop(Iop_QNarrow32Ux4, mkexpr(vA), mkexpr(vB)) );
   8722       // TODO: set VSCR[SAT]
   8723       return True;
   8724 
   8725    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   8726       // This insn does a signed->unsigned saturating conversion.
   8727       // Conversion done here, then uses unsigned->unsigned vpk insn:
   8728       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   8729       IRTemp vA_tmp = newTemp(Ity_V128);
   8730       IRTemp vB_tmp = newTemp(Ity_V128);
   8731       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8732       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   8733                             unop(Iop_NotV128,
   8734                                  binop(Iop_SarN16x8,
   8735                                        mkexpr(vA), mkU8(15)))) );
   8736       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   8737                             unop(Iop_NotV128,
   8738                                  binop(Iop_SarN16x8,
   8739                                        mkexpr(vB), mkU8(15)))) );
   8740       putVReg( vD_addr, binop(Iop_QNarrow16Ux8,
   8741                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   8742       // TODO: set VSCR[SAT]
   8743       return True;
   8744    }
   8745    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   8746       // This insn does a signed->unsigned saturating conversion.
   8747       // Conversion done here, then uses unsigned->unsigned vpk insn:
   8748       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   8749       IRTemp vA_tmp = newTemp(Ity_V128);
   8750       IRTemp vB_tmp = newTemp(Ity_V128);
   8751       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8752       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   8753                             unop(Iop_NotV128,
   8754                                  binop(Iop_SarN32x4,
   8755                                        mkexpr(vA), mkU8(31)))) );
   8756       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   8757                             unop(Iop_NotV128,
   8758                                  binop(Iop_SarN32x4,
   8759                                        mkexpr(vB), mkU8(31)))) );
   8760       putVReg( vD_addr, binop(Iop_QNarrow32Ux4,
   8761                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   8762       // TODO: set VSCR[SAT]
   8763       return True;
   8764    }
   8765    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   8766       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8767       putVReg( vD_addr,
   8768                binop(Iop_QNarrow16Sx8, mkexpr(vA), mkexpr(vB)) );
   8769       // TODO: set VSCR[SAT]
   8770       return True;
   8771 
   8772    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   8773       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8774       putVReg( vD_addr,
   8775                binop(Iop_QNarrow32Sx4, mkexpr(vA), mkexpr(vB)) );
   8776       // TODO: set VSCR[SAT]
   8777       return True;
   8778 
   8779    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   8780       /* CAB: Worth a new primop? */
   8781       /* Using shifts to compact pixel elements, then packing them */
   8782       IRTemp a1 = newTemp(Ity_V128);
   8783       IRTemp a2 = newTemp(Ity_V128);
   8784       IRTemp a3 = newTemp(Ity_V128);
   8785       IRTemp a_tmp = newTemp(Ity_V128);
   8786       IRTemp b1 = newTemp(Ity_V128);
   8787       IRTemp b2 = newTemp(Ity_V128);
   8788       IRTemp b3 = newTemp(Ity_V128);
   8789       IRTemp b_tmp = newTemp(Ity_V128);
   8790       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8791       assign( a1, binop(Iop_ShlN16x8,
   8792                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   8793                         mkU8(10)) );
   8794       assign( a2, binop(Iop_ShlN16x8,
   8795                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   8796                         mkU8(5)) );
   8797       assign( a3,  binop(Iop_ShrN16x8,
   8798                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   8799                          mkU8(11)) );
   8800       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   8801                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   8802 
   8803       assign( b1, binop(Iop_ShlN16x8,
   8804                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   8805                         mkU8(10)) );
   8806       assign( b2, binop(Iop_ShlN16x8,
   8807                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   8808                         mkU8(5)) );
   8809       assign( b3,  binop(Iop_ShrN16x8,
   8810                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   8811                          mkU8(11)) );
   8812       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   8813                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   8814 
   8815       putVReg( vD_addr, binop(Iop_Narrow32x4,
   8816                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   8817       return True;
   8818    }
   8819 
   8820    default:
   8821       break; // Fall through...
   8822    }
   8823 
   8824 
   8825    if (vA_addr != 0) {
   8826       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   8827       return False;
   8828    }
   8829 
   8830    signs = newTemp(Ity_V128);
   8831    zeros = newTemp(Ity_V128);
   8832    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   8833 
   8834    switch (opc2) {
   8835    /* Unpacking */
   8836    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   8837       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   8838       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   8839       putVReg( vD_addr,
   8840                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   8841       break;
   8842    }
   8843    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   8844       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   8845       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   8846       putVReg( vD_addr,
   8847                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   8848       break;
   8849    }
   8850    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   8851       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   8852       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   8853       putVReg( vD_addr,
   8854                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   8855       break;
   8856    }
   8857    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   8858       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   8859       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   8860       putVReg( vD_addr,
   8861                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   8862       break;
   8863    }
   8864    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   8865       /* CAB: Worth a new primop? */
   8866       /* Using shifts to isolate pixel elements, then expanding them */
   8867       IRTemp z0  = newTemp(Ity_V128);
   8868       IRTemp z1  = newTemp(Ity_V128);
   8869       IRTemp z01 = newTemp(Ity_V128);
   8870       IRTemp z2  = newTemp(Ity_V128);
   8871       IRTemp z3  = newTemp(Ity_V128);
   8872       IRTemp z23 = newTemp(Ity_V128);
   8873       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   8874       assign( z0,  binop(Iop_ShlN16x8,
   8875                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   8876                          mkU8(8)) );
   8877       assign( z1,  binop(Iop_ShrN16x8,
   8878                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   8879                          mkU8(11)) );
   8880       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   8881                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   8882       assign( z2,  binop(Iop_ShrN16x8,
   8883                          binop(Iop_ShlN16x8,
   8884                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   8885                                mkU8(11)),
   8886                          mkU8(3)) );
   8887       assign( z3,  binop(Iop_ShrN16x8,
   8888                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   8889                          mkU8(11)) );
   8890       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   8891                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   8892       putVReg( vD_addr,
   8893                binop(Iop_OrV128,
   8894                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   8895                      mkexpr(z23)) );
   8896       break;
   8897    }
   8898    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   8899       /* identical to vupkhpx, except interleaving LO */
   8900       IRTemp z0  = newTemp(Ity_V128);
   8901       IRTemp z1  = newTemp(Ity_V128);
   8902       IRTemp z01 = newTemp(Ity_V128);
   8903       IRTemp z2  = newTemp(Ity_V128);
   8904       IRTemp z3  = newTemp(Ity_V128);
   8905       IRTemp z23 = newTemp(Ity_V128);
   8906       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   8907       assign( z0,  binop(Iop_ShlN16x8,
   8908                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   8909                          mkU8(8)) );
   8910       assign( z1,  binop(Iop_ShrN16x8,
   8911                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   8912                          mkU8(11)) );
   8913       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   8914                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   8915       assign( z2,  binop(Iop_ShrN16x8,
   8916                          binop(Iop_ShlN16x8,
   8917                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   8918                                mkU8(11)),
   8919                          mkU8(3)) );
   8920       assign( z3,  binop(Iop_ShrN16x8,
   8921                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   8922                          mkU8(11)) );
   8923       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   8924                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   8925       putVReg( vD_addr,
   8926                binop(Iop_OrV128,
   8927                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   8928                      mkexpr(z23)) );
   8929       break;
   8930    }
   8931    default:
   8932       vex_printf("dis_av_pack(ppc)(opc2)\n");
   8933       return False;
   8934    }
   8935    return True;
   8936 }
   8937 
   8938 
   8939 /*
   8940   AltiVec Floating Point Arithmetic Instructions
   8941 */
   8942 static Bool dis_av_fp_arith ( UInt theInstr )
   8943 {
   8944    /* VA-Form */
   8945    UChar opc1     = ifieldOPC(theInstr);
   8946    UChar vD_addr  = ifieldRegDS(theInstr);
   8947    UChar vA_addr  = ifieldRegA(theInstr);
   8948    UChar vB_addr  = ifieldRegB(theInstr);
   8949    UChar vC_addr  = ifieldRegC(theInstr);
   8950    UInt  opc2=0;
   8951 
   8952    IRTemp vA = newTemp(Ity_V128);
   8953    IRTemp vB = newTemp(Ity_V128);
   8954    IRTemp vC = newTemp(Ity_V128);
   8955    assign( vA, getVReg(vA_addr));
   8956    assign( vB, getVReg(vB_addr));
   8957    assign( vC, getVReg(vC_addr));
   8958 
   8959    if (opc1 != 0x4) {
   8960       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   8961       return False;
   8962    }
   8963 
   8964    opc2 = IFIELD( theInstr, 0, 6 );
   8965    switch (opc2) {
   8966    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   8967       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   8968           vD_addr, vA_addr, vC_addr, vB_addr);
   8969       putVReg( vD_addr,
   8970                binop(Iop_Add32Fx4, mkexpr(vB),
   8971                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   8972       return True;
   8973 
   8974    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   8975       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   8976           vD_addr, vA_addr, vC_addr, vB_addr);
   8977       putVReg( vD_addr,
   8978                binop(Iop_Sub32Fx4,
   8979                      mkexpr(vB),
   8980                      binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
   8981       return True;
   8982    }
   8983 
   8984    default:
   8985      break; // Fall through...
   8986    }
   8987 
   8988    opc2 = IFIELD( theInstr, 0, 11 );
   8989    switch (opc2) {
   8990    case 0x00A: // vaddfp (Add FP, AV p137)
   8991       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8992       putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
   8993       return True;
   8994 
   8995   case 0x04A: // vsubfp (Subtract FP, AV p261)
   8996       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   8997       putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
   8998       return True;
   8999 
   9000    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   9001       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   9002       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   9003       return True;
   9004 
   9005    case 0x44A: // vminfp (Minimum FP, AV p187)
   9006       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   9007       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   9008       return True;
   9009 
   9010    default:
   9011       break; // Fall through...
   9012    }
   9013 
   9014 
   9015    if (vA_addr != 0) {
   9016       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   9017       return False;
   9018    }
   9019 
   9020    switch (opc2) {
   9021    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   9022       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   9023       putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
   9024       return True;
   9025 
   9026    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   9027       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   9028       putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
   9029       return True;
   9030 
   9031    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   9032       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   9033       DIP(" => not implemented\n");
   9034       return False;
   9035 
   9036    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   9037       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   9038       DIP(" => not implemented\n");
   9039       return False;
   9040 
   9041    default:
   9042       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   9043       return False;
   9044    }
   9045    return True;
   9046 }
   9047 
   9048 /*
   9049   AltiVec Floating Point Compare Instructions
   9050 */
   9051 static Bool dis_av_fp_cmp ( UInt theInstr )
   9052 {
   9053    /* VXR-Form */
   9054    UChar opc1     = ifieldOPC(theInstr);
   9055    UChar vD_addr  = ifieldRegDS(theInstr);
   9056    UChar vA_addr  = ifieldRegA(theInstr);
   9057    UChar vB_addr  = ifieldRegB(theInstr);
   9058    UChar flag_rC  = ifieldBIT10(theInstr);
   9059    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   9060 
   9061    Bool cmp_bounds = False;
   9062 
   9063    IRTemp vA = newTemp(Ity_V128);
   9064    IRTemp vB = newTemp(Ity_V128);
   9065    IRTemp vD = newTemp(Ity_V128);
   9066    assign( vA, getVReg(vA_addr));
   9067    assign( vB, getVReg(vB_addr));
   9068 
   9069    if (opc1 != 0x4) {
   9070       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   9071       return False;
   9072    }
   9073 
   9074    switch (opc2) {
   9075    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   9076       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   9077                                       vD_addr, vA_addr, vB_addr);
   9078       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   9079       break;
   9080 
   9081    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   9082       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   9083                                       vD_addr, vA_addr, vB_addr);
   9084       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   9085       break;
   9086 
   9087    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   9088       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   9089                                       vD_addr, vA_addr, vB_addr);
   9090       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   9091       break;
   9092 
   9093    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   9094       IRTemp gt      = newTemp(Ity_V128);
   9095       IRTemp lt      = newTemp(Ity_V128);
   9096       IRTemp zeros   = newTemp(Ity_V128);
   9097       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   9098                                      vD_addr, vA_addr, vB_addr);
   9099       cmp_bounds = True;
   9100       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   9101 
   9102       /* Note: making use of fact that the ppc backend for compare insns
   9103          return zero'd lanes if either of the corresponding arg lanes is
   9104          a nan.
   9105 
   9106          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   9107          need this for the other compares too (vcmpeqfp etc)...
   9108          Better still, tighten down the spec for compare irops.
   9109        */
   9110       assign( gt, unop(Iop_NotV128,
   9111                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   9112       assign( lt, unop(Iop_NotV128,
   9113                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   9114                              binop(Iop_Sub32Fx4, mkexpr(zeros),
   9115                                                  mkexpr(vB)))) );
   9116 
   9117       // finally, just shift gt,lt to correct position
   9118       assign( vD, binop(Iop_ShlN32x4,
   9119                         binop(Iop_OrV128,
   9120                               binop(Iop_AndV128, mkexpr(gt),
   9121                                     unop(Iop_Dup32x4, mkU32(0x2))),
   9122                               binop(Iop_AndV128, mkexpr(lt),
   9123                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   9124                         mkU8(30)) );
   9125       break;
   9126    }
   9127 
   9128    default:
   9129       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   9130       return False;
   9131    }
   9132 
   9133    putVReg( vD_addr, mkexpr(vD) );
   9134 
   9135    if (flag_rC) {
   9136       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   9137    }
   9138    return True;
   9139 }
   9140 
   9141 /*
   9142   AltiVec Floating Point Convert/Round Instructions
   9143 */
   9144 static Bool dis_av_fp_convert ( UInt theInstr )
   9145 {
   9146    /* VX-Form */
   9147    UChar opc1     = ifieldOPC(theInstr);
   9148    UChar vD_addr  = ifieldRegDS(theInstr);
   9149    UChar UIMM_5   = ifieldRegA(theInstr);
   9150    UChar vB_addr  = ifieldRegB(theInstr);
   9151    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   9152 
   9153    IRTemp vB        = newTemp(Ity_V128);
   9154    IRTemp vScale    = newTemp(Ity_V128);
   9155    IRTemp vInvScale = newTemp(Ity_V128);
   9156 
   9157    float scale, inv_scale;
   9158 
   9159    assign( vB, getVReg(vB_addr));
   9160 
   9161    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   9162    scale = (float)( (unsigned int) 1<<UIMM_5 );
   9163    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   9164    inv_scale = 1/scale;
   9165    assign( vInvScale,
   9166            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   9167 
   9168    if (opc1 != 0x4) {
   9169       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   9170       return False;
   9171    }
   9172 
   9173    switch (opc2) {
   9174    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   9175       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   9176       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   9177                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   9178                               mkexpr(vInvScale)) );
   9179       return True;
   9180 
   9181    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   9182       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   9183 
   9184       putVReg( vD_addr, binop(Iop_Mul32Fx4,
   9185                               unop(Iop_I32StoFx4, mkexpr(vB)),
   9186                               mkexpr(vInvScale)) );
   9187       return True;
   9188 
   9189    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   9190       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   9191       putVReg( vD_addr,
   9192                unop(Iop_QFtoI32Ux4_RZ,
   9193                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   9194       return True;
   9195 
   9196    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   9197       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   9198       putVReg( vD_addr,
   9199                unop(Iop_QFtoI32Sx4_RZ,
   9200                      binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
   9201       return True;
   9202 
   9203    default:
   9204      break;    // Fall through...
   9205    }
   9206 
   9207    if (UIMM_5 != 0) {
   9208       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   9209       return False;
   9210    }
   9211 
   9212    switch (opc2) {
   9213    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   9214       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   9215       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   9216       break;
   9217 
   9218    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   9219       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   9220       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   9221       break;
   9222 
   9223    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   9224       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   9225       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   9226       break;
   9227 
   9228    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   9229       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   9230       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   9231       break;
   9232 
   9233    default:
   9234       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   9235       return False;
   9236    }
   9237    return True;
   9238 }
   9239 
   9240 
   9241 
   9242 
   9243 
   9244 /*------------------------------------------------------------*/
   9245 /*--- Disassemble a single instruction                     ---*/
   9246 /*------------------------------------------------------------*/
   9247 
   9248 /* Disassemble a single instruction into IR.  The instruction
   9249    is located in host memory at &guest_code[delta]. */
   9250 
   9251 static
   9252 DisResult disInstr_PPC_WRK (
   9253              Bool         put_IP,
   9254              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   9255              Bool         resteerCisOk,
   9256              void*        callback_opaque,
   9257              Long         delta64,
   9258              VexArchInfo* archinfo,
   9259              VexAbiInfo*  abiinfo
   9260           )
   9261 {
   9262    UChar     opc1;
   9263    UInt      opc2;
   9264    DisResult dres;
   9265    UInt      theInstr;
   9266    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   9267    Bool      allow_F  = False;
   9268    Bool      allow_V  = False;
   9269    Bool      allow_FX = False;
   9270    Bool      allow_GX = False;
   9271    UInt      hwcaps = archinfo->hwcaps;
   9272    Long      delta;
   9273 
   9274    /* What insn variants are we supporting today? */
   9275    if (mode64) {
   9276       allow_F  = True;
   9277       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   9278       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   9279       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   9280    } else {
   9281       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   9282       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   9283       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   9284       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   9285    }
   9286 
   9287    /* The running delta */
   9288    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   9289 
   9290    /* Set result defaults. */
   9291    dres.whatNext   = Dis_Continue;
   9292    dres.len        = 0;
   9293    dres.continueAt = 0;
   9294 
   9295    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   9296       4-aligned.  So just fish the whole thing out of memory right now
   9297       and have done. */
   9298    theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
   9299 
   9300    if (0) vex_printf("insn: 0x%x\n", theInstr);
   9301 
   9302    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   9303 
   9304    /* We may be asked to update the guest CIA before going further. */
   9305    if (put_IP)
   9306       putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   9307 
   9308    /* Spot "Special" instructions (see comment at top of file). */
   9309    {
   9310       UChar* code = (UChar*)(guest_code + delta);
   9311       /* Spot the 16-byte preamble:
   9312          32-bit mode:
   9313             54001800  rlwinm 0,0,3,0,0
   9314             54006800  rlwinm 0,0,13,0,0
   9315             5400E800  rlwinm 0,0,29,0,0
   9316             54009800  rlwinm 0,0,19,0,0
   9317          64-bit mode:
   9318             78001800  rotldi 0,0,3
   9319             78006800  rotldi 0,0,13
   9320             7800E802  rotldi 0,0,61
   9321             78009802  rotldi 0,0,51
   9322       */
   9323       UInt word1 = mode64 ? 0x78001800 : 0x54001800;
   9324       UInt word2 = mode64 ? 0x78006800 : 0x54006800;
   9325       UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
   9326       UInt word4 = mode64 ? 0x78009802 : 0x54009800;
   9327       if (getUIntBigendianly(code+ 0) == word1 &&
   9328           getUIntBigendianly(code+ 4) == word2 &&
   9329           getUIntBigendianly(code+ 8) == word3 &&
   9330           getUIntBigendianly(code+12) == word4) {
   9331          /* Got a "Special" instruction preamble.  Which one is it? */
   9332          if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   9333             /* %R3 = client_request ( %R4 ) */
   9334             DIP("r3 = client_request ( %%r4 )\n");
   9335             delta += 20;
   9336             irsb->next     = mkSzImm( ty, guest_CIA_bbstart + delta );
   9337             irsb->jumpkind = Ijk_ClientReq;
   9338             dres.whatNext  = Dis_StopHere;
   9339             goto decode_success;
   9340          }
   9341          else
   9342          if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   9343             /* %R3 = guest_NRADDR */
   9344             DIP("r3 = guest_NRADDR\n");
   9345             delta += 20;
   9346             dres.len = 20;
   9347             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   9348             goto decode_success;
   9349          }
   9350          else
   9351          if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   9352             /*  branch-and-link-to-noredir %R11 */
   9353             DIP("branch-and-link-to-noredir r11\n");
   9354             delta += 20;
   9355             putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   9356             irsb->next     = getIReg(11);
   9357             irsb->jumpkind = Ijk_NoRedir;
   9358             dres.whatNext  = Dis_StopHere;
   9359             goto decode_success;
   9360          }
   9361          else
   9362          if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   9363             /* %R3 = guest_NRADDR_GPR2 */
   9364             DIP("r3 = guest_NRADDR_GPR2\n");
   9365             delta += 20;
   9366             dres.len = 20;
   9367             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   9368             goto decode_success;
   9369          }
   9370          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   9371             can print the insn following the Special-insn preamble. */
   9372          theInstr = getUIntBigendianly(code+16);
   9373          opc1     = ifieldOPC(theInstr);
   9374          opc2     = ifieldOPClo10(theInstr);
   9375          goto decode_failure;
   9376          /*NOTREACHED*/
   9377       }
   9378    }
   9379 
   9380    opc1 = ifieldOPC(theInstr);
   9381    opc2 = ifieldOPClo10(theInstr);
   9382 
   9383    // Note: all 'reserved' bits must be cleared, else invalid
   9384    switch (opc1) {
   9385 
   9386    /* Integer Arithmetic Instructions */
   9387    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   9388    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   9389       if (dis_int_arith( theInstr )) goto decode_success;
   9390       goto decode_failure;
   9391 
   9392    /* Integer Compare Instructions */
   9393    case 0x0B: case 0x0A: // cmpi, cmpli
   9394       if (dis_int_cmp( theInstr )) goto decode_success;
   9395       goto decode_failure;
   9396 
   9397    /* Integer Logical Instructions */
   9398    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   9399    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   9400       if (dis_int_logic( theInstr )) goto decode_success;
   9401       goto decode_failure;
   9402 
   9403    /* Integer Rotate Instructions */
   9404    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   9405       if (dis_int_rot( theInstr )) goto decode_success;
   9406       goto decode_failure;
   9407 
   9408    /* 64bit Integer Rotate Instructions */
   9409    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   9410       if (dis_int_rot( theInstr )) goto decode_success;
   9411       goto decode_failure;
   9412 
   9413    /* Integer Load Instructions */
   9414    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   9415    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   9416    case 0x20: case 0x21:            // lwz,  lwzu
   9417       if (dis_int_load( theInstr )) goto decode_success;
   9418       goto decode_failure;
   9419 
   9420    /* Integer Store Instructions */
   9421    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   9422    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   9423       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   9424       goto decode_failure;
   9425 
   9426    /* Integer Load and Store Multiple Instructions */
   9427    case 0x2E: case 0x2F: // lmw, stmw
   9428       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   9429       goto decode_failure;
   9430 
   9431    /* Branch Instructions */
   9432    case 0x12: case 0x10: // b, bc
   9433       if (dis_branch(theInstr, abiinfo, &dres,
   9434                                resteerOkFn, callback_opaque))
   9435          goto decode_success;
   9436       goto decode_failure;
   9437 
   9438    /* System Linkage Instructions */
   9439    case 0x11: // sc
   9440       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   9441       goto decode_failure;
   9442 
   9443    /* Trap Instructions */
   9444    case 0x02: case 0x03: // tdi, twi
   9445       if (dis_trapi(theInstr, &dres)) goto decode_success;
   9446       goto decode_failure;
   9447 
   9448    /* Floating Point Load Instructions */
   9449    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   9450    case 0x33:                       // lfdu
   9451       if (!allow_F) goto decode_noF;
   9452       if (dis_fp_load( theInstr )) goto decode_success;
   9453       goto decode_failure;
   9454 
   9455    /* Floating Point Store Instructions */
   9456    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   9457    case 0x37:                       // stfdux
   9458       if (!allow_F) goto decode_noF;
   9459       if (dis_fp_store( theInstr )) goto decode_success;
   9460       goto decode_failure;
   9461 
   9462       /* Floating Point Load Double Pair Instructions */
   9463    case 0x39: case 0x3D:
   9464       if (!allow_F) goto decode_noF;
   9465       if (dis_fp_pair( theInstr )) goto decode_success;
   9466       goto decode_failure;
   9467 
   9468    /* 64bit Integer Loads */
   9469    case 0x3A:  // ld, ldu, lwa
   9470       if (!mode64) goto decode_failure;
   9471       if (dis_int_load( theInstr )) goto decode_success;
   9472       goto decode_failure;
   9473 
   9474    case 0x3B:
   9475       if (!allow_F) goto decode_noF;
   9476       opc2 = IFIELD(theInstr, 1, 5);
   9477       switch (opc2) {
   9478       /* Floating Point Arith Instructions */
   9479       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   9480       case 0x19:                       // fmuls
   9481          if (dis_fp_arith(theInstr)) goto decode_success;
   9482          goto decode_failure;
   9483       case 0x16:                       // fsqrts
   9484          if (!allow_FX) goto decode_noFX;
   9485          if (dis_fp_arith(theInstr)) goto decode_success;
   9486          goto decode_failure;
   9487       case 0x18:                       // fres
   9488          if (!allow_GX) goto decode_noGX;
   9489          if (dis_fp_arith(theInstr)) goto decode_success;
   9490          goto decode_failure;
   9491 
   9492       /* Floating Point Mult-Add Instructions */
   9493       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   9494       case 0x1F:                       // fnmadds
   9495          if (dis_fp_multadd(theInstr)) goto decode_success;
   9496          goto decode_failure;
   9497 
   9498       case 0x1A:                       // frsqrtes
   9499          if (!allow_GX) goto decode_noGX;
   9500          if (dis_fp_arith(theInstr)) goto decode_success;
   9501          goto decode_failure;
   9502 
   9503       default:
   9504          goto decode_failure;
   9505       }
   9506       break;
   9507 
   9508    /* 64bit Integer Stores */
   9509    case 0x3E:  // std, stdu
   9510       if (!mode64) goto decode_failure;
   9511       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   9512       goto decode_failure;
   9513 
   9514    case 0x3F:
   9515       if (!allow_F) goto decode_noF;
   9516       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   9517          so we can simply fall through the first switch statement */
   9518 
   9519       opc2 = IFIELD(theInstr, 1, 5);
   9520       switch (opc2) {
   9521       /* Floating Point Arith Instructions */
   9522       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   9523       case 0x19:                       // fmul
   9524          if (dis_fp_arith(theInstr)) goto decode_success;
   9525          goto decode_failure;
   9526       case 0x16:                       // fsqrt
   9527          if (!allow_FX) goto decode_noFX;
   9528          if (dis_fp_arith(theInstr)) goto decode_success;
   9529          goto decode_failure;
   9530       case 0x17: case 0x1A:            // fsel, frsqrte
   9531          if (!allow_GX) goto decode_noGX;
   9532          if (dis_fp_arith(theInstr)) goto decode_success;
   9533          goto decode_failure;
   9534 
   9535       /* Floating Point Mult-Add Instructions */
   9536       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   9537       case 0x1F:                       // fnmadd
   9538          if (dis_fp_multadd(theInstr)) goto decode_success;
   9539          goto decode_failure;
   9540 
   9541       case 0x18:                       // fre
   9542          if (!allow_GX) goto decode_noGX;
   9543          if (dis_fp_arith(theInstr)) goto decode_success;
   9544          goto decode_failure;
   9545 
   9546       default:
   9547          break; // Fall through
   9548       }
   9549 
   9550       opc2 = IFIELD(theInstr, 1, 10);
   9551       switch (opc2) {
   9552       /* Floating Point Compare Instructions */
   9553       case 0x000: // fcmpu
   9554       case 0x020: // fcmpo
   9555          if (dis_fp_cmp(theInstr)) goto decode_success;
   9556          goto decode_failure;
   9557 
   9558       /* Floating Point Rounding/Conversion Instructions */
   9559       case 0x00C: // frsp
   9560       case 0x00E: // fctiw
   9561       case 0x00F: // fctiwz
   9562       case 0x32E: // fctid
   9563       case 0x32F: // fctidz
   9564       case 0x34E: // fcfid
   9565          if (dis_fp_round(theInstr)) goto decode_success;
   9566          goto decode_failure;
   9567 
   9568       /* Power6 rounding stuff */
   9569       case 0x1E8: // frim
   9570       case 0x1C8: // frip
   9571       case 0x188: // frin
   9572       case 0x1A8: // friz
   9573          /* A hack to check for P6 capability . . . */
   9574          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   9575              (dis_fp_round(theInstr)))
   9576             goto decode_success;
   9577          goto decode_failure;
   9578 
   9579       /* Floating Point Move Instructions */
   9580       case 0x008: // fcpsgn
   9581       case 0x028: // fneg
   9582       case 0x048: // fmr
   9583       case 0x088: // fnabs
   9584       case 0x108: // fabs
   9585          if (dis_fp_move( theInstr )) goto decode_success;
   9586          goto decode_failure;
   9587 
   9588       /* Floating Point Status/Control Register Instructions */
   9589       case 0x026: // mtfsb1
   9590       case 0x040: // mcrfs
   9591       case 0x046: // mtfsb0
   9592       case 0x086: // mtfsfi
   9593       case 0x247: // mffs
   9594       case 0x2C7: // mtfsf
   9595          if (dis_fp_scr( theInstr )) goto decode_success;
   9596          goto decode_failure;
   9597 
   9598       default:
   9599          goto decode_failure;
   9600       }
   9601       break;
   9602 
   9603    case 0x13:
   9604       switch (opc2) {
   9605 
   9606       /* Condition Register Logical Instructions */
   9607       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   9608       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   9609       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   9610          if (dis_cond_logic( theInstr )) goto decode_success;
   9611          goto decode_failure;
   9612 
   9613       /* Branch Instructions */
   9614       case 0x210: case 0x010: // bcctr, bclr
   9615          if (dis_branch(theInstr, abiinfo, &dres,
   9616                                   resteerOkFn, callback_opaque))
   9617             goto decode_success;
   9618          goto decode_failure;
   9619 
   9620       /* Memory Synchronization Instructions */
   9621       case 0x096: // isync
   9622          if (dis_memsync( theInstr )) goto decode_success;
   9623          goto decode_failure;
   9624 
   9625       default:
   9626          goto decode_failure;
   9627       }
   9628       break;
   9629 
   9630 
   9631    case 0x1F:
   9632 
   9633       /* For arith instns, bit10 is the OE flag (overflow enable) */
   9634 
   9635       opc2 = IFIELD(theInstr, 1, 9);
   9636       switch (opc2) {
   9637       /* Integer Arithmetic Instructions */
   9638       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   9639       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   9640       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   9641       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   9642       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   9643       case 0x0C8:                         // subfze
   9644          if (dis_int_arith( theInstr )) goto decode_success;
   9645          goto decode_failure;
   9646 
   9647       /* 64bit Integer Arithmetic */
   9648       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   9649       case 0x1C9: case 0x1E9:             // divdu, divd
   9650          if (!mode64) goto decode_failure;
   9651          if (dis_int_arith( theInstr )) goto decode_success;
   9652          goto decode_failure;
   9653 
   9654       case 0x1FC:                         // cmpb
   9655          if (dis_int_logic( theInstr )) goto decode_success;
   9656          goto decode_failure;
   9657 
   9658       default:
   9659          break;  // Fall through...
   9660       }
   9661 
   9662       /* All remaining opcodes use full 10 bits. */
   9663 
   9664       opc2 = IFIELD(theInstr, 1, 10);
   9665       switch (opc2) {
   9666       /* Integer Compare Instructions  */
   9667       case 0x000: case 0x020: // cmp, cmpl
   9668          if (dis_int_cmp( theInstr )) goto decode_success;
   9669          goto decode_failure;
   9670 
   9671       /* Integer Logical Instructions */
   9672       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   9673       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   9674       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   9675       case 0x19C: case 0x13C:             // orc,  xor
   9676       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   9677          if (dis_int_logic( theInstr )) goto decode_success;
   9678          goto decode_failure;
   9679 
   9680       /* 64bit Integer Logical Instructions */
   9681       case 0x3DA: case 0x03A: // extsw, cntlzd
   9682          if (!mode64) goto decode_failure;
   9683          if (dis_int_logic( theInstr )) goto decode_success;
   9684          goto decode_failure;
   9685 
   9686          /* 64bit Integer Parity Instructions */
   9687       case 0xba: case 0x9a: // prtyd, prtyw
   9688          if (dis_int_parity( theInstr )) goto decode_success;
   9689          goto decode_failure;
   9690 
   9691       /* Integer Shift Instructions */
   9692       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   9693       case 0x218:                         // srw
   9694          if (dis_int_shift( theInstr )) goto decode_success;
   9695          goto decode_failure;
   9696 
   9697       /* 64bit Integer Shift Instructions */
   9698       case 0x01B: case 0x31A: // sld, srad
   9699       case 0x33A: case 0x33B: // sradi
   9700       case 0x21B:             // srd
   9701          if (!mode64) goto decode_failure;
   9702          if (dis_int_shift( theInstr )) goto decode_success;
   9703          goto decode_failure;
   9704 
   9705       /* Integer Load Instructions */
   9706       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   9707       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   9708       case 0x017: case 0x037:             // lwzx,  lwzux
   9709          if (dis_int_load( theInstr )) goto decode_success;
   9710          goto decode_failure;
   9711 
   9712       /* 64bit Integer Load Instructions */
   9713       case 0x035: case 0x015:             // ldux,  ldx
   9714       case 0x175: case 0x155:             // lwaux, lwax
   9715          if (!mode64) goto decode_failure;
   9716          if (dis_int_load( theInstr )) goto decode_success;
   9717          goto decode_failure;
   9718 
   9719       /* Integer Store Instructions */
   9720       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   9721       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   9722          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   9723          goto decode_failure;
   9724 
   9725       /* 64bit Integer Store Instructions */
   9726       case 0x0B5: case 0x095: // stdux, stdx
   9727          if (!mode64) goto decode_failure;
   9728          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   9729          goto decode_failure;
   9730 
   9731       /* Integer Load and Store with Byte Reverse Instructions */
   9732       case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
   9733       case 0x296:                         // stwbrx
   9734          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   9735          goto decode_failure;
   9736 
   9737       /* Integer Load and Store String Instructions */
   9738       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   9739       case 0x295: {                       // stswx
   9740          Bool stopHere = False;
   9741          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   9742          if (!ok) goto decode_failure;
   9743          if (stopHere) {
   9744             irsb->next     = mkSzImm(ty, nextInsnAddr());
   9745             irsb->jumpkind = Ijk_Boring;
   9746             dres.whatNext  = Dis_StopHere;
   9747          }
   9748          goto decode_success;
   9749       }
   9750 
   9751       /* Memory Synchronization Instructions */
   9752       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   9753       case 0x256:                         // sync
   9754          if (dis_memsync( theInstr )) goto decode_success;
   9755          goto decode_failure;
   9756 
   9757       /* 64bit Memory Synchronization Instructions */
   9758       case 0x054: case 0x0D6: // ldarx, stdcx.
   9759          if (!mode64) goto decode_failure;
   9760          if (dis_memsync( theInstr )) goto decode_success;
   9761          goto decode_failure;
   9762 
   9763       /* Processor Control Instructions */
   9764       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   9765       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   9766          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   9767          goto decode_failure;
   9768 
   9769       /* Cache Management Instructions */
   9770       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   9771       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   9772       case 0x3D6:                         // icbi
   9773          if (dis_cache_manage( theInstr, &dres, archinfo ))
   9774             goto decode_success;
   9775          goto decode_failure;
   9776 
   9777 //zz       /* External Control Instructions */
   9778 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   9779 //zz          DIP("external control op => not implemented\n");
   9780 //zz          goto decode_failure;
   9781 
   9782       /* Trap Instructions */
   9783       case 0x004: case 0x044:             // tw,   td
   9784          if (dis_trap(theInstr, &dres)) goto decode_success;
   9785          goto decode_failure;
   9786 
   9787       /* Floating Point Load Instructions */
   9788       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   9789       case 0x277:                         // lfdux
   9790          if (!allow_F) goto decode_noF;
   9791          if (dis_fp_load( theInstr )) goto decode_success;
   9792          goto decode_failure;
   9793 
   9794       /* Floating Point Store Instructions */
   9795       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   9796       case 0x2F7:                         // stfdu, stfiwx
   9797          if (!allow_F) goto decode_noF;
   9798          if (dis_fp_store( theInstr )) goto decode_success;
   9799          goto decode_failure;
   9800       case 0x3D7:                         // stfiwx
   9801          if (!allow_F) goto decode_noF;
   9802          if (!allow_GX) goto decode_noGX;
   9803          if (dis_fp_store( theInstr )) goto decode_success;
   9804          goto decode_failure;
   9805 
   9806          /* Floating Point Double Pair Indexed Instructions */
   9807       case 0x317: // lfdpx (Power6)
   9808       case 0x397: // stfdpx (Power6)
   9809          if (!allow_F) goto decode_noF;
   9810          if (dis_fp_pair(theInstr)) goto decode_success;
   9811          goto decode_failure;
   9812 
   9813       case 0x357:                         // lfiwax
   9814          if (!allow_F) goto decode_noF;
   9815          if (dis_fp_load( theInstr )) goto decode_success;
   9816          goto decode_failure;
   9817 
   9818       /* AltiVec instructions */
   9819 
   9820       /* AV Cache Control - Data streams */
   9821       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   9822          if (!allow_V) goto decode_noV;
   9823          if (dis_av_datastream( theInstr )) goto decode_success;
   9824          goto decode_failure;
   9825 
   9826       /* AV Load */
   9827       case 0x006: case 0x026:             // lvsl, lvsr
   9828       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   9829       case 0x067: case 0x167:             // lvx, lvxl
   9830          if (!allow_V) goto decode_noV;
   9831          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   9832          goto decode_failure;
   9833 
   9834       /* AV Store */
   9835       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   9836       case 0x0E7: case 0x1E7:             // stvx, stvxl
   9837          if (!allow_V) goto decode_noV;
   9838          if (dis_av_store( theInstr )) goto decode_success;
   9839          goto decode_failure;
   9840 
   9841       default:
   9842          /* Deal with some other cases that we would otherwise have
   9843             punted on. */
   9844          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   9845          /* only decode this insn when reserved bit 0 (31 in IBM's
   9846             notation) is zero */
   9847          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   9848             UInt rT = ifieldRegDS( theInstr );
   9849             UInt rA = ifieldRegA( theInstr );
   9850             UInt rB = ifieldRegB( theInstr );
   9851             UInt bi = ifieldRegC( theInstr );
   9852             putIReg(
   9853                rT,
   9854                IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
   9855                              getIReg(rB),
   9856                              rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   9857                                      : getIReg(rA) )
   9858             );
   9859             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   9860             goto decode_success;
   9861          }
   9862          goto decode_failure;
   9863       }
   9864       break;
   9865 
   9866 
   9867    case 0x04:
   9868       /* AltiVec instructions */
   9869 
   9870       opc2 = IFIELD(theInstr, 0, 6);
   9871       switch (opc2) {
   9872       /* AV Mult-Add, Mult-Sum */
   9873       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   9874       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   9875       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   9876          if (!allow_V) goto decode_noV;
   9877          if (dis_av_multarith( theInstr )) goto decode_success;
   9878          goto decode_failure;
   9879 
   9880       /* AV Permutations */
   9881       case 0x2A:                       // vsel
   9882       case 0x2B:                       // vperm
   9883       case 0x2C:                       // vsldoi
   9884          if (!allow_V) goto decode_noV;
   9885          if (dis_av_permute( theInstr )) goto decode_success;
   9886          goto decode_failure;
   9887 
   9888       /* AV Floating Point Mult-Add/Sub */
   9889       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   9890          if (!allow_V) goto decode_noV;
   9891          if (dis_av_fp_arith( theInstr )) goto decode_success;
   9892          goto decode_failure;
   9893 
   9894       default:
   9895          break;  // Fall through...
   9896       }
   9897 
   9898       opc2 = IFIELD(theInstr, 0, 11);
   9899       switch (opc2) {
   9900       /* AV Arithmetic */
   9901       case 0x180:                         // vaddcuw
   9902       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   9903       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   9904       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   9905       case 0x580:                         // vsubcuw
   9906       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   9907       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   9908       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   9909       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   9910       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   9911       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   9912       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   9913       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   9914       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   9915       case 0x008: case 0x048:             // vmuloub, vmulouh
   9916       case 0x108: case 0x148:             // vmulosb, vmulosh
   9917       case 0x208: case 0x248:             // vmuleub, vmuleuh
   9918       case 0x308: case 0x348:             // vmulesb, vmulesh
   9919       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   9920       case 0x688: case 0x788:             // vsum2sws, vsumsws
   9921          if (!allow_V) goto decode_noV;
   9922          if (dis_av_arith( theInstr )) goto decode_success;
   9923          goto decode_failure;
   9924 
   9925       /* AV Rotate, Shift */
   9926       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   9927       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   9928       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   9929       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   9930       case 0x1C4: case 0x2C4:             // vsl, vsr
   9931       case 0x40C: case 0x44C:             // vslo, vsro
   9932          if (!allow_V) goto decode_noV;
   9933          if (dis_av_shift( theInstr )) goto decode_success;
   9934          goto decode_failure;
   9935 
   9936       /* AV Logic */
   9937       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   9938       case 0x4C4: case 0x504:             // vxor, vnor
   9939          if (!allow_V) goto decode_noV;
   9940          if (dis_av_logic( theInstr )) goto decode_success;
   9941          goto decode_failure;
   9942 
   9943       /* AV Processor Control */
   9944       case 0x604: case 0x644:             // mfvscr, mtvscr
   9945          if (!allow_V) goto decode_noV;
   9946          if (dis_av_procctl( theInstr )) goto decode_success;
   9947          goto decode_failure;
   9948 
   9949       /* AV Floating Point Arithmetic */
   9950       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   9951       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   9952       case 0x1CA:                         // vlogefp
   9953       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   9954          if (!allow_V) goto decode_noV;
   9955          if (dis_av_fp_arith( theInstr )) goto decode_success;
   9956          goto decode_failure;
   9957 
   9958       /* AV Floating Point Round/Convert */
   9959       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   9960       case 0x2CA:                         // vrfim
   9961       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   9962       case 0x3CA:                         // vctsxs
   9963          if (!allow_V) goto decode_noV;
   9964          if (dis_av_fp_convert( theInstr )) goto decode_success;
   9965          goto decode_failure;
   9966 
   9967       /* AV Merge, Splat */
   9968       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   9969       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   9970       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   9971       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   9972          if (!allow_V) goto decode_noV;
   9973          if (dis_av_permute( theInstr )) goto decode_success;
   9974          goto decode_failure;
   9975 
   9976       /* AV Pack, Unpack */
   9977       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   9978       case 0x0CE:                         // vpkuwus
   9979       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   9980       case 0x1CE:                         // vpkswss
   9981       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   9982       case 0x2CE:                         // vupklsh
   9983       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   9984          if (!allow_V) goto decode_noV;
   9985          if (dis_av_pack( theInstr )) goto decode_success;
   9986          goto decode_failure;
   9987 
   9988       default:
   9989          break;  // Fall through...
   9990       }
   9991 
   9992       opc2 = IFIELD(theInstr, 0, 10);
   9993       switch (opc2) {
   9994 
   9995       /* AV Compare */
   9996       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   9997       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   9998       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   9999          if (!allow_V) goto decode_noV;
   10000          if (dis_av_cmp( theInstr )) goto decode_success;
   10001          goto decode_failure;
   10002 
   10003       /* AV Floating Point Compare */
   10004       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   10005       case 0x3C6:                         // vcmpbfp
   10006          if (!allow_V) goto decode_noV;
   10007          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   10008          goto decode_failure;
   10009 
   10010       default:
   10011          goto decode_failure;
   10012       }
   10013       break;
   10014 
   10015    default:
   10016       goto decode_failure;
   10017 
   10018    decode_noF:
   10019       vassert(!allow_F);
   10020       vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
   10021       goto decode_failure;
   10022    decode_noV:
   10023       vassert(!allow_V);
   10024       vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
   10025       goto decode_failure;
   10026    decode_noFX:
   10027       vassert(!allow_FX);
   10028       vex_printf("disInstr(ppc): "
   10029                  "declined to decode a GeneralPurpose-Optional insn.\n");
   10030       goto decode_failure;
   10031    decode_noGX:
   10032       vassert(!allow_GX);
   10033       vex_printf("disInstr(ppc): "
   10034                  "declined to decode a Graphics-Optional insn.\n");
   10035       goto decode_failure;
   10036 
   10037    decode_failure:
   10038    /* All decode failures end up here. */
   10039    opc2 = (theInstr) & 0x7FF;
   10040    vex_printf("disInstr(ppc): unhandled instruction: "
   10041               "0x%x\n", theInstr);
   10042    vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   10043               opc1, opc1, opc2, opc2);
   10044 
   10045    /* Tell the dispatcher that this insn cannot be decoded, and so has
   10046       not been executed, and (is currently) the next to be executed.
   10047       CIA should be up-to-date since it made so at the start of each
   10048       insn, but nevertheless be paranoid and update it again right
   10049       now. */
   10050    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   10051    irsb->next     = mkSzImm(ty, guest_CIA_curr_instr);
   10052    irsb->jumpkind = Ijk_NoDecode;
   10053    dres.whatNext  = Dis_StopHere;
   10054    dres.len       = 0;
   10055    return dres;
   10056 
   10057    } /* switch (opc) for the main (primary) opcode switch. */
   10058 
   10059   decode_success:
   10060    /* All decode successes end up here. */
   10061    DIP("\n");
   10062 
   10063    if (dres.len == 0) {
   10064       dres.len = 4;
   10065    } else {
   10066       vassert(dres.len == 20);
   10067    }
   10068    return dres;
   10069 }
   10070 
   10071 #undef DIP
   10072 #undef DIS
   10073 
   10074 
   10075 /*------------------------------------------------------------*/
   10076 /*--- Top-level fn                                         ---*/
   10077 /*------------------------------------------------------------*/
   10078 
   10079 /* Disassemble a single instruction into IR.  The instruction
   10080    is located in host memory at &guest_code[delta]. */
   10081 
   10082 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   10083                          Bool         put_IP,
   10084                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   10085                          Bool         resteerCisOk,
   10086                          void*        callback_opaque,
   10087                          UChar*       guest_code_IN,
   10088                          Long         delta,
   10089                          Addr64       guest_IP,
   10090                          VexArch      guest_arch,
   10091                          VexArchInfo* archinfo,
   10092                          VexAbiInfo*  abiinfo,
   10093                          Bool         host_bigendian_IN )
   10094 {
   10095    IRType     ty;
   10096    DisResult  dres;
   10097    UInt       mask32, mask64;
   10098    UInt hwcaps_guest = archinfo->hwcaps;
   10099 
   10100    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   10101 
   10102    /* global -- ick */
   10103    mode64 = guest_arch == VexArchPPC64;
   10104    ty = mode64 ? Ity_I64 : Ity_I32;
   10105 
   10106    /* do some sanity checks */
   10107    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   10108             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX;
   10109 
   10110    mask64 = VEX_HWCAPS_PPC64_V
   10111             | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX;
   10112 
   10113    if (mode64) {
   10114       vassert((hwcaps_guest & mask32) == 0);
   10115    } else {
   10116       vassert((hwcaps_guest & mask64) == 0);
   10117    }
   10118 
   10119    /* Set globals (see top of this file) */
   10120    guest_code           = guest_code_IN;
   10121    irsb                 = irsb_IN;
   10122    host_is_bigendian    = host_bigendian_IN;
   10123 
   10124    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   10125    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   10126 
   10127    dres = disInstr_PPC_WRK ( put_IP,
   10128                              resteerOkFn, resteerCisOk, callback_opaque,
   10129                              delta, archinfo, abiinfo );
   10130 
   10131    return dres;
   10132 }
   10133 
   10134 
   10135 /*------------------------------------------------------------*/
   10136 /*--- Unused stuff                                         ---*/
   10137 /*------------------------------------------------------------*/
   10138 
   10139 ///* A potentially more memcheck-friendly implementation of Clz32, with
   10140 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   10141 //
   10142 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   10143 //{
   10144 //   /* Welcome ... to SSA R Us. */
   10145 //   IRTemp n1  = newTemp(Ity_I32);
   10146 //   IRTemp n2  = newTemp(Ity_I32);
   10147 //   IRTemp n3  = newTemp(Ity_I32);
   10148 //   IRTemp n4  = newTemp(Ity_I32);
   10149 //   IRTemp n5  = newTemp(Ity_I32);
   10150 //   IRTemp n6  = newTemp(Ity_I32);
   10151 //   IRTemp n7  = newTemp(Ity_I32);
   10152 //   IRTemp n8  = newTemp(Ity_I32);
   10153 //   IRTemp n9  = newTemp(Ity_I32);
   10154 //   IRTemp n10 = newTemp(Ity_I32);
   10155 //   IRTemp n11 = newTemp(Ity_I32);
   10156 //   IRTemp n12 = newTemp(Ity_I32);
   10157 //
   10158 //   /* First, propagate the most significant 1-bit into all lower
   10159 //      positions in the word. */
   10160 //   /* unsigned int clz ( unsigned int n )
   10161 //      {
   10162 //         n |= (n >> 1);
   10163 //         n |= (n >> 2);
   10164 //         n |= (n >> 4);
   10165 //         n |= (n >> 8);
   10166 //         n |= (n >> 16);
   10167 //         return bitcount(~n);
   10168 //      }
   10169 //   */
   10170 //   assign(n1, mkexpr(arg));
   10171 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   10172 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   10173 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   10174 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   10175 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   10176 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   10177 //      a word of the form 1---10---0, then do a population-count idiom
   10178 //      (to count the 1s, which is the number of leading zeroes, or 32
   10179 //      if the original word was 0. */
   10180 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   10181 //
   10182 //   /* unsigned int bitcount ( unsigned int n )
   10183 //      {
   10184 //         n = n - ((n >> 1) & 0x55555555);
   10185 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   10186 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   10187 //         n = n + (n >> 8);
   10188 //         n = (n + (n >> 16)) & 0x3F;
   10189 //         return n;
   10190 //      }
   10191 //   */
   10192 //   assign(n8,
   10193 //          binop(Iop_Sub32,
   10194 //                mkexpr(n7),
   10195 //                binop(Iop_And32,
   10196 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   10197 //                      mkU32(0x55555555))));
   10198 //   assign(n9,
   10199 //          binop(Iop_Add32,
   10200 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   10201 //                binop(Iop_And32,
   10202 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   10203 //                      mkU32(0x33333333))));
   10204 //   assign(n10,
   10205 //          binop(Iop_And32,
   10206 //                binop(Iop_Add32,
   10207 //                      mkexpr(n9),
   10208 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   10209 //                mkU32(0x0F0F0F0F)));
   10210 //   assign(n11,
   10211 //          binop(Iop_Add32,
   10212 //                mkexpr(n10),
   10213 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   10214 //   assign(n12,
   10215 //          binop(Iop_Add32,
   10216 //                mkexpr(n11),
   10217 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   10218 //   return
   10219 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   10220 //}
   10221 
   10222 /*--------------------------------------------------------------------*/
   10223 /*--- end                                         guest_ppc_toIR.c ---*/
   10224 /*--------------------------------------------------------------------*/
   10225