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-2015 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 
     30    Neither the names of the U.S. Department of Energy nor the
     31    University of California nor the names of its contributors may be
     32    used to endorse or promote products derived from this software
     33    without prior written permission.
     34 */
     35 
     36 /* TODO 18/Nov/05:
     37 
     38    Spot rld... cases which are simply left/right shifts and emit
     39    Shl64/Shr64 accordingly.
     40 
     41    Altivec
     42    - datastream insns
     43    - lvxl,stvxl: load/store with 'least recently used' hint
     44    - vexptefp, vlogefp
     45 
     46    LIMITATIONS:
     47 
     48    Various, including:
     49 
     50    - Some invalid forms of lswi and lswx are accepted when they should
     51      not be.
     52 
     53    - Floating Point:
     54      - All exceptions disabled in FPSCR
     55      - condition codes not set in FPSCR
     56 
     57    - Altivec floating point:
     58      - vmaddfp, vnmsubfp
     59        Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
     60        system default of Non-Java mode, we get some small errors
     61        (lowest bit only).
     62        This is because Non-Java mode brutally hacks denormalised results
     63        to zero, whereas we keep maximum accuracy.  However, using
     64        Non-Java mode would give us more inaccuracy, as our intermediate
     65        results would then be zeroed, too.
     66 
     67    - AbiHints for the stack red zone are only emitted for
     68        unconditional calls and returns (bl, blr).  They should also be
     69        emitted for conditional calls and returns, but we don't have a
     70        way to express that right now.  Ah well.
     71 
     72    - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
     73        ignores the rounding mode, and generates code that assumes
     74        round-to-nearest.  This means V will compute incorrect results
     75        for uses of these IROps when the rounding mode (first) arg is
     76        not mkU32(Irrm_NEAREST).
     77 */
     78 
     79 /* "Special" instructions.
     80 
     81    This instruction decoder can decode four special instructions
     82    which mean nothing natively (are no-ops as far as regs/mem are
     83    concerned) but have meaning for supporting Valgrind.  A special
     84    instruction is flagged by a 16-byte preamble:
     85 
     86       32-bit mode: 5400183E 5400683E 5400E83E 5400983E
     87                    (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
     88                     rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
     89 
     90       64-bit mode: 78001800 78006800 7800E802 78009802
     91                    (rotldi 0,0,3; rotldi 0,0,13;
     92                     rotldi 0,0,61; rotldi 0,0,51)
     93 
     94    Following that, one of the following 3 are allowed
     95    (standard interpretation in parentheses):
     96 
     97       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
     98       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
     99       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11  Big endian
    100       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R12  Little endian
    101       7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
    102       7CA52B78 (or 5,5,5)   IR injection
    103 
    104    Any other bytes following the 16-byte preamble are illegal and
    105    constitute a failure in instruction decoding.  This all assumes
    106    that the preamble will never occur except in specific code
    107    fragments designed for Valgrind to catch.
    108 */
    109 
    110 /*  Little Endian notes  */
    111 /*
    112  * Vector operations in little Endian mode behave in non-obvious ways at times.
    113  * Below is an attempt at explaining this.
    114  *
    115  * LE/BE vector example
    116  *   With a vector of unsigned ints declared as follows:
    117  *     vector unsigned int vec_inA =
    118                             { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
    119  *   The '0x11111111' word is word zero in both LE and BE format.  But the
    120  *   loaded vector register will have word zero on the far left in BE mode and
    121  *   on the far right in LE mode. The lvx and stvx instructions work naturally
    122  *   for whatever endianness is in effect.  For example, in LE mode, the stvx
    123  *   stores word zero (far right word) of the vector at the lowest memory
    124  *   address of the EA; in BE mode, stvx still stores word zero at the lowest
    125  *   memory address, but with word zero interpreted as the one at the far left
    126  *   of the register.
    127  *
    128  *   The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
    129  *   When the compiler generates an lxvd2x instruction to load the
    130  *   above-declared vector of unsigned integers, it loads the vector as two
    131  *   double words, but they are in BE word-wise format.  To put the vector in
    132  *   the right order for LE, the compiler also generates an xxswapd after the
    133  *   load, which puts it in proper LE format.  Similarly, the stxvd2x
    134  *   instruction has a BE bias, storing the vector in BE word-wise format. But
    135  *   the compiler also generates an xxswapd prior to the store, thus ensuring
    136  *   the vector is stored in memory in the correct LE order.
    137  *
    138  *   Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
    139  *   of a double words and words within a vector.  Because of the reverse order
    140  *   of numbering for LE as described above, the high part refers to word 1 in
    141  *   LE format. When input data is saved to a guest state vector register
    142  *   (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
    143  *   register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
    144  *   The saving of the data to memory must be done in proper LE order.  For the
    145  *   inverse operation of extracting data from a vector register (e.g.,
    146  *   Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
    147  *   in stvx), and then integer registers are loaded from the memory location
    148  *   from where the vector register was saved.  Again, this must be done in
    149  *   proper LE order.  So for these various vector Iops, we have LE-specific
    150  *   code in host_ppc_isel.c
    151  *
    152  *   Another unique behavior of vectors in LE mode is with the vector scalar
    153  *   (VSX) operations that operate on "double word 0" of the source register,
    154  *   storing the result in "double word 0" of the output vector register.  For
    155  *   these operations, "double word 0" is interpreted as "high half of the
    156  *   register" (i.e, the part on the left side).
    157  *
    158  */
    159 /* Translates PPC32/64 code to IR. */
    160 
    161 /* References
    162 
    163 #define PPC32
    164    "PowerPC Microprocessor Family:
    165     The Programming Environments Manual for 32-Bit Microprocessors"
    166     02/21/2000
    167     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
    168 
    169 #define PPC64
    170    "PowerPC Microprocessor Family:
    171     Programming Environments Manual for 64-Bit Microprocessors"
    172     06/10/2003
    173    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
    174 
    175 #define AV
    176    "PowerPC Microprocessor Family:
    177     AltiVec(TM) Technology Programming Environments Manual"
    178     07/10/2003
    179    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
    180 */
    181 
    182 #include "libvex_basictypes.h"
    183 #include "libvex_ir.h"
    184 #include "libvex.h"
    185 #include "libvex_emnote.h"
    186 #include "libvex_guest_ppc32.h"
    187 #include "libvex_guest_ppc64.h"
    188 
    189 #include "main_util.h"
    190 #include "main_globals.h"
    191 #include "guest_generic_bb_to_IR.h"
    192 #include "guest_ppc_defs.h"
    193 
    194 /*------------------------------------------------------------*/
    195 /*--- Globals                                              ---*/
    196 /*------------------------------------------------------------*/
    197 
    198 /* These are set at the start of the translation of an insn, right
    199    down in disInstr_PPC, so that we don't have to pass them around
    200    endlessly.  They are all constant during the translation of any
    201    given insn. */
    202 
    203 /* We need to know this to do sub-register accesses correctly. */
    204 static VexEndness host_endness;
    205 
    206 /* Pointer to the guest code area. */
    207 static const UChar* guest_code;
    208 
    209 /* The guest address corresponding to guest_code[0]. */
    210 static Addr64 guest_CIA_bbstart;
    211 
    212 /* The guest address for the instruction currently being
    213    translated. */
    214 static Addr64 guest_CIA_curr_instr;
    215 
    216 /* The IRSB* into which we're generating code. */
    217 static IRSB* irsb;
    218 
    219 /* Is our guest binary 32 or 64bit?  Set at each call to
    220    disInstr_PPC below. */
    221 static Bool mode64 = False;
    222 
    223 // Given a pointer to a function as obtained by "& functionname" in C,
    224 // produce a pointer to the actual entry point for the function.  For
    225 // most platforms it's the identity function.  Unfortunately, on
    226 // ppc64-linux it isn't (sigh)
    227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
    228 {
    229    if (vbi->host_ppc_calls_use_fndescrs) {
    230       /* f is a pointer to a 3-word function descriptor, of which the
    231          first word is the entry address. */
    232       /* note, this is correct even with cross-jitting, since this is
    233          purely a host issue, not a guest one. */
    234       HWord* fdescr = (HWord*)f;
    235       return (void*)(fdescr[0]);
    236    } else {
    237       /* Simple; "& f" points directly at the code for f. */
    238       return f;
    239    }
    240 }
    241 
    242 #define SIGN_BIT  0x8000000000000000ULL
    243 #define SIGN_MASK 0x7fffffffffffffffULL
    244 #define SIGN_BIT32  0x80000000
    245 #define SIGN_MASK32 0x7fffffff
    246 
    247 
    248 /*------------------------------------------------------------*/
    249 /*--- Debugging output                                     ---*/
    250 /*------------------------------------------------------------*/
    251 
    252 #define DIP(format, args...)           \
    253    if (vex_traceflags & VEX_TRACE_FE)  \
    254       vex_printf(format, ## args)
    255 
    256 #define DIS(buf, format, args...)      \
    257    if (vex_traceflags & VEX_TRACE_FE)  \
    258       vex_sprintf(buf, format, ## args)
    259 
    260 
    261 /*------------------------------------------------------------*/
    262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
    263 /*------------------------------------------------------------*/
    264 
    265 #define offsetofPPCGuestState(_x) \
    266    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
    267              offsetof(VexGuestPPC32State, _x))
    268 
    269 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
    270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
    271 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
    272 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
    273 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
    274 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
    275 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
    276 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
    277 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
    278 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
    279 #define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
    280 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
    281 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
    282 #define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
    283 #define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
    284 #define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
    285 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
    286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
    287 #define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
    288 #define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
    289 #define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
    290 #define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
    291 #define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
    292 #define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
    293 
    294 
    295 /*------------------------------------------------------------*/
    296 /*--- Extract instruction fields                          --- */
    297 /*------------------------------------------------------------*/
    298 
    299 /* Extract field from insn, given idx (zero = lsb) and field length */
    300 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
    301 
    302 /* Extract primary opcode, instr[31:26] */
    303 static UChar ifieldOPC( UInt instr ) {
    304    return toUChar( IFIELD( instr, 26, 6 ) );
    305 }
    306 
    307 /* Extract 10-bit secondary opcode, instr[10:1] */
    308 static UInt ifieldOPClo10 ( UInt instr) {
    309    return IFIELD( instr, 1, 10 );
    310 }
    311 
    312 /* Extract 9-bit secondary opcode, instr[9:1] */
    313 static UInt ifieldOPClo9 ( UInt instr) {
    314    return IFIELD( instr, 1, 9 );
    315 }
    316 
    317 /* Extract 8-bit secondary opcode, instr[8:1] */
    318 static UInt ifieldOPClo8 ( UInt instr) {
    319    return IFIELD( instr, 1, 8 );
    320 }
    321 
    322 /* Extract 5-bit secondary opcode, instr[5:1] */
    323 static UInt ifieldOPClo5 ( UInt instr) {
    324    return IFIELD( instr, 1, 5 );
    325 }
    326 
    327 /* Extract RD (destination register) field, instr[25:21] */
    328 static UChar ifieldRegDS( UInt instr ) {
    329    return toUChar( IFIELD( instr, 21, 5 ) );
    330 }
    331 
    332 /* Extract XT (destination register) field, instr[0,25:21] */
    333 static UChar ifieldRegXT ( UInt instr )
    334 {
    335   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
    336   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
    337   return (upper_bit << 5) | lower_bits;
    338 }
    339 
    340 /* Extract XS (store source register) field, instr[0,25:21] */
    341 static inline UChar ifieldRegXS ( UInt instr )
    342 {
    343   return ifieldRegXT ( instr );
    344 }
    345 
    346 /* Extract RA (1st source register) field, instr[20:16] */
    347 static UChar ifieldRegA ( UInt instr ) {
    348    return toUChar( IFIELD( instr, 16, 5 ) );
    349 }
    350 
    351 /* Extract XA (1st source register) field, instr[2,20:16] */
    352 static UChar ifieldRegXA ( UInt instr )
    353 {
    354   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
    355   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
    356   return (upper_bit << 5) | lower_bits;
    357 }
    358 
    359 /* Extract RB (2nd source register) field, instr[15:11] */
    360 static UChar ifieldRegB ( UInt instr ) {
    361    return toUChar( IFIELD( instr, 11, 5 ) );
    362 }
    363 
    364 /* Extract XB (2nd source register) field, instr[1,15:11] */
    365 static UChar ifieldRegXB ( UInt instr )
    366 {
    367   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
    368   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
    369   return (upper_bit << 5) | lower_bits;
    370 }
    371 
    372 /* Extract RC (3rd source register) field, instr[10:6] */
    373 static UChar ifieldRegC ( UInt instr ) {
    374    return toUChar( IFIELD( instr, 6, 5 ) );
    375 }
    376 
    377 /* Extract XC (3rd source register) field, instr[3,10:6] */
    378 static UChar ifieldRegXC ( UInt instr )
    379 {
    380   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
    381   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
    382   return (upper_bit << 5) | lower_bits;
    383 }
    384 
    385 /* Extract bit 10, instr[10] */
    386 static UChar ifieldBIT10 ( UInt instr ) {
    387    return toUChar( IFIELD( instr, 10, 1 ) );
    388 }
    389 
    390 /* Extract 2nd lowest bit, instr[1] */
    391 static UChar ifieldBIT1 ( UInt instr ) {
    392    return toUChar( IFIELD( instr, 1, 1 ) );
    393 }
    394 
    395 /* Extract lowest bit, instr[0] */
    396 static UChar ifieldBIT0 ( UInt instr ) {
    397    return toUChar( instr & 0x1 );
    398 }
    399 
    400 /* Extract unsigned bottom half, instr[15:0] */
    401 static UInt ifieldUIMM16 ( UInt instr ) {
    402    return instr & 0xFFFF;
    403 }
    404 
    405 /* Extract unsigned bottom 26 bits, instr[25:0] */
    406 static UInt ifieldUIMM26 ( UInt instr ) {
    407    return instr & 0x3FFFFFF;
    408 }
    409 
    410 /* Extract DM field, instr[9:8] */
    411 static UChar ifieldDM ( UInt instr ) {
    412    return toUChar( IFIELD( instr, 8, 2 ) );
    413 }
    414 
    415 /* Extract SHW field, instr[9:8] */
    416 static inline UChar ifieldSHW ( UInt instr )
    417 {
    418   return ifieldDM ( instr );
    419 }
    420 
    421 /*------------------------------------------------------------*/
    422 /*--- Guest-state identifiers                              ---*/
    423 /*------------------------------------------------------------*/
    424 
    425 typedef enum {
    426     PPC_GST_CIA,    // Current Instruction Address
    427     PPC_GST_LR,     // Link Register
    428     PPC_GST_CTR,    // Count Register
    429     PPC_GST_XER,    // Overflow, carry flags, byte count
    430     PPC_GST_CR,     // Condition Register
    431     PPC_GST_FPSCR,  // Floating Point Status/Control Register
    432     PPC_GST_VRSAVE, // Vector Save/Restore Register
    433     PPC_GST_VSCR,   // Vector Status and Control Register
    434     PPC_GST_EMWARN, // Emulation warnings
    435     PPC_GST_CMSTART,// For icbi: start of area to invalidate
    436     PPC_GST_CMLEN,  // For icbi: length of area to invalidate
    437     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
    438     PPC_GST_SPRG3_RO, // SPRG3
    439     PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
    440     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
    441     PPC_GST_TEXASR, // Transactional EXception And Summary Register
    442     PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
    443     PPC_GST_PPR,     // Program Priority register
    444     PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
    445     PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
    446                       * register is initialized to a non-zero value.  Currently
    447                       * Valgrind is not supporting the register value to
    448                       * automatically decrement. Could be added later if
    449                       * needed.
    450                       */
    451     PPC_GST_MAX
    452 } PPC_GST;
    453 
    454 #define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
    455 #define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
    456 #define MASK_VSCR_VALID 0x00010001
    457 
    458 
    459 /*------------------------------------------------------------*/
    460 /*---  FP Helpers                                          ---*/
    461 /*------------------------------------------------------------*/
    462 
    463 /* Produce the 32-bit pattern corresponding to the supplied
    464    float. */
    465 static UInt float_to_bits ( Float f )
    466 {
    467    union { UInt i; Float f; } u;
    468    vassert(4 == sizeof(UInt));
    469    vassert(4 == sizeof(Float));
    470    vassert(4 == sizeof(u));
    471    u.f = f;
    472    return u.i;
    473 }
    474 
    475 
    476 /*------------------------------------------------------------*/
    477 /*--- Misc Helpers                                         ---*/
    478 /*------------------------------------------------------------*/
    479 
    480 /* Generate mask with 1's from 'begin' through 'end',
    481    wrapping if begin > end.
    482    begin->end works from right to left, 0=lsb
    483 */
    484 static UInt MASK32( UInt begin, UInt end )
    485 {
    486    UInt m1, m2, mask;
    487    vassert(begin < 32);
    488    vassert(end < 32);
    489    m1   = ((UInt)(-1)) << begin;
    490    m2   = ((UInt)(-1)) << end << 1;
    491    mask = m1 ^ m2;
    492    if (begin > end) mask = ~mask;  // wrap mask
    493    return mask;
    494 }
    495 
    496 static ULong MASK64( UInt begin, UInt end )
    497 {
    498    ULong m1, m2, mask;
    499    vassert(begin < 64);
    500    vassert(end < 64);
    501    m1   = ((ULong)(-1)) << begin;
    502    m2   = ((ULong)(-1)) << end << 1;
    503    mask = m1 ^ m2;
    504    if (begin > end) mask = ~mask;  // wrap mask
    505    return mask;
    506 }
    507 
    508 static Addr64 nextInsnAddr( void )
    509 {
    510    return guest_CIA_curr_instr + 4;
    511 }
    512 
    513 
    514 /*------------------------------------------------------------*/
    515 /*--- Helper bits and pieces for deconstructing the        ---*/
    516 /*--- ppc32/64 insn stream.                                ---*/
    517 /*------------------------------------------------------------*/
    518 
    519 /* Add a statement to the list held by "irsb". */
    520 static void stmt ( IRStmt* st )
    521 {
    522    addStmtToIRSB( irsb, st );
    523 }
    524 
    525 /* Generate a new temporary of the given type. */
    526 static IRTemp newTemp ( IRType ty )
    527 {
    528    vassert(isPlausibleIRType(ty));
    529    return newIRTemp( irsb->tyenv, ty );
    530 }
    531 
    532 /* Various simple conversions */
    533 
    534 static UChar extend_s_5to8 ( UChar x )
    535 {
    536    return toUChar((((Int)x) << 27) >> 27);
    537 }
    538 
    539 static UInt extend_s_8to32( UChar x )
    540 {
    541    return (UInt)((((Int)x) << 24) >> 24);
    542 }
    543 
    544 static UInt extend_s_16to32 ( UInt x )
    545 {
    546    return (UInt)((((Int)x) << 16) >> 16);
    547 }
    548 
    549 static ULong extend_s_16to64 ( UInt x )
    550 {
    551    return (ULong)((((Long)x) << 48) >> 48);
    552 }
    553 
    554 static ULong extend_s_26to64 ( UInt x )
    555 {
    556    return (ULong)((((Long)x) << 38) >> 38);
    557 }
    558 
    559 static ULong extend_s_32to64 ( UInt x )
    560 {
    561    return (ULong)((((Long)x) << 32) >> 32);
    562 }
    563 
    564 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
    565    of the underlying host. */
    566 static UInt getUIntPPCendianly ( const UChar* p )
    567 {
    568    UInt w = 0;
    569    if (host_endness == VexEndnessBE) {
    570        w = (w << 8) | p[0];
    571        w = (w << 8) | p[1];
    572        w = (w << 8) | p[2];
    573        w = (w << 8) | p[3];
    574    } else {
    575        w = (w << 8) | p[3];
    576        w = (w << 8) | p[2];
    577        w = (w << 8) | p[1];
    578        w = (w << 8) | p[0];
    579    }
    580    return w;
    581 }
    582 
    583 
    584 /*------------------------------------------------------------*/
    585 /*--- Helpers for constructing IR.                         ---*/
    586 /*------------------------------------------------------------*/
    587 
    588 static void assign ( IRTemp dst, IRExpr* e )
    589 {
    590    stmt( IRStmt_WrTmp(dst, e) );
    591 }
    592 
    593 /* This generates a normal (non store-conditional) store. */
    594 static void store ( IRExpr* addr, IRExpr* data )
    595 {
    596    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    597    vassert(tyA == Ity_I32 || tyA == Ity_I64);
    598 
    599    if (host_endness == VexEndnessBE)
    600       stmt( IRStmt_Store(Iend_BE, addr, data) );
    601    else
    602       stmt( IRStmt_Store(Iend_LE, addr, data) );
    603 }
    604 
    605 static IRExpr* unop ( IROp op, IRExpr* a )
    606 {
    607    return IRExpr_Unop(op, a);
    608 }
    609 
    610 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    611 {
    612    return IRExpr_Binop(op, a1, a2);
    613 }
    614 
    615 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
    616 {
    617    return IRExpr_Triop(op, a1, a2, a3);
    618 }
    619 
    620 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
    621                               IRExpr* a3, IRExpr* a4 )
    622 {
    623    return IRExpr_Qop(op, a1, a2, a3, a4);
    624 }
    625 
    626 static IRExpr* mkexpr ( IRTemp tmp )
    627 {
    628    return IRExpr_RdTmp(tmp);
    629 }
    630 
    631 static IRExpr* mkU8 ( UChar i )
    632 {
    633    return IRExpr_Const(IRConst_U8(i));
    634 }
    635 
    636 static IRExpr* mkU16 ( UInt i )
    637 {
    638    return IRExpr_Const(IRConst_U16(i));
    639 }
    640 
    641 static IRExpr* mkU32 ( UInt i )
    642 {
    643    return IRExpr_Const(IRConst_U32(i));
    644 }
    645 
    646 static IRExpr* mkU64 ( ULong i )
    647 {
    648    return IRExpr_Const(IRConst_U64(i));
    649 }
    650 
    651 static IRExpr* mkV128 ( UShort i )
    652 {
    653    vassert(i == 0 || i == 0xffff);
    654    return IRExpr_Const(IRConst_V128(i));
    655 }
    656 
    657 /* This generates a normal (non load-linked) load. */
    658 static IRExpr* load ( IRType ty, IRExpr* addr )
    659 {
    660    if (host_endness == VexEndnessBE)
    661       return IRExpr_Load(Iend_BE, ty, addr);
    662    else
    663       return IRExpr_Load(Iend_LE, ty, addr);
    664 }
    665 
    666 static IRStmt* stmt_load ( IRTemp result,
    667                            IRExpr* addr, IRExpr* storedata )
    668 {
    669    if (host_endness == VexEndnessBE)
    670       return IRStmt_LLSC(Iend_BE, result, addr, storedata);
    671    else
    672       return IRStmt_LLSC(Iend_LE, result, addr, storedata);
    673 }
    674 
    675 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
    676 {
    677    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    678    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    679    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
    680                                           unop(Iop_1Uto32, arg2)));
    681 }
    682 
    683 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
    684 {
    685    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
    686    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
    687    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
    688                                            unop(Iop_1Uto32, arg2)));
    689 }
    690 
    691 /* expand V128_8Ux16 to 2x V128_16Ux8's */
    692 static void expand8Ux16( IRExpr* vIn,
    693                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    694 {
    695    IRTemp ones8x16 = newTemp(Ity_V128);
    696 
    697    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    698    vassert(vEvn && *vEvn == IRTemp_INVALID);
    699    vassert(vOdd && *vOdd == IRTemp_INVALID);
    700    *vEvn = newTemp(Ity_V128);
    701    *vOdd = newTemp(Ity_V128);
    702 
    703    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    704    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
    705    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
    706                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    707 }
    708 
    709 /* expand V128_8Sx16 to 2x V128_16Sx8's */
    710 static void expand8Sx16( IRExpr* vIn,
    711                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    712 {
    713    IRTemp ones8x16 = newTemp(Ity_V128);
    714 
    715    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    716    vassert(vEvn && *vEvn == IRTemp_INVALID);
    717    vassert(vOdd && *vOdd == IRTemp_INVALID);
    718    *vEvn = newTemp(Ity_V128);
    719    *vOdd = newTemp(Ity_V128);
    720 
    721    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
    722    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
    723    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
    724                         binop(Iop_ShrV128, vIn, mkU8(8))) );
    725 }
    726 
    727 /* expand V128_16Uto8 to 2x V128_32Ux4's */
    728 static void expand16Ux8( IRExpr* vIn,
    729                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    730 {
    731    IRTemp ones16x8 = newTemp(Ity_V128);
    732 
    733    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    734    vassert(vEvn && *vEvn == IRTemp_INVALID);
    735    vassert(vOdd && *vOdd == IRTemp_INVALID);
    736    *vEvn = newTemp(Ity_V128);
    737    *vOdd = newTemp(Ity_V128);
    738 
    739    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    740    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
    741    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
    742                         binop(Iop_ShrV128, vIn, mkU8(16))) );
    743 }
    744 
    745 /* expand V128_16Sto8 to 2x V128_32Sx4's */
    746 static void expand16Sx8( IRExpr* vIn,
    747                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
    748 {
    749    IRTemp ones16x8 = newTemp(Ity_V128);
    750 
    751    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
    752    vassert(vEvn && *vEvn == IRTemp_INVALID);
    753    vassert(vOdd && *vOdd == IRTemp_INVALID);
    754    *vEvn = newTemp(Ity_V128);
    755    *vOdd = newTemp(Ity_V128);
    756 
    757    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
    758    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
    759    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
    760                        binop(Iop_ShrV128, vIn, mkU8(16))) );
    761 }
    762 
    763 /* break V128 to 4xF64's*/
    764 static void breakV128to4xF64( IRExpr* t128,
    765                               /*OUTs*/
    766                               IRTemp* t3, IRTemp* t2,
    767                               IRTemp* t1, IRTemp* t0 )
    768 {
    769    IRTemp hi64 = newTemp(Ity_I64);
    770    IRTemp lo64 = newTemp(Ity_I64);
    771 
    772    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    773    vassert(t0 && *t0 == IRTemp_INVALID);
    774    vassert(t1 && *t1 == IRTemp_INVALID);
    775    vassert(t2 && *t2 == IRTemp_INVALID);
    776    vassert(t3 && *t3 == IRTemp_INVALID);
    777    *t0 = newTemp(Ity_F64);
    778    *t1 = newTemp(Ity_F64);
    779    *t2 = newTemp(Ity_F64);
    780    *t3 = newTemp(Ity_F64);
    781 
    782    assign( hi64, unop(Iop_V128HIto64, t128) );
    783    assign( lo64, unop(Iop_V128to64,   t128) );
    784    assign( *t3,
    785            unop( Iop_F32toF64,
    786                  unop( Iop_ReinterpI32asF32,
    787                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
    788    assign( *t2,
    789            unop( Iop_F32toF64,
    790                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
    791    assign( *t1,
    792            unop( Iop_F32toF64,
    793                  unop( Iop_ReinterpI32asF32,
    794                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
    795    assign( *t0,
    796            unop( Iop_F32toF64,
    797                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
    798 }
    799 
    800 
    801 /* break V128 to 4xI32's, then sign-extend to I64's */
    802 static void breakV128to4x64S( IRExpr* t128,
    803                               /*OUTs*/
    804                               IRTemp* t3, IRTemp* t2,
    805                               IRTemp* t1, IRTemp* t0 )
    806 {
    807    IRTemp hi64 = newTemp(Ity_I64);
    808    IRTemp lo64 = newTemp(Ity_I64);
    809 
    810    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    811    vassert(t0 && *t0 == IRTemp_INVALID);
    812    vassert(t1 && *t1 == IRTemp_INVALID);
    813    vassert(t2 && *t2 == IRTemp_INVALID);
    814    vassert(t3 && *t3 == IRTemp_INVALID);
    815    *t0 = newTemp(Ity_I64);
    816    *t1 = newTemp(Ity_I64);
    817    *t2 = newTemp(Ity_I64);
    818    *t3 = newTemp(Ity_I64);
    819 
    820    assign( hi64, unop(Iop_V128HIto64, t128) );
    821    assign( lo64, unop(Iop_V128to64,   t128) );
    822    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    823    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
    824    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    825    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
    826 }
    827 
    828 /* break V128 to 4xI32's, then zero-extend to I64's */
    829 static void breakV128to4x64U ( IRExpr* t128,
    830                                /*OUTs*/
    831                                IRTemp* t3, IRTemp* t2,
    832                                IRTemp* t1, IRTemp* t0 )
    833 {
    834    IRTemp hi64 = newTemp(Ity_I64);
    835    IRTemp lo64 = newTemp(Ity_I64);
    836 
    837    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    838    vassert(t0 && *t0 == IRTemp_INVALID);
    839    vassert(t1 && *t1 == IRTemp_INVALID);
    840    vassert(t2 && *t2 == IRTemp_INVALID);
    841    vassert(t3 && *t3 == IRTemp_INVALID);
    842    *t0 = newTemp(Ity_I64);
    843    *t1 = newTemp(Ity_I64);
    844    *t2 = newTemp(Ity_I64);
    845    *t3 = newTemp(Ity_I64);
    846 
    847    assign( hi64, unop(Iop_V128HIto64, t128) );
    848    assign( lo64, unop(Iop_V128to64,   t128) );
    849    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
    850    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
    851    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
    852    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
    853 }
    854 
    855 static void breakV128to4x32( IRExpr* t128,
    856                               /*OUTs*/
    857                               IRTemp* t3, IRTemp* t2,
    858                               IRTemp* t1, IRTemp* t0 )
    859 {
    860    IRTemp hi64 = newTemp(Ity_I64);
    861    IRTemp lo64 = newTemp(Ity_I64);
    862 
    863    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
    864    vassert(t0 && *t0 == IRTemp_INVALID);
    865    vassert(t1 && *t1 == IRTemp_INVALID);
    866    vassert(t2 && *t2 == IRTemp_INVALID);
    867    vassert(t3 && *t3 == IRTemp_INVALID);
    868    *t0 = newTemp(Ity_I32);
    869    *t1 = newTemp(Ity_I32);
    870    *t2 = newTemp(Ity_I32);
    871    *t3 = newTemp(Ity_I32);
    872 
    873    assign( hi64, unop(Iop_V128HIto64, t128) );
    874    assign( lo64, unop(Iop_V128to64,   t128) );
    875    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
    876    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
    877    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
    878    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
    879 }
    880 
    881 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
    882                                IRTemp t1, IRTemp t0 )
    883 {
    884    return
    885       binop( Iop_64HLtoV128,
    886              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
    887              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
    888    );
    889 }
    890 
    891 
    892 /* Signed saturating narrow 64S to 32 */
    893 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
    894 {
    895    IRTemp hi32 = newTemp(Ity_I32);
    896    IRTemp lo32 = newTemp(Ity_I32);
    897 
    898    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    899 
    900    assign( hi32, unop(Iop_64HIto32, t64));
    901    assign( lo32, unop(Iop_64to32,   t64));
    902 
    903    return IRExpr_ITE(
    904              /* if (hi32 == (lo32 >>s 31)) */
    905              binop(Iop_CmpEQ32, mkexpr(hi32),
    906                    binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
    907              /* then: within signed-32 range: lo half good enough */
    908              mkexpr(lo32),
    909              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
    910              binop(Iop_Add32, mkU32(0x7FFFFFFF),
    911                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
    912 }
    913 
    914 /* Unsigned saturating narrow 64S to 32 */
    915 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
    916 {
    917    IRTemp hi32 = newTemp(Ity_I32);
    918    IRTemp lo32 = newTemp(Ity_I32);
    919 
    920    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
    921 
    922    assign( hi32, unop(Iop_64HIto32, t64));
    923    assign( lo32, unop(Iop_64to32,   t64));
    924 
    925    return IRExpr_ITE(
    926             /* if (top 32 bits of t64 are 0) */
    927             binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
    928             /* then: within unsigned-32 range: lo half good enough */
    929             mkexpr(lo32),
    930             /* else: positive saturate -> 0xFFFFFFFF */
    931             mkU32(0xFFFFFFFF));
    932 }
    933 
    934 /* Signed saturate narrow 64->32, combining to V128 */
    935 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
    936                                  IRExpr* t1, IRExpr* t0 )
    937 {
    938    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    939    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    940    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    941    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    942    return binop(Iop_64HLtoV128,
    943                 binop(Iop_32HLto64,
    944                       mkQNarrow64Sto32( t3 ),
    945                       mkQNarrow64Sto32( t2 )),
    946                 binop(Iop_32HLto64,
    947                       mkQNarrow64Sto32( t1 ),
    948                       mkQNarrow64Sto32( t0 )));
    949 }
    950 
    951 /* Unsigned saturate narrow 64->32, combining to V128 */
    952 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
    953                                  IRExpr* t1, IRExpr* t0 )
    954 {
    955    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
    956    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
    957    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
    958    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
    959    return binop(Iop_64HLtoV128,
    960                 binop(Iop_32HLto64,
    961                       mkQNarrow64Uto32( t3 ),
    962                       mkQNarrow64Uto32( t2 )),
    963                 binop(Iop_32HLto64,
    964                       mkQNarrow64Uto32( t1 ),
    965                       mkQNarrow64Uto32( t0 )));
    966 }
    967 
    968 /* Simulate irops Iop_MullOdd*, since we don't have them  */
    969 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
    970       binop(Iop_MullEven8Ux16, \
    971             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    972             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    973 
    974 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
    975       binop(Iop_MullEven8Sx16, \
    976             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
    977             binop(Iop_ShrV128, expr_vB, mkU8(8)))
    978 
    979 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
    980       binop(Iop_MullEven16Ux8, \
    981             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    982             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    983 
    984 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
    985       binop(Iop_MullEven32Ux4, \
    986             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    987             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    988 
    989 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
    990       binop(Iop_MullEven16Sx8, \
    991             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
    992             binop(Iop_ShrV128, expr_vB, mkU8(16)))
    993 
    994 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
    995       binop(Iop_MullEven32Sx4, \
    996             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
    997             binop(Iop_ShrV128, expr_vB, mkU8(32)))
    998 
    999 
   1000 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
   1001 {
   1002    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
   1003    return unop(Iop_32Sto64, unop(Iop_64to32, src));
   1004 }
   1005 
   1006 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
   1007 {
   1008    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
   1009    return unop(Iop_32Uto64, unop(Iop_64to32, src));
   1010 }
   1011 
   1012 static IROp mkSzOp ( IRType ty, IROp op8 )
   1013 {
   1014    Int adj;
   1015    vassert(ty == Ity_I8  || ty == Ity_I16 ||
   1016            ty == Ity_I32 || ty == Ity_I64);
   1017    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
   1018            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
   1019            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
   1020            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
   1021            op8 == Iop_Not8 );
   1022    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
   1023    return adj + op8;
   1024 }
   1025 
   1026 /* Make sure we get valid 32 and 64bit addresses */
   1027 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
   1028 {
   1029    vassert(ty == Ity_I32 || ty == Ity_I64);
   1030    return ( ty == Ity_I64 ?
   1031             (Addr64)addr :
   1032             (Addr64)extend_s_32to64( toUInt(addr) ) );
   1033 }
   1034 
   1035 /* sz, ULong -> IRExpr */
   1036 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
   1037 {
   1038    vassert(ty == Ity_I32 || ty == Ity_I64);
   1039    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
   1040 }
   1041 
   1042 /* sz, ULong -> IRConst */
   1043 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
   1044 {
   1045    vassert(ty == Ity_I32 || ty == Ity_I64);
   1046    return ( ty == Ity_I64 ?
   1047             IRConst_U64(imm64) :
   1048             IRConst_U32((UInt)imm64) );
   1049 }
   1050 
   1051 /* Sign extend imm16 -> IRExpr* */
   1052 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
   1053 {
   1054    vassert(ty == Ity_I32 || ty == Ity_I64);
   1055    return ( ty == Ity_I64 ?
   1056             mkU64(extend_s_16to64(imm16)) :
   1057             mkU32(extend_s_16to32(imm16)) );
   1058 }
   1059 
   1060 /* Sign extend imm32 -> IRExpr* */
   1061 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
   1062 {
   1063    vassert(ty == Ity_I32 || ty == Ity_I64);
   1064    return ( ty == Ity_I64 ?
   1065             mkU64(extend_s_32to64(imm32)) :
   1066             mkU32(imm32) );
   1067 }
   1068 
   1069 /* IR narrows I32/I64 -> I8/I16/I32 */
   1070 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
   1071 {
   1072    vassert(ty == Ity_I32 || ty == Ity_I64);
   1073    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
   1074 }
   1075 
   1076 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
   1077 {
   1078    vassert(ty == Ity_I32 || ty == Ity_I64);
   1079    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
   1080 }
   1081 
   1082 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
   1083 {
   1084    vassert(ty == Ity_I32 || ty == Ity_I64);
   1085    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
   1086 }
   1087 
   1088 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
   1089 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
   1090 {
   1091    IROp op;
   1092    vassert(ty == Ity_I32 || ty == Ity_I64);
   1093    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
   1094    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
   1095    return unop(op, src);
   1096 }
   1097 
   1098 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
   1099 {
   1100    IROp op;
   1101    vassert(ty == Ity_I32 || ty == Ity_I64);
   1102    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
   1103    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
   1104    return unop(op, src);
   1105 }
   1106 
   1107 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
   1108 {
   1109    vassert(ty == Ity_I32 || ty == Ity_I64);
   1110    if (ty == Ity_I32)
   1111       return src;
   1112    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
   1113 }
   1114 
   1115 
   1116 static Int integerGuestRegOffset ( UInt archreg )
   1117 {
   1118    vassert(archreg < 32);
   1119 
   1120    // jrs: probably not necessary; only matters if we reference sub-parts
   1121    // of the ppc registers, but that isn't the case
   1122    // later: this might affect Altivec though?
   1123 
   1124    switch (archreg) {
   1125    case  0: return offsetofPPCGuestState(guest_GPR0);
   1126    case  1: return offsetofPPCGuestState(guest_GPR1);
   1127    case  2: return offsetofPPCGuestState(guest_GPR2);
   1128    case  3: return offsetofPPCGuestState(guest_GPR3);
   1129    case  4: return offsetofPPCGuestState(guest_GPR4);
   1130    case  5: return offsetofPPCGuestState(guest_GPR5);
   1131    case  6: return offsetofPPCGuestState(guest_GPR6);
   1132    case  7: return offsetofPPCGuestState(guest_GPR7);
   1133    case  8: return offsetofPPCGuestState(guest_GPR8);
   1134    case  9: return offsetofPPCGuestState(guest_GPR9);
   1135    case 10: return offsetofPPCGuestState(guest_GPR10);
   1136    case 11: return offsetofPPCGuestState(guest_GPR11);
   1137    case 12: return offsetofPPCGuestState(guest_GPR12);
   1138    case 13: return offsetofPPCGuestState(guest_GPR13);
   1139    case 14: return offsetofPPCGuestState(guest_GPR14);
   1140    case 15: return offsetofPPCGuestState(guest_GPR15);
   1141    case 16: return offsetofPPCGuestState(guest_GPR16);
   1142    case 17: return offsetofPPCGuestState(guest_GPR17);
   1143    case 18: return offsetofPPCGuestState(guest_GPR18);
   1144    case 19: return offsetofPPCGuestState(guest_GPR19);
   1145    case 20: return offsetofPPCGuestState(guest_GPR20);
   1146    case 21: return offsetofPPCGuestState(guest_GPR21);
   1147    case 22: return offsetofPPCGuestState(guest_GPR22);
   1148    case 23: return offsetofPPCGuestState(guest_GPR23);
   1149    case 24: return offsetofPPCGuestState(guest_GPR24);
   1150    case 25: return offsetofPPCGuestState(guest_GPR25);
   1151    case 26: return offsetofPPCGuestState(guest_GPR26);
   1152    case 27: return offsetofPPCGuestState(guest_GPR27);
   1153    case 28: return offsetofPPCGuestState(guest_GPR28);
   1154    case 29: return offsetofPPCGuestState(guest_GPR29);
   1155    case 30: return offsetofPPCGuestState(guest_GPR30);
   1156    case 31: return offsetofPPCGuestState(guest_GPR31);
   1157    default: break;
   1158    }
   1159    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
   1160 }
   1161 
   1162 static IRExpr* getIReg ( UInt archreg )
   1163 {
   1164    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1165    vassert(archreg < 32);
   1166    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
   1167 }
   1168 
   1169 /* Ditto, but write to a reg instead. */
   1170 static void putIReg ( UInt archreg, IRExpr* e )
   1171 {
   1172    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1173    vassert(archreg < 32);
   1174    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
   1175    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
   1176 }
   1177 
   1178 
   1179 /* Floating point egisters are mapped to VSX registers[0..31]. */
   1180 static Int floatGuestRegOffset ( UInt archreg )
   1181 {
   1182    vassert(archreg < 32);
   1183 
   1184    if (host_endness == VexEndnessLE) {
   1185       switch (archreg) {
   1186          case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
   1187          case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
   1188          case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
   1189          case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
   1190          case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
   1191          case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
   1192          case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
   1193          case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
   1194          case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
   1195          case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
   1196          case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
   1197          case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
   1198          case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
   1199          case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
   1200          case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
   1201          case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
   1202          case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
   1203          case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
   1204          case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
   1205          case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
   1206          case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
   1207          case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
   1208          case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
   1209          case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
   1210          case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
   1211          case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
   1212          case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
   1213          case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
   1214          case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
   1215          case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
   1216          case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
   1217          case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
   1218          default: break;
   1219       }
   1220    } else {
   1221       switch (archreg) {
   1222          case  0: return offsetofPPCGuestState(guest_VSR0);
   1223          case  1: return offsetofPPCGuestState(guest_VSR1);
   1224          case  2: return offsetofPPCGuestState(guest_VSR2);
   1225          case  3: return offsetofPPCGuestState(guest_VSR3);
   1226          case  4: return offsetofPPCGuestState(guest_VSR4);
   1227          case  5: return offsetofPPCGuestState(guest_VSR5);
   1228          case  6: return offsetofPPCGuestState(guest_VSR6);
   1229          case  7: return offsetofPPCGuestState(guest_VSR7);
   1230          case  8: return offsetofPPCGuestState(guest_VSR8);
   1231          case  9: return offsetofPPCGuestState(guest_VSR9);
   1232          case 10: return offsetofPPCGuestState(guest_VSR10);
   1233          case 11: return offsetofPPCGuestState(guest_VSR11);
   1234          case 12: return offsetofPPCGuestState(guest_VSR12);
   1235          case 13: return offsetofPPCGuestState(guest_VSR13);
   1236          case 14: return offsetofPPCGuestState(guest_VSR14);
   1237          case 15: return offsetofPPCGuestState(guest_VSR15);
   1238          case 16: return offsetofPPCGuestState(guest_VSR16);
   1239          case 17: return offsetofPPCGuestState(guest_VSR17);
   1240          case 18: return offsetofPPCGuestState(guest_VSR18);
   1241          case 19: return offsetofPPCGuestState(guest_VSR19);
   1242          case 20: return offsetofPPCGuestState(guest_VSR20);
   1243          case 21: return offsetofPPCGuestState(guest_VSR21);
   1244          case 22: return offsetofPPCGuestState(guest_VSR22);
   1245          case 23: return offsetofPPCGuestState(guest_VSR23);
   1246          case 24: return offsetofPPCGuestState(guest_VSR24);
   1247          case 25: return offsetofPPCGuestState(guest_VSR25);
   1248          case 26: return offsetofPPCGuestState(guest_VSR26);
   1249          case 27: return offsetofPPCGuestState(guest_VSR27);
   1250          case 28: return offsetofPPCGuestState(guest_VSR28);
   1251          case 29: return offsetofPPCGuestState(guest_VSR29);
   1252          case 30: return offsetofPPCGuestState(guest_VSR30);
   1253          case 31: return offsetofPPCGuestState(guest_VSR31);
   1254          default: break;
   1255       }
   1256    }
   1257    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
   1258 }
   1259 
   1260 static IRExpr* getFReg ( UInt archreg )
   1261 {
   1262    vassert(archreg < 32);
   1263    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
   1264 }
   1265 
   1266 /* Ditto, but write to a reg instead. */
   1267 static void putFReg ( UInt archreg, IRExpr* e )
   1268 {
   1269    vassert(archreg < 32);
   1270    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
   1271    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
   1272 }
   1273 
   1274 /* get Decimal float value.  Note, they share floating point register file. */
   1275 static IRExpr* getDReg(UInt archreg) {
   1276    IRExpr *e;
   1277    vassert( archreg < 32 );
   1278    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
   1279    return e;
   1280 }
   1281 static IRExpr* getDReg32(UInt archreg) {
   1282    IRExpr *e;
   1283    vassert( archreg < 32 );
   1284    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
   1285    return e;
   1286 }
   1287 
   1288 /* Read a floating point register pair and combine their contents into a
   1289  128-bit value */
   1290 static IRExpr *getDReg_pair(UInt archreg) {
   1291    IRExpr *high = getDReg( archreg );
   1292    IRExpr *low = getDReg( archreg + 1 );
   1293 
   1294    return binop( Iop_D64HLtoD128, high, low );
   1295 }
   1296 
   1297 /* Ditto, but write to a reg instead. */
   1298 static void putDReg32(UInt archreg, IRExpr* e) {
   1299    vassert( archreg < 32 );
   1300    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
   1301    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1302 }
   1303 
   1304 static void putDReg(UInt archreg, IRExpr* e) {
   1305    vassert( archreg < 32 );
   1306    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
   1307    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
   1308 }
   1309 
   1310 /* Write a 128-bit floating point value into a register pair. */
   1311 static void putDReg_pair(UInt archreg, IRExpr *e) {
   1312    IRTemp low = newTemp( Ity_D64 );
   1313    IRTemp high = newTemp( Ity_D64 );
   1314 
   1315    vassert( archreg < 32 );
   1316    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
   1317 
   1318    assign( low, unop( Iop_D128LOtoD64, e ) );
   1319    assign( high, unop( Iop_D128HItoD64, e ) );
   1320 
   1321    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
   1322    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
   1323 }
   1324 
   1325 static Int vsxGuestRegOffset ( UInt archreg )
   1326 {
   1327    vassert(archreg < 64);
   1328    switch (archreg) {
   1329    case  0: return offsetofPPCGuestState(guest_VSR0);
   1330    case  1: return offsetofPPCGuestState(guest_VSR1);
   1331    case  2: return offsetofPPCGuestState(guest_VSR2);
   1332    case  3: return offsetofPPCGuestState(guest_VSR3);
   1333    case  4: return offsetofPPCGuestState(guest_VSR4);
   1334    case  5: return offsetofPPCGuestState(guest_VSR5);
   1335    case  6: return offsetofPPCGuestState(guest_VSR6);
   1336    case  7: return offsetofPPCGuestState(guest_VSR7);
   1337    case  8: return offsetofPPCGuestState(guest_VSR8);
   1338    case  9: return offsetofPPCGuestState(guest_VSR9);
   1339    case 10: return offsetofPPCGuestState(guest_VSR10);
   1340    case 11: return offsetofPPCGuestState(guest_VSR11);
   1341    case 12: return offsetofPPCGuestState(guest_VSR12);
   1342    case 13: return offsetofPPCGuestState(guest_VSR13);
   1343    case 14: return offsetofPPCGuestState(guest_VSR14);
   1344    case 15: return offsetofPPCGuestState(guest_VSR15);
   1345    case 16: return offsetofPPCGuestState(guest_VSR16);
   1346    case 17: return offsetofPPCGuestState(guest_VSR17);
   1347    case 18: return offsetofPPCGuestState(guest_VSR18);
   1348    case 19: return offsetofPPCGuestState(guest_VSR19);
   1349    case 20: return offsetofPPCGuestState(guest_VSR20);
   1350    case 21: return offsetofPPCGuestState(guest_VSR21);
   1351    case 22: return offsetofPPCGuestState(guest_VSR22);
   1352    case 23: return offsetofPPCGuestState(guest_VSR23);
   1353    case 24: return offsetofPPCGuestState(guest_VSR24);
   1354    case 25: return offsetofPPCGuestState(guest_VSR25);
   1355    case 26: return offsetofPPCGuestState(guest_VSR26);
   1356    case 27: return offsetofPPCGuestState(guest_VSR27);
   1357    case 28: return offsetofPPCGuestState(guest_VSR28);
   1358    case 29: return offsetofPPCGuestState(guest_VSR29);
   1359    case 30: return offsetofPPCGuestState(guest_VSR30);
   1360    case 31: return offsetofPPCGuestState(guest_VSR31);
   1361    case 32: return offsetofPPCGuestState(guest_VSR32);
   1362    case 33: return offsetofPPCGuestState(guest_VSR33);
   1363    case 34: return offsetofPPCGuestState(guest_VSR34);
   1364    case 35: return offsetofPPCGuestState(guest_VSR35);
   1365    case 36: return offsetofPPCGuestState(guest_VSR36);
   1366    case 37: return offsetofPPCGuestState(guest_VSR37);
   1367    case 38: return offsetofPPCGuestState(guest_VSR38);
   1368    case 39: return offsetofPPCGuestState(guest_VSR39);
   1369    case 40: return offsetofPPCGuestState(guest_VSR40);
   1370    case 41: return offsetofPPCGuestState(guest_VSR41);
   1371    case 42: return offsetofPPCGuestState(guest_VSR42);
   1372    case 43: return offsetofPPCGuestState(guest_VSR43);
   1373    case 44: return offsetofPPCGuestState(guest_VSR44);
   1374    case 45: return offsetofPPCGuestState(guest_VSR45);
   1375    case 46: return offsetofPPCGuestState(guest_VSR46);
   1376    case 47: return offsetofPPCGuestState(guest_VSR47);
   1377    case 48: return offsetofPPCGuestState(guest_VSR48);
   1378    case 49: return offsetofPPCGuestState(guest_VSR49);
   1379    case 50: return offsetofPPCGuestState(guest_VSR50);
   1380    case 51: return offsetofPPCGuestState(guest_VSR51);
   1381    case 52: return offsetofPPCGuestState(guest_VSR52);
   1382    case 53: return offsetofPPCGuestState(guest_VSR53);
   1383    case 54: return offsetofPPCGuestState(guest_VSR54);
   1384    case 55: return offsetofPPCGuestState(guest_VSR55);
   1385    case 56: return offsetofPPCGuestState(guest_VSR56);
   1386    case 57: return offsetofPPCGuestState(guest_VSR57);
   1387    case 58: return offsetofPPCGuestState(guest_VSR58);
   1388    case 59: return offsetofPPCGuestState(guest_VSR59);
   1389    case 60: return offsetofPPCGuestState(guest_VSR60);
   1390    case 61: return offsetofPPCGuestState(guest_VSR61);
   1391    case 62: return offsetofPPCGuestState(guest_VSR62);
   1392    case 63: return offsetofPPCGuestState(guest_VSR63);
   1393    default: break;
   1394    }
   1395    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
   1396 }
   1397 
   1398 /* Vector registers are mapped to VSX registers[32..63]. */
   1399 static Int vectorGuestRegOffset ( UInt archreg )
   1400 {
   1401    vassert(archreg < 32);
   1402 
   1403    switch (archreg) {
   1404    case  0: return offsetofPPCGuestState(guest_VSR32);
   1405    case  1: return offsetofPPCGuestState(guest_VSR33);
   1406    case  2: return offsetofPPCGuestState(guest_VSR34);
   1407    case  3: return offsetofPPCGuestState(guest_VSR35);
   1408    case  4: return offsetofPPCGuestState(guest_VSR36);
   1409    case  5: return offsetofPPCGuestState(guest_VSR37);
   1410    case  6: return offsetofPPCGuestState(guest_VSR38);
   1411    case  7: return offsetofPPCGuestState(guest_VSR39);
   1412    case  8: return offsetofPPCGuestState(guest_VSR40);
   1413    case  9: return offsetofPPCGuestState(guest_VSR41);
   1414    case 10: return offsetofPPCGuestState(guest_VSR42);
   1415    case 11: return offsetofPPCGuestState(guest_VSR43);
   1416    case 12: return offsetofPPCGuestState(guest_VSR44);
   1417    case 13: return offsetofPPCGuestState(guest_VSR45);
   1418    case 14: return offsetofPPCGuestState(guest_VSR46);
   1419    case 15: return offsetofPPCGuestState(guest_VSR47);
   1420    case 16: return offsetofPPCGuestState(guest_VSR48);
   1421    case 17: return offsetofPPCGuestState(guest_VSR49);
   1422    case 18: return offsetofPPCGuestState(guest_VSR50);
   1423    case 19: return offsetofPPCGuestState(guest_VSR51);
   1424    case 20: return offsetofPPCGuestState(guest_VSR52);
   1425    case 21: return offsetofPPCGuestState(guest_VSR53);
   1426    case 22: return offsetofPPCGuestState(guest_VSR54);
   1427    case 23: return offsetofPPCGuestState(guest_VSR55);
   1428    case 24: return offsetofPPCGuestState(guest_VSR56);
   1429    case 25: return offsetofPPCGuestState(guest_VSR57);
   1430    case 26: return offsetofPPCGuestState(guest_VSR58);
   1431    case 27: return offsetofPPCGuestState(guest_VSR59);
   1432    case 28: return offsetofPPCGuestState(guest_VSR60);
   1433    case 29: return offsetofPPCGuestState(guest_VSR61);
   1434    case 30: return offsetofPPCGuestState(guest_VSR62);
   1435    case 31: return offsetofPPCGuestState(guest_VSR63);
   1436    default: break;
   1437    }
   1438    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
   1439 }
   1440 
   1441 static IRExpr* getVReg ( UInt archreg )
   1442 {
   1443    vassert(archreg < 32);
   1444    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
   1445 }
   1446 
   1447 /* Ditto, but write to a reg instead. */
   1448 static void putVReg ( UInt archreg, IRExpr* e )
   1449 {
   1450    vassert(archreg < 32);
   1451    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1452    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
   1453 }
   1454 
   1455 /* Get contents of VSX guest register */
   1456 static IRExpr* getVSReg ( UInt archreg )
   1457 {
   1458    vassert(archreg < 64);
   1459    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
   1460 }
   1461 
   1462 /* Ditto, but write to a VSX reg instead. */
   1463 static void putVSReg ( UInt archreg, IRExpr* e )
   1464 {
   1465    vassert(archreg < 64);
   1466    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
   1467    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
   1468 }
   1469 
   1470 
   1471 static Int guestCR321offset ( UInt cr )
   1472 {
   1473    switch (cr) {
   1474    case 0: return offsetofPPCGuestState(guest_CR0_321 );
   1475    case 1: return offsetofPPCGuestState(guest_CR1_321 );
   1476    case 2: return offsetofPPCGuestState(guest_CR2_321 );
   1477    case 3: return offsetofPPCGuestState(guest_CR3_321 );
   1478    case 4: return offsetofPPCGuestState(guest_CR4_321 );
   1479    case 5: return offsetofPPCGuestState(guest_CR5_321 );
   1480    case 6: return offsetofPPCGuestState(guest_CR6_321 );
   1481    case 7: return offsetofPPCGuestState(guest_CR7_321 );
   1482    default: vpanic("guestCR321offset(ppc)");
   1483    }
   1484 }
   1485 
   1486 static Int guestCR0offset ( UInt cr )
   1487 {
   1488    switch (cr) {
   1489    case 0: return offsetofPPCGuestState(guest_CR0_0 );
   1490    case 1: return offsetofPPCGuestState(guest_CR1_0 );
   1491    case 2: return offsetofPPCGuestState(guest_CR2_0 );
   1492    case 3: return offsetofPPCGuestState(guest_CR3_0 );
   1493    case 4: return offsetofPPCGuestState(guest_CR4_0 );
   1494    case 5: return offsetofPPCGuestState(guest_CR5_0 );
   1495    case 6: return offsetofPPCGuestState(guest_CR6_0 );
   1496    case 7: return offsetofPPCGuestState(guest_CR7_0 );
   1497    default: vpanic("guestCR3offset(ppc)");
   1498    }
   1499 }
   1500 
   1501 typedef enum {
   1502    _placeholder0,
   1503    _placeholder1,
   1504    _placeholder2,
   1505    BYTE,
   1506    HWORD,
   1507    WORD,
   1508    DWORD
   1509 } _popcount_data_type;
   1510 
   1511 /* Generate an IR sequence to do a popcount operation on the supplied
   1512    IRTemp, and return a new IRTemp holding the result.  'ty' may be
   1513    Ity_I32 or Ity_I64 only. */
   1514 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
   1515 {
   1516   /* Do count across 2^data_type bits,
   1517      byte:        data_type = 3
   1518      half word:   data_type = 4
   1519      word:        data_type = 5
   1520      double word: data_type = 6  (not supported for 32-bit type)
   1521     */
   1522    Int shift[6];
   1523    _popcount_data_type idx, i;
   1524    IRTemp mask[6];
   1525    IRTemp old = IRTemp_INVALID;
   1526    IRTemp nyu = IRTemp_INVALID;
   1527 
   1528    vassert(ty == Ity_I64 || ty == Ity_I32);
   1529 
   1530    if (ty == Ity_I32) {
   1531 
   1532       for (idx = 0; idx < WORD; idx++) {
   1533          mask[idx]  = newTemp(ty);
   1534          shift[idx] = 1 << idx;
   1535       }
   1536       assign(mask[0], mkU32(0x55555555));
   1537       assign(mask[1], mkU32(0x33333333));
   1538       assign(mask[2], mkU32(0x0F0F0F0F));
   1539       assign(mask[3], mkU32(0x00FF00FF));
   1540       assign(mask[4], mkU32(0x0000FFFF));
   1541       old = src;
   1542       for (i = 0; i < data_type; i++) {
   1543          nyu = newTemp(ty);
   1544          assign(nyu,
   1545                 binop(Iop_Add32,
   1546                       binop(Iop_And32,
   1547                             mkexpr(old),
   1548                             mkexpr(mask[i])),
   1549                       binop(Iop_And32,
   1550                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1551                             mkexpr(mask[i]))));
   1552          old = nyu;
   1553       }
   1554       return nyu;
   1555    }
   1556 
   1557 // else, ty == Ity_I64
   1558    vassert(mode64);
   1559 
   1560    for (i = 0; i < DWORD; i++) {
   1561       mask[i] = newTemp( Ity_I64 );
   1562       shift[i] = 1 << i;
   1563    }
   1564    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
   1565    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
   1566    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
   1567    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
   1568    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
   1569    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
   1570    old = src;
   1571    for (i = 0; i < data_type; i++) {
   1572       nyu = newTemp( Ity_I64 );
   1573       assign( nyu,
   1574               binop( Iop_Add64,
   1575                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
   1576                      binop( Iop_And64,
   1577                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
   1578                             mkexpr( mask[i] ) ) ) );
   1579       old = nyu;
   1580    }
   1581    return nyu;
   1582 }
   1583 
   1584 /* Special purpose population count function for
   1585  * vpopcntd in 32-bit mode.
   1586  */
   1587 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
   1588 {
   1589    Int i, shift[6];
   1590    IRTemp mask[6];
   1591    IRTemp old = IRTemp_INVALID;
   1592    IRTemp nyu1 = IRTemp_INVALID;
   1593    IRTemp nyu2 = IRTemp_INVALID;
   1594    IRTemp retval = newTemp(Ity_I64);
   1595 
   1596    vassert(!mode64);
   1597 
   1598    for (i = 0; i < WORD; i++) {
   1599       mask[i]  = newTemp(Ity_I32);
   1600       shift[i] = 1 << i;
   1601    }
   1602    assign(mask[0], mkU32(0x55555555));
   1603    assign(mask[1], mkU32(0x33333333));
   1604    assign(mask[2], mkU32(0x0F0F0F0F));
   1605    assign(mask[3], mkU32(0x00FF00FF));
   1606    assign(mask[4], mkU32(0x0000FFFF));
   1607    old = src1;
   1608    for (i = 0; i < WORD; i++) {
   1609       nyu1 = newTemp(Ity_I32);
   1610       assign(nyu1,
   1611              binop(Iop_Add32,
   1612                    binop(Iop_And32,
   1613                          mkexpr(old),
   1614                          mkexpr(mask[i])),
   1615                    binop(Iop_And32,
   1616                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1617                          mkexpr(mask[i]))));
   1618       old = nyu1;
   1619    }
   1620 
   1621    old = src2;
   1622    for (i = 0; i < WORD; i++) {
   1623       nyu2 = newTemp(Ity_I32);
   1624       assign(nyu2,
   1625              binop(Iop_Add32,
   1626                    binop(Iop_And32,
   1627                          mkexpr(old),
   1628                          mkexpr(mask[i])),
   1629                    binop(Iop_And32,
   1630                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
   1631                          mkexpr(mask[i]))));
   1632       old = nyu2;
   1633    }
   1634    assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
   1635    return retval;
   1636 }
   1637 
   1638 
   1639 // ROTL(src32/64, rot_amt5/6)
   1640 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
   1641                                           IRExpr* rot_amt )
   1642 {
   1643    IRExpr *mask, *rot;
   1644    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
   1645 
   1646    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
   1647       // rot = (src << rot_amt) | (src >> (64-rot_amt))
   1648       mask = binop(Iop_And8, rot_amt, mkU8(63));
   1649       rot  = binop(Iop_Or64,
   1650                 binop(Iop_Shl64, src, mask),
   1651                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
   1652    } else {
   1653       // rot = (src << rot_amt) | (src >> (32-rot_amt))
   1654       mask = binop(Iop_And8, rot_amt, mkU8(31));
   1655       rot  = binop(Iop_Or32,
   1656                 binop(Iop_Shl32, src, mask),
   1657                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
   1658    }
   1659    /* Note: the ITE not merely an optimisation; it's needed
   1660       because otherwise the Shr is a shift by the word size when
   1661       mask denotes zero.  For rotates by immediates, a lot of
   1662       this junk gets folded out. */
   1663    return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
   1664                       /* non-zero rotate */ rot,
   1665                       /*     zero rotate */ src);
   1666 }
   1667 
   1668 /* Standard effective address calc: (rA + rB) */
   1669 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
   1670 {
   1671    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1672    vassert(rA < 32);
   1673    vassert(rB < 32);
   1674    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
   1675 }
   1676 
   1677 /* Standard effective address calc: (rA + simm) */
   1678 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
   1679 {
   1680    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1681    vassert(rA < 32);
   1682    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
   1683                 mkSzExtendS16(ty, simm16));
   1684 }
   1685 
   1686 /* Standard effective address calc: (rA|0) */
   1687 static IRExpr* ea_rAor0 ( UInt rA )
   1688 {
   1689    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1690    vassert(rA < 32);
   1691    if (rA == 0) {
   1692       return mkSzImm(ty, 0);
   1693    } else {
   1694       return getIReg(rA);
   1695    }
   1696 }
   1697 
   1698 /* Standard effective address calc: (rA|0) + rB */
   1699 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
   1700 {
   1701    vassert(rA < 32);
   1702    vassert(rB < 32);
   1703    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
   1704 }
   1705 
   1706 /* Standard effective address calc: (rA|0) + simm16 */
   1707 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
   1708 {
   1709    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1710    vassert(rA < 32);
   1711    if (rA == 0) {
   1712       return mkSzExtendS16(ty, simm16);
   1713    } else {
   1714       return ea_rA_simm( rA, simm16 );
   1715    }
   1716 }
   1717 
   1718 
   1719 /* Align effective address */
   1720 static IRExpr* addr_align( IRExpr* addr, UChar align )
   1721 {
   1722    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   1723    ULong mask;
   1724    switch (align) {
   1725    case 1:  return addr;                    // byte aligned
   1726    case 2:  mask = ~0ULL << 1; break;       // half-word aligned
   1727    case 4:  mask = ~0ULL << 2; break;       // word aligned
   1728    case 16: mask = ~0ULL << 4; break;       // quad-word aligned
   1729    default:
   1730       vex_printf("addr_align: align = %u\n", align);
   1731       vpanic("addr_align(ppc)");
   1732    }
   1733 
   1734    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
   1735    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
   1736 }
   1737 
   1738 
   1739 /* Exit the trace if ADDR (intended to be a guest memory address) is
   1740    not ALIGN-aligned, generating a request for a SIGBUS followed by a
   1741    restart of the current insn. */
   1742 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
   1743 {
   1744    vassert(align == 2 || align == 4 || align == 8 || align == 16);
   1745    if (mode64) {
   1746       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
   1747       stmt(
   1748          IRStmt_Exit(
   1749             binop(Iop_CmpNE64,
   1750                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
   1751                   mkU64(0)),
   1752             Ijk_SigBUS,
   1753             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
   1754          )
   1755       );
   1756    } else {
   1757       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
   1758       stmt(
   1759          IRStmt_Exit(
   1760             binop(Iop_CmpNE32,
   1761                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
   1762                   mkU32(0)),
   1763             Ijk_SigBUS,
   1764             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
   1765          )
   1766       );
   1767    }
   1768 }
   1769 
   1770 
   1771 /* Generate AbiHints which mark points at which the ELF or PowerOpen
   1772    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
   1773    N) becomes undefined.  That is at function calls and returns.  ELF
   1774    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
   1775    the address of the next instruction to be executed.
   1776 */
   1777 static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
   1778                                    IRTemp nia, const HChar* who )
   1779 {
   1780    Int szB = vbi->guest_stack_redzone_size;
   1781    if (0) vex_printf("AbiHint: %s\n", who);
   1782    vassert(szB >= 0);
   1783    if (szB > 0) {
   1784       if (mode64) {
   1785          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
   1786          stmt( IRStmt_AbiHint(
   1787                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
   1788                   szB,
   1789                   mkexpr(nia)
   1790          ));
   1791       } else {
   1792          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
   1793          stmt( IRStmt_AbiHint(
   1794                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
   1795                   szB,
   1796                   mkexpr(nia)
   1797          ));
   1798       }
   1799    }
   1800 }
   1801 
   1802 
   1803 /*------------------------------------------------------------*/
   1804 /*--- Helpers for condition codes.                         ---*/
   1805 /*------------------------------------------------------------*/
   1806 
   1807 /* Condition register layout.
   1808 
   1809    In the hardware, CR is laid out like this.  The leftmost end is the
   1810    most significant bit in the register; however the IBM documentation
   1811    numbers the bits backwards for some reason.
   1812 
   1813    CR0      CR1    ..........   CR6       CR7
   1814    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
   1815    31  28                             3    0     (normal bit numbering)
   1816 
   1817    Each CR field is 4 bits:  [<,>,==,SO]
   1818 
   1819    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
   1820 
   1821    Indexing from BI to guest state:
   1822 
   1823      let    n = BI / 4
   1824           off = BI % 4
   1825      this references CR n:
   1826 
   1827         off==0   ->  guest_CRn_321 >> 3
   1828         off==1   ->  guest_CRn_321 >> 2
   1829         off==2   ->  guest_CRn_321 >> 1
   1830         off==3   ->  guest_CRn_SO
   1831 
   1832    Bear in mind the only significant bit in guest_CRn_SO is bit 0
   1833    (normal notation) and in guest_CRn_321 the significant bits are
   1834    3, 2 and 1 (normal notation).
   1835 */
   1836 
   1837 static void putCR321 ( UInt cr, IRExpr* e )
   1838 {
   1839    vassert(cr < 8);
   1840    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1841    stmt( IRStmt_Put(guestCR321offset(cr), e) );
   1842 }
   1843 
   1844 static void putCR0 ( UInt cr, IRExpr* e )
   1845 {
   1846    vassert(cr < 8);
   1847    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   1848    stmt( IRStmt_Put(guestCR0offset(cr), e) );
   1849 }
   1850 
   1851 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
   1852 {
   1853    vassert(cr < 8);
   1854    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
   1855 }
   1856 
   1857 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
   1858 {
   1859    vassert(cr < 8);
   1860    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
   1861 }
   1862 
   1863 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1864    return it at the bottom of an I32; the top 31 bits are guaranteed
   1865    to be zero. */
   1866 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
   1867 {
   1868    UInt n   = bi / 4;
   1869    UInt off = bi % 4;
   1870    vassert(bi < 32);
   1871    if (off == 3) {
   1872       /* Fetch the SO bit for this CR field */
   1873       /* Note: And32 is redundant paranoia iff guest state only has 0
   1874          or 1 in that slot. */
   1875       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1876    } else {
   1877       /* Fetch the <, > or == bit for this CR field */
   1878       return binop( Iop_And32,
   1879                     binop( Iop_Shr32,
   1880                            unop(Iop_8Uto32, getCR321(n)),
   1881                            mkU8(toUChar(3-off)) ),
   1882                     mkU32(1) );
   1883    }
   1884 }
   1885 
   1886 /* Dually, write the least significant bit of BIT to the specified CR
   1887    bit.  Indexing as per getCRbit. */
   1888 static void putCRbit ( UInt bi, IRExpr* bit )
   1889 {
   1890    UInt    n, off;
   1891    IRExpr* safe;
   1892    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
   1893    safe = binop(Iop_And32, bit, mkU32(1));
   1894    n   = bi / 4;
   1895    off = bi % 4;
   1896    vassert(bi < 32);
   1897    if (off == 3) {
   1898       /* This is the SO bit for this CR field */
   1899       putCR0(n, unop(Iop_32to8, safe));
   1900    } else {
   1901       off = 3 - off;
   1902       vassert(off == 1 || off == 2 || off == 3);
   1903       putCR321(
   1904          n,
   1905          unop( Iop_32to8,
   1906                binop( Iop_Or32,
   1907                       /* old value with field masked out */
   1908                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
   1909                                        mkU32(~(1 << off))),
   1910                       /* new value in the right place */
   1911                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
   1912                )
   1913          )
   1914       );
   1915    }
   1916 }
   1917 
   1918 /* Fetch the specified CR bit (as per IBM/hardware notation) and
   1919    return it somewhere in an I32; it does not matter where, but
   1920    whichever bit it is, all other bits are guaranteed to be zero.  In
   1921    other words, the I32-typed expression will be zero if the bit is
   1922    zero and nonzero if the bit is 1.  Write into *where the index
   1923    of where the bit will be. */
   1924 
   1925 static
   1926 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
   1927 {
   1928    UInt n   = bi / 4;
   1929    UInt off = bi % 4;
   1930    vassert(bi < 32);
   1931    if (off == 3) {
   1932       /* Fetch the SO bit for this CR field */
   1933       /* Note: And32 is redundant paranoia iff guest state only has 0
   1934          or 1 in that slot. */
   1935       *where = 0;
   1936       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
   1937    } else {
   1938       /* Fetch the <, > or == bit for this CR field */
   1939       *where = 3-off;
   1940       return binop( Iop_And32,
   1941                     unop(Iop_8Uto32, getCR321(n)),
   1942                     mkU32(1 << (3-off)) );
   1943    }
   1944 }
   1945 
   1946 /* Set the CR0 flags following an arithmetic operation.
   1947    (Condition Register CR0 Field Definition, PPC32 p60)
   1948 */
   1949 static IRExpr* getXER_SO ( void );
   1950 static void set_CR0 ( IRExpr* result )
   1951 {
   1952    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
   1953            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
   1954    if (mode64) {
   1955       putCR321( 0, unop(Iop_64to8,
   1956                         binop(Iop_CmpORD64S, result, mkU64(0))) );
   1957    } else {
   1958       putCR321( 0, unop(Iop_32to8,
   1959                         binop(Iop_CmpORD32S, result, mkU32(0))) );
   1960    }
   1961    putCR0( 0, getXER_SO() );
   1962 }
   1963 
   1964 
   1965 /* Set the CR6 flags following an AltiVec compare operation.
   1966  * NOTE: This also works for VSX single-precision compares.
   1967  * */
   1968 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
   1969 {
   1970    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
   1971       all_ones  = (v[0] && v[1] && v[2] && v[3])
   1972       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
   1973    */
   1974    IRTemp v0 = newTemp(Ity_V128);
   1975    IRTemp v1 = newTemp(Ity_V128);
   1976    IRTemp v2 = newTemp(Ity_V128);
   1977    IRTemp v3 = newTemp(Ity_V128);
   1978    IRTemp rOnes  = newTemp(Ity_I8);
   1979    IRTemp rZeros = newTemp(Ity_I8);
   1980 
   1981    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
   1982 
   1983    assign( v0, result );
   1984    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
   1985    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
   1986    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
   1987 
   1988    assign( rZeros, unop(Iop_1Uto8,
   1989        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   1990              unop(Iop_Not32,
   1991                   unop(Iop_V128to32,
   1992                        binop(Iop_OrV128,
   1993                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
   1994                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
   1995                   ))) );
   1996 
   1997    if (test_all_ones) {
   1998       assign( rOnes, unop(Iop_1Uto8,
   1999          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
   2000                unop(Iop_V128to32,
   2001                     binop(Iop_AndV128,
   2002                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
   2003                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
   2004                     ))) );
   2005       putCR321( 6, binop(Iop_Or8,
   2006                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
   2007                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
   2008    } else {
   2009       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
   2010    }
   2011    putCR0( 6, mkU8(0) );
   2012 }
   2013 
   2014 
   2015 
   2016 /*------------------------------------------------------------*/
   2017 /*--- Helpers for XER flags.                               ---*/
   2018 /*------------------------------------------------------------*/
   2019 
   2020 static void putXER_SO ( IRExpr* e )
   2021 {
   2022    IRExpr* so;
   2023    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2024    so = binop(Iop_And8, e, mkU8(1));
   2025    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
   2026 }
   2027 
   2028 static void putXER_OV ( IRExpr* e )
   2029 {
   2030    IRExpr* ov;
   2031    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2032    ov = binop(Iop_And8, e, mkU8(1));
   2033    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
   2034 }
   2035 
   2036 static void putXER_CA ( IRExpr* e )
   2037 {
   2038    IRExpr* ca;
   2039    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2040    ca = binop(Iop_And8, e, mkU8(1));
   2041    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
   2042 }
   2043 
   2044 static void putXER_BC ( IRExpr* e )
   2045 {
   2046    IRExpr* bc;
   2047    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
   2048    bc = binop(Iop_And8, e, mkU8(0x7F));
   2049    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
   2050 }
   2051 
   2052 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
   2053 {
   2054    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
   2055 }
   2056 
   2057 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
   2058 {
   2059    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
   2060 }
   2061 
   2062 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
   2063 {
   2064    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
   2065 }
   2066 
   2067 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
   2068 {
   2069    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
   2070 }
   2071 
   2072 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
   2073 {
   2074    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
   2075    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
   2076 }
   2077 
   2078 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
   2079 {
   2080    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   2081 }
   2082 
   2083 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
   2084 {
   2085    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
   2086    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
   2087 }
   2088 
   2089 
   2090 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
   2091    %XER.SO accordingly. */
   2092 
   2093 static void set_XER_OV_32( UInt op, IRExpr* res,
   2094                            IRExpr* argL, IRExpr* argR )
   2095 {
   2096    IRTemp  t64;
   2097    IRExpr* xer_ov;
   2098    vassert(op < PPCG_FLAG_OP_NUMBER);
   2099    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
   2100    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
   2101    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
   2102 
   2103 #  define INT32_MIN 0x80000000
   2104 
   2105 #  define XOR2(_aa,_bb) \
   2106       binop(Iop_Xor32,(_aa),(_bb))
   2107 
   2108 #  define XOR3(_cc,_dd,_ee) \
   2109       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
   2110 
   2111 #  define AND3(_ff,_gg,_hh) \
   2112       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
   2113 
   2114 #define NOT(_jj) \
   2115       unop(Iop_Not32, (_jj))
   2116 
   2117    switch (op) {
   2118    case /* 0  */ PPCG_FLAG_OP_ADD:
   2119    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2120       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
   2121       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2122       xer_ov
   2123          = AND3( XOR3(argL,argR,mkU32(-1)),
   2124                  XOR2(argL,res),
   2125                  mkU32(INT32_MIN) );
   2126       /* xer_ov can only be 0 or 1<<31 */
   2127       xer_ov
   2128          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2129       break;
   2130 
   2131    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2132       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
   2133       xer_ov
   2134          = mkOR1(
   2135               mkAND1(
   2136                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
   2137                  binop(Iop_CmpEQ32, argR, mkU32(-1))
   2138               ),
   2139               binop(Iop_CmpEQ32, argR, mkU32(0) )
   2140            );
   2141       xer_ov
   2142          = unop(Iop_1Uto32, xer_ov);
   2143       break;
   2144 
   2145    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2146       /* argR == 0 */
   2147       xer_ov
   2148          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
   2149       break;
   2150 
   2151    case /* 4  */ PPCG_FLAG_OP_MULLW:
   2152       /* OV true if result can't be represented in 32 bits
   2153          i.e sHi != sign extension of sLo */
   2154       t64 = newTemp(Ity_I64);
   2155       assign( t64, binop(Iop_MullS32, argL, argR) );
   2156       xer_ov
   2157          = binop( Iop_CmpNE32,
   2158                   unop(Iop_64HIto32, mkexpr(t64)),
   2159                   binop( Iop_Sar32,
   2160                          unop(Iop_64to32, mkexpr(t64)),
   2161                          mkU8(31))
   2162                   );
   2163       xer_ov
   2164          = unop(Iop_1Uto32, xer_ov);
   2165       break;
   2166 
   2167    case /* 5  */ PPCG_FLAG_OP_NEG:
   2168       /* argL == INT32_MIN */
   2169       xer_ov
   2170          = unop( Iop_1Uto32,
   2171                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
   2172       break;
   2173 
   2174    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2175    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2176    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2177       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
   2178       xer_ov
   2179          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
   2180                  XOR2(NOT(argL),res),
   2181                  mkU32(INT32_MIN) );
   2182       /* xer_ov can only be 0 or 1<<31 */
   2183       xer_ov
   2184          = binop(Iop_Shr32, xer_ov, mkU8(31) );
   2185       break;
   2186 
   2187    case PPCG_FLAG_OP_DIVWEU:
   2188       xer_ov
   2189                = binop( Iop_Or32,
   2190                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2191                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
   2192       break;
   2193 
   2194    case PPCG_FLAG_OP_DIVWE:
   2195 
   2196       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
   2197        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
   2198        * an overflow is implied.
   2199        */
   2200       xer_ov = binop( Iop_Or32,
   2201                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
   2202                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
   2203                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
   2204                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
   2205       break;
   2206 
   2207 
   2208 
   2209    default:
   2210       vex_printf("set_XER_OV: op = %u\n", op);
   2211       vpanic("set_XER_OV(ppc)");
   2212    }
   2213 
   2214    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2215    putXER_OV( unop(Iop_32to8, xer_ov) );
   2216 
   2217    /* Update the summary overflow */
   2218    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2219 
   2220 #  undef INT32_MIN
   2221 #  undef AND3
   2222 #  undef XOR3
   2223 #  undef XOR2
   2224 #  undef NOT
   2225 }
   2226 
   2227 static void set_XER_OV_64( UInt op, IRExpr* res,
   2228                            IRExpr* argL, IRExpr* argR )
   2229 {
   2230    IRExpr* xer_ov;
   2231    vassert(op < PPCG_FLAG_OP_NUMBER);
   2232    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
   2233    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
   2234    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
   2235 
   2236 #  define INT64_MIN 0x8000000000000000ULL
   2237 
   2238 #  define XOR2(_aa,_bb) \
   2239       binop(Iop_Xor64,(_aa),(_bb))
   2240 
   2241 #  define XOR3(_cc,_dd,_ee) \
   2242       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
   2243 
   2244 #  define AND3(_ff,_gg,_hh) \
   2245       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
   2246 
   2247 #define NOT(_jj) \
   2248       unop(Iop_Not64, (_jj))
   2249 
   2250    switch (op) {
   2251    case /* 0  */ PPCG_FLAG_OP_ADD:
   2252    case /* 1  */ PPCG_FLAG_OP_ADDE:
   2253       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
   2254       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
   2255       xer_ov
   2256          = AND3( XOR3(argL,argR,mkU64(-1)),
   2257                  XOR2(argL,res),
   2258                  mkU64(INT64_MIN) );
   2259       /* xer_ov can only be 0 or 1<<63 */
   2260       xer_ov
   2261          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2262       break;
   2263 
   2264    case /* 2  */ PPCG_FLAG_OP_DIVW:
   2265       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
   2266       xer_ov
   2267          = mkOR1(
   2268               mkAND1(
   2269                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
   2270                  binop(Iop_CmpEQ64, argR, mkU64(-1))
   2271               ),
   2272               binop(Iop_CmpEQ64, argR, mkU64(0) )
   2273            );
   2274       break;
   2275 
   2276    case /* 3  */ PPCG_FLAG_OP_DIVWU:
   2277       /* argR == 0 */
   2278       xer_ov
   2279          = binop(Iop_CmpEQ64, argR, mkU64(0));
   2280       break;
   2281 
   2282    case /* 4  */ PPCG_FLAG_OP_MULLW: {
   2283       /* OV true if result can't be represented in 64 bits
   2284          i.e sHi != sign extension of sLo */
   2285       xer_ov
   2286          = binop( Iop_CmpNE32,
   2287                   unop(Iop_64HIto32, res),
   2288                   binop( Iop_Sar32,
   2289                          unop(Iop_64to32, res),
   2290                          mkU8(31))
   2291                   );
   2292       break;
   2293    }
   2294 
   2295    case /* 5  */ PPCG_FLAG_OP_NEG:
   2296       /* argL == INT64_MIN */
   2297       xer_ov
   2298          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
   2299       break;
   2300 
   2301    case /* 6  */ PPCG_FLAG_OP_SUBF:
   2302    case /* 7  */ PPCG_FLAG_OP_SUBFC:
   2303    case /* 8  */ PPCG_FLAG_OP_SUBFE:
   2304       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
   2305       xer_ov
   2306          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
   2307                  XOR2(NOT(argL),res),
   2308                  mkU64(INT64_MIN) );
   2309       /* xer_ov can only be 0 or 1<<63 */
   2310       xer_ov
   2311          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
   2312       break;
   2313 
   2314    case PPCG_FLAG_OP_DIVDE:
   2315 
   2316       /* If argR == 0, we must set the OV bit.  But there's another condition
   2317        * where we can get overflow set for divde . . . when the
   2318        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
   2319        * both dividend and divisor are non-zero, it implies an overflow.
   2320        */
   2321       xer_ov
   2322                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2323                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
   2324                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
   2325                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
   2326       break;
   2327 
   2328    case PPCG_FLAG_OP_DIVDEU:
   2329      /* If argR == 0 or if argL >= argR, set OV. */
   2330      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
   2331                          binop( Iop_CmpLE64U, argR, argL ) );
   2332      break;
   2333 
   2334    case /* 18 */ PPCG_FLAG_OP_MULLD: {
   2335       IRTemp  t128;
   2336       /* OV true if result can't be represented in 64 bits
   2337          i.e sHi != sign extension of sLo */
   2338       t128 = newTemp(Ity_I128);
   2339       assign( t128, binop(Iop_MullS64, argL, argR) );
   2340       xer_ov
   2341          = binop( Iop_CmpNE64,
   2342                   unop(Iop_128HIto64, mkexpr(t128)),
   2343                   binop( Iop_Sar64,
   2344                          unop(Iop_128to64, mkexpr(t128)),
   2345                          mkU8(63))
   2346                   );
   2347       break;
   2348    }
   2349 
   2350    default:
   2351       vex_printf("set_XER_OV: op = %u\n", op);
   2352       vpanic("set_XER_OV(ppc64)");
   2353    }
   2354 
   2355    /* xer_ov MUST denote either 0 or 1, no other value allowed */
   2356    putXER_OV( unop(Iop_1Uto8, xer_ov) );
   2357 
   2358    /* Update the summary overflow */
   2359    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
   2360 
   2361 #  undef INT64_MIN
   2362 #  undef AND3
   2363 #  undef XOR3
   2364 #  undef XOR2
   2365 #  undef NOT
   2366 }
   2367 
   2368 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
   2369                          IRExpr* argL, IRExpr* argR )
   2370 {
   2371    if (ty == Ity_I32)
   2372       set_XER_OV_32( op, res, argL, argR );
   2373    else
   2374       set_XER_OV_64( op, res, argL, argR );
   2375 }
   2376 
   2377 
   2378 
   2379 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
   2380    value being OLDCA.  Set %XER.CA accordingly. */
   2381 
   2382 static void set_XER_CA_32 ( UInt op, IRExpr* res,
   2383                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2384 {
   2385    IRExpr* xer_ca;
   2386    vassert(op < PPCG_FLAG_OP_NUMBER);
   2387    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
   2388    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
   2389    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
   2390    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
   2391 
   2392    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2393       seems reasonable given that it's always generated by
   2394       getXER_CA32(), which masks it accordingly.  In any case it being
   2395       0 or 1 is an invariant of the ppc guest state representation;
   2396       if it has any other value, that invariant has been violated. */
   2397 
   2398    switch (op) {
   2399    case /* 0 */ PPCG_FLAG_OP_ADD:
   2400       /* res <u argL */
   2401       xer_ca
   2402          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
   2403       break;
   2404 
   2405    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2406       /* res <u argL || (old_ca==1 && res==argL) */
   2407       xer_ca
   2408          = mkOR1(
   2409               binop(Iop_CmpLT32U, res, argL),
   2410               mkAND1(
   2411                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2412                  binop(Iop_CmpEQ32, res, argL)
   2413               )
   2414            );
   2415       xer_ca
   2416          = unop(Iop_1Uto32, xer_ca);
   2417       break;
   2418 
   2419    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2420       /* res <u argR || (old_ca==1 && res==argR) */
   2421       xer_ca
   2422          = mkOR1(
   2423               binop(Iop_CmpLT32U, res, argR),
   2424               mkAND1(
   2425                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
   2426                  binop(Iop_CmpEQ32, res, argR)
   2427               )
   2428            );
   2429       xer_ca
   2430          = unop(Iop_1Uto32, xer_ca);
   2431       break;
   2432 
   2433    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2434    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2435       /* res <=u argR */
   2436       xer_ca
   2437          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
   2438       break;
   2439 
   2440    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2441       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2442          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2443          bit of argL. */
   2444       /* This term valid for shift amount < 32 only */
   2445       xer_ca
   2446          = binop(
   2447               Iop_And32,
   2448               binop(Iop_Sar32, argL, mkU8(31)),
   2449               binop( Iop_And32,
   2450                      argL,
   2451                      binop( Iop_Sub32,
   2452                             binop(Iop_Shl32, mkU32(1),
   2453                                              unop(Iop_32to8,argR)),
   2454                             mkU32(1) )
   2455                      )
   2456               );
   2457       xer_ca
   2458          = IRExpr_ITE(
   2459               /* shift amt > 31 ? */
   2460               binop(Iop_CmpLT32U, mkU32(31), argR),
   2461               /* yes -- get sign bit of argL */
   2462               binop(Iop_Shr32, argL, mkU8(31)),
   2463               /* no -- be like srawi */
   2464               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
   2465            );
   2466       break;
   2467 
   2468    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2469       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
   2470          0.  Since the shift amount is known to be in the range
   2471          0 .. 31 inclusive the following seems viable:
   2472          xer.ca == 1 iff the following is nonzero:
   2473          (argL >>s 31)           -- either all 0s or all 1s
   2474          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2475       xer_ca
   2476          = binop(
   2477               Iop_And32,
   2478               binop(Iop_Sar32, argL, mkU8(31)),
   2479               binop( Iop_And32,
   2480                      argL,
   2481                      binop( Iop_Sub32,
   2482                             binop(Iop_Shl32, mkU32(1),
   2483                                              unop(Iop_32to8,argR)),
   2484                             mkU32(1) )
   2485                      )
   2486               );
   2487       xer_ca
   2488          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
   2489       break;
   2490 
   2491    default:
   2492       vex_printf("set_XER_CA: op = %u\n", op);
   2493       vpanic("set_XER_CA(ppc)");
   2494    }
   2495 
   2496    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2497    putXER_CA( unop(Iop_32to8, xer_ca) );
   2498 }
   2499 
   2500 static void set_XER_CA_64 ( UInt op, IRExpr* res,
   2501                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2502 {
   2503    IRExpr* xer_ca;
   2504    vassert(op < PPCG_FLAG_OP_NUMBER);
   2505    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
   2506    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
   2507    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
   2508    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
   2509 
   2510    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
   2511       seems reasonable given that it's always generated by
   2512       getXER_CA32(), which masks it accordingly.  In any case it being
   2513       0 or 1 is an invariant of the ppc guest state representation;
   2514       if it has any other value, that invariant has been violated. */
   2515 
   2516    switch (op) {
   2517    case /* 0 */ PPCG_FLAG_OP_ADD:
   2518       /* res <u argL */
   2519       xer_ca
   2520          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
   2521       break;
   2522 
   2523    case /* 1 */ PPCG_FLAG_OP_ADDE:
   2524       /* res <u argL || (old_ca==1 && res==argL) */
   2525       xer_ca
   2526          = mkOR1(
   2527               binop(Iop_CmpLT64U, res, argL),
   2528               mkAND1(
   2529                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2530                  binop(Iop_CmpEQ64, res, argL)
   2531                  )
   2532               );
   2533       xer_ca
   2534          = unop(Iop_1Uto32, xer_ca);
   2535       break;
   2536 
   2537    case /* 8 */ PPCG_FLAG_OP_SUBFE:
   2538       /* res <u argR || (old_ca==1 && res==argR) */
   2539       xer_ca
   2540          = mkOR1(
   2541               binop(Iop_CmpLT64U, res, argR),
   2542               mkAND1(
   2543                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
   2544                  binop(Iop_CmpEQ64, res, argR)
   2545               )
   2546            );
   2547       xer_ca
   2548          = unop(Iop_1Uto32, xer_ca);
   2549       break;
   2550 
   2551    case /* 7 */ PPCG_FLAG_OP_SUBFC:
   2552    case /* 9 */ PPCG_FLAG_OP_SUBFI:
   2553       /* res <=u argR */
   2554       xer_ca
   2555          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
   2556       break;
   2557 
   2558 
   2559    case /* 10 */ PPCG_FLAG_OP_SRAW:
   2560       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
   2561          If it is <= 31, behave like SRAWI; else XER.CA is the sign
   2562          bit of argL. */
   2563          /* This term valid for shift amount < 31 only */
   2564 
   2565       xer_ca
   2566          = binop(
   2567               Iop_And64,
   2568               binop(Iop_Sar64, argL, mkU8(31)),
   2569               binop( Iop_And64,
   2570                      argL,
   2571                      binop( Iop_Sub64,
   2572                             binop(Iop_Shl64, mkU64(1),
   2573                                              unop(Iop_64to8,argR)),
   2574                             mkU64(1) )
   2575               )
   2576            );
   2577       xer_ca
   2578          = IRExpr_ITE(
   2579               /* shift amt > 31 ? */
   2580               binop(Iop_CmpLT64U, mkU64(31), argR),
   2581               /* yes -- get sign bit of argL */
   2582               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2583               /* no -- be like srawi */
   2584               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2585           );
   2586       break;
   2587 
   2588    case /* 11 */ PPCG_FLAG_OP_SRAWI:
   2589       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2590          Since the shift amount is known to be in the range 0 .. 31
   2591          inclusive the following seems viable:
   2592          xer.ca == 1 iff the following is nonzero:
   2593          (argL >>s 31)           -- either all 0s or all 1s
   2594          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2595 
   2596       xer_ca
   2597          = binop(
   2598               Iop_And64,
   2599               binop(Iop_Sar64, argL, mkU8(31)),
   2600               binop( Iop_And64,
   2601                      argL,
   2602                      binop( Iop_Sub64,
   2603                             binop(Iop_Shl64, mkU64(1),
   2604                                              unop(Iop_64to8,argR)),
   2605                             mkU64(1) )
   2606               )
   2607            );
   2608       xer_ca
   2609          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2610       break;
   2611 
   2612 
   2613    case /* 12 */ PPCG_FLAG_OP_SRAD:
   2614       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
   2615          If it is <= 63, behave like SRADI; else XER.CA is the sign
   2616          bit of argL. */
   2617          /* This term valid for shift amount < 63 only */
   2618 
   2619       xer_ca
   2620          = binop(
   2621               Iop_And64,
   2622               binop(Iop_Sar64, argL, mkU8(63)),
   2623               binop( Iop_And64,
   2624                      argL,
   2625                      binop( Iop_Sub64,
   2626                             binop(Iop_Shl64, mkU64(1),
   2627                                              unop(Iop_64to8,argR)),
   2628                             mkU64(1) )
   2629               )
   2630            );
   2631       xer_ca
   2632          = IRExpr_ITE(
   2633               /* shift amt > 63 ? */
   2634               binop(Iop_CmpLT64U, mkU64(63), argR),
   2635               /* yes -- get sign bit of argL */
   2636               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
   2637               /* no -- be like sradi */
   2638               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
   2639            );
   2640       break;
   2641 
   2642 
   2643    case /* 13 */ PPCG_FLAG_OP_SRADI:
   2644       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
   2645          Since the shift amount is known to be in the range 0 .. 63
   2646          inclusive, the following seems viable:
   2647          xer.ca == 1 iff the following is nonzero:
   2648          (argL >>s 63)           -- either all 0s or all 1s
   2649          & (argL & (1<<argR)-1)  -- the stuff shifted out */
   2650 
   2651       xer_ca
   2652          = binop(
   2653               Iop_And64,
   2654               binop(Iop_Sar64, argL, mkU8(63)),
   2655               binop( Iop_And64,
   2656                      argL,
   2657                      binop( Iop_Sub64,
   2658                             binop(Iop_Shl64, mkU64(1),
   2659                                              unop(Iop_64to8,argR)),
   2660                             mkU64(1) )
   2661               )
   2662            );
   2663       xer_ca
   2664          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
   2665       break;
   2666 
   2667    default:
   2668       vex_printf("set_XER_CA: op = %u\n", op);
   2669       vpanic("set_XER_CA(ppc64)");
   2670    }
   2671 
   2672    /* xer_ca MUST denote either 0 or 1, no other value allowed */
   2673    putXER_CA( unop(Iop_32to8, xer_ca) );
   2674 }
   2675 
   2676 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
   2677                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
   2678 {
   2679    if (ty == Ity_I32)
   2680       set_XER_CA_32( op, res, argL, argR, oldca );
   2681    else
   2682       set_XER_CA_64( op, res, argL, argR, oldca );
   2683 }
   2684 
   2685 
   2686 
   2687 /*------------------------------------------------------------*/
   2688 /*--- Read/write to guest-state                           --- */
   2689 /*------------------------------------------------------------*/
   2690 
   2691 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
   2692 {
   2693    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   2694    switch (reg) {
   2695    case PPC_GST_SPRG3_RO:
   2696       return IRExpr_Get( OFFB_SPRG3_RO, ty );
   2697 
   2698    case PPC_GST_CIA:
   2699       return IRExpr_Get( OFFB_CIA, ty );
   2700 
   2701    case PPC_GST_LR:
   2702       return IRExpr_Get( OFFB_LR, ty );
   2703 
   2704    case PPC_GST_CTR:
   2705       return IRExpr_Get( OFFB_CTR, ty );
   2706 
   2707    case PPC_GST_VRSAVE:
   2708       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
   2709 
   2710    case PPC_GST_VSCR:
   2711       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
   2712                               mkU32(MASK_VSCR_VALID));
   2713 
   2714    case PPC_GST_CR: {
   2715       /* Synthesise the entire CR into a single word.  Expensive. */
   2716 #     define FIELD(_n)                                               \
   2717          binop(Iop_Shl32,                                            \
   2718                unop(Iop_8Uto32,                                      \
   2719                     binop(Iop_Or8,                                   \
   2720                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
   2721                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
   2722                     )                                                \
   2723                ),                                                    \
   2724                mkU8(4 * (7-(_n)))                                    \
   2725          )
   2726       return binop(Iop_Or32,
   2727                    binop(Iop_Or32,
   2728                          binop(Iop_Or32, FIELD(0), FIELD(1)),
   2729                          binop(Iop_Or32, FIELD(2), FIELD(3))
   2730                          ),
   2731                    binop(Iop_Or32,
   2732                          binop(Iop_Or32, FIELD(4), FIELD(5)),
   2733                          binop(Iop_Or32, FIELD(6), FIELD(7))
   2734                          )
   2735                    );
   2736 #     undef FIELD
   2737    }
   2738 
   2739    case PPC_GST_XER:
   2740       return binop(Iop_Or32,
   2741                    binop(Iop_Or32,
   2742                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
   2743                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
   2744                    binop(Iop_Or32,
   2745                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
   2746                          getXER_BC32()));
   2747 
   2748    case PPC_GST_TFHAR:
   2749       return IRExpr_Get( OFFB_TFHAR, ty );
   2750 
   2751    case PPC_GST_TEXASR:
   2752       return IRExpr_Get( OFFB_TEXASR, ty );
   2753 
   2754    case PPC_GST_TEXASRU:
   2755       return IRExpr_Get( OFFB_TEXASRU, ty );
   2756 
   2757    case PPC_GST_TFIAR:
   2758       return IRExpr_Get( OFFB_TFIAR, ty );
   2759 
   2760    case PPC_GST_PPR:
   2761       return IRExpr_Get( OFFB_PPR, ty );
   2762 
   2763    case PPC_GST_PPR32:
   2764       return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
   2765 
   2766    case PPC_GST_PSPB:
   2767       return IRExpr_Get( OFFB_PSPB, ty );
   2768 
   2769    default:
   2770       vex_printf("getGST(ppc): reg = %u", reg);
   2771       vpanic("getGST(ppc)");
   2772    }
   2773 }
   2774 
   2775 /* Get a masked word from the given reg */
   2776 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
   2777 {
   2778    IRTemp val = newTemp(Ity_I32);
   2779    vassert( reg < PPC_GST_MAX );
   2780 
   2781    switch (reg) {
   2782 
   2783    case PPC_GST_FPSCR: {
   2784       /* Vex-generated code expects the FPSCR to be set as follows:
   2785          all exceptions masked, round-to-nearest.
   2786          This corresponds to a FPSCR value of 0x0. */
   2787 
   2788       /* In the lower 32 bits of FPSCR, we're only keeping track of
   2789        * the binary floating point rounding mode, so if the mask isn't
   2790        * asking for this, just return 0x0.
   2791        */
   2792       if (mask & MASK_FPSCR_RN) {
   2793          assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
   2794       } else {
   2795          assign( val, mkU32(0x0) );
   2796       }
   2797       break;
   2798    }
   2799 
   2800    default:
   2801       vex_printf("getGST_masked(ppc): reg = %u", reg);
   2802       vpanic("getGST_masked(ppc)");
   2803    }
   2804 
   2805    if (mask != 0xFFFFFFFF) {
   2806       return binop(Iop_And32, mkexpr(val), mkU32(mask));
   2807    } else {
   2808       return mkexpr(val);
   2809    }
   2810 }
   2811 
   2812 /* Get a masked word from the given reg */
   2813 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
   2814    IRExpr * val;
   2815    vassert( reg < PPC_GST_MAX );
   2816 
   2817    switch (reg) {
   2818 
   2819    case PPC_GST_FPSCR: {
   2820       /* In the upper 32 bits of FPSCR, we're only keeping track
   2821        * of the decimal floating point rounding mode, so if the mask
   2822        * isn't asking for this, just return 0x0.
   2823        */
   2824       if (mask & MASK_FPSCR_DRN) {
   2825          val = binop( Iop_And32,
   2826                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
   2827                       unop( Iop_64HIto32, mkU64( mask ) ) );
   2828       } else {
   2829          val = mkU32( 0x0ULL );
   2830       }
   2831       break;
   2832    }
   2833 
   2834    default:
   2835       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
   2836       vpanic( "getGST_masked_upper(ppc)" );
   2837    }
   2838    return val;
   2839 }
   2840 
   2841 
   2842 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
   2843    and return it at the bottom of an I32; the top 27 bits are
   2844    guaranteed to be zero. */
   2845 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
   2846 {
   2847    UInt shft, mask;
   2848 
   2849    vassert( fld < 8 );
   2850    vassert( reg < PPC_GST_MAX );
   2851 
   2852    shft = 4*(7-fld);
   2853    mask = 0xF<<shft;
   2854 
   2855    switch (reg) {
   2856    case PPC_GST_XER:
   2857       vassert(fld ==7);
   2858       return binop(Iop_Or32,
   2859                    binop(Iop_Or32,
   2860                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
   2861                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
   2862                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
   2863       break;
   2864 
   2865    default:
   2866       if (shft == 0)
   2867          return getGST_masked( reg, mask );
   2868       else
   2869          return binop(Iop_Shr32,
   2870                       getGST_masked( reg, mask ),
   2871                       mkU8(toUChar( shft )));
   2872    }
   2873 }
   2874 
   2875 static void putGST ( PPC_GST reg, IRExpr* src )
   2876 {
   2877    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   2878    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
   2879    vassert( reg < PPC_GST_MAX );
   2880    switch (reg) {
   2881    case PPC_GST_IP_AT_SYSCALL:
   2882       vassert( ty_src == ty );
   2883       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
   2884       break;
   2885    case PPC_GST_CIA:
   2886       vassert( ty_src == ty );
   2887       stmt( IRStmt_Put( OFFB_CIA, src ) );
   2888       break;
   2889    case PPC_GST_LR:
   2890       vassert( ty_src == ty );
   2891       stmt( IRStmt_Put( OFFB_LR, src ) );
   2892       break;
   2893    case PPC_GST_CTR:
   2894       vassert( ty_src == ty );
   2895       stmt( IRStmt_Put( OFFB_CTR, src ) );
   2896       break;
   2897    case PPC_GST_VRSAVE:
   2898       vassert( ty_src == Ity_I32 );
   2899       stmt( IRStmt_Put( OFFB_VRSAVE,src));
   2900       break;
   2901    case PPC_GST_VSCR:
   2902       vassert( ty_src == Ity_I32 );
   2903       stmt( IRStmt_Put( OFFB_VSCR,
   2904                         binop(Iop_And32, src,
   2905                               mkU32(MASK_VSCR_VALID)) ) );
   2906       break;
   2907    case PPC_GST_XER:
   2908       vassert( ty_src == Ity_I32 );
   2909       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
   2910       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
   2911       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
   2912       putXER_BC( unop(Iop_32to8, src) );
   2913       break;
   2914 
   2915    case PPC_GST_EMWARN:
   2916       vassert( ty_src == Ity_I32 );
   2917       stmt( IRStmt_Put( OFFB_EMNOTE,src) );
   2918       break;
   2919 
   2920    case PPC_GST_CMSTART:
   2921       vassert( ty_src == ty );
   2922       stmt( IRStmt_Put( OFFB_CMSTART, src) );
   2923       break;
   2924 
   2925    case PPC_GST_CMLEN:
   2926       vassert( ty_src == ty );
   2927       stmt( IRStmt_Put( OFFB_CMLEN, src) );
   2928       break;
   2929 
   2930    case PPC_GST_TEXASR:
   2931       vassert( ty_src == Ity_I64 );
   2932       stmt( IRStmt_Put( OFFB_TEXASR, src ) );
   2933       break;
   2934 
   2935    case PPC_GST_TEXASRU:
   2936       vassert( ty_src == Ity_I32 );
   2937       stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
   2938       break;
   2939 
   2940    case PPC_GST_TFIAR:
   2941       vassert( ty_src == Ity_I64 );
   2942       stmt( IRStmt_Put( OFFB_TFIAR, src ) );
   2943       break;
   2944    case PPC_GST_TFHAR:
   2945       vassert( ty_src == Ity_I64 );
   2946       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
   2947       break;
   2948 
   2949    case PPC_GST_PPR32:
   2950    case PPC_GST_PPR:
   2951       {
   2952          /* The Program Priority Register (PPR) stores the priority in
   2953           * bits [52:50].  The user setable priorities are:
   2954           *
   2955           *    001  very low
   2956           *    010  low
   2957           *    011  medium low
   2958           *    100  medium
   2959           *    101  medium high
   2960           *
   2961           * If the argument is not between 0b001 and 0b100 the priority is set
   2962           * to 0b100.  The priority can only be set to 0b101 if the the Problem
   2963           * State Boost Register is non-zero.  The value of the PPR is not
   2964           * changed if the input is not valid.
   2965           */
   2966 
   2967          IRTemp not_valid = newTemp(Ity_I64);
   2968          IRTemp has_perm = newTemp(Ity_I64);
   2969          IRTemp new_src  = newTemp(Ity_I64);
   2970          IRTemp PSPB_val = newTemp(Ity_I64);
   2971          IRTemp value    = newTemp(Ity_I64);
   2972 
   2973          vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
   2974          assign( PSPB_val, binop( Iop_32HLto64,
   2975                                   mkU32( 0 ),
   2976                                   IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
   2977          if( reg == PPC_GST_PPR32 ) {
   2978             vassert( ty_src == Ity_I32 );
   2979             assign( value, binop( Iop_32HLto64,
   2980                                   mkU32(0),
   2981                                   binop( Iop_And32,
   2982                                          binop( Iop_Shr32, src,  mkU8( 18 ) ),
   2983                                          mkU32( 0x7 ) ) ) );
   2984          } else {
   2985             vassert( ty_src == Ity_I64 );
   2986             assign( value, binop( Iop_And64,
   2987                                   binop( Iop_Shr64, src,  mkU8( 50 ) ),
   2988                                   mkU64( 0x7 ) ) );
   2989          }
   2990          assign( has_perm,
   2991                  binop( Iop_And64,
   2992                         unop( Iop_1Sto64,
   2993                               binop( Iop_CmpEQ64,
   2994                                      mkexpr( PSPB_val ),
   2995                                      mkU64( 0 ) ) ),
   2996                         unop( Iop_1Sto64,
   2997                               binop( Iop_CmpEQ64,
   2998                                      mkU64( 0x5 ),
   2999                                      mkexpr( value ) ) ) ) );
   3000          assign( not_valid,
   3001                  binop( Iop_Or64,
   3002                         unop( Iop_1Sto64,
   3003                               binop( Iop_CmpEQ64,
   3004                                      mkexpr( value ),
   3005                                      mkU64( 0 ) ) ),
   3006                         unop( Iop_1Sto64,
   3007                               binop( Iop_CmpLT64U,
   3008                                      mkU64( 0x5 ),
   3009                                      mkexpr( value ) ) ) ) );
   3010          assign( new_src,
   3011                  binop( Iop_Or64,
   3012                         binop( Iop_And64,
   3013                                unop( Iop_Not64,
   3014                                      mkexpr( not_valid ) ),
   3015                                src ),
   3016                         binop( Iop_And64,
   3017                                mkexpr( not_valid ),
   3018                                binop( Iop_Or64,
   3019                                       binop( Iop_And64,
   3020                                              mkexpr( has_perm),
   3021                                              binop( Iop_Shl64,
   3022                                                     mkexpr( value ),
   3023                                                     mkU8( 50 ) ) ),
   3024                                       binop( Iop_And64,
   3025                                              IRExpr_Get( OFFB_PPR, ty ),
   3026                                              unop( Iop_Not64,
   3027                                                    mkexpr( has_perm )
   3028                                                    ) ) ) ) ) );
   3029 
   3030                  /* make sure we only set the valid bit field [52:50] */
   3031                  stmt( IRStmt_Put( OFFB_PPR,
   3032                                    binop( Iop_And64,
   3033                                           mkexpr( new_src ),
   3034                                           mkU64( 0x1C000000000000) ) ) );
   3035       break;
   3036       }
   3037    default:
   3038       vex_printf("putGST(ppc): reg = %u", reg);
   3039       vpanic("putGST(ppc)");
   3040    }
   3041 }
   3042 
   3043 /* Write masked src to the given reg */
   3044 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
   3045 {
   3046    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   3047    vassert( reg < PPC_GST_MAX );
   3048    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
   3049 
   3050    switch (reg) {
   3051    case PPC_GST_FPSCR: {
   3052       /* Allow writes to either binary or decimal floating point
   3053          Rounding Mode.
   3054       */
   3055       /* If any part of |mask| covers FPSCR.RN, update the bits of
   3056          FPSCR.RN by copying in |src| for locations where the
   3057          corresponding bit in |mask| is 1, and leaving it unchanged
   3058          for corresponding |mask| zero bits. */
   3059       if (mask & MASK_FPSCR_RN) {
   3060          stmt(
   3061             IRStmt_Put(
   3062                OFFB_FPROUND,
   3063                unop(
   3064                   Iop_32to8,
   3065                   binop(
   3066                      Iop_Or32,
   3067                      binop(
   3068                         Iop_And32,
   3069                         unop(Iop_64to32, src),
   3070                         mkU32(MASK_FPSCR_RN & mask)
   3071                      ),
   3072                      binop(
   3073                         Iop_And32,
   3074                         unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
   3075                         mkU32(MASK_FPSCR_RN & ~mask)
   3076                      )
   3077                   )
   3078                )
   3079             )
   3080          );
   3081       }
   3082       /* Similarly, update FPSCR.DRN if any bits of |mask|
   3083          corresponding to FPSCR.DRN are set. */
   3084       if (mask & MASK_FPSCR_DRN) {
   3085          stmt(
   3086             IRStmt_Put(
   3087                OFFB_DFPROUND,
   3088                unop(
   3089                   Iop_32to8,
   3090                   binop(
   3091                      Iop_Or32,
   3092                      binop(
   3093                         Iop_And32,
   3094                         unop(Iop_64HIto32, src),
   3095                         mkU32((MASK_FPSCR_DRN & mask) >> 32)
   3096                      ),
   3097                      binop(
   3098                         Iop_And32,
   3099                         unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
   3100                         mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
   3101                      )
   3102                   )
   3103                )
   3104             )
   3105          );
   3106       }
   3107 
   3108       /* Give EmNote for attempted writes to:
   3109          - Exception Controls
   3110          - Non-IEEE Mode
   3111       */
   3112       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
   3113          VexEmNote ew = EmWarn_PPCexns;
   3114 
   3115          /* If any of the src::exception_control bits are actually set,
   3116             side-exit to the next insn, reporting the warning,
   3117             so that Valgrind's dispatcher sees the warning. */
   3118          putGST( PPC_GST_EMWARN, mkU32(ew) );
   3119          stmt(
   3120             IRStmt_Exit(
   3121                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
   3122                Ijk_EmWarn,
   3123                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   3124       }
   3125 
   3126       /* Ignore all other writes */
   3127       break;
   3128    }
   3129 
   3130    default:
   3131       vex_printf("putGST_masked(ppc): reg = %u", reg);
   3132       vpanic("putGST_masked(ppc)");
   3133    }
   3134 }
   3135 
   3136 /* Write the least significant nibble of src to the specified
   3137    REG[FLD] (as per IBM/hardware notation). */
   3138 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
   3139 {
   3140    UInt shft;
   3141    ULong mask;
   3142 
   3143    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
   3144    vassert( fld < 16 );
   3145    vassert( reg < PPC_GST_MAX );
   3146 
   3147    if (fld < 8)
   3148       shft = 4*(7-fld);
   3149    else
   3150       shft = 4*(15-fld);
   3151    mask = 0xF;
   3152    mask = mask << shft;
   3153 
   3154    switch (reg) {
   3155    case PPC_GST_CR:
   3156       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
   3157       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
   3158       break;
   3159 
   3160    default:
   3161       {
   3162          IRExpr * src64 = unop( Iop_32Uto64, src );
   3163 
   3164          if (shft == 0) {
   3165             putGST_masked( reg, src64, mask );
   3166          } else {
   3167             putGST_masked( reg,
   3168                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
   3169                            mask );
   3170          }
   3171       }
   3172    }
   3173 }
   3174 
   3175 /*------------------------------------------------------------*/
   3176 /* Helpers for VSX instructions that do floating point
   3177  * operations and need to determine if a src contains a
   3178  * special FP value.
   3179  *
   3180  *------------------------------------------------------------*/
   3181 
   3182 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
   3183 #define FP_FRAC_PART(x) binop( Iop_And64, \
   3184                                mkexpr( x ), \
   3185                                mkU64( NONZERO_FRAC_MASK ) )
   3186 
   3187 // Returns exponent part of a single precision floating point as I32
   3188 static IRExpr * fp_exp_part_sp(IRTemp src)
   3189 {
   3190    return binop( Iop_And32,
   3191                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   3192                  mkU32( 0xff ) );
   3193 }
   3194 
   3195 // Returns exponent part of floating point as I32
   3196 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
   3197 {
   3198    IRExpr * exp;
   3199    if (sp)
   3200       return fp_exp_part_sp(src);
   3201 
   3202    if (!mode64)
   3203       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
   3204                                                       mkexpr( src ) ),
   3205                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
   3206    else
   3207       exp = unop( Iop_64to32,
   3208                   binop( Iop_And64,
   3209                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
   3210                          mkU64( 0x7ff ) ) );
   3211    return exp;
   3212 }
   3213 
   3214 static IRExpr * is_Inf_sp(IRTemp src)
   3215 {
   3216    IRTemp frac_part = newTemp(Ity_I32);
   3217    IRExpr * Inf_exp;
   3218 
   3219    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
   3220    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
   3221    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
   3222 }
   3223 
   3224 
   3225 // Infinity: exp = 7ff and fraction is zero; s = 0/1
   3226 static IRExpr * is_Inf(IRTemp src, Bool sp)
   3227 {
   3228    IRExpr * Inf_exp, * hi32, * low32;
   3229    IRTemp frac_part;
   3230 
   3231    if (sp)
   3232       return is_Inf_sp(src);
   3233 
   3234    frac_part = newTemp(Ity_I64);
   3235    assign( frac_part, FP_FRAC_PART(src) );
   3236    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
   3237    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   3238    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   3239    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   3240                                   mkU32( 0 ) ) );
   3241 }
   3242 
   3243 static IRExpr * is_Zero_sp(IRTemp src)
   3244 {
   3245    IRTemp sign_less_part = newTemp(Ity_I32);
   3246    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
   3247    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
   3248 }
   3249 
   3250 // Zero: exp is zero and fraction is zero; s = 0/1
   3251 static IRExpr * is_Zero(IRTemp src, Bool sp)
   3252 {
   3253    IRExpr * hi32, * low32;
   3254    IRTemp sign_less_part;
   3255    if (sp)
   3256       return is_Zero_sp(src);
   3257 
   3258    sign_less_part = newTemp(Ity_I64);
   3259 
   3260    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
   3261    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
   3262    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
   3263    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
   3264                               mkU32( 0 ) );
   3265 }
   3266 
   3267 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
   3268  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
   3269  *  This function returns an IRExpr value of '1' for any type of NaN.
   3270  */
   3271 static IRExpr * is_NaN(IRTemp src)
   3272 {
   3273    IRExpr * NaN_exp, * hi32, * low32;
   3274    IRTemp frac_part = newTemp(Ity_I64);
   3275 
   3276    assign( frac_part, FP_FRAC_PART(src) );
   3277    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   3278    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   3279    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
   3280                     mkU32( 0x7ff ) );
   3281 
   3282    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   3283                                                mkU32( 0 ) ) );
   3284 }
   3285 
   3286 /* This function returns an IRExpr value of '1' for any type of NaN.
   3287  * The passed 'src' argument is assumed to be Ity_I32.
   3288  */
   3289 static IRExpr * is_NaN_32(IRTemp src)
   3290 {
   3291 #define NONZERO_FRAC_MASK32 0x007fffffULL
   3292 #define FP_FRAC_PART32(x) binop( Iop_And32, \
   3293                                  mkexpr( x ), \
   3294                                  mkU32( NONZERO_FRAC_MASK32 ) )
   3295 
   3296    IRExpr * frac_part = FP_FRAC_PART32(src);
   3297    IRExpr * exp_part = binop( Iop_And32,
   3298                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
   3299                               mkU32( 0x0ff ) );
   3300    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
   3301 
   3302    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
   3303 }
   3304 
   3305 /* This function takes an Ity_I32 input argument interpreted
   3306  * as a single-precision floating point value. If src is a
   3307  * SNaN, it is changed to a QNaN and returned; otherwise,
   3308  * the original value is returned.
   3309  */
   3310 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
   3311 {
   3312 #define SNAN_MASK32 0x00400000
   3313    IRTemp tmp = newTemp(Ity_I32);
   3314    IRTemp mask = newTemp(Ity_I32);
   3315    IRTemp is_SNAN = newTemp(Ity_I1);
   3316 
   3317    vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
   3318    assign(tmp, src);
   3319 
   3320    /* check if input is SNaN, if it is convert to QNaN */
   3321    assign( is_SNAN,
   3322            mkAND1( is_NaN_32( tmp ),
   3323                    binop( Iop_CmpEQ32,
   3324                           binop( Iop_And32, mkexpr( tmp ),
   3325                                  mkU32( SNAN_MASK32 ) ),
   3326                           mkU32( 0 ) ) ) );
   3327    /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
   3328    assign ( mask, binop( Iop_And32,
   3329                          unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
   3330                          mkU32( SNAN_MASK32 ) ) );
   3331    return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
   3332 }
   3333 
   3334 
   3335 /* This helper function performs the negation part of operations of the form:
   3336  *    "Negate Multiply-<op>"
   3337  *  where "<op>" is either "Add" or "Sub".
   3338  *
   3339  * This function takes one argument -- the floating point intermediate result (converted to
   3340  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
   3341  * the operation described above.
   3342  */
   3343 static IRTemp getNegatedResult(IRTemp intermediateResult)
   3344 {
   3345    ULong signbit_mask = 0x8000000000000000ULL;
   3346    IRTemp signbit_32 = newTemp(Ity_I32);
   3347    IRTemp resultantSignbit = newTemp(Ity_I1);
   3348    IRTemp negatedResult = newTemp(Ity_I64);
   3349    assign( signbit_32, binop( Iop_Shr32,
   3350                           unop( Iop_64HIto32,
   3351                                  binop( Iop_And64, mkexpr( intermediateResult ),
   3352                                         mkU64( signbit_mask ) ) ),
   3353                                  mkU8( 31 ) ) );
   3354    /* We negate the signbit if and only if the intermediate result from the
   3355     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3356     */
   3357    assign( resultantSignbit,
   3358         unop( Iop_Not1,
   3359               binop( Iop_CmpEQ32,
   3360                      binop( Iop_Xor32,
   3361                             mkexpr( signbit_32 ),
   3362                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
   3363                      mkU32( 1 ) ) ) );
   3364 
   3365    assign( negatedResult,
   3366         binop( Iop_Or64,
   3367                binop( Iop_And64,
   3368                       mkexpr( intermediateResult ),
   3369                       mkU64( ~signbit_mask ) ),
   3370                binop( Iop_32HLto64,
   3371                       binop( Iop_Shl32,
   3372                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3373                              mkU8( 31 ) ),
   3374                       mkU32( 0 ) ) ) );
   3375 
   3376    return negatedResult;
   3377 }
   3378 
   3379 /* This helper function performs the negation part of operations of the form:
   3380  *    "Negate Multiply-<op>"
   3381  *  where "<op>" is either "Add" or "Sub".
   3382  *
   3383  * This function takes one argument -- the floating point intermediate result (converted to
   3384  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
   3385  * the operation described above.
   3386  */
   3387 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
   3388 {
   3389    UInt signbit_mask = 0x80000000;
   3390    IRTemp signbit_32 = newTemp(Ity_I32);
   3391    IRTemp resultantSignbit = newTemp(Ity_I1);
   3392    IRTemp negatedResult = newTemp(Ity_I32);
   3393    assign( signbit_32, binop( Iop_Shr32,
   3394                                  binop( Iop_And32, mkexpr( intermediateResult ),
   3395                                         mkU32( signbit_mask ) ),
   3396                                  mkU8( 31 ) ) );
   3397    /* We negate the signbit if and only if the intermediate result from the
   3398     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
   3399     */
   3400    assign( resultantSignbit,
   3401         unop( Iop_Not1,
   3402               binop( Iop_CmpEQ32,
   3403                      binop( Iop_Xor32,
   3404                             mkexpr( signbit_32 ),
   3405                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
   3406                      mkU32( 1 ) ) ) );
   3407 
   3408    assign( negatedResult,
   3409            binop( Iop_Or32,
   3410                   binop( Iop_And32,
   3411                          mkexpr( intermediateResult ),
   3412                          mkU32( ~signbit_mask ) ),
   3413                   binop( Iop_Shl32,
   3414                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
   3415                          mkU8( 31 ) ) ) );
   3416 
   3417    return negatedResult;
   3418 }
   3419 
   3420 /*------------------------------------------------------------*/
   3421 /* Transactional memory helpers
   3422  *
   3423  *------------------------------------------------------------*/
   3424 
   3425 static ULong generate_TMreason( UInt failure_code,
   3426                                              UInt persistant,
   3427                                              UInt nest_overflow,
   3428                                              UInt tm_exact )
   3429 {
   3430    ULong tm_err_code =
   3431      ( (ULong) 0) << (63-6)   /* Failure code */
   3432      | ( (ULong) persistant) << (63-7)     /* Failure persistant */
   3433      | ( (ULong) 0) << (63-8)   /* Disallowed */
   3434      | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
   3435      | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
   3436      | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
   3437      | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
   3438      | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
   3439      | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
   3440      | ( (ULong) 0) << (63-15)  /* Implementation-specific */
   3441      | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
   3442      | ( (ULong) 0) << (63-30)  /* Reserved */
   3443      | ( (ULong) 0) << (63-31)  /* Abort */
   3444      | ( (ULong) 0) << (63-32)  /* Suspend */
   3445      | ( (ULong) 0) << (63-33)  /* Reserved */
   3446      | ( (ULong) 0) << (63-35)  /* Privilege */
   3447      | ( (ULong) 0) << (63-36)  /* Failure Summary */
   3448      | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
   3449      | ( (ULong) 0) << (63-38)  /* ROT */
   3450      | ( (ULong) 0) << (63-51)  /* Reserved */
   3451      | ( (ULong) 0) << (63-63);  /* Transaction Level */
   3452 
   3453      return tm_err_code;
   3454 }
   3455 
   3456 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
   3457                             Addr64 handler_address )
   3458 {
   3459    putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
   3460    putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
   3461    putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
   3462    putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
   3463 }
   3464 
   3465 /*------------------------------------------------------------*/
   3466 /*--- Integer Instruction Translation                     --- */
   3467 /*------------------------------------------------------------*/
   3468 
   3469 /*
   3470   Integer Arithmetic Instructions
   3471 */
   3472 static Bool dis_int_arith ( UInt theInstr )
   3473 {
   3474    /* D-Form, XO-Form */
   3475    UChar opc1    = ifieldOPC(theInstr);
   3476    UChar rD_addr = ifieldRegDS(theInstr);
   3477    UChar rA_addr = ifieldRegA(theInstr);
   3478    UInt  uimm16  = ifieldUIMM16(theInstr);
   3479    UChar rB_addr = ifieldRegB(theInstr);
   3480    UChar flag_OE = ifieldBIT10(theInstr);
   3481    UInt  opc2    = ifieldOPClo9(theInstr);
   3482    UChar flag_rC = ifieldBIT0(theInstr);
   3483 
   3484    Long   simm16 = extend_s_16to64(uimm16);
   3485    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   3486    IRTemp rA     = newTemp(ty);
   3487    IRTemp rB     = newTemp(ty);
   3488    IRTemp rD     = newTemp(ty);
   3489 
   3490    Bool do_rc = False;
   3491 
   3492    assign( rA, getIReg(rA_addr) );
   3493    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
   3494 
   3495    switch (opc1) {
   3496    /* D-Form */
   3497    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
   3498       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3499       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3500                          mkSzExtendS16(ty, uimm16) ) );
   3501       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3502                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3503                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3504       break;
   3505 
   3506    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
   3507       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3508       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3509                          mkSzExtendS16(ty, uimm16) ) );
   3510       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3511                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3512                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3513       do_rc = True;  // Always record to CR
   3514       flag_rC = 1;
   3515       break;
   3516 
   3517    case 0x0E: // addi   (Add Immediate, PPC32 p350)
   3518       // li rD,val   == addi rD,0,val
   3519       // la disp(rA) == addi rD,rA,disp
   3520       if ( rA_addr == 0 ) {
   3521          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
   3522          assign( rD, mkSzExtendS16(ty, uimm16) );
   3523       } else {
   3524          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3525          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3526                             mkSzExtendS16(ty, uimm16) ) );
   3527       }
   3528       break;
   3529 
   3530    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
   3531       // lis rD,val == addis rD,0,val
   3532       if ( rA_addr == 0 ) {
   3533          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
   3534          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
   3535       } else {
   3536          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
   3537          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3538                             mkSzExtendS32(ty, uimm16 << 16) ) );
   3539       }
   3540       break;
   3541 
   3542    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
   3543       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3544       if (mode64)
   3545          assign( rD, unop(Iop_128to64,
   3546                           binop(Iop_MullS64, mkexpr(rA),
   3547                                 mkSzExtendS16(ty, uimm16))) );
   3548       else
   3549          assign( rD, unop(Iop_64to32,
   3550                           binop(Iop_MullS32, mkexpr(rA),
   3551                                 mkSzExtendS16(ty, uimm16))) );
   3552       break;
   3553 
   3554    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
   3555       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
   3556       // rD = simm16 - rA
   3557       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3558                          mkSzExtendS16(ty, uimm16),
   3559                          mkexpr(rA)) );
   3560       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
   3561                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
   3562                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3563       break;
   3564 
   3565    /* XO-Form */
   3566    case 0x1F:
   3567       do_rc = True;    // All below record to CR
   3568 
   3569       switch (opc2) {
   3570       case 0x10A: // add  (Add, PPC32 p347)
   3571          DIP("add%s%s r%u,r%u,r%u\n",
   3572              flag_OE ? "o" : "", flag_rC ? ".":"",
   3573              rD_addr, rA_addr, rB_addr);
   3574          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3575                             mkexpr(rA), mkexpr(rB) ) );
   3576          if (flag_OE) {
   3577             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3578                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3579          }
   3580          break;
   3581 
   3582       case 0x00A: // addc      (Add Carrying, PPC32 p348)
   3583          DIP("addc%s%s r%u,r%u,r%u\n",
   3584              flag_OE ? "o" : "", flag_rC ? ".":"",
   3585              rD_addr, rA_addr, rB_addr);
   3586          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3587                             mkexpr(rA), mkexpr(rB)) );
   3588          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
   3589                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3590                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3591          if (flag_OE) {
   3592             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
   3593                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3594          }
   3595          break;
   3596 
   3597       case 0x08A: { // adde      (Add Extended, PPC32 p349)
   3598          IRTemp old_xer_ca = newTemp(ty);
   3599          DIP("adde%s%s r%u,r%u,r%u\n",
   3600              flag_OE ? "o" : "", flag_rC ? ".":"",
   3601              rD_addr, rA_addr, rB_addr);
   3602          // rD = rA + rB + XER[CA]
   3603          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3604          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3605                             binop( mkSzOp(ty, Iop_Add8),
   3606                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3607          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3608                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3609                      mkexpr(old_xer_ca) );
   3610          if (flag_OE) {
   3611             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3612                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3613          }
   3614          break;
   3615       }
   3616 
   3617       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
   3618          IRTemp old_xer_ca = newTemp(ty);
   3619          IRExpr *min_one;
   3620          if (rB_addr != 0) {
   3621             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
   3622             return False;
   3623          }
   3624          DIP("addme%s%s r%u,r%u,r%u\n",
   3625              flag_OE ? "o" : "", flag_rC ? ".":"",
   3626              rD_addr, rA_addr, rB_addr);
   3627          // rD = rA + (-1) + XER[CA]
   3628          // => Just another form of adde
   3629          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3630          min_one = mkSzImm(ty, (Long)-1);
   3631          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
   3632                             binop( mkSzOp(ty, Iop_Add8),
   3633                                    min_one, mkexpr(old_xer_ca)) ));
   3634          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3635                      mkexpr(rD), mkexpr(rA), min_one,
   3636                      mkexpr(old_xer_ca) );
   3637          if (flag_OE) {
   3638             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3639                         mkexpr(rD), mkexpr(rA), min_one );
   3640          }
   3641          break;
   3642       }
   3643 
   3644       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
   3645          IRTemp old_xer_ca = newTemp(ty);
   3646          if (rB_addr != 0) {
   3647             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
   3648             return False;
   3649          }
   3650          DIP("addze%s%s r%u,r%u,r%u\n",
   3651              flag_OE ? "o" : "", flag_rC ? ".":"",
   3652              rD_addr, rA_addr, rB_addr);
   3653          // rD = rA + (0) + XER[CA]
   3654          // => Just another form of adde
   3655          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3656          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3657                             mkexpr(rA), mkexpr(old_xer_ca)) );
   3658          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
   3659                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3660                      mkexpr(old_xer_ca) );
   3661          if (flag_OE) {
   3662             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
   3663                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3664          }
   3665          break;
   3666       }
   3667 
   3668       case 0x1EB: // divw       (Divide Word, PPC32 p388)
   3669          DIP("divw%s%s r%u,r%u,r%u\n",
   3670              flag_OE ? "o" : "", flag_rC ? ".":"",
   3671              rD_addr, rA_addr, rB_addr);
   3672          if (mode64) {
   3673             /* Note:
   3674                XER settings are mode independent, and reflect the
   3675                overflow of the low-order 32bit result
   3676                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3677             */
   3678             /* rD[hi32] are undefined: setting them to sign of lo32
   3679                 - makes set_CR0 happy */
   3680             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
   3681             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
   3682             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
   3683                                                          divisor) ) );
   3684             if (flag_OE) {
   3685                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3686                            mkexpr(rD), dividend, divisor );
   3687             }
   3688          } else {
   3689             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
   3690             if (flag_OE) {
   3691                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3692                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3693             }
   3694          }
   3695          /* Note:
   3696             if (0x8000_0000 / -1) or (x / 0)
   3697             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3698             => But _no_ exception raised. */
   3699          break;
   3700 
   3701       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
   3702          DIP("divwu%s%s r%u,r%u,r%u\n",
   3703              flag_OE ? "o" : "", flag_rC ? ".":"",
   3704              rD_addr, rA_addr, rB_addr);
   3705          if (mode64) {
   3706             /* Note:
   3707                XER settings are mode independent, and reflect the
   3708                overflow of the low-order 32bit result
   3709                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
   3710             */
   3711             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
   3712             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
   3713             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
   3714                                                          divisor) ) );
   3715             if (flag_OE) {
   3716                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3717                            mkexpr(rD), dividend, divisor );
   3718             }
   3719          } else {
   3720             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
   3721             if (flag_OE) {
   3722                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3723                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3724             }
   3725          }
   3726          /* Note: ditto comment divw, for (x / 0) */
   3727          break;
   3728 
   3729       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
   3730          if (flag_OE != 0) {
   3731             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
   3732             return False;
   3733          }
   3734          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3735              rD_addr, rA_addr, rB_addr);
   3736          if (mode64) {
   3737             /* rD[hi32] are undefined: setting them to sign of lo32
   3738                 - makes set_CR0 happy */
   3739             assign( rD, binop(Iop_Sar64,
   3740                            binop(Iop_Mul64,
   3741                                  mk64lo32Sto64( mkexpr(rA) ),
   3742                                  mk64lo32Sto64( mkexpr(rB) )),
   3743                               mkU8(32)) );
   3744          } else {
   3745             assign( rD, unop(Iop_64HIto32,
   3746                              binop(Iop_MullS32,
   3747                                    mkexpr(rA), mkexpr(rB))) );
   3748          }
   3749          break;
   3750 
   3751       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
   3752          if (flag_OE != 0) {
   3753             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
   3754             return False;
   3755          }
   3756          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3757              rD_addr, rA_addr, rB_addr);
   3758          if (mode64) {
   3759             /* rD[hi32] are undefined: setting them to sign of lo32
   3760                 - makes set_CR0 happy */
   3761             assign( rD, binop(Iop_Sar64,
   3762                            binop(Iop_Mul64,
   3763                                  mk64lo32Uto64( mkexpr(rA) ),
   3764                                  mk64lo32Uto64( mkexpr(rB) ) ),
   3765                               mkU8(32)) );
   3766          } else {
   3767             assign( rD, unop(Iop_64HIto32,
   3768                              binop(Iop_MullU32,
   3769                                    mkexpr(rA), mkexpr(rB))) );
   3770          }
   3771          break;
   3772 
   3773       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
   3774          DIP("mullw%s%s r%u,r%u,r%u\n",
   3775              flag_OE ? "o" : "", flag_rC ? ".":"",
   3776              rD_addr, rA_addr, rB_addr);
   3777          if (mode64) {
   3778             /* rD[hi32] are undefined: setting them to sign of lo32
   3779                 - set_XER_OV() and set_CR0() depend on this */
   3780             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
   3781             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
   3782             assign( rD, binop(Iop_MullS32, a, b) );
   3783             if (flag_OE) {
   3784                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3785                            mkexpr(rD),
   3786                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
   3787             }
   3788          } else {
   3789             assign( rD, unop(Iop_64to32,
   3790                              binop(Iop_MullU32,
   3791                                    mkexpr(rA), mkexpr(rB))) );
   3792             if (flag_OE) {
   3793                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
   3794                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3795             }
   3796          }
   3797          break;
   3798 
   3799       case 0x068: // neg        (Negate, PPC32 p493)
   3800          if (rB_addr != 0) {
   3801             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
   3802             return False;
   3803          }
   3804          DIP("neg%s%s r%u,r%u\n",
   3805              flag_OE ? "o" : "", flag_rC ? ".":"",
   3806              rD_addr, rA_addr);
   3807          // rD = (~rA) + 1
   3808          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3809                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
   3810                             mkSzImm(ty, 1)) );
   3811          if (flag_OE) {
   3812             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
   3813                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3814          }
   3815          break;
   3816 
   3817       case 0x028: // subf       (Subtract From, PPC32 p537)
   3818          DIP("subf%s%s r%u,r%u,r%u\n",
   3819              flag_OE ? "o" : "", flag_rC ? ".":"",
   3820              rD_addr, rA_addr, rB_addr);
   3821          // rD = rB - rA
   3822          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3823                             mkexpr(rB), mkexpr(rA)) );
   3824          if (flag_OE) {
   3825             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
   3826                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3827          }
   3828          break;
   3829 
   3830       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
   3831          DIP("subfc%s%s r%u,r%u,r%u\n",
   3832              flag_OE ? "o" : "", flag_rC ? ".":"",
   3833              rD_addr, rA_addr, rB_addr);
   3834          // rD = rB - rA
   3835          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
   3836                             mkexpr(rB), mkexpr(rA)) );
   3837          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
   3838                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3839                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
   3840          if (flag_OE) {
   3841             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
   3842                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3843          }
   3844          break;
   3845 
   3846       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
   3847          IRTemp old_xer_ca = newTemp(ty);
   3848          DIP("subfe%s%s r%u,r%u,r%u\n",
   3849              flag_OE ? "o" : "", flag_rC ? ".":"",
   3850              rD_addr, rA_addr, rB_addr);
   3851          // rD = (log not)rA + rB + XER[CA]
   3852          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3853          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3854                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3855                             binop( mkSzOp(ty, Iop_Add8),
   3856                                    mkexpr(rB), mkexpr(old_xer_ca))) );
   3857          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3858                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
   3859                      mkexpr(old_xer_ca) );
   3860          if (flag_OE) {
   3861             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3862                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3863          }
   3864          break;
   3865       }
   3866 
   3867       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
   3868          IRTemp old_xer_ca = newTemp(ty);
   3869          IRExpr *min_one;
   3870          if (rB_addr != 0) {
   3871             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
   3872             return False;
   3873          }
   3874          DIP("subfme%s%s r%u,r%u\n",
   3875              flag_OE ? "o" : "", flag_rC ? ".":"",
   3876              rD_addr, rA_addr);
   3877          // rD = (log not)rA + (-1) + XER[CA]
   3878          // => Just another form of subfe
   3879          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3880          min_one = mkSzImm(ty, (Long)-1);
   3881          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3882                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
   3883                             binop( mkSzOp(ty, Iop_Add8),
   3884                                    min_one, mkexpr(old_xer_ca))) );
   3885          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3886                      mkexpr(rD), mkexpr(rA), min_one,
   3887                      mkexpr(old_xer_ca) );
   3888          if (flag_OE) {
   3889             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3890                         mkexpr(rD), mkexpr(rA), min_one );
   3891          }
   3892          break;
   3893       }
   3894 
   3895       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
   3896          IRTemp old_xer_ca = newTemp(ty);
   3897          if (rB_addr != 0) {
   3898             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
   3899             return False;
   3900          }
   3901          DIP("subfze%s%s r%u,r%u\n",
   3902              flag_OE ? "o" : "", flag_rC ? ".":"",
   3903              rD_addr, rA_addr);
   3904          // rD = (log not)rA + (0) + XER[CA]
   3905          // => Just another form of subfe
   3906          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
   3907          assign( rD, binop( mkSzOp(ty, Iop_Add8),
   3908                            unop( mkSzOp(ty, Iop_Not8),
   3909                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
   3910          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
   3911                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
   3912                      mkexpr(old_xer_ca) );
   3913          if (flag_OE) {
   3914             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
   3915                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
   3916          }
   3917          break;
   3918       }
   3919 
   3920 
   3921       /* 64bit Arithmetic */
   3922       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
   3923          if (flag_OE != 0) {
   3924             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
   3925             return False;
   3926          }
   3927          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3928              rD_addr, rA_addr, rB_addr);
   3929          assign( rD, unop(Iop_128HIto64,
   3930                           binop(Iop_MullS64,
   3931                                 mkexpr(rA), mkexpr(rB))) );
   3932 
   3933          break;
   3934 
   3935       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
   3936          if (flag_OE != 0) {
   3937             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
   3938             return False;
   3939          }
   3940          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   3941              rD_addr, rA_addr, rB_addr);
   3942          assign( rD, unop(Iop_128HIto64,
   3943                           binop(Iop_MullU64,
   3944                                 mkexpr(rA), mkexpr(rB))) );
   3945          break;
   3946 
   3947       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
   3948          DIP("mulld%s%s r%u,r%u,r%u\n",
   3949              flag_OE ? "o" : "", flag_rC ? ".":"",
   3950              rD_addr, rA_addr, rB_addr);
   3951          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
   3952          if (flag_OE) {
   3953             set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
   3954                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3955          }
   3956          break;
   3957 
   3958       case 0x1E9: // divd (Divide DWord, PPC64 p419)
   3959          DIP("divd%s%s r%u,r%u,r%u\n",
   3960              flag_OE ? "o" : "", flag_rC ? ".":"",
   3961              rD_addr, rA_addr, rB_addr);
   3962          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
   3963          if (flag_OE) {
   3964             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
   3965                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3966          }
   3967          break;
   3968          /* Note:
   3969             if (0x8000_0000_0000_0000 / -1) or (x / 0)
   3970             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
   3971             => But _no_ exception raised. */
   3972 
   3973       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
   3974          DIP("divdu%s%s r%u,r%u,r%u\n",
   3975              flag_OE ? "o" : "", flag_rC ? ".":"",
   3976              rD_addr, rA_addr, rB_addr);
   3977          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
   3978          if (flag_OE) {
   3979             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
   3980                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
   3981          }
   3982          break;
   3983          /* Note: ditto comment divd, for (x / 0) */
   3984 
   3985       case 0x18B: // divweu (Divide Word Extended Unsigned)
   3986       {
   3987         /*
   3988          *  If (RA) >= (RB), or if an attempt is made to perform the division
   3989          *         <anything> / 0
   3990          * then the contents of register RD are undefined as are (if Rc=1) the contents of
   3991          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
   3992          * to 1.
   3993          */
   3994          IRTemp res = newTemp(Ity_I32);
   3995          IRExpr * dividend, * divisor;
   3996          DIP("divweu%s%s r%u,r%u,r%u\n",
   3997              flag_OE ? "o" : "", flag_rC ? ".":"",
   3998                                          rD_addr, rA_addr, rB_addr);
   3999          if (mode64) {
   4000             dividend = unop( Iop_64to32, mkexpr( rA ) );
   4001             divisor = unop( Iop_64to32, mkexpr( rB ) );
   4002             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   4003             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   4004          } else {
   4005             dividend = mkexpr( rA );
   4006             divisor =  mkexpr( rB );
   4007             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
   4008             assign( rD, mkexpr( res) );
   4009          }
   4010 
   4011          if (flag_OE) {
   4012             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
   4013                            mkexpr(res), dividend, divisor );
   4014          }
   4015          break;
   4016       }
   4017 
   4018       case 0x1AB: // divwe (Divide Word Extended)
   4019       {
   4020          /*
   4021           * If the quotient cannot be represented in 32 bits, or if an
   4022           * attempt is made to perform the division
   4023           *      <anything> / 0
   4024           * then the contents of register RD are undefined as are (if
   4025           * Rc=1) the contents of the LT, GT, and EQ bits of CR
   4026           * Field 0. In these cases, if OE=1 then OV is set to 1.
   4027           */
   4028 
   4029          IRTemp res = newTemp(Ity_I32);
   4030          IRExpr * dividend, * divisor;
   4031          DIP("divwe%s%s r%u,r%u,r%u\n",
   4032              flag_OE ? "o" : "", flag_rC ? ".":"",
   4033                                          rD_addr, rA_addr, rB_addr);
   4034          if (mode64) {
   4035             dividend = unop( Iop_64to32, mkexpr( rA ) );
   4036             divisor = unop( Iop_64to32, mkexpr( rB ) );
   4037             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   4038             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
   4039          } else {
   4040             dividend = mkexpr( rA );
   4041             divisor =  mkexpr( rB );
   4042             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
   4043             assign( rD, mkexpr( res) );
   4044          }
   4045 
   4046          if (flag_OE) {
   4047             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
   4048                            mkexpr(res), dividend, divisor );
   4049          }
   4050          break;
   4051       }
   4052 
   4053 
   4054       case 0x1A9: // divde (Divide Doubleword Extended)
   4055         /*
   4056          * If the quotient cannot be represented in 64 bits, or if an
   4057          * attempt is made to perform the division
   4058          *      <anything> / 0
   4059          * then the contents of register RD are undefined as are (if
   4060          * Rc=1) the contents of the LT, GT, and EQ bits of CR
   4061          * Field 0. In these cases, if OE=1 then OV is set to 1.
   4062          */
   4063          DIP("divde%s%s r%u,r%u,r%u\n",
   4064              flag_OE ? "o" : "", flag_rC ? ".":"",
   4065              rD_addr, rA_addr, rB_addr);
   4066          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
   4067          if (flag_OE) {
   4068             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
   4069                            mkexpr( rA ), mkexpr( rB ) );
   4070          }
   4071          break;
   4072 
   4073       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
   4074         // Same CR and OV rules as given for divweu above
   4075         DIP("divdeu%s%s r%u,r%u,r%u\n",
   4076             flag_OE ? "o" : "", flag_rC ? ".":"",
   4077             rD_addr, rA_addr, rB_addr);
   4078         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
   4079         if (flag_OE) {
   4080            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
   4081                           mkexpr( rA ), mkexpr( rB ) );
   4082         }
   4083         break;
   4084 
   4085       default:
   4086          vex_printf("dis_int_arith(ppc)(opc2)\n");
   4087          return False;
   4088       }
   4089       break;
   4090 
   4091    default:
   4092       vex_printf("dis_int_arith(ppc)(opc1)\n");
   4093       return False;
   4094    }
   4095 
   4096    putIReg( rD_addr, mkexpr(rD) );
   4097 
   4098    if (do_rc && flag_rC) {
   4099       set_CR0( mkexpr(rD) );
   4100    }
   4101    return True;
   4102 }
   4103 
   4104 
   4105 
   4106 /*
   4107   Integer Compare Instructions
   4108 */
   4109 static Bool dis_int_cmp ( UInt theInstr )
   4110 {
   4111    /* D-Form, X-Form */
   4112    UChar opc1    = ifieldOPC(theInstr);
   4113    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   4114    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
   4115    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
   4116    UChar rA_addr = ifieldRegA(theInstr);
   4117    UInt  uimm16  = ifieldUIMM16(theInstr);
   4118    UChar rB_addr = ifieldRegB(theInstr);
   4119    UInt  opc2    = ifieldOPClo10(theInstr);
   4120    UChar b0      = ifieldBIT0(theInstr);
   4121 
   4122    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   4123    IRExpr *a = getIReg(rA_addr);
   4124    IRExpr *b;
   4125 
   4126    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
   4127       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
   4128       return False;
   4129    }
   4130 
   4131    if (b22 != 0) {
   4132       vex_printf("dis_int_cmp(ppc)(b22)\n");
   4133       return False;
   4134    }
   4135 
   4136    switch (opc1) {
   4137    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
   4138       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
   4139           (Int)extend_s_16to32(uimm16));
   4140       b = mkSzExtendS16( ty, uimm16 );
   4141       if (flag_L == 1) {
   4142          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   4143       } else {
   4144          a = mkNarrowTo32( ty, a );
   4145          b = mkNarrowTo32( ty, b );
   4146          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
   4147       }
   4148       putCR0( crfD, getXER_SO() );
   4149       break;
   4150 
   4151    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
   4152       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
   4153       b = mkSzImm( ty, uimm16 );
   4154       if (flag_L == 1) {
   4155          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   4156       } else {
   4157          a = mkNarrowTo32( ty, a );
   4158          b = mkNarrowTo32( ty, b );
   4159          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   4160       }
   4161       putCR0( crfD, getXER_SO() );
   4162       break;
   4163 
   4164    /* X Form */
   4165    case 0x1F:
   4166       if (b0 != 0) {
   4167          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
   4168          return False;
   4169       }
   4170       b = getIReg(rB_addr);
   4171 
   4172       switch (opc2) {
   4173       case 0x000: // cmp (Compare, PPC32 p367)
   4174          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   4175          /* Comparing a reg with itself produces a result which
   4176             doesn't depend on the contents of the reg.  Therefore
   4177             remove the false dependency, which has been known to cause
   4178             memcheck to produce false errors. */
   4179          if (rA_addr == rB_addr)
   4180             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   4181                     ? mkU64(0)  : mkU32(0);
   4182          if (flag_L == 1) {
   4183             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
   4184          } else {
   4185             a = mkNarrowTo32( ty, a );
   4186             b = mkNarrowTo32( ty, b );
   4187             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
   4188          }
   4189          putCR0( crfD, getXER_SO() );
   4190          break;
   4191 
   4192       case 0x020: // cmpl (Compare Logical, PPC32 p369)
   4193          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
   4194          /* Comparing a reg with itself produces a result which
   4195             doesn't depend on the contents of the reg.  Therefore
   4196             remove the false dependency, which has been known to cause
   4197             memcheck to produce false errors. */
   4198          if (rA_addr == rB_addr)
   4199             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
   4200                     ? mkU64(0)  : mkU32(0);
   4201          if (flag_L == 1) {
   4202             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
   4203          } else {
   4204             a = mkNarrowTo32( ty, a );
   4205             b = mkNarrowTo32( ty, b );
   4206             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
   4207          }
   4208          putCR0( crfD, getXER_SO() );
   4209          break;
   4210 
   4211       default:
   4212          vex_printf("dis_int_cmp(ppc)(opc2)\n");
   4213          return False;
   4214       }
   4215       break;
   4216 
   4217    default:
   4218       vex_printf("dis_int_cmp(ppc)(opc1)\n");
   4219       return False;
   4220    }
   4221 
   4222    return True;
   4223 }
   4224 
   4225 
   4226 /*
   4227   Integer Logical Instructions
   4228 */
   4229 static Bool dis_int_logic ( UInt theInstr )
   4230 {
   4231    /* D-Form, X-Form */
   4232    UChar opc1    = ifieldOPC(theInstr);
   4233    UChar rS_addr = ifieldRegDS(theInstr);
   4234    UChar rA_addr = ifieldRegA(theInstr);
   4235    UInt  uimm16  = ifieldUIMM16(theInstr);
   4236    UChar rB_addr = ifieldRegB(theInstr);
   4237    UInt  opc2    = ifieldOPClo10(theInstr);
   4238    UChar flag_rC = ifieldBIT0(theInstr);
   4239 
   4240    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4241    IRTemp rS     = newTemp(ty);
   4242    IRTemp rA     = newTemp(ty);
   4243    IRTemp rB     = newTemp(ty);
   4244    IRExpr* irx;
   4245    Bool do_rc    = False;
   4246 
   4247    assign( rS, getIReg(rS_addr) );
   4248    assign( rB, getIReg(rB_addr) );
   4249 
   4250    switch (opc1) {
   4251    case 0x1C: // andi. (AND Immediate, PPC32 p358)
   4252       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4253       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4254                          mkSzImm(ty, uimm16)) );
   4255       do_rc = True;  // Always record to CR
   4256       flag_rC = 1;
   4257       break;
   4258 
   4259    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
   4260       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4261       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4262                          mkSzImm(ty, uimm16 << 16)) );
   4263       do_rc = True;  // Always record to CR
   4264       flag_rC = 1;
   4265       break;
   4266 
   4267    case 0x18: // ori (OR Immediate, PPC32 p497)
   4268       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4269       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4270                          mkSzImm(ty, uimm16)) );
   4271       break;
   4272 
   4273    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
   4274       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4275       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4276                          mkSzImm(ty, uimm16 << 16)) );
   4277       break;
   4278 
   4279    case 0x1A: // xori (XOR Immediate, PPC32 p550)
   4280       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4281       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4282                          mkSzImm(ty, uimm16)) );
   4283       break;
   4284 
   4285    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
   4286       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
   4287       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
   4288                          mkSzImm(ty, uimm16 << 16)) );
   4289       break;
   4290 
   4291    /* X Form */
   4292    case 0x1F:
   4293       do_rc = True; // All below record to CR, except for where we return at case end.
   4294 
   4295       switch (opc2) {
   4296       case 0x01C: // and (AND, PPC32 p356)
   4297          DIP("and%s r%u,r%u,r%u\n",
   4298              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4299          assign(rA, binop( mkSzOp(ty, Iop_And8),
   4300                            mkexpr(rS), mkexpr(rB)));
   4301          break;
   4302 
   4303       case 0x03C: // andc (AND with Complement, PPC32 p357)
   4304          DIP("andc%s r%u,r%u,r%u\n",
   4305              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4306          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
   4307                            unop( mkSzOp(ty, Iop_Not8),
   4308                                  mkexpr(rB))));
   4309          break;
   4310 
   4311       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
   4312          IRExpr* lo32;
   4313          if (rB_addr!=0) {
   4314             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
   4315             return False;
   4316          }
   4317          DIP("cntlzw%s r%u,r%u\n",
   4318              flag_rC ? ".":"", rA_addr, rS_addr);
   4319 
   4320          // mode64: count in low word only
   4321          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
   4322 
   4323          // Iop_Clz32 undefined for arg==0, so deal with that case:
   4324          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
   4325          assign(rA, mkWidenFrom32(ty,
   4326                          IRExpr_ITE( irx,
   4327                                      unop(Iop_Clz32, lo32),
   4328                                      mkU32(32)),
   4329                          False));
   4330 
   4331          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
   4332          break;
   4333       }
   4334 
   4335       case 0x11C: // eqv (Equivalent, PPC32 p396)
   4336          DIP("eqv%s r%u,r%u,r%u\n",
   4337              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4338          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4339                            binop( mkSzOp(ty, Iop_Xor8),
   4340                                   mkexpr(rS), mkexpr(rB))) );
   4341          break;
   4342 
   4343       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
   4344          if (rB_addr!=0) {
   4345             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
   4346             return False;
   4347          }
   4348          DIP("extsb%s r%u,r%u\n",
   4349              flag_rC ? ".":"", rA_addr, rS_addr);
   4350          if (mode64)
   4351             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
   4352          else
   4353             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
   4354          break;
   4355 
   4356       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
   4357          if (rB_addr!=0) {
   4358             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
   4359             return False;
   4360          }
   4361          DIP("extsh%s r%u,r%u\n",
   4362              flag_rC ? ".":"", rA_addr, rS_addr);
   4363          if (mode64)
   4364             assign( rA, unop(Iop_16Sto64,
   4365                              unop(Iop_64to16, mkexpr(rS))) );
   4366          else
   4367             assign( rA, unop(Iop_16Sto32,
   4368                              unop(Iop_32to16, mkexpr(rS))) );
   4369          break;
   4370 
   4371       case 0x1DC: // nand (NAND, PPC32 p492)
   4372          DIP("nand%s r%u,r%u,r%u\n",
   4373              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4374          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4375                            binop( mkSzOp(ty, Iop_And8),
   4376                                   mkexpr(rS), mkexpr(rB))) );
   4377          break;
   4378 
   4379       case 0x07C: // nor (NOR, PPC32 p494)
   4380          DIP("nor%s r%u,r%u,r%u\n",
   4381              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4382          assign( rA, unop( mkSzOp(ty, Iop_Not8),
   4383                            binop( mkSzOp(ty, Iop_Or8),
   4384                                   mkexpr(rS), mkexpr(rB))) );
   4385          break;
   4386 
   4387       case 0x1BC: // or (OR, PPC32 p495)
   4388          if ((!flag_rC) && rS_addr == rB_addr) {
   4389             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
   4390             assign( rA, mkexpr(rS) );
   4391          } else {
   4392             DIP("or%s r%u,r%u,r%u\n",
   4393                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4394             assign( rA, binop( mkSzOp(ty, Iop_Or8),
   4395                                mkexpr(rS), mkexpr(rB)) );
   4396          }
   4397          break;
   4398 
   4399       case 0x19C: // orc  (OR with Complement, PPC32 p496)
   4400          DIP("orc%s r%u,r%u,r%u\n",
   4401              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4402          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
   4403                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
   4404          break;
   4405 
   4406       case 0x13C: // xor (XOR, PPC32 p549)
   4407          DIP("xor%s r%u,r%u,r%u\n",
   4408              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   4409          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
   4410                             mkexpr(rS), mkexpr(rB)) );
   4411          break;
   4412 
   4413 
   4414       /* 64bit Integer Logical Instructions */
   4415       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
   4416          if (rB_addr!=0) {
   4417             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
   4418             return False;
   4419          }
   4420          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
   4421          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
   4422          break;
   4423 
   4424       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
   4425          if (rB_addr!=0) {
   4426             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
   4427             return False;
   4428          }
   4429          DIP("cntlzd%s r%u,r%u\n",
   4430              flag_rC ? ".":"", rA_addr, rS_addr);
   4431          // Iop_Clz64 undefined for arg==0, so deal with that case:
   4432          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
   4433          assign(rA, IRExpr_ITE( irx,
   4434                                 unop(Iop_Clz64, mkexpr(rS)),
   4435                                 mkU64(64) ));
   4436          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
   4437          break;
   4438 
   4439       case 0x1FC: // cmpb (Power6: compare bytes)
   4440          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4441 
   4442          if (mode64)
   4443             assign( rA, unop( Iop_V128to64,
   4444                               binop( Iop_CmpEQ8x16,
   4445                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
   4446                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
   4447                                      )) );
   4448          else
   4449             assign( rA, unop( Iop_V128to32,
   4450                               binop( Iop_CmpEQ8x16,
   4451                                      unop( Iop_32UtoV128, mkexpr(rS) ),
   4452                                      unop( Iop_32UtoV128, mkexpr(rB) )
   4453                                      )) );
   4454          break;
   4455 
   4456       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
   4457          IRTemp frB = newTemp(Ity_F64);
   4458          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
   4459 
   4460          assign( frB, getFReg(rB_addr));  // always F64
   4461          if (mode64)
   4462             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   4463          else
   4464             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
   4465 
   4466          putIReg( rS_addr, mkexpr(rA));
   4467          return True;
   4468       }
   4469 
   4470       case 0x25F: { // mffgpr (move floating-point from general purpose register)
   4471          IRTemp frA = newTemp(Ity_F64);
   4472          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
   4473 
   4474          if (mode64)
   4475             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
   4476          else
   4477             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
   4478 
   4479          putFReg( rS_addr, mkexpr(frA));
   4480          return True;
   4481       }
   4482       case 0x1FA: // popcntd (population count doubleword
   4483       {
   4484     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
   4485     	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
   4486     	  putIReg( rA_addr, mkexpr(result) );
   4487     	  return True;
   4488       }
   4489       case 0x17A: // popcntw (Population Count Words)
   4490       {
   4491          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
   4492          if (mode64) {
   4493             IRTemp resultHi, resultLo;
   4494             IRTemp argLo = newTemp(Ity_I32);
   4495             IRTemp argHi = newTemp(Ity_I32);
   4496             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4497             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4498             resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
   4499             resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
   4500             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
   4501          } else {
   4502             IRTemp result = gen_POPCOUNT(ty, rS, WORD);
   4503             putIReg( rA_addr, mkexpr(result) );
   4504          }
   4505          return True;
   4506       }
   4507       case 0x7A: // popcntb (Population Count Byte)
   4508       {
   4509          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
   4510 
   4511          if (mode64) {
   4512             IRTemp resultHi, resultLo;
   4513             IRTemp argLo = newTemp(Ity_I32);
   4514             IRTemp argHi = newTemp(Ity_I32);
   4515             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
   4516             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
   4517             resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
   4518             resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
   4519             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
   4520                                     mkexpr(resultLo)));
   4521          } else {
   4522             IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
   4523             putIReg( rA_addr, mkexpr(result) );
   4524          }
   4525          return True;
   4526       }
   4527        case 0x0FC: // bpermd (Bit Permute Doubleword)
   4528        {
   4529           /* This is a lot of rigmarole to emulate bpermd like this, as it
   4530            * could be done much faster by implementing a call to the native
   4531            * instruction.  However, where possible I want to avoid using new
   4532            * native instructions so that we can use valgrind to emulate those
   4533            * instructions on older PPC64 hardware.
   4534            */
   4535  #define BPERMD_IDX_MASK 0x00000000000000FFULL
   4536  #define BPERMD_BIT_MASK 0x8000000000000000ULL
   4537           int i;
   4538           IRExpr * rS_expr = mkexpr(rS);
   4539           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
   4540           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
   4541           for (i = 0; i < 8; i++) {
   4542              IRTemp idx_tmp = newTemp( Ity_I64 );
   4543              IRTemp perm_bit = newTemp( Ity_I64 );
   4544              IRTemp idx = newTemp( Ity_I8 );
   4545              IRTemp idx_LT64 = newTemp( Ity_I1 );
   4546              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
   4547 
   4548              assign( idx_tmp,
   4549                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
   4550              assign( idx_LT64,
   4551                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
   4552              assign( idx,
   4553                            binop( Iop_And8,
   4554                                   unop( Iop_1Sto8,
   4555                                         mkexpr(idx_LT64) ),
   4556                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
   4557              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
   4558               * to determine which bit of rB to use for the perm bit, and then we shift
   4559               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
   4560               * to set the final perm bit.
   4561               */
   4562              assign( idx_LT64_ity64,
   4563                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
   4564              assign( perm_bit,
   4565                            binop( Iop_And64,
   4566                                   mkexpr( idx_LT64_ity64 ),
   4567                                   binop( Iop_Shr64,
   4568                                          binop( Iop_And64,
   4569                                                 mkU64( BPERMD_BIT_MASK ),
   4570                                                 binop( Iop_Shl64,
   4571                                                        mkexpr( rB ),
   4572                                                        mkexpr( idx ) ) ),
   4573                                          mkU8( 63 ) ) ) );
   4574              res = binop( Iop_Or64,
   4575                                 res,
   4576                                 binop( Iop_Shl64,
   4577                                        mkexpr( perm_bit ),
   4578                                        mkU8( i ) ) );
   4579              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
   4580           }
   4581           putIReg(rA_addr, res);
   4582           return True;
   4583        }
   4584 
   4585       default:
   4586          vex_printf("dis_int_logic(ppc)(opc2)\n");
   4587          return False;
   4588       }
   4589       break;
   4590 
   4591    default:
   4592       vex_printf("dis_int_logic(ppc)(opc1)\n");
   4593       return False;
   4594    }
   4595 
   4596    putIReg( rA_addr, mkexpr(rA) );
   4597 
   4598    if (do_rc && flag_rC) {
   4599       set_CR0( mkexpr(rA) );
   4600    }
   4601    return True;
   4602 }
   4603 
   4604 /*
   4605   Integer Parity Instructions
   4606 */
   4607 static Bool dis_int_parity ( UInt theInstr )
   4608 {
   4609    /* X-Form */
   4610    UChar opc1    = ifieldOPC(theInstr);
   4611    UChar rS_addr = ifieldRegDS(theInstr);
   4612    UChar rA_addr = ifieldRegA(theInstr);
   4613    UChar rB_addr = ifieldRegB(theInstr);
   4614    UInt  opc2    = ifieldOPClo10(theInstr);
   4615    UChar b0      = ifieldBIT0(theInstr);
   4616    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4617 
   4618    IRTemp rS     = newTemp(ty);
   4619    IRTemp rA     = newTemp(ty);
   4620    IRTemp iTot1  = newTemp(Ity_I32);
   4621    IRTemp iTot2  = newTemp(Ity_I32);
   4622    IRTemp iTot3  = newTemp(Ity_I32);
   4623    IRTemp iTot4  = newTemp(Ity_I32);
   4624    IRTemp iTot5  = newTemp(Ity_I32);
   4625    IRTemp iTot6  = newTemp(Ity_I32);
   4626    IRTemp iTot7  = newTemp(Ity_I32);
   4627    IRTemp iTot8  = newTemp(Ity_I32);
   4628    IRTemp rS1    = newTemp(ty);
   4629    IRTemp rS2    = newTemp(ty);
   4630    IRTemp rS3    = newTemp(ty);
   4631    IRTemp rS4    = newTemp(ty);
   4632    IRTemp rS5    = newTemp(ty);
   4633    IRTemp rS6    = newTemp(ty);
   4634    IRTemp rS7    = newTemp(ty);
   4635    IRTemp iHi    = newTemp(Ity_I32);
   4636    IRTemp iLo    = newTemp(Ity_I32);
   4637    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
   4638    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
   4639 
   4640    if (opc1 != 0x1f || rB_addr || b0) {
   4641       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
   4642       return False;
   4643    }
   4644 
   4645    assign( rS, getIReg(rS_addr) );
   4646 
   4647    switch (opc2) {
   4648    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
   4649       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
   4650       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4651       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4652       assign( iTot2, binop(Iop_Add32,
   4653                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4654                            mkexpr(iTot1)) );
   4655       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4656       assign( iTot3, binop(Iop_Add32,
   4657                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4658                            mkexpr(iTot2)) );
   4659       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4660       assign( iTot4, binop(Iop_Add32,
   4661                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4662                            mkexpr(iTot3)) );
   4663       if (mode64) {
   4664          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4665          assign( iTot5, binop(Iop_Add32,
   4666                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
   4667                               mkexpr(iTot4)) );
   4668          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4669          assign( iTot6, binop(Iop_Add32,
   4670                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4671                               mkexpr(iTot5)) );
   4672          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4673          assign( iTot7, binop(Iop_Add32,
   4674                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4675                               mkexpr(iTot6)) );
   4676          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
   4677          assign( iTot8, binop(Iop_Add32,
   4678                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4679                               mkexpr(iTot7)) );
   4680          assign( rA, unop(Iop_32Uto64,
   4681                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
   4682       } else
   4683          assign( rA, mkexpr(iTot4) );
   4684 
   4685       break;
   4686    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
   4687       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
   4688       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
   4689       assign( iTot2, binop(Iop_Add32,
   4690                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
   4691                            mkexpr(iTot1)) );
   4692       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
   4693       assign( iTot3, binop(Iop_Add32,
   4694                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
   4695                            mkexpr(iTot2)) );
   4696       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
   4697       assign( iTot4, binop(Iop_Add32,
   4698                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
   4699                            mkexpr(iTot3)) );
   4700       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
   4701 
   4702       if (mode64) {
   4703          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
   4704          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
   4705          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
   4706          assign( iTot6, binop(Iop_Add32,
   4707                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
   4708                               mkexpr(iTot5)) );
   4709          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
   4710          assign( iTot7, binop(Iop_Add32,
   4711                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
   4712                               mkexpr(iTot6)) );
   4713          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
   4714          assign( iTot8, binop(Iop_Add32,
   4715                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
   4716                               mkexpr(iTot7)) );
   4717          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
   4718             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
   4719       } else
   4720          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
   4721       break;
   4722    default:
   4723       vex_printf("dis_int_parity(ppc)(opc2)\n");
   4724       return False;
   4725    }
   4726 
   4727    putIReg( rA_addr, mkexpr(rA) );
   4728 
   4729    return True;
   4730 }
   4731 
   4732 
   4733 /*
   4734   Integer Rotate Instructions
   4735 */
   4736 static Bool dis_int_rot ( UInt theInstr )
   4737 {
   4738    /* M-Form, MDS-Form */
   4739    UChar opc1    = ifieldOPC(theInstr);
   4740    UChar rS_addr = ifieldRegDS(theInstr);
   4741    UChar rA_addr = ifieldRegA(theInstr);
   4742    UChar rB_addr = ifieldRegB(theInstr);
   4743    UChar sh_imm  = rB_addr;
   4744    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
   4745    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
   4746    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
   4747    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
   4748    UChar b1      = ifieldBIT1(theInstr);
   4749    UChar flag_rC = ifieldBIT0(theInstr);
   4750 
   4751    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   4752    IRTemp rS     = newTemp(ty);
   4753    IRTemp rA     = newTemp(ty);
   4754    IRTemp rB     = newTemp(ty);
   4755    IRTemp rot    = newTemp(ty);
   4756    IRExpr *r;
   4757    UInt   mask32;
   4758    ULong  mask64;
   4759 
   4760    assign( rS, getIReg(rS_addr) );
   4761    assign( rB, getIReg(rB_addr) );
   4762 
   4763    switch (opc1) {
   4764    case 0x14: {
   4765       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
   4766       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4767           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4768       if (mode64) {
   4769          // tmp32 = (ROTL(rS_Lo32, Imm)
   4770          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
   4771          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4772          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4773          r = unop(Iop_32Uto64, r);
   4774          assign( rot, binop(Iop_Or64, r,
   4775                             binop(Iop_Shl64, r, mkU8(32))) );
   4776          assign( rA,
   4777             binop(Iop_Or64,
   4778                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
   4779                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
   4780       }
   4781       else {
   4782          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
   4783          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4784          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4785          assign( rA,
   4786             binop(Iop_Or32,
   4787                   binop(Iop_And32, mkU32(mask32), r),
   4788                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
   4789       }
   4790       break;
   4791    }
   4792 
   4793    case 0x15: {
   4794       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
   4795       vassert(MaskBeg < 32);
   4796       vassert(MaskEnd < 32);
   4797       vassert(sh_imm  < 32);
   4798 
   4799       if (mode64) {
   4800          IRTemp rTmp = newTemp(Ity_I64);
   4801          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4802          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4803              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4804          // tmp32 = (ROTL(rS_Lo32, Imm)
   4805          // rA = ((tmp32 || tmp32) & mask64)
   4806          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
   4807          r = unop(Iop_32Uto64, r);
   4808          assign( rTmp, r );
   4809          r = NULL;
   4810          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
   4811                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
   4812          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4813       }
   4814       else {
   4815          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
   4816             /* Special-case the ,n,0,31-n form as that is just n-bit
   4817                shift left, PPC32 p501 */
   4818             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4819                 rA_addr, rS_addr, sh_imm);
   4820             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
   4821          }
   4822          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
   4823             /* Special-case the ,32-n,n,31 form as that is just n-bit
   4824                unsigned shift right, PPC32 p501 */
   4825             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   4826                 rA_addr, rS_addr, MaskBeg);
   4827             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
   4828          }
   4829          else {
   4830             /* General case. */
   4831             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4832             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
   4833                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
   4834             // rA = ROTL(rS, Imm) & mask
   4835             assign( rA, binop(Iop_And32,
   4836                               ROTL(mkexpr(rS), mkU8(sh_imm)),
   4837                               mkU32(mask32)) );
   4838          }
   4839       }
   4840       break;
   4841    }
   4842 
   4843    case 0x17: {
   4844       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
   4845       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
   4846           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
   4847       if (mode64) {
   4848          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
   4849          /* weird insn alert!
   4850             tmp32 = (ROTL(rS_Lo32, rB[0-4])
   4851             rA = ((tmp32 || tmp32) & mask64)
   4852          */
   4853          // note, ROTL does the masking, so we don't do it here
   4854          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
   4855                    unop(Iop_64to8, mkexpr(rB)) );
   4856          r = unop(Iop_32Uto64, r);
   4857          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
   4858          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
   4859       } else {
   4860          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
   4861          // rA = ROTL(rS, rB[0-4]) & mask
   4862          // note, ROTL does the masking, so we don't do it here
   4863          assign( rA, binop(Iop_And32,
   4864                            ROTL(mkexpr(rS),
   4865                                 unop(Iop_32to8, mkexpr(rB))),
   4866                            mkU32(mask32)) );
   4867       }
   4868       break;
   4869    }
   4870 
   4871    /* 64bit Integer Rotates */
   4872    case 0x1E: {
   4873       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
   4874       sh_imm |= b1 << 5;
   4875 
   4876       vassert( msk_imm < 64 );
   4877       vassert( sh_imm < 64 );
   4878 
   4879       switch (opc2) {
   4880       case 0x4: {
   4881          /* r = ROTL64( rS, rB_lo6) */
   4882          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
   4883 
   4884          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
   4885             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4886                 rA_addr, rS_addr, rB_addr, msk_imm);
   4887             // note, ROTL does the masking, so we don't do it here
   4888             mask64 = MASK64(0, 63-msk_imm);
   4889             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4890             break;
   4891          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
   4892             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
   4893                 rA_addr, rS_addr, rB_addr, msk_imm);
   4894             mask64 = MASK64(63-msk_imm, 63);
   4895             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4896             break;
   4897          }
   4898          break;
   4899       }
   4900       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
   4901          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4902              rA_addr, rS_addr, sh_imm, msk_imm);
   4903          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4904          mask64 = MASK64(sh_imm, 63-msk_imm);
   4905          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4906          break;
   4907          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
   4908          /*
   4909            Hmm... looks like this'll do the job more simply:
   4910            r = SHL(rS, sh_imm)
   4911            m = ~(1 << (63-msk_imm))
   4912            assign(rA, r & m);
   4913          */
   4914 
   4915       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
   4916          if (mode64
   4917              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
   4918             /* special-case the ,64-n,n form as that is just
   4919                unsigned shift-right by n */
   4920             DIP("srdi%s r%u,r%u,%u\n",
   4921                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
   4922             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
   4923          } else {
   4924             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4925                 rA_addr, rS_addr, sh_imm, msk_imm);
   4926             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4927             mask64 = MASK64(0, 63-msk_imm);
   4928             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4929          }
   4930          break;
   4931 
   4932       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
   4933          if (mode64
   4934              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
   4935             /* special-case the ,n,63-n form as that is just
   4936                shift-left by n */
   4937             DIP("sldi%s r%u,r%u,%u\n",
   4938                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   4939             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
   4940          } else {
   4941             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4942                 rA_addr, rS_addr, sh_imm, msk_imm);
   4943             r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4944             mask64 = MASK64(63-msk_imm, 63);
   4945             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
   4946          }
   4947          break;
   4948 
   4949       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
   4950          IRTemp rA_orig = newTemp(ty);
   4951          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
   4952              rA_addr, rS_addr, sh_imm, msk_imm);
   4953          r = ROTL(mkexpr(rS), mkU8(sh_imm));
   4954          mask64 = MASK64(sh_imm, 63-msk_imm);
   4955          assign( rA_orig, getIReg(rA_addr) );
   4956          assign( rA, binop(Iop_Or64,
   4957                            binop(Iop_And64, mkU64(mask64),  r),
   4958                            binop(Iop_And64, mkU64(~mask64),
   4959                                             mkexpr(rA_orig))) );
   4960          break;
   4961       }
   4962       default:
   4963          vex_printf("dis_int_rot(ppc)(opc2)\n");
   4964          return False;
   4965       }
   4966       break;
   4967    }
   4968 
   4969    default:
   4970       vex_printf("dis_int_rot(ppc)(opc1)\n");
   4971       return False;
   4972    }
   4973 
   4974    putIReg( rA_addr, mkexpr(rA) );
   4975 
   4976    if (flag_rC) {
   4977       set_CR0( mkexpr(rA) );
   4978    }
   4979    return True;
   4980 }
   4981 
   4982 
   4983 /*
   4984   Integer Load Instructions
   4985 */
   4986 static Bool dis_int_load ( UInt theInstr )
   4987 {
   4988    /* D-Form, X-Form, DS-Form */
   4989    UChar opc1     = ifieldOPC(theInstr);
   4990    UChar rD_addr  = ifieldRegDS(theInstr);
   4991    UChar rA_addr  = ifieldRegA(theInstr);
   4992    UInt  uimm16   = ifieldUIMM16(theInstr);
   4993    UChar rB_addr  = ifieldRegB(theInstr);
   4994    UInt  opc2     = ifieldOPClo10(theInstr);
   4995    UChar b1       = ifieldBIT1(theInstr);
   4996    UChar b0       = ifieldBIT0(theInstr);
   4997 
   4998    Int     simm16 = extend_s_16to32(uimm16);
   4999    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   5000    IRTemp  EA     = newTemp(ty);
   5001    IRExpr* val;
   5002 
   5003    switch (opc1) {
   5004    case 0x1F: // register offset
   5005       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5006       break;
   5007    case 0x38: // immediate offset: 64bit: lq: maskoff
   5008               // lowest 4 bits of immediate before forming EA
   5009       simm16 = simm16 & 0xFFFFFFF0;
   5010       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5011       break;
   5012    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
   5013               // lowest 2 bits of immediate before forming EA
   5014       simm16 = simm16 & 0xFFFFFFFC;
   5015       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5016       break;
   5017    default:   // immediate offset
   5018       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5019       break;
   5020    }
   5021 
   5022    switch (opc1) {
   5023    case 0x22: // lbz (Load B & Zero, PPC32 p433)
   5024       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5025       val = load(Ity_I8, mkexpr(EA));
   5026       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   5027       break;
   5028 
   5029    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
   5030       if (rA_addr == 0 || rA_addr == rD_addr) {
   5031          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
   5032          return False;
   5033       }
   5034       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5035       val = load(Ity_I8, mkexpr(EA));
   5036       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   5037       putIReg( rA_addr, mkexpr(EA) );
   5038       break;
   5039 
   5040    case 0x2A: // lha (Load HW Alg, PPC32 p445)
   5041       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5042       val = load(Ity_I16, mkexpr(EA));
   5043       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5044       break;
   5045 
   5046    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
   5047       if (rA_addr == 0 || rA_addr == rD_addr) {
   5048          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
   5049          return False;
   5050       }
   5051       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5052       val = load(Ity_I16, mkexpr(EA));
   5053       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5054       putIReg( rA_addr, mkexpr(EA) );
   5055       break;
   5056 
   5057    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
   5058       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5059       val = load(Ity_I16, mkexpr(EA));
   5060       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5061       break;
   5062 
   5063    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
   5064       if (rA_addr == 0 || rA_addr == rD_addr) {
   5065          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
   5066          return False;
   5067       }
   5068       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5069       val = load(Ity_I16, mkexpr(EA));
   5070       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5071       putIReg( rA_addr, mkexpr(EA) );
   5072       break;
   5073 
   5074    case 0x20: // lwz (Load W & Zero, PPC32 p460)
   5075       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5076       val = load(Ity_I32, mkexpr(EA));
   5077       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5078       break;
   5079 
   5080    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
   5081       if (rA_addr == 0 || rA_addr == rD_addr) {
   5082          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
   5083          return False;
   5084       }
   5085       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
   5086       val = load(Ity_I32, mkexpr(EA));
   5087       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5088       putIReg( rA_addr, mkexpr(EA) );
   5089       break;
   5090 
   5091    /* X Form */
   5092    case 0x1F:
   5093       if (b0 != 0) {
   5094          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
   5095          return False;
   5096       }
   5097 
   5098       switch (opc2) {
   5099       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
   5100          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5101          if (rA_addr == 0 || rA_addr == rD_addr) {
   5102             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   5103             return False;
   5104          }
   5105          val = load(Ity_I8, mkexpr(EA));
   5106          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   5107          putIReg( rA_addr, mkexpr(EA) );
   5108          break;
   5109 
   5110       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
   5111          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5112          val = load(Ity_I8, mkexpr(EA));
   5113          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
   5114          break;
   5115 
   5116       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
   5117          if (rA_addr == 0 || rA_addr == rD_addr) {
   5118             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
   5119             return False;
   5120          }
   5121          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5122          val = load(Ity_I16, mkexpr(EA));
   5123          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5124          putIReg( rA_addr, mkexpr(EA) );
   5125          break;
   5126 
   5127       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
   5128          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5129          val = load(Ity_I16, mkexpr(EA));
   5130          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
   5131          break;
   5132 
   5133       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
   5134          if (rA_addr == 0 || rA_addr == rD_addr) {
   5135             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
   5136             return False;
   5137          }
   5138          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5139          val = load(Ity_I16, mkexpr(EA));
   5140          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5141          putIReg( rA_addr, mkexpr(EA) );
   5142          break;
   5143 
   5144       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
   5145          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5146          val = load(Ity_I16, mkexpr(EA));
   5147          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
   5148          break;
   5149 
   5150       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
   5151          if (rA_addr == 0 || rA_addr == rD_addr) {
   5152             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
   5153             return False;
   5154          }
   5155          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5156          val = load(Ity_I32, mkexpr(EA));
   5157          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5158          putIReg( rA_addr, mkexpr(EA) );
   5159          break;
   5160 
   5161       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
   5162          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5163          val = load(Ity_I32, mkexpr(EA));
   5164          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
   5165          break;
   5166 
   5167 
   5168       /* 64bit Loads */
   5169       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
   5170          if (rA_addr == 0 || rA_addr == rD_addr) {
   5171             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
   5172             return False;
   5173          }
   5174          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5175          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5176          putIReg( rA_addr, mkexpr(EA) );
   5177          break;
   5178 
   5179       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
   5180          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5181          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5182          break;
   5183 
   5184       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
   5185          if (rA_addr == 0 || rA_addr == rD_addr) {
   5186             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
   5187             return False;
   5188          }
   5189          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5190          putIReg( rD_addr,
   5191                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5192          putIReg( rA_addr, mkexpr(EA) );
   5193          break;
   5194 
   5195       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
   5196          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5197          putIReg( rD_addr,
   5198                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5199          break;
   5200 
   5201       default:
   5202          vex_printf("dis_int_load(ppc)(opc2)\n");
   5203          return False;
   5204       }
   5205       break;
   5206 
   5207    /* DS Form - 64bit Loads.  In each case EA will have been formed
   5208       with the lowest 2 bits masked off the immediate offset. */
   5209    case 0x3A:
   5210       switch ((b1<<1) | b0) {
   5211       case 0x0: // ld (Load DWord, PPC64 p472)
   5212          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5213          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5214          break;
   5215 
   5216       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
   5217          if (rA_addr == 0 || rA_addr == rD_addr) {
   5218             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
   5219             return False;
   5220          }
   5221          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5222          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
   5223          putIReg( rA_addr, mkexpr(EA) );
   5224          break;
   5225 
   5226       case 0x2: // lwa (Load Word Alg, PPC64 p499)
   5227          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5228          putIReg( rD_addr,
   5229                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
   5230          break;
   5231 
   5232       default:
   5233          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   5234          return False;
   5235       }
   5236       break;
   5237 
   5238    case 0x38: {
   5239       IRTemp  high = newTemp(ty);
   5240       IRTemp  low  = newTemp(ty);
   5241       /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
   5242       DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5243       /* NOTE: there are some changes to XER[41:42] that have not been
   5244        * implemented.
   5245        */
   5246       // trap if EA misaligned on 16 byte address
   5247       if (mode64) {
   5248          if (host_endness == VexEndnessBE) {
   5249             assign(high, load(ty, mkexpr( EA ) ) );
   5250             assign(low, load(ty, binop( Iop_Add64,
   5251                                         mkexpr( EA ),
   5252                                         mkU64( 8 ) ) ) );
   5253 	 } else {
   5254             assign(low, load(ty, mkexpr( EA ) ) );
   5255             assign(high, load(ty, binop( Iop_Add64,
   5256                                          mkexpr( EA ),
   5257                                          mkU64( 8 ) ) ) );
   5258 	 }
   5259       } else {
   5260          assign(high, load(ty, binop( Iop_Add32,
   5261                                       mkexpr( EA ),
   5262                                       mkU32( 4 ) ) ) );
   5263          assign(low, load(ty, binop( Iop_Add32,
   5264                                       mkexpr( EA ),
   5265                                       mkU32( 12 ) ) ) );
   5266       }
   5267       gen_SIGBUS_if_misaligned( EA, 16 );
   5268       putIReg( rD_addr,  mkexpr( high) );
   5269       putIReg( rD_addr+1,  mkexpr( low) );
   5270       break;
   5271    }
   5272    default:
   5273       vex_printf("dis_int_load(ppc)(opc1)\n");
   5274       return False;
   5275    }
   5276    return True;
   5277 }
   5278 
   5279 
   5280 
   5281 /*
   5282   Integer Store Instructions
   5283 */
   5284 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
   5285 {
   5286    /* D-Form, X-Form, DS-Form */
   5287    UChar opc1    = ifieldOPC(theInstr);
   5288    UInt  rS_addr = ifieldRegDS(theInstr);
   5289    UInt  rA_addr = ifieldRegA(theInstr);
   5290    UInt  uimm16  = ifieldUIMM16(theInstr);
   5291    UInt  rB_addr = ifieldRegB(theInstr);
   5292    UInt  opc2    = ifieldOPClo10(theInstr);
   5293    UChar b1      = ifieldBIT1(theInstr);
   5294    UChar b0      = ifieldBIT0(theInstr);
   5295 
   5296    Int    simm16 = extend_s_16to32(uimm16);
   5297    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   5298    IRTemp rS     = newTemp(ty);
   5299    IRTemp rB     = newTemp(ty);
   5300    IRTemp EA     = newTemp(ty);
   5301 
   5302    assign( rB, getIReg(rB_addr) );
   5303    assign( rS, getIReg(rS_addr) );
   5304 
   5305    switch (opc1) {
   5306    case 0x1F: // register offset
   5307       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   5308       break;
   5309    case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
   5310               // lowest 2 bits of immediate before forming EA
   5311       simm16 = simm16 & 0xFFFFFFFC;
   5312    default:   // immediate offset
   5313       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
   5314       break;
   5315    }
   5316 
   5317    switch (opc1) {
   5318    case 0x26: // stb (Store B, PPC32 p509)
   5319       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5320       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5321       break;
   5322 
   5323    case 0x27: // stbu (Store B, Update, PPC32 p510)
   5324       if (rA_addr == 0 ) {
   5325          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
   5326          return False;
   5327       }
   5328       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5329       putIReg( rA_addr, mkexpr(EA) );
   5330       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5331       break;
   5332 
   5333    case 0x2C: // sth (Store HW, PPC32 p522)
   5334       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5335       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5336       break;
   5337 
   5338    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
   5339       if (rA_addr == 0) {
   5340          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
   5341          return False;
   5342       }
   5343       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5344       putIReg( rA_addr, mkexpr(EA) );
   5345       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5346       break;
   5347 
   5348    case 0x24: // stw (Store W, PPC32 p530)
   5349       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5350       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5351       break;
   5352 
   5353    case 0x25: // stwu (Store W, Update, PPC32 p534)
   5354       if (rA_addr == 0) {
   5355          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
   5356          return False;
   5357       }
   5358       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5359       putIReg( rA_addr, mkexpr(EA) );
   5360       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5361       break;
   5362 
   5363    /* X Form : all these use EA_indexed */
   5364    case 0x1F:
   5365       if (b0 != 0) {
   5366          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
   5367          return False;
   5368       }
   5369 
   5370       switch (opc2) {
   5371       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
   5372          if (rA_addr == 0) {
   5373             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
   5374             return False;
   5375          }
   5376          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5377          putIReg( rA_addr, mkexpr(EA) );
   5378          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5379          break;
   5380 
   5381       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
   5382          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5383          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
   5384          break;
   5385 
   5386       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
   5387          if (rA_addr == 0) {
   5388             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
   5389             return False;
   5390          }
   5391          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5392          putIReg( rA_addr, mkexpr(EA) );
   5393          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5394          break;
   5395 
   5396       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
   5397          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5398          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
   5399          break;
   5400 
   5401       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
   5402          if (rA_addr == 0) {
   5403             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
   5404             return False;
   5405          }
   5406          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5407          putIReg( rA_addr, mkexpr(EA) );
   5408          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5409          break;
   5410 
   5411       case 0x097: // stwx (Store W Indexed, PPC32 p536)
   5412          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5413          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
   5414          break;
   5415 
   5416 
   5417       /* 64bit Stores */
   5418       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
   5419          if (rA_addr == 0) {
   5420             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
   5421             return False;
   5422          }
   5423          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5424          putIReg( rA_addr, mkexpr(EA) );
   5425          store( mkexpr(EA), mkexpr(rS) );
   5426          break;
   5427 
   5428       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
   5429          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5430          store( mkexpr(EA), mkexpr(rS) );
   5431          break;
   5432 
   5433       default:
   5434          vex_printf("dis_int_store(ppc)(opc2)\n");
   5435          return False;
   5436       }
   5437       break;
   5438 
   5439    /* DS Form - 64bit Stores.  In each case EA will have been formed
   5440       with the lowest 2 bits masked off the immediate offset. */
   5441    case 0x3E:
   5442       switch ((b1<<1) | b0) {
   5443       case 0x0: // std (Store DWord, PPC64 p580)
   5444          if (!mode64)
   5445             return False;
   5446 
   5447          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5448          store( mkexpr(EA), mkexpr(rS) );
   5449          break;
   5450 
   5451       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
   5452          if (!mode64)
   5453             return False;
   5454 
   5455          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5456          putIReg( rA_addr, mkexpr(EA) );
   5457          store( mkexpr(EA), mkexpr(rS) );
   5458          break;
   5459 
   5460       case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
   5461          IRTemp EA_hi = newTemp(ty);
   5462          IRTemp EA_lo = newTemp(ty);
   5463          DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5464 
   5465          if (mode64) {
   5466             if (host_endness == VexEndnessBE) {
   5467 
   5468                /* upper 64-bits */
   5469                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
   5470 
   5471                /* lower 64-bits */
   5472                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
   5473 	    } else {
   5474                /* upper 64-bits */
   5475                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
   5476 
   5477                /* lower 64-bits */
   5478                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
   5479 	    }
   5480          } else {
   5481             /* upper half of upper 64-bits */
   5482             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
   5483 
   5484             /* lower half of upper 64-bits */
   5485             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
   5486          }
   5487          store( mkexpr(EA_hi), mkexpr(rS) );
   5488          store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
   5489          break;
   5490       }
   5491       default:
   5492          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
   5493          return False;
   5494       }
   5495       break;
   5496 
   5497    default:
   5498       vex_printf("dis_int_store(ppc)(opc1)\n");
   5499       return False;
   5500    }
   5501    return True;
   5502 }
   5503 
   5504 
   5505 
   5506 /*
   5507   Integer Load/Store Multiple Instructions
   5508 */
   5509 static Bool dis_int_ldst_mult ( UInt theInstr )
   5510 {
   5511    /* D-Form */
   5512    UChar opc1     = ifieldOPC(theInstr);
   5513    UChar rD_addr  = ifieldRegDS(theInstr);
   5514    UChar rS_addr  = rD_addr;
   5515    UChar rA_addr  = ifieldRegA(theInstr);
   5516    UInt  uimm16   = ifieldUIMM16(theInstr);
   5517 
   5518    Int     simm16 = extend_s_16to32(uimm16);
   5519    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
   5520    IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
   5521    IRTemp  EA     = newTemp(ty);
   5522    UInt    r      = 0;
   5523    UInt    ea_off = 0;
   5524    IRExpr* irx_addr;
   5525 
   5526    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
   5527 
   5528    switch (opc1) {
   5529    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
   5530       if (rA_addr >= rD_addr) {
   5531          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
   5532          return False;
   5533       }
   5534       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
   5535       for (r = rD_addr; r <= 31; r++) {
   5536          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5537          putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
   5538                                        False) );
   5539          ea_off += 4;
   5540       }
   5541       break;
   5542 
   5543    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
   5544       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
   5545       for (r = rS_addr; r <= 31; r++) {
   5546          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
   5547          store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
   5548          ea_off += 4;
   5549       }
   5550       break;
   5551 
   5552    default:
   5553       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
   5554       return False;
   5555    }
   5556    return True;
   5557 }
   5558 
   5559 
   5560 
   5561 /*
   5562   Integer Load/Store String Instructions
   5563 */
   5564 static
   5565 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5566                              IRTemp EA,        // EA
   5567                              Int    rD,        // first dst register
   5568                              Int    maxBytes ) // 32 or 128
   5569 {
   5570    Int     i, shift = 24;
   5571    IRExpr* e_nbytes = mkexpr(tNBytes);
   5572    IRExpr* e_EA     = mkexpr(EA);
   5573    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5574 
   5575    vassert(rD >= 0 && rD < 32);
   5576    rD--; if (rD < 0) rD = 31;
   5577 
   5578    for (i = 0; i < maxBytes; i++) {
   5579       /* if (nBytes < (i+1)) goto NIA; */
   5580       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5581                          Ijk_Boring,
   5582                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
   5583       /* when crossing into a new dest register, set it to zero. */
   5584       if ((i % 4) == 0) {
   5585          rD++; if (rD == 32) rD = 0;
   5586          putIReg(rD, mkSzImm(ty, 0));
   5587          shift = 24;
   5588       }
   5589       /* rD |=  (8Uto32(*(EA+i))) << shift */
   5590       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5591       putIReg(
   5592          rD,
   5593          mkWidenFrom32(
   5594             ty,
   5595             binop(
   5596                Iop_Or32,
   5597                mkNarrowTo32(ty, getIReg(rD)),
   5598                binop(
   5599                   Iop_Shl32,
   5600                   unop(
   5601                      Iop_8Uto32,
   5602                      load( Ity_I8,
   5603                            binop( mkSzOp(ty,Iop_Add8),
   5604                                   e_EA, mkSzImm(ty,i)))
   5605                   ),
   5606                   mkU8(toUChar(shift))
   5607                )
   5608             ),
   5609             /*Signed*/False
   5610 	 )
   5611       );
   5612       shift -= 8;
   5613    }
   5614 }
   5615 
   5616 static
   5617 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
   5618                               IRTemp EA,        // EA
   5619                               Int    rS,        // first src register
   5620                               Int    maxBytes ) // 32 or 128
   5621 {
   5622    Int     i, shift = 24;
   5623    IRExpr* e_nbytes = mkexpr(tNBytes);
   5624    IRExpr* e_EA     = mkexpr(EA);
   5625    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
   5626 
   5627    vassert(rS >= 0 && rS < 32);
   5628    rS--; if (rS < 0) rS = 31;
   5629 
   5630    for (i = 0; i < maxBytes; i++) {
   5631       /* if (nBytes < (i+1)) goto NIA; */
   5632       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
   5633                          Ijk_Boring,
   5634                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
   5635       /* check for crossing into a new src register. */
   5636       if ((i % 4) == 0) {
   5637          rS++; if (rS == 32) rS = 0;
   5638          shift = 24;
   5639       }
   5640       /* *(EA+i) = 32to8(rS >> shift) */
   5641       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
   5642       store(
   5643             binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
   5644             unop( Iop_32to8,
   5645                   binop( Iop_Shr32,
   5646                          mkNarrowTo32( ty, getIReg(rS) ),
   5647                          mkU8( toUChar(shift) )))
   5648       );
   5649       shift -= 8;
   5650    }
   5651 }
   5652 
   5653 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
   5654 {
   5655    /* X-Form */
   5656    UChar opc1     = ifieldOPC(theInstr);
   5657    UChar rD_addr  = ifieldRegDS(theInstr);
   5658    UChar rS_addr  = rD_addr;
   5659    UChar rA_addr  = ifieldRegA(theInstr);
   5660    UChar rB_addr  = ifieldRegB(theInstr);
   5661    UChar NumBytes = rB_addr;
   5662    UInt  opc2     = ifieldOPClo10(theInstr);
   5663    UChar b0       = ifieldBIT0(theInstr);
   5664 
   5665    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   5666    IRTemp t_EA    = newTemp(ty);
   5667    IRTemp t_nbytes = IRTemp_INVALID;
   5668 
   5669    *stopHere = False;
   5670 
   5671    if (opc1 != 0x1F || b0 != 0) {
   5672       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
   5673       return False;
   5674    }
   5675 
   5676    switch (opc2) {
   5677    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
   5678       /* NB: does not reject the case where RA is in the range of
   5679          registers to be loaded.  It should. */
   5680       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
   5681       assign( t_EA, ea_rAor0(rA_addr) );
   5682       if (NumBytes == 8 && !mode64) {
   5683          /* Special case hack */
   5684          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
   5685          putIReg( rD_addr,
   5686                   load(Ity_I32, mkexpr(t_EA)) );
   5687          putIReg( (rD_addr+1) % 32,
   5688                   load(Ity_I32,
   5689                        binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
   5690       } else {
   5691          t_nbytes = newTemp(Ity_I32);
   5692          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5693          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5694          *stopHere = True;
   5695       }
   5696       return True;
   5697 
   5698    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
   5699       /* NB: does not reject the case where RA is in the range of
   5700          registers to be loaded.  It should.  Although considering
   5701          that that can only be detected at run time, it's not easy to
   5702          do so. */
   5703       if (rD_addr == rA_addr || rD_addr == rB_addr)
   5704          return False;
   5705       if (rD_addr == 0 && rA_addr == 0)
   5706          return False;
   5707       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   5708       t_nbytes = newTemp(Ity_I32);
   5709       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5710       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5711       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
   5712       *stopHere = True;
   5713       return True;
   5714 
   5715    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
   5716       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
   5717       assign( t_EA, ea_rAor0(rA_addr) );
   5718       if (NumBytes == 8 && !mode64) {
   5719          /* Special case hack */
   5720          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
   5721          store( mkexpr(t_EA),
   5722                 getIReg(rD_addr) );
   5723          store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
   5724                 getIReg((rD_addr+1) % 32) );
   5725       } else {
   5726          t_nbytes = newTemp(Ity_I32);
   5727          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
   5728          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
   5729          *stopHere = True;
   5730       }
   5731       return True;
   5732 
   5733    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
   5734       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   5735       t_nbytes = newTemp(Ity_I32);
   5736       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
   5737       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
   5738       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
   5739       *stopHere = True;
   5740       return True;
   5741 
   5742    default:
   5743       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
   5744       return False;
   5745    }
   5746    return True;
   5747 }
   5748 
   5749 
   5750 /* ------------------------------------------------------------------
   5751    Integer Branch Instructions
   5752    ------------------------------------------------------------------ */
   5753 
   5754 /*
   5755   Branch helper function
   5756   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
   5757   Returns an I32 which is 0x00000000 if the ctr condition failed
   5758   and 0xFFFFFFFF otherwise.
   5759 */
   5760 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
   5761 {
   5762    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   5763    IRTemp ok = newTemp(Ity_I32);
   5764 
   5765    if ((BO >> 2) & 1) {     // independent of ctr
   5766       assign( ok, mkU32(0xFFFFFFFF) );
   5767    } else {
   5768       if ((BO >> 1) & 1) {  // ctr == 0 ?
   5769          assign( ok, unop( Iop_1Sto32,
   5770                            binop( mkSzOp(ty, Iop_CmpEQ8),
   5771                                   getGST( PPC_GST_CTR ),
   5772                                   mkSzImm(ty,0))) );
   5773       } else {              // ctr != 0 ?
   5774          assign( ok, unop( Iop_1Sto32,
   5775                            binop( mkSzOp(ty, Iop_CmpNE8),
   5776                                   getGST( PPC_GST_CTR ),
   5777                                   mkSzImm(ty,0))) );
   5778       }
   5779    }
   5780    return mkexpr(ok);
   5781 }
   5782 
   5783 
   5784 /*
   5785   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
   5786   Returns an I32 which is either 0 if the condition failed or
   5787   some arbitrary nonzero value otherwise. */
   5788 
   5789 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
   5790 {
   5791    Int where;
   5792    IRTemp res   = newTemp(Ity_I32);
   5793    IRTemp cr_bi = newTemp(Ity_I32);
   5794 
   5795    if ((BO >> 4) & 1) {
   5796       assign( res, mkU32(1) );
   5797    } else {
   5798       // ok = (CR[BI] == BO[3]) Note, the following relies on
   5799       // getCRbit_anywhere returning a value which
   5800       // is either zero or has exactly 1 bit set.
   5801       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
   5802 
   5803       if ((BO >> 3) & 1) {
   5804          /* We can use cr_bi as-is. */
   5805          assign( res, mkexpr(cr_bi) );
   5806       } else {
   5807          /* We have to invert the sense of the information held in
   5808             cr_bi.  For that we need to know which bit
   5809             getCRbit_anywhere regards as significant. */
   5810          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
   5811                                        mkU32(1<<where)) );
   5812       }
   5813    }
   5814    return mkexpr(res);
   5815 }
   5816 
   5817 
   5818 /*
   5819   Integer Branch Instructions
   5820 */
   5821 static Bool dis_branch ( UInt theInstr,
   5822                          const VexAbiInfo* vbi,
   5823                          /*OUT*/DisResult* dres,
   5824                          Bool (*resteerOkFn)(void*,Addr),
   5825                          void* callback_opaque )
   5826 {
   5827    UChar opc1    = ifieldOPC(theInstr);
   5828    UChar BO      = ifieldRegDS(theInstr);
   5829    UChar BI      = ifieldRegA(theInstr);
   5830    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
   5831    UChar b11to15 = ifieldRegB(theInstr);
   5832    UInt  opc2    = ifieldOPClo10(theInstr);
   5833    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
   5834    UChar flag_AA = ifieldBIT1(theInstr);
   5835    UChar flag_LK = ifieldBIT0(theInstr);
   5836 
   5837    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
   5838    Addr64   tgt       = 0;
   5839    UInt     BD        = extend_s_16to32(BD_u16);
   5840    IRTemp   do_branch = newTemp(Ity_I32);
   5841    IRTemp   ctr_ok    = newTemp(Ity_I32);
   5842    IRTemp   cond_ok   = newTemp(Ity_I32);
   5843    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
   5844    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
   5845    IRTemp   lr_old    = newTemp(ty);
   5846 
   5847    /* Hack to pass through code that just wants to read the PC */
   5848    if (theInstr == 0x429F0005) {
   5849       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
   5850       putGST( PPC_GST_LR, e_nia );
   5851       return True;
   5852    }
   5853 
   5854    /* The default what-next.  Individual cases can override it. */
   5855    dres->whatNext = Dis_StopHere;
   5856    vassert(dres->jk_StopHere == Ijk_INVALID);
   5857 
   5858    switch (opc1) {
   5859    case 0x12: // b     (Branch, PPC32 p360)
   5860       if (flag_AA) {
   5861          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
   5862       } else {
   5863          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
   5864                              (Long)extend_s_26to64(LI_u26) );
   5865       }
   5866       if (mode64) {
   5867          DIP("b%s%s 0x%llx\n",
   5868              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
   5869       } else {
   5870          DIP("b%s%s 0x%x\n",
   5871              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
   5872       }
   5873 
   5874       if (flag_LK) {
   5875          putGST( PPC_GST_LR, e_nia );
   5876          if (vbi->guest_ppc_zap_RZ_at_bl
   5877              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
   5878             IRTemp t_tgt = newTemp(ty);
   5879             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
   5880             make_redzone_AbiHint( vbi, t_tgt,
   5881                                   "branch-and-link (unconditional call)" );
   5882          }
   5883       }
   5884 
   5885       if (resteerOkFn( callback_opaque, tgt )) {
   5886          dres->whatNext   = Dis_ResteerU;
   5887          dres->continueAt = tgt;
   5888       } else {
   5889          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
   5890          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
   5891       }
   5892       break;
   5893 
   5894    case 0x10: // bc    (Branch Conditional, PPC32 p361)
   5895       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
   5896           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
   5897 
   5898       if (!(BO & 0x4)) {
   5899          putGST( PPC_GST_CTR,
   5900                  binop(mkSzOp(ty, Iop_Sub8),
   5901                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5902       }
   5903 
   5904       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
   5905          cond_ok is either zero or nonzero, since that's the cheapest
   5906          way to compute it.  Anding them together gives a value which
   5907          is either zero or non zero and so that's what we must test
   5908          for in the IRStmt_Exit. */
   5909       assign( ctr_ok,  branch_ctr_ok( BO ) );
   5910       assign( cond_ok, branch_cond_ok( BO, BI ) );
   5911       assign( do_branch,
   5912               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5913 
   5914       if (flag_AA) {
   5915          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
   5916       } else {
   5917          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
   5918                             (Long)extend_s_16to64(BD_u16));
   5919       }
   5920       if (flag_LK)
   5921          putGST( PPC_GST_LR, e_nia );
   5922 
   5923       stmt( IRStmt_Exit(
   5924                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
   5925                flag_LK ? Ijk_Call : Ijk_Boring,
   5926                mkSzConst(ty, tgt), OFFB_CIA ) );
   5927 
   5928       dres->jk_StopHere = Ijk_Boring;
   5929       putGST( PPC_GST_CIA, e_nia );
   5930       break;
   5931 
   5932    case 0x13:
   5933       /* For bclr and bcctr, it appears that the lowest two bits of
   5934          b11to15 are a branch hint, and so we only need to ensure it's
   5935          of the form 000XX. */
   5936       if ((b11to15 & ~3) != 0) {
   5937          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
   5938          return False;
   5939       }
   5940 
   5941       switch (opc2) {
   5942       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
   5943          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
   5944             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
   5945             return False;
   5946          }
   5947          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5948 
   5949          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5950 
   5951          /* FIXME: this is confusing.  lr_old holds the old value
   5952             of ctr, not lr :-) */
   5953          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
   5954 
   5955          if (flag_LK)
   5956             putGST( PPC_GST_LR, e_nia );
   5957 
   5958          stmt( IRStmt_Exit(
   5959                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
   5960                   Ijk_Boring,
   5961                   c_nia, OFFB_CIA ));
   5962 
   5963          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
   5964             make_redzone_AbiHint( vbi, lr_old,
   5965                                   "b-ctr-l (indirect call)" );
   5966 	 }
   5967 
   5968          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
   5969          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   5970          break;
   5971 
   5972       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
   5973          Bool vanilla_return = False;
   5974          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
   5975             DIP("blr\n");
   5976             vanilla_return = True;
   5977          } else {
   5978             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
   5979          }
   5980 
   5981          if (!(BO & 0x4)) {
   5982             putGST( PPC_GST_CTR,
   5983                     binop(mkSzOp(ty, Iop_Sub8),
   5984                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
   5985          }
   5986 
   5987          /* See comments above for 'bc' about this */
   5988          assign( ctr_ok,  branch_ctr_ok( BO ) );
   5989          assign( cond_ok, branch_cond_ok( BO, BI ) );
   5990          assign( do_branch,
   5991                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
   5992 
   5993          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
   5994 
   5995          if (flag_LK)
   5996             putGST( PPC_GST_LR,  e_nia );
   5997 
   5998          stmt( IRStmt_Exit(
   5999                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
   6000                   Ijk_Boring,
   6001                   c_nia, OFFB_CIA ));
   6002 
   6003          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
   6004             make_redzone_AbiHint( vbi, lr_old,
   6005                                   "branch-to-lr (unconditional return)" );
   6006          }
   6007 
   6008          /* blrl is pretty strange; it's like a return that sets the
   6009             return address of its caller to the insn following this
   6010             one.  Mark it as a return. */
   6011          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
   6012          putGST( PPC_GST_CIA, mkexpr(lr_old) );
   6013          break;
   6014       }
   6015       default:
   6016          vex_printf("dis_int_branch(ppc)(opc2)\n");
   6017          return False;
   6018       }
   6019       break;
   6020 
   6021    default:
   6022       vex_printf("dis_int_branch(ppc)(opc1)\n");
   6023       return False;
   6024    }
   6025 
   6026    return True;
   6027 }
   6028 
   6029 
   6030 
   6031 /*
   6032   Condition Register Logical Instructions
   6033 */
   6034 static Bool dis_cond_logic ( UInt theInstr )
   6035 {
   6036    /* XL-Form */
   6037    UChar opc1      = ifieldOPC(theInstr);
   6038    UChar crbD_addr = ifieldRegDS(theInstr);
   6039    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
   6040    UChar crbA_addr = ifieldRegA(theInstr);
   6041    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
   6042    UChar crbB_addr = ifieldRegB(theInstr);
   6043    UInt  opc2      = ifieldOPClo10(theInstr);
   6044    UChar b0        = ifieldBIT0(theInstr);
   6045 
   6046    IRTemp crbD     = newTemp(Ity_I32);
   6047    IRTemp crbA     = newTemp(Ity_I32);
   6048    IRTemp crbB     = newTemp(Ity_I32);
   6049 
   6050    if (opc1 != 19 || b0 != 0) {
   6051       vex_printf("dis_cond_logic(ppc)(opc1)\n");
   6052       return False;
   6053    }
   6054 
   6055    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
   6056       if (((crbD_addr & 0x3) != 0) ||
   6057           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
   6058          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
   6059          return False;
   6060       }
   6061       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
   6062       putCR0(   crfD_addr, getCR0(  crfS_addr) );
   6063       putCR321( crfD_addr, getCR321(crfS_addr) );
   6064    } else {
   6065       assign( crbA, getCRbit(crbA_addr) );
   6066       if (crbA_addr == crbB_addr)
   6067          crbB = crbA;
   6068       else
   6069          assign( crbB, getCRbit(crbB_addr) );
   6070 
   6071       switch (opc2) {
   6072       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
   6073          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6074          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
   6075          break;
   6076       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
   6077          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6078          assign( crbD, binop(Iop_And32,
   6079                              mkexpr(crbA),
   6080                              unop(Iop_Not32, mkexpr(crbB))) );
   6081          break;
   6082       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
   6083          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6084          assign( crbD, unop(Iop_Not32,
   6085                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
   6086          break;
   6087       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
   6088          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6089          assign( crbD, unop(Iop_Not32,
   6090                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
   6091          break;
   6092       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
   6093          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6094          assign( crbD, unop(Iop_Not32,
   6095                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
   6096          break;
   6097       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
   6098          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6099          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
   6100          break;
   6101       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
   6102          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6103          assign( crbD, binop(Iop_Or32,
   6104                              mkexpr(crbA),
   6105                              unop(Iop_Not32, mkexpr(crbB))) );
   6106          break;
   6107       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
   6108          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
   6109          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
   6110          break;
   6111       default:
   6112          vex_printf("dis_cond_logic(ppc)(opc2)\n");
   6113          return False;
   6114       }
   6115 
   6116       putCRbit( crbD_addr, mkexpr(crbD) );
   6117    }
   6118    return True;
   6119 }
   6120 
   6121 
   6122 /*
   6123   Trap instructions
   6124 */
   6125 
   6126 /* Do the code generation for a trap.  Returned Bool is true iff
   6127    this is an unconditional trap.  If the two arg IRExpr*s are
   6128    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
   6129    then they are 64-bit, and we must be disassembling 64-bit
   6130    instructions. */
   6131 static Bool do_trap ( UChar TO,
   6132                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
   6133 {
   6134    IRTemp argL, argR;
   6135    IRExpr *argLe, *argRe, *cond, *tmp;
   6136 
   6137    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
   6138 
   6139    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
   6140    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
   6141    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
   6142    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
   6143    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
   6144    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
   6145    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
   6146    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
   6147    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
   6148    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
   6149 
   6150    const UChar b11100 = 0x1C;
   6151    const UChar b00111 = 0x07;
   6152 
   6153    if (is32bit) {
   6154       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
   6155       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
   6156    } else {
   6157       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
   6158       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
   6159       vassert( mode64 );
   6160    }
   6161 
   6162    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
   6163       /* Unconditional trap.  Just do the exit without
   6164          testing the arguments. */
   6165       stmt( IRStmt_Exit(
   6166                binop(opCMPEQ, const0, const0),
   6167                Ijk_SigTRAP,
   6168                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   6169                OFFB_CIA
   6170       ));
   6171       return True; /* unconditional trap */
   6172    }
   6173 
   6174    if (is32bit) {
   6175       argL = newTemp(Ity_I32);
   6176       argR = newTemp(Ity_I32);
   6177    } else {
   6178       argL = newTemp(Ity_I64);
   6179       argR = newTemp(Ity_I64);
   6180    }
   6181 
   6182    assign( argL, argL0 );
   6183    assign( argR, argR0 );
   6184 
   6185    argLe = mkexpr(argL);
   6186    argRe = mkexpr(argR);
   6187 
   6188    cond = const0;
   6189    if (TO & 16) { // L <s R
   6190       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
   6191       cond = binop(opOR, tmp, cond);
   6192    }
   6193    if (TO & 8) { // L >s R
   6194       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
   6195       cond = binop(opOR, tmp, cond);
   6196    }
   6197    if (TO & 4) { // L == R
   6198       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
   6199       cond = binop(opOR, tmp, cond);
   6200    }
   6201    if (TO & 2) { // L <u R
   6202       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
   6203       cond = binop(opOR, tmp, cond);
   6204    }
   6205    if (TO & 1) { // L >u R
   6206       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
   6207       cond = binop(opOR, tmp, cond);
   6208    }
   6209    stmt( IRStmt_Exit(
   6210             binop(opCMPNE, cond, const0),
   6211             Ijk_SigTRAP,
   6212             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
   6213             OFFB_CIA
   6214    ));
   6215    return False; /* not an unconditional trap */
   6216 }
   6217 
   6218 static Bool dis_trapi ( UInt theInstr,
   6219                         /*OUT*/DisResult* dres )
   6220 {
   6221    /* D-Form */
   6222    UChar  opc1    = ifieldOPC(theInstr);
   6223    UChar  TO      = ifieldRegDS(theInstr);
   6224    UChar  rA_addr = ifieldRegA(theInstr);
   6225    UInt   uimm16  = ifieldUIMM16(theInstr);
   6226    ULong  simm16  = extend_s_16to64(uimm16);
   6227    Addr64 cia     = guest_CIA_curr_instr;
   6228    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   6229    Bool   uncond  = False;
   6230 
   6231    switch (opc1) {
   6232    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
   6233       uncond = do_trap( TO,
   6234                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   6235                                : getIReg(rA_addr),
   6236                         mkU32( (UInt)simm16 ),
   6237                         cia );
   6238       if (TO == 4) {
   6239          DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
   6240       } else {
   6241          DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
   6242       }
   6243       break;
   6244    case 0x02: // tdi
   6245       if (!mode64)
   6246          return False;
   6247       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
   6248       if (TO == 4) {
   6249          DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
   6250       } else {
   6251          DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
   6252       }
   6253       break;
   6254    default:
   6255       return False;
   6256    }
   6257 
   6258    if (uncond) {
   6259       /* If the trap shows signs of being unconditional, don't
   6260          continue decoding past it. */
   6261       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6262       dres->jk_StopHere = Ijk_Boring;
   6263       dres->whatNext    = Dis_StopHere;
   6264    }
   6265 
   6266    return True;
   6267 }
   6268 
   6269 static Bool dis_trap ( UInt theInstr,
   6270                         /*OUT*/DisResult* dres )
   6271 {
   6272    /* X-Form */
   6273    UInt   opc2    = ifieldOPClo10(theInstr);
   6274    UChar  TO      = ifieldRegDS(theInstr);
   6275    UChar  rA_addr = ifieldRegA(theInstr);
   6276    UChar  rB_addr = ifieldRegB(theInstr);
   6277    Addr64 cia     = guest_CIA_curr_instr;
   6278    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
   6279    Bool   uncond  = False;
   6280 
   6281    if (ifieldBIT0(theInstr) != 0)
   6282       return False;
   6283 
   6284    switch (opc2) {
   6285    case 0x004: // tw  (Trap Word, PPC64 p540)
   6286       uncond = do_trap( TO,
   6287                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
   6288                                : getIReg(rA_addr),
   6289                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
   6290                                : getIReg(rB_addr),
   6291                         cia );
   6292       if (TO == 4) {
   6293          DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
   6294       } else {
   6295          DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
   6296       }
   6297       break;
   6298    case 0x044: // td (Trap Doubleword, PPC64 p534)
   6299       if (!mode64)
   6300          return False;
   6301       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
   6302       if (TO == 4) {
   6303          DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
   6304       } else {
   6305          DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
   6306       }
   6307       break;
   6308    default:
   6309       return False;
   6310    }
   6311 
   6312    if (uncond) {
   6313       /* If the trap shows signs of being unconditional, don't
   6314          continue decoding past it. */
   6315       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6316       dres->jk_StopHere = Ijk_Boring;
   6317       dres->whatNext    = Dis_StopHere;
   6318    }
   6319 
   6320    return True;
   6321 }
   6322 
   6323 
   6324 /*
   6325   System Linkage Instructions
   6326 */
   6327 static Bool dis_syslink ( UInt theInstr,
   6328                           const VexAbiInfo* abiinfo, DisResult* dres )
   6329 {
   6330    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   6331 
   6332    if (theInstr != 0x44000002) {
   6333       vex_printf("dis_syslink(ppc)(theInstr)\n");
   6334       return False;
   6335    }
   6336 
   6337    // sc  (System Call, PPC32 p504)
   6338    DIP("sc\n");
   6339 
   6340    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
   6341       Valgrind can back the guest up to this instruction if it needs
   6342       to restart the syscall. */
   6343    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
   6344 
   6345    /* It's important that all ArchRegs carry their up-to-date value
   6346       at this point.  So we declare an end-of-block here, which
   6347       forces any TempRegs caching ArchRegs to be flushed. */
   6348    putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
   6349 
   6350    dres->whatNext    = Dis_StopHere;
   6351    dres->jk_StopHere = Ijk_Sys_syscall;
   6352    return True;
   6353 }
   6354 
   6355 
   6356 /*
   6357   Memory Synchronization Instructions
   6358 
   6359   Note on Reservations:
   6360   We rely on the assumption that V will in fact only allow one thread at
   6361   once to run.  In effect, a thread can make a reservation, but we don't
   6362   check any stores it does.  Instead, the reservation is cancelled when
   6363   the scheduler switches to another thread (run_thread_for_a_while()).
   6364 */
   6365 static Bool dis_memsync ( UInt theInstr )
   6366 {
   6367    /* X-Form, XL-Form */
   6368    UChar opc1    = ifieldOPC(theInstr);
   6369    UInt  b11to25 = IFIELD(theInstr, 11, 15);
   6370    UChar flag_L  = ifieldRegDS(theInstr);
   6371    UInt  b11to20 = IFIELD(theInstr, 11, 10);
   6372    UInt  M0      = IFIELD(theInstr, 11, 5);
   6373    UChar rD_addr = ifieldRegDS(theInstr);
   6374    UChar rS_addr = rD_addr;
   6375    UChar rA_addr = ifieldRegA(theInstr);
   6376    UChar rB_addr = ifieldRegB(theInstr);
   6377    UInt  opc2    = ifieldOPClo10(theInstr);
   6378    UChar b0      = ifieldBIT0(theInstr);
   6379 
   6380    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   6381    IRTemp EA     = newTemp(ty);
   6382 
   6383    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   6384 
   6385    switch (opc1) {
   6386    /* XL-Form */
   6387    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
   6388       if (opc2 != 0x096) {
   6389          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
   6390          return False;
   6391       }
   6392       if (b11to25 != 0 || b0 != 0) {
   6393          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
   6394          return False;
   6395       }
   6396       DIP("isync\n");
   6397       stmt( IRStmt_MBE(Imbe_Fence) );
   6398       break;
   6399 
   6400    /* X-Form */
   6401    case 0x1F:
   6402       switch (opc2) {
   6403       case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
   6404          if (M0 == 0) {
   6405             if (b11to20 != 0 || b0 != 0) {
   6406                vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
   6407                return False;
   6408             }
   6409             DIP("eieio\n");
   6410          } else {
   6411             if (b11to20 != 0 || b0 != 0) {
   6412                vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
   6413                return False;
   6414             }
   6415             DIP("mbar %d\n", M0);
   6416          }
   6417          /* Insert a memory fence, just to be on the safe side. */
   6418          stmt( IRStmt_MBE(Imbe_Fence) );
   6419          break;
   6420 
   6421       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
   6422          IRTemp res;
   6423          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6424             in the documentation) is merely a hint bit to the
   6425             hardware, I think as to whether or not contention is
   6426             likely.  So we can just ignore it. */
   6427          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
   6428 
   6429          // trap if misaligned
   6430          gen_SIGBUS_if_misaligned( EA, 4 );
   6431 
   6432          // and actually do the load
   6433          res = newTemp(Ity_I32);
   6434          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6435 
   6436          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
   6437          break;
   6438       }
   6439 
   6440       case 0x034: { // lbarx (Load Word and Reserve Indexed)
   6441          IRTemp res;
   6442          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6443             in the documentation) is merely a hint bit to the
   6444             hardware, I think as to whether or not contention is
   6445             likely.  So we can just ignore it. */
   6446          DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
   6447 
   6448          // and actually do the load
   6449          res = newTemp(Ity_I8);
   6450          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6451 
   6452          putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
   6453          break;
   6454      }
   6455 
   6456       case 0x074: { // lharx (Load Word and Reserve Indexed)
   6457          IRTemp res;
   6458          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6459             in the documentation) is merely a hint bit to the
   6460             hardware, I think as to whether or not contention is
   6461             likely.  So we can just ignore it. */
   6462          DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
   6463 
   6464          // trap if misaligned
   6465          gen_SIGBUS_if_misaligned( EA, 2 );
   6466 
   6467          // and actually do the load
   6468          res = newTemp(Ity_I16);
   6469          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
   6470 
   6471          putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
   6472          break;
   6473       }
   6474 
   6475       case 0x096: {
   6476          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
   6477          // Note this has to handle stwcx. in both 32- and 64-bit modes,
   6478          // so isn't quite as straightforward as it might otherwise be.
   6479          IRTemp rS = newTemp(Ity_I32);
   6480          IRTemp resSC;
   6481          if (b0 != 1) {
   6482             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   6483             return False;
   6484          }
   6485          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6486 
   6487          // trap if misaligned
   6488          gen_SIGBUS_if_misaligned( EA, 4 );
   6489 
   6490          // Get the data to be stored, and narrow to 32 bits if necessary
   6491          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
   6492 
   6493          // Do the store, and get success/failure bit into resSC
   6494          resSC = newTemp(Ity_I1);
   6495          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6496 
   6497          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6498          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6499          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6500          putCR0(0, getXER_SO());
   6501 
   6502          /* Note:
   6503             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6504             whether rS is stored is dependent on that value. */
   6505          /* So I guess we can just ignore this case? */
   6506          break;
   6507       }
   6508 
   6509       case 0x2B6: {
   6510          // stbcx. (Store Byte Conditional Indexed)
   6511          // Note this has to handle stbcx. in both 32- and 64-bit modes,
   6512          // so isn't quite as straightforward as it might otherwise be.
   6513          IRTemp rS = newTemp(Ity_I8);
   6514          IRTemp resSC;
   6515          if (b0 != 1) {
   6516             vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
   6517             return False;
   6518          }
   6519          DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6520 
   6521          // Get the data to be stored, and narrow to 32 bits if necessary
   6522          assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
   6523 
   6524          // Do the store, and get success/failure bit into resSC
   6525          resSC = newTemp(Ity_I1);
   6526          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6527 
   6528          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6529          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6530          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6531          putCR0(0, getXER_SO());
   6532 
   6533          /* Note:
   6534             If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
   6535             whether rS is stored is dependent on that value. */
   6536          /* So I guess we can just ignore this case? */
   6537          break;
   6538       }
   6539 
   6540       case 0x2D6: {
   6541          // sthcx. (Store Word Conditional Indexed, PPC32 p532)
   6542          // Note this has to handle sthcx. in both 32- and 64-bit modes,
   6543          // so isn't quite as straightforward as it might otherwise be.
   6544          IRTemp rS = newTemp(Ity_I16);
   6545          IRTemp resSC;
   6546          if (b0 != 1) {
   6547             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
   6548             return False;
   6549          }
   6550          DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6551 
   6552          // trap if misaligned
   6553          gen_SIGBUS_if_misaligned( EA, 2 );
   6554 
   6555          // Get the data to be stored, and narrow to 16 bits if necessary
   6556          assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
   6557 
   6558          // Do the store, and get success/failure bit into resSC
   6559          resSC = newTemp(Ity_I1);
   6560          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6561 
   6562          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6563          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6564          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6565          putCR0(0, getXER_SO());
   6566 
   6567          /* Note:
   6568             If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
   6569             whether rS is stored is dependent on that value. */
   6570          /* So I guess we can just ignore this case? */
   6571          break;
   6572       }
   6573 
   6574       case 0x256: // sync (Synchronize, PPC32 p543),
   6575                   // also lwsync (L==1), ptesync (L==2)
   6576          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
   6577 
   6578             The PowerPC architecture used in IBM chips has expanded
   6579             the sync instruction into two variants: lightweight sync
   6580             and heavyweight sync.  The original sync instruction is
   6581             the new heavyweight sync and lightweight sync is a strict
   6582             subset of the heavyweight sync functionality. This allows
   6583             the programmer to specify a less expensive operation on
   6584             high-end systems when the full sync functionality is not
   6585             necessary.
   6586 
   6587             The basic "sync" mnemonic now utilizes an operand. "sync"
   6588             without an operand now becomes a extended mnemonic for
   6589             heavyweight sync.  Processors without the lwsync
   6590             instruction will not decode the L field and will perform a
   6591             heavyweight sync.  Everything is backward compatible.
   6592 
   6593             sync    =       sync 0
   6594             lwsync  =       sync 1
   6595             ptesync =       sync 2    *** TODO - not implemented ***
   6596          */
   6597          if (b11to20 != 0 || b0 != 0) {
   6598             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
   6599             return False;
   6600          }
   6601          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
   6602             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
   6603             return False;
   6604          }
   6605          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
   6606          /* Insert a memory fence.  It's sometimes important that these
   6607             are carried through to the generated code. */
   6608          stmt( IRStmt_MBE(Imbe_Fence) );
   6609          break;
   6610 
   6611       /* 64bit Memsync */
   6612       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
   6613          IRTemp res;
   6614          /* According to the PowerPC ISA version 2.05, b0 (called EH
   6615             in the documentation) is merely a hint bit to the
   6616             hardware, I think as to whether or not contention is
   6617             likely.  So we can just ignore it. */
   6618          if (!mode64)
   6619             return False;
   6620          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
   6621 
   6622          // trap if misaligned
   6623          gen_SIGBUS_if_misaligned( EA, 8 );
   6624 
   6625          // and actually do the load
   6626          res = newTemp(Ity_I64);
   6627          stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
   6628 
   6629          putIReg( rD_addr, mkexpr(res) );
   6630          break;
   6631       }
   6632 
   6633       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
   6634          // A marginally simplified version of the stwcx. case
   6635          IRTemp rS = newTemp(Ity_I64);
   6636          IRTemp resSC;
   6637          if (b0 != 1) {
   6638             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
   6639             return False;
   6640          }
   6641          if (!mode64)
   6642             return False;
   6643          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6644 
   6645          // trap if misaligned
   6646          gen_SIGBUS_if_misaligned( EA, 8 );
   6647 
   6648          // Get the data to be stored
   6649          assign( rS, getIReg(rS_addr) );
   6650 
   6651          // Do the store, and get success/failure bit into resSC
   6652          resSC = newTemp(Ity_I1);
   6653          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
   6654 
   6655          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6656          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6657          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
   6658          putCR0(0, getXER_SO());
   6659 
   6660          /* Note:
   6661             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
   6662             whether rS is stored is dependent on that value. */
   6663          /* So I guess we can just ignore this case? */
   6664          break;
   6665       }
   6666 
   6667       /* 128bit Memsync */
   6668       case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
   6669          IRTemp res_hi = newTemp(ty);
   6670          IRTemp res_lo = newTemp(ty);
   6671 
   6672          /* According to the PowerPC ISA version 2.07, b0 (called EH
   6673             in the documentation) is merely a hint bit to the
   6674             hardware, I think as to whether or not contention is
   6675             likely.  So we can just ignore it. */
   6676          DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
   6677 
   6678          // trap if misaligned
   6679          gen_SIGBUS_if_misaligned( EA, 16 );
   6680 
   6681          // and actually do the load
   6682          if (mode64) {
   6683             if (host_endness == VexEndnessBE) {
   6684                stmt( stmt_load( res_hi,
   6685                                 mkexpr(EA), NULL/*this is a load*/) );
   6686                stmt( stmt_load( res_lo,
   6687                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
   6688                                 NULL/*this is a load*/) );
   6689 	    } else {
   6690                stmt( stmt_load( res_lo,
   6691                                 mkexpr(EA), NULL/*this is a load*/) );
   6692                stmt( stmt_load( res_hi,
   6693                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
   6694                                 NULL/*this is a load*/) );
   6695             }
   6696          } else {
   6697             stmt( stmt_load( res_hi,
   6698                              binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
   6699                              NULL/*this is a load*/) );
   6700             stmt( stmt_load( res_lo,
   6701                              binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
   6702                              NULL/*this is a load*/) );
   6703          }
   6704          putIReg( rD_addr,   mkexpr(res_hi) );
   6705          putIReg( rD_addr+1, mkexpr(res_lo) );
   6706          break;
   6707       }
   6708 
   6709       case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
   6710          // A marginally simplified version of the stwcx. case
   6711          IRTemp rS_hi = newTemp(ty);
   6712          IRTemp rS_lo = newTemp(ty);
   6713          IRTemp resSC;
   6714          if (b0 != 1) {
   6715             vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
   6716             return False;
   6717          }
   6718 
   6719          DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   6720 
   6721          // trap if misaligned
   6722          gen_SIGBUS_if_misaligned( EA, 16 );
   6723          // Get the data to be stored
   6724          assign( rS_hi, getIReg(rS_addr) );
   6725          assign( rS_lo, getIReg(rS_addr+1) );
   6726 
   6727          // Do the store, and get success/failure bit into resSC
   6728          resSC = newTemp(Ity_I1);
   6729 
   6730          if (mode64) {
   6731             if (host_endness == VexEndnessBE) {
   6732                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
   6733                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
   6734                       mkexpr(rS_lo) );
   6735 	    } else {
   6736                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
   6737                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
   6738                       mkexpr(rS_hi) );
   6739 	    }
   6740          } else {
   6741             stmt( stmt_load( resSC, binop( Iop_Add32,
   6742                                            mkexpr(EA),
   6743                                            mkU32(4) ),
   6744                                            mkexpr(rS_hi) ) );
   6745             store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
   6746          }
   6747 
   6748          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
   6749          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
   6750          putCR321(0, binop( Iop_Shl8,
   6751                             unop(Iop_1Uto8, mkexpr(resSC) ),
   6752                             mkU8(1)));
   6753          putCR0(0, getXER_SO());
   6754          break;
   6755       }
   6756 
   6757       default:
   6758          vex_printf("dis_memsync(ppc)(opc2)\n");
   6759          return False;
   6760       }
   6761       break;
   6762 
   6763    default:
   6764       vex_printf("dis_memsync(ppc)(opc1)\n");
   6765       return False;
   6766    }
   6767    return True;
   6768 }
   6769 
   6770 
   6771 
   6772 /*
   6773   Integer Shift Instructions
   6774 */
   6775 static Bool dis_int_shift ( UInt theInstr )
   6776 {
   6777    /* X-Form, XS-Form */
   6778    UChar opc1    = ifieldOPC(theInstr);
   6779    UChar rS_addr = ifieldRegDS(theInstr);
   6780    UChar rA_addr = ifieldRegA(theInstr);
   6781    UChar rB_addr = ifieldRegB(theInstr);
   6782    UChar sh_imm  = rB_addr;
   6783    UInt  opc2    = ifieldOPClo10(theInstr);
   6784    UChar b1      = ifieldBIT1(theInstr);
   6785    UChar flag_rC = ifieldBIT0(theInstr);
   6786 
   6787    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
   6788    IRTemp  rA         = newTemp(ty);
   6789    IRTemp  rS         = newTemp(ty);
   6790    IRTemp  rB         = newTemp(ty);
   6791    IRTemp  outofrange = newTemp(Ity_I1);
   6792    IRTemp  rS_lo32    = newTemp(Ity_I32);
   6793    IRTemp  rB_lo32    = newTemp(Ity_I32);
   6794    IRExpr* e_tmp;
   6795 
   6796    assign( rS, getIReg(rS_addr) );
   6797    assign( rB, getIReg(rB_addr) );
   6798    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
   6799    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
   6800 
   6801    if (opc1 == 0x1F) {
   6802       switch (opc2) {
   6803       case 0x018: { // slw (Shift Left Word, PPC32 p505)
   6804          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6805              rA_addr, rS_addr, rB_addr);
   6806          /* rA = rS << rB */
   6807          /* ppc32 semantics are:
   6808             slw(x,y) = (x << (y & 31))         -- primary result
   6809                        & ~((y << 26) >>s 31)   -- make result 0
   6810                                                   for y in 32 .. 63
   6811          */
   6812          e_tmp =
   6813             binop( Iop_And32,
   6814                binop( Iop_Shl32,
   6815                       mkexpr(rS_lo32),
   6816                       unop( Iop_32to8,
   6817                             binop(Iop_And32,
   6818                                   mkexpr(rB_lo32), mkU32(31)))),
   6819                unop( Iop_Not32,
   6820                      binop( Iop_Sar32,
   6821                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
   6822                             mkU8(31))) );
   6823          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6824          break;
   6825       }
   6826 
   6827       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
   6828          IRTemp sh_amt = newTemp(Ity_I32);
   6829          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6830              rA_addr, rS_addr, rB_addr);
   6831          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
   6832             amt = rB & 63
   6833             rA = Sar32( rS, amt > 31 ? 31 : amt )
   6834             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
   6835          */
   6836          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
   6837                                           mkexpr(rB_lo32)) );
   6838          assign( outofrange,
   6839                  binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
   6840          e_tmp = binop( Iop_Sar32,
   6841                         mkexpr(rS_lo32),
   6842                         unop( Iop_32to8,
   6843                               IRExpr_ITE( mkexpr(outofrange),
   6844                                           mkU32(31),
   6845                                           mkexpr(sh_amt)) ) );
   6846          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
   6847 
   6848          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
   6849                      mkexpr(rA),
   6850                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
   6851                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
   6852                      mkWidenFrom32(ty, getXER_CA32(), True) );
   6853          break;
   6854       }
   6855 
   6856       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
   6857          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
   6858              rA_addr, rS_addr, sh_imm);
   6859          vassert(sh_imm < 32);
   6860          if (mode64) {
   6861             assign( rA, binop(Iop_Sar64,
   6862                               binop(Iop_Shl64, getIReg(rS_addr),
   6863                                                mkU8(32)),
   6864                               mkU8(32 + sh_imm)) );
   6865          } else {
   6866             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
   6867                                          mkU8(sh_imm)) );
   6868          }
   6869 
   6870          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
   6871                      mkexpr(rA),
   6872                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
   6873                      mkSzImm(ty, sh_imm),
   6874                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6875          break;
   6876 
   6877       case 0x218: // srw (Shift Right Word, PPC32 p508)
   6878          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
   6879              rA_addr, rS_addr, rB_addr);
   6880          /* rA = rS >>u rB */
   6881          /* ppc32 semantics are:
   6882             srw(x,y) = (x >>u (y & 31))        -- primary result
   6883                        & ~((y << 26) >>s 31)   -- make result 0
   6884                                                   for y in 32 .. 63
   6885          */
   6886          e_tmp =
   6887             binop(
   6888                Iop_And32,
   6889                binop( Iop_Shr32,
   6890                       mkexpr(rS_lo32),
   6891                       unop( Iop_32to8,
   6892                             binop(Iop_And32, mkexpr(rB_lo32),
   6893                                              mkU32(31)))),
   6894                unop( Iop_Not32,
   6895                      binop( Iop_Sar32,
   6896                             binop(Iop_Shl32, mkexpr(rB_lo32),
   6897                                              mkU8(26)),
   6898                             mkU8(31))));
   6899          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
   6900          break;
   6901 
   6902 
   6903       /* 64bit Shifts */
   6904       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
   6905          DIP("sld%s r%u,r%u,r%u\n",
   6906              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6907          /* rA = rS << rB */
   6908          /* ppc64 semantics are:
   6909             slw(x,y) = (x << (y & 63))         -- primary result
   6910                        & ~((y << 57) >>s 63)   -- make result 0
   6911                                                   for y in 64 ..
   6912          */
   6913          assign( rA,
   6914             binop(
   6915                Iop_And64,
   6916                binop( Iop_Shl64,
   6917                       mkexpr(rS),
   6918                       unop( Iop_64to8,
   6919                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6920                unop( Iop_Not64,
   6921                      binop( Iop_Sar64,
   6922                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6923                             mkU8(63)))) );
   6924          break;
   6925 
   6926       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
   6927          IRTemp sh_amt = newTemp(Ity_I64);
   6928          DIP("srad%s r%u,r%u,r%u\n",
   6929              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6930          /* amt = rB & 127
   6931             rA = Sar64( rS, amt > 63 ? 63 : amt )
   6932             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
   6933          */
   6934          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
   6935          assign( outofrange,
   6936                  binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
   6937          assign( rA,
   6938                  binop( Iop_Sar64,
   6939                         mkexpr(rS),
   6940                         unop( Iop_64to8,
   6941                               IRExpr_ITE( mkexpr(outofrange),
   6942                                           mkU64(63),
   6943                                           mkexpr(sh_amt)) ))
   6944                );
   6945          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
   6946                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
   6947                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6948          break;
   6949       }
   6950 
   6951       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
   6952          sh_imm |= b1<<5;
   6953          vassert(sh_imm < 64);
   6954          DIP("sradi%s r%u,r%u,%u\n",
   6955              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
   6956          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
   6957 
   6958          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
   6959                      mkexpr(rA),
   6960                      getIReg(rS_addr),
   6961                      mkU64(sh_imm),
   6962                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
   6963          break;
   6964 
   6965       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
   6966          DIP("srd%s r%u,r%u,r%u\n",
   6967              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
   6968          /* rA = rS >>u rB */
   6969          /* ppc semantics are:
   6970             srw(x,y) = (x >>u (y & 63))        -- primary result
   6971                        & ~((y << 57) >>s 63)   -- make result 0
   6972                                                   for y in 64 .. 127
   6973          */
   6974          assign( rA,
   6975             binop(
   6976                Iop_And64,
   6977                binop( Iop_Shr64,
   6978                       mkexpr(rS),
   6979                       unop( Iop_64to8,
   6980                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
   6981                unop( Iop_Not64,
   6982                      binop( Iop_Sar64,
   6983                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
   6984                             mkU8(63)))) );
   6985          break;
   6986 
   6987       default:
   6988          vex_printf("dis_int_shift(ppc)(opc2)\n");
   6989          return False;
   6990       }
   6991    } else {
   6992       vex_printf("dis_int_shift(ppc)(opc1)\n");
   6993       return False;
   6994    }
   6995 
   6996    putIReg( rA_addr, mkexpr(rA) );
   6997 
   6998    if (flag_rC) {
   6999       set_CR0( mkexpr(rA) );
   7000    }
   7001    return True;
   7002 }
   7003 
   7004 
   7005 
   7006 /*
   7007   Integer Load/Store Reverse Instructions
   7008 */
   7009 /* Generates code to swap the byte order in an Ity_I32. */
   7010 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
   7011 {
   7012    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   7013    return
   7014       binop(Iop_Or32,
   7015          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
   7016       binop(Iop_Or32,
   7017          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   7018                           mkU32(0x00FF0000)),
   7019       binop(Iop_Or32,
   7020          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   7021                           mkU32(0x0000FF00)),
   7022          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
   7023                           mkU32(0x000000FF) )
   7024       )));
   7025 }
   7026 
   7027 /* Generates code to swap the byte order in the lower half of an Ity_I32,
   7028    and zeroes the upper half. */
   7029 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
   7030 {
   7031    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
   7032    return
   7033       binop(Iop_Or32,
   7034          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
   7035                           mkU32(0x0000FF00)),
   7036          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
   7037                           mkU32(0x000000FF))
   7038       );
   7039 }
   7040 
   7041 static Bool dis_int_ldst_rev ( UInt theInstr )
   7042 {
   7043    /* X-Form */
   7044    UChar opc1    = ifieldOPC(theInstr);
   7045    UChar rD_addr = ifieldRegDS(theInstr);
   7046    UChar rS_addr = rD_addr;
   7047    UChar rA_addr = ifieldRegA(theInstr);
   7048    UChar rB_addr = ifieldRegB(theInstr);
   7049    UInt  opc2    = ifieldOPClo10(theInstr);
   7050    UChar b0      = ifieldBIT0(theInstr);
   7051 
   7052    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   7053    IRTemp EA = newTemp(ty);
   7054    IRTemp w1 = newTemp(Ity_I32);
   7055    IRTemp w2 = newTemp(Ity_I32);
   7056 
   7057    if (opc1 != 0x1F || b0 != 0) {
   7058       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
   7059       return False;
   7060    }
   7061 
   7062    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7063 
   7064    switch (opc2) {
   7065 
   7066       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
   7067          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   7068          assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
   7069          assign( w2, gen_byterev16(w1) );
   7070          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   7071                                          /* Signed */False) );
   7072          break;
   7073 
   7074       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
   7075          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   7076          assign( w1, load(Ity_I32, mkexpr(EA)) );
   7077          assign( w2, gen_byterev32(w1) );
   7078          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
   7079                                          /* Signed */False) );
   7080          break;
   7081 
   7082       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
   7083       {
   7084          IRExpr * nextAddr;
   7085          IRTemp w3 = newTemp( Ity_I32 );
   7086          IRTemp w4 = newTemp( Ity_I32 );
   7087          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
   7088          assign( w1, load( Ity_I32, mkexpr( EA ) ) );
   7089          assign( w2, gen_byterev32( w1 ) );
   7090          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   7091                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
   7092          assign( w3, load( Ity_I32, nextAddr ) );
   7093          assign( w4, gen_byterev32( w3 ) );
   7094          if (host_endness == VexEndnessLE)
   7095             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
   7096          else
   7097             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
   7098          break;
   7099       }
   7100 
   7101       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
   7102          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   7103          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   7104          store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
   7105          break;
   7106 
   7107       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
   7108          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   7109          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
   7110          store( mkexpr(EA), gen_byterev32(w1) );
   7111          break;
   7112 
   7113       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
   7114       {
   7115          IRTemp lo = newTemp(Ity_I32);
   7116          IRTemp hi = newTemp(Ity_I32);
   7117          IRTemp rS = newTemp(Ity_I64);
   7118          assign( rS, getIReg( rS_addr ) );
   7119          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
   7120          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
   7121          assign(hi, unop(Iop_64to32, mkexpr(rS)));
   7122          store( mkexpr( EA ),
   7123                 binop( Iop_32HLto64, gen_byterev32( hi ),
   7124                        gen_byterev32( lo ) ) );
   7125          break;
   7126       }
   7127 
   7128       default:
   7129          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
   7130          return False;
   7131    }
   7132    return True;
   7133 }
   7134 
   7135 
   7136 
   7137 /*
   7138   Processor Control Instructions
   7139 */
   7140 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
   7141 {
   7142    UChar opc1     = ifieldOPC(theInstr);
   7143 
   7144    /* X-Form */
   7145    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   7146    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   7147    UChar rD_addr  = ifieldRegDS(theInstr);
   7148    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
   7149 
   7150    /* XFX-Form */
   7151    UChar rS_addr  = rD_addr;
   7152    UInt  SPR      = b11to20;
   7153    UInt  TBR      = b11to20;
   7154    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
   7155    UInt  CRM      = IFIELD( theInstr, 12, 8 );
   7156    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
   7157 
   7158    UInt  opc2     = ifieldOPClo10(theInstr);
   7159    UChar b0       = ifieldBIT0(theInstr);
   7160 
   7161    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   7162    IRTemp rS = newTemp(ty);
   7163    assign( rS, getIReg(rS_addr) );
   7164 
   7165    /* Reorder SPR field as per PPC32 p470 */
   7166    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
   7167    /* Reorder TBR field as per PPC32 p475 */
   7168    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
   7169 
   7170    /* b0 = 0, inst is treated as floating point inst for reservation purposes
   7171     * b0 = 1, inst is treated as vector inst for reservation purposes
   7172     */
   7173    if (opc1 != 0x1F) {
   7174       vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
   7175       return False;
   7176    }
   7177 
   7178    switch (opc2) {
   7179    /* X-Form */
   7180    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
   7181       if (b21to22 != 0 || b11to20 != 0) {
   7182          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
   7183          return False;
   7184       }
   7185       DIP("mcrxr crf%d\n", crfD);
   7186       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
   7187       putGST_field( PPC_GST_CR,
   7188                     getGST_field( PPC_GST_XER, 7 ),
   7189                     crfD );
   7190 
   7191       // Clear XER[0-3]
   7192       putXER_SO( mkU8(0) );
   7193       putXER_OV( mkU8(0) );
   7194       putXER_CA( mkU8(0) );
   7195       break;
   7196    }
   7197 
   7198    case 0x013:
   7199       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
   7200       // b20==1 & b11==0: mfocrf (Move from One CR Field)
   7201       // However it seems that the 'mfcr' behaviour is an acceptable
   7202       // implementation of mfocr (from the 2.02 arch spec)
   7203       if (b11to20 == 0) {
   7204          DIP("mfcr r%u\n", rD_addr);
   7205          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   7206                                          /* Signed */False) );
   7207          break;
   7208       }
   7209       if (b20 == 1 && b11 == 0) {
   7210          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
   7211          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
   7212                                          /* Signed */False) );
   7213          break;
   7214       }
   7215       /* not decodable */
   7216       return False;
   7217 
   7218    /* XFX-Form */
   7219    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
   7220 
   7221       switch (SPR) {  // Choose a register...
   7222       case 0x1:
   7223          DIP("mfxer r%u\n", rD_addr);
   7224          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
   7225                                          /* Signed */False) );
   7226          break;
   7227       case 0x8:
   7228          DIP("mflr r%u\n", rD_addr);
   7229          putIReg( rD_addr, getGST( PPC_GST_LR ) );
   7230          break;
   7231       case 0x9:
   7232          DIP("mfctr r%u\n", rD_addr);
   7233          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
   7234          break;
   7235       case 0x80:  // 128
   7236          DIP("mfspr r%u (TFHAR)\n", rD_addr);
   7237          putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
   7238          break;
   7239       case 0x81:  // 129
   7240          DIP("mfspr r%u (TFIAR)\n", rD_addr);
   7241          putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
   7242          break;
   7243       case 0x82:  // 130
   7244          DIP("mfspr r%u (TEXASR)\n", rD_addr);
   7245          putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
   7246          break;
   7247       case 0x83:  // 131
   7248          DIP("mfspr r%u (TEXASRU)\n", rD_addr);
   7249          putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
   7250          break;
   7251       case 0x9F:  // 159
   7252          DIP("mfspr r%u (PSPB)\n", rD_addr);
   7253          putIReg( rD_addr, getGST( PPC_GST_PSPB) );
   7254          break;
   7255       case 0x380:  // 896
   7256          DIP("mfspr r%u (PPR)\n", rD_addr);
   7257          putIReg( rD_addr, getGST( PPC_GST_PPR) );
   7258          break;
   7259       case 0x382:  // 898
   7260          DIP("mfspr r%u (PPR)32\n", rD_addr);
   7261          putIReg( rD_addr, getGST( PPC_GST_PPR32) );
   7262          break;
   7263       case 0x100:
   7264          DIP("mfvrsave r%u\n", rD_addr);
   7265          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
   7266                                          /* Signed */False) );
   7267          break;
   7268 
   7269       case 0x103:
   7270          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
   7271          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
   7272          break;
   7273 
   7274       /* Even a lowly PPC7400 can run the associated helper, so no
   7275          obvious need for feature testing at this point. */
   7276       case 268 /* 0x10C */:
   7277       case 269 /* 0x10D */: {
   7278          UInt     arg  = SPR==268 ? 0 : 1;
   7279          IRTemp   val  = newTemp(Ity_I32);
   7280          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
   7281          IRDirty* d    = unsafeIRDirty_1_N(
   7282                             val,
   7283                             0/*regparms*/,
   7284                             "ppc32g_dirtyhelper_MFSPR_268_269",
   7285                             fnptr_to_fnentry
   7286                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
   7287                             args
   7288                          );
   7289          /* execute the dirty call, dumping the result in val. */
   7290          stmt( IRStmt_Dirty(d) );
   7291          putIReg( rD_addr,
   7292                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   7293          DIP("mfspr r%u,%u", rD_addr, SPR);
   7294          break;
   7295       }
   7296 
   7297       /* Again, runs natively on PPC7400 (7447, really).  Not
   7298          bothering with a feature test. */
   7299       case 287: /* 0x11F */ {
   7300          IRTemp   val  = newTemp(Ity_I32);
   7301          IRExpr** args = mkIRExprVec_0();
   7302          IRDirty* d    = unsafeIRDirty_1_N(
   7303                             val,
   7304                             0/*regparms*/,
   7305                             "ppc32g_dirtyhelper_MFSPR_287",
   7306                             fnptr_to_fnentry
   7307                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
   7308                             args
   7309                          );
   7310          /* execute the dirty call, dumping the result in val. */
   7311          stmt( IRStmt_Dirty(d) );
   7312          putIReg( rD_addr,
   7313                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
   7314          DIP("mfspr r%u,%u", rD_addr, SPR);
   7315          break;
   7316       }
   7317 
   7318       default:
   7319          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
   7320          return False;
   7321       }
   7322       break;
   7323 
   7324    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
   7325       IRTemp   val  = newTemp(Ity_I64);
   7326       IRExpr** args = mkIRExprVec_0();
   7327       IRDirty* d    = unsafeIRDirty_1_N(
   7328                               val,
   7329                               0/*regparms*/,
   7330                               "ppcg_dirtyhelper_MFTB",
   7331                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
   7332                               args );
   7333       /* execute the dirty call, dumping the result in val. */
   7334       stmt( IRStmt_Dirty(d) );
   7335 
   7336       switch (TBR) {
   7337       case 269:
   7338          DIP("mftbu r%u", rD_addr);
   7339          putIReg( rD_addr,
   7340                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
   7341                                 /* Signed */False) );
   7342          break;
   7343       case 268:
   7344          DIP("mftb r%u", rD_addr);
   7345          putIReg( rD_addr, (mode64) ? mkexpr(val) :
   7346                                       unop(Iop_64to32, mkexpr(val)) );
   7347          break;
   7348       default:
   7349          return False; /* illegal instruction */
   7350       }
   7351       break;
   7352    }
   7353 
   7354    case 0x090: {
   7355       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
   7356       // b20==1: mtocrf (Move to One Cond Reg Field)
   7357       Int   cr;
   7358       UChar shft;
   7359       if (b11 != 0)
   7360          return False;
   7361       if (b20 == 1) {
   7362          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
   7363             1 field is written.  It seems more robust to decline to
   7364             decode the insn if so. */
   7365          switch (CRM) {
   7366             case 0x01: case 0x02: case 0x04: case 0x08:
   7367             case 0x10: case 0x20: case 0x40: case 0x80:
   7368                break;
   7369             default:
   7370                return False;
   7371          }
   7372       }
   7373       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
   7374                            CRM, rS_addr);
   7375       /* Write to each field specified by CRM */
   7376       for (cr = 0; cr < 8; cr++) {
   7377          if ((CRM & (1 << (7-cr))) == 0)
   7378             continue;
   7379          shft = 4*(7-cr);
   7380          putGST_field( PPC_GST_CR,
   7381                        binop(Iop_Shr32,
   7382                              mkNarrowTo32(ty, mkexpr(rS)),
   7383                              mkU8(shft)), cr );
   7384       }
   7385       break;
   7386    }
   7387 
   7388    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
   7389 
   7390       switch (SPR) {  // Choose a register...
   7391       case 0x1:
   7392          DIP("mtxer r%u\n", rS_addr);
   7393          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
   7394          break;
   7395       case 0x8:
   7396          DIP("mtlr r%u\n", rS_addr);
   7397          putGST( PPC_GST_LR, mkexpr(rS) );
   7398          break;
   7399       case 0x9:
   7400          DIP("mtctr r%u\n", rS_addr);
   7401          putGST( PPC_GST_CTR, mkexpr(rS) );
   7402          break;
   7403       case 0x100:
   7404          DIP("mtvrsave r%u\n", rS_addr);
   7405          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
   7406          break;
   7407       case 0x80:  // 128
   7408          DIP("mtspr r%u (TFHAR)\n", rS_addr);
   7409          putGST( PPC_GST_TFHAR, mkexpr(rS) );
   7410          break;
   7411       case 0x81:  // 129
   7412          DIP("mtspr r%u (TFIAR)\n", rS_addr);
   7413          putGST( PPC_GST_TFIAR, mkexpr(rS) );
   7414          break;
   7415       case 0x82:  // 130
   7416          DIP("mtspr r%u (TEXASR)\n", rS_addr);
   7417          putGST( PPC_GST_TEXASR, mkexpr(rS) );
   7418          break;
   7419       case 0x9F:  // 159
   7420          DIP("mtspr r%u (PSPB)\n", rS_addr);
   7421          putGST( PPC_GST_PSPB, mkexpr(rS) );
   7422          break;
   7423       case 0x380:  // 896
   7424          DIP("mtspr r%u (PPR)\n", rS_addr);
   7425          putGST( PPC_GST_PPR, mkexpr(rS) );
   7426          break;
   7427       case 0x382:  // 898
   7428          DIP("mtspr r%u (PPR32)\n", rS_addr);
   7429          putGST( PPC_GST_PPR32, mkexpr(rS) );
   7430          break;
   7431       default:
   7432          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
   7433          return False;
   7434       }
   7435       break;
   7436 
   7437    case 0x33:                // mfvsrd
   7438    {
   7439       UChar XS = ifieldRegXS( theInstr );
   7440       UChar rA_addr = ifieldRegA(theInstr);
   7441       IRExpr * high64;
   7442       IRTemp vS = newTemp( Ity_V128 );
   7443       DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
   7444 
   7445       /*  XS = SX || S
   7446        *  For SX=0, mfvsrd is treated as a Floating-Point
   7447        *            instruction in terms of resource availability.
   7448        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7449        *            terms of resource availability.
   7450        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7451        */
   7452       assign( vS, getVSReg( XS ) );
   7453       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7454       putIReg( rA_addr, (mode64) ? high64 :
   7455       unop( Iop_64to32, high64 ) );
   7456       break;
   7457    }
   7458 
   7459    case 0x73:                // mfvsrwz
   7460    {
   7461       UChar XS = ifieldRegXS( theInstr );
   7462       UChar rA_addr = ifieldRegA(theInstr);
   7463       IRExpr * high64;
   7464       IRTemp vS = newTemp( Ity_V128 );
   7465       DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
   7466       /*  XS = SX || S
   7467        *  For SX=0, mfvsrwz is treated as a Floating-Point
   7468        *            instruction in terms of resource availability.
   7469        *  For SX=1, mfvsrwz is treated as a Vector instruction in
   7470        *            terms of resource availability.
   7471        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7472        */
   7473 
   7474       assign( vS, getVSReg( XS ) );
   7475       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   7476       /* move value to the destination setting the upper 32-bits to zero */
   7477       putIReg( rA_addr, (mode64) ?
   7478                                   binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
   7479                                   unop(  Iop_64to32,
   7480                                          binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
   7481       break;
   7482    }
   7483 
   7484    case 0xB3:                // mtvsrd
   7485    {
   7486       UChar XT = ifieldRegXT( theInstr );
   7487       UChar rA_addr = ifieldRegA(theInstr);
   7488       IRTemp rA = newTemp(ty);
   7489       DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
   7490       /*  XS = SX || S
   7491        *  For SX=0, mfvsrd is treated as a Floating-Point
   7492        *            instruction in terms of resource availability.
   7493        *  For SX=1, mfvsrd is treated as a Vector instruction in
   7494        *            terms of resource availability.
   7495        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7496        */
   7497       assign( rA, getIReg(rA_addr) );
   7498 
   7499       if (mode64)
   7500          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
   7501       else
   7502          putVSReg( XT, binop( Iop_64HLtoV128,
   7503                               binop( Iop_32HLto64,
   7504                                      mkU32( 0 ),
   7505                                      mkexpr( rA ) ),
   7506                                      mkU64( 0 ) ) );
   7507       break;
   7508    }
   7509 
   7510    case 0xD3:                // mtvsrwa
   7511    {
   7512       UChar XT = ifieldRegXT( theInstr );
   7513       UChar rA_addr = ifieldRegA(theInstr);
   7514       IRTemp rA = newTemp( Ity_I32 );
   7515       DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
   7516       /*  XS = SX || S
   7517        *  For SX=0, mtvsrwa is treated as a Floating-Point
   7518        *            instruction in terms of resource availability.
   7519        *  For SX=1, mtvsrwa is treated as a Vector instruction in
   7520        *            terms of resource availability.
   7521        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7522        */
   7523       if (mode64)
   7524          assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7525       else
   7526          assign( rA, getIReg(rA_addr) );
   7527 
   7528       putVSReg( XT, binop( Iop_64HLtoV128,
   7529                            unop( Iop_32Sto64, mkexpr( rA ) ),
   7530                            mkU64( 0 ) ) );
   7531       break;
   7532    }
   7533 
   7534    case 0xF3:                // mtvsrwz
   7535       {
   7536          UChar XT = ifieldRegXT( theInstr );
   7537          UChar rA_addr = ifieldRegA(theInstr);
   7538          IRTemp rA = newTemp( Ity_I32 );
   7539          DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
   7540          /*  XS = SX || S
   7541           *  For SX=0, mtvsrwz is treated as a Floating-Point
   7542           *            instruction in terms of resource availability.
   7543           *  For SX=1, mtvsrwz is treated as a Vector instruction in
   7544           *            terms of resource availability.
   7545           * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
   7546           */
   7547          if (mode64)
   7548              assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
   7549          else
   7550              assign( rA, getIReg(rA_addr) );
   7551 
   7552          putVSReg( XT, binop( Iop_64HLtoV128,
   7553                               binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
   7554                               mkU64( 0 ) ) );
   7555          break;
   7556       }
   7557 
   7558    default:
   7559       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
   7560       return False;
   7561    }
   7562    return True;
   7563 }
   7564 
   7565 
   7566 /*
   7567   Cache Management Instructions
   7568 */
   7569 static Bool dis_cache_manage ( UInt         theInstr,
   7570                                DisResult*   dres,
   7571                                const VexArchInfo* guest_archinfo )
   7572 {
   7573    /* X-Form */
   7574    UChar opc1    = ifieldOPC(theInstr);
   7575    UChar b21to25 = ifieldRegDS(theInstr);
   7576    UChar rA_addr = ifieldRegA(theInstr);
   7577    UChar rB_addr = ifieldRegB(theInstr);
   7578    UInt  opc2    = ifieldOPClo10(theInstr);
   7579    UChar b0      = ifieldBIT0(theInstr);
   7580    UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
   7581    Bool  is_dcbzl = False;
   7582 
   7583    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7584 
   7585    // Check for valid hint values for dcbt and dcbtst as currently described in
   7586    // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
   7587    // means of modeling the hint anyway.
   7588    if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
   7589       if (b21to25 == 0x10 || b21to25 < 0x10)
   7590          b21to25 = 0;
   7591    }
   7592    if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
   7593       b21to25 = 0;
   7594 
   7595    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
   7596       if (b21to25 == 1) {
   7597          is_dcbzl = True;
   7598          b21to25 = 0;
   7599          if (!(guest_archinfo->ppc_dcbzl_szB)) {
   7600             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
   7601             return False;
   7602          }
   7603       }
   7604    }
   7605 
   7606    if (opc1 != 0x1F || b0 != 0) {
   7607       if (0) vex_printf("dis_cache_manage %d %d\n",
   7608                         opc1, b0);
   7609       vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
   7610       return False;
   7611    }
   7612 
   7613    /* stay sane .. */
   7614    vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
   7615 
   7616    switch (opc2) {
   7617 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
   7618 //zz       vassert(0); /* AWAITING TEST CASE */
   7619 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
   7620 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
   7621 //zz       break;
   7622 
   7623    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
   7624       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
   7625       /* nop as far as vex is concerned */
   7626       break;
   7627 
   7628    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
   7629       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
   7630       /* nop as far as vex is concerned */
   7631       break;
   7632 
   7633    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
   7634       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
   7635       /* nop as far as vex is concerned */
   7636       break;
   7637 
   7638    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
   7639       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
   7640       /* nop as far as vex is concerned */
   7641       break;
   7642 
   7643    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
   7644                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
   7645       /* Clear all bytes in cache block at (rA|0) + rB. */
   7646       IRTemp  EA   = newTemp(ty);
   7647       IRTemp  addr = newTemp(ty);
   7648       IRExpr* irx_addr;
   7649       UInt    i;
   7650       UInt clearszB;
   7651       if (is_dcbzl) {
   7652           clearszB = guest_archinfo->ppc_dcbzl_szB;
   7653           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
   7654       }
   7655       else {
   7656           clearszB = guest_archinfo->ppc_dcbz_szB;
   7657           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
   7658       }
   7659 
   7660       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7661 
   7662       if (mode64) {
   7663          /* Round EA down to the start of the containing block. */
   7664          assign( addr, binop( Iop_And64,
   7665                               mkexpr(EA),
   7666                               mkU64( ~((ULong)clearszB-1) )) );
   7667 
   7668          for (i = 0; i < clearszB / 8; i++) {
   7669             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
   7670             store( irx_addr, mkU64(0) );
   7671          }
   7672       } else {
   7673          /* Round EA down to the start of the containing block. */
   7674          assign( addr, binop( Iop_And32,
   7675                               mkexpr(EA),
   7676                               mkU32( ~(clearszB-1) )) );
   7677 
   7678          for (i = 0; i < clearszB / 4; i++) {
   7679             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
   7680             store( irx_addr, mkU32(0) );
   7681          }
   7682       }
   7683       break;
   7684    }
   7685 
   7686    case 0x3D6: {
   7687       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
   7688       /* Invalidate all translations containing code from the cache
   7689          block at (rA|0) + rB. */
   7690       IRTemp EA   = newTemp(ty);
   7691       IRTemp addr = newTemp(ty);
   7692       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
   7693       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7694 
   7695       /* Round EA down to the start of the containing block. */
   7696       assign( addr, binop( mkSzOp(ty, Iop_And8),
   7697                            mkexpr(EA),
   7698                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
   7699       putGST( PPC_GST_CMSTART, mkexpr(addr) );
   7700       putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
   7701 
   7702       /* be paranoid ... */
   7703       stmt( IRStmt_MBE(Imbe_Fence) );
   7704 
   7705       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
   7706       dres->jk_StopHere = Ijk_InvalICache;
   7707       dres->whatNext    = Dis_StopHere;
   7708       break;
   7709    }
   7710 
   7711    default:
   7712       vex_printf("dis_cache_manage(ppc)(opc2)\n");
   7713       return False;
   7714    }
   7715    return True;
   7716 }
   7717 
   7718 
   7719 /*------------------------------------------------------------*/
   7720 /*--- Floating Point Helpers                               ---*/
   7721 /*------------------------------------------------------------*/
   7722 
   7723 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
   7724 /* Produces a value in 0 .. 3, which is encoded as per the type
   7725    IRRoundingMode.  PPCRoundingMode encoding is different to
   7726    IRRoundingMode, so need to map it.
   7727 */
   7728 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
   7729 {
   7730 /*
   7731    rounding mode | PPC | IR
   7732    ------------------------
   7733    to nearest    | 00  | 00
   7734    to zero       | 01  | 11
   7735    to +infinity  | 10  | 10
   7736    to -infinity  | 11  | 01
   7737 */
   7738    IRTemp rm_PPC32 = newTemp(Ity_I32);
   7739    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
   7740 
   7741    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7742    return binop( Iop_Xor32,
   7743                  mkexpr(rm_PPC32),
   7744                  binop( Iop_And32,
   7745                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
   7746                         mkU32(2) ));
   7747 }
   7748 
   7749 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
   7750  * mapping would still work with the extended three bit DFP rounding
   7751  * mode designator.
   7752 
   7753  *  rounding mode                     | PPC  |  IR
   7754  *  -----------------------------------------------
   7755  *  to nearest, ties to even          | 000  | 000
   7756  *  to zero                           | 001  | 011
   7757  *  to +infinity                      | 010  | 010
   7758  *  to -infinity                      | 011  | 001
   7759  *  to nearest, ties away from 0      | 100  | 100
   7760  *  to nearest, ties toward 0         | 101  | 111
   7761  *  to away from 0                    | 110  | 110
   7762  *  to prepare for shorter precision  | 111  | 101
   7763  */
   7764 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
   7765 {
   7766    IRTemp rm_PPC32 = newTemp( Ity_I32 );
   7767    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
   7768 
   7769    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
   7770    return binop( Iop_Xor32,
   7771                  mkexpr( rm_PPC32 ),
   7772                  binop( Iop_And32,
   7773                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
   7774                         mkU32( 2 ) ) );
   7775 }
   7776 
   7777 #define NANmaskSingle   0x7F800000
   7778 #define NANmaskDouble   0x7FF00000
   7779 
   7780 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
   7781 {
   7782    IRTemp exp_zero  = newTemp(Ity_I8);
   7783    IRTemp frac_mask = newTemp(Ity_I32);
   7784    IRTemp frac_not_zero = newTemp(Ity_I8);
   7785 
   7786    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
   7787     * The input value is always 64-bits, for single precision values, the
   7788     * lower 32 bits must be zero.
   7789     *
   7790     * Single Pricision
   7791     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
   7792     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
   7793     *  [31:0]  unused for single precision representation
   7794     *
   7795     * Double Pricision
   7796     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
   7797     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
   7798     *
   7799     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
   7800     */
   7801    assign( frac_mask, unop( Iop_Not32,
   7802                             binop( Iop_Or32,
   7803                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
   7804 
   7805    assign( exp_zero,
   7806            unop( Iop_1Sto8,
   7807                  binop( Iop_CmpEQ32,
   7808                         binop( Iop_And32,
   7809                                unop( Iop_64HIto32,
   7810                                      unop( Iop_ReinterpF64asI64,
   7811                                            value ) ),
   7812                                Hi32Mask ),
   7813                         Hi32Mask ) ) );
   7814    assign( frac_not_zero,
   7815            binop( Iop_Or8,
   7816                   unop( Iop_1Sto8,
   7817                         binop( Iop_CmpNE32,
   7818                                binop( Iop_And32,
   7819                                       unop( Iop_64HIto32,
   7820                                             unop( Iop_ReinterpF64asI64,
   7821                                                   value ) ),
   7822                                       mkexpr( frac_mask ) ),
   7823                                mkU32( 0x0 ) ) ),
   7824                   unop( Iop_1Sto8,
   7825                         binop( Iop_CmpNE32,
   7826                                binop( Iop_And32,
   7827                                       unop( Iop_64to32,
   7828                                             unop( Iop_ReinterpF64asI64,
   7829                                                   value ) ),
   7830                                       mkU32( 0xFFFFFFFF ) ),
   7831                                mkU32( 0x0 ) ) ) ) );
   7832    return unop( Iop_8Sto32,
   7833                 binop( Iop_And8,
   7834                        mkexpr( exp_zero ),
   7835                        mkexpr( frac_not_zero ) ) );
   7836 }
   7837 
   7838 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
   7839 {
   7840    /* This function will only complement the 64-bit floating point value if it
   7841     * is not Nan.  NaN is not a signed value.  Need to do computations using
   7842     * 32-bit operands to ensure it will run in 32-bit mode.
   7843     */
   7844    return  binop( Iop_32HLto64,
   7845                   binop( Iop_Or32,
   7846                          binop( Iop_And32,
   7847                                 nan_mask,
   7848                                 unop( Iop_64HIto32,
   7849                                       unop( Iop_ReinterpF64asI64,
   7850                                             value ) ) ),
   7851                          binop( Iop_And32,
   7852                                 unop( Iop_Not32,
   7853                                       nan_mask ),
   7854                                 unop( Iop_64HIto32,
   7855                                       unop( Iop_ReinterpF64asI64,
   7856                                             unop( Iop_NegF64,
   7857                                                   value ) ) ) ) ),
   7858                   unop( Iop_64to32,
   7859                         unop( Iop_ReinterpF64asI64, value ) ) );
   7860 }
   7861 
   7862 /*------------------------------------------------------------*/
   7863 /*--- Floating Point Instruction Translation               ---*/
   7864 /*------------------------------------------------------------*/
   7865 
   7866 /*
   7867   Floating Point Load Instructions
   7868 */
   7869 static Bool dis_fp_load ( UInt theInstr )
   7870 {
   7871    /* X-Form, D-Form */
   7872    UChar opc1      = ifieldOPC(theInstr);
   7873    UChar frD_addr  = ifieldRegDS(theInstr);
   7874    UChar rA_addr   = ifieldRegA(theInstr);
   7875    UChar rB_addr   = ifieldRegB(theInstr);
   7876    UInt  opc2      = ifieldOPClo10(theInstr);
   7877    UChar b0        = ifieldBIT0(theInstr);
   7878    UInt  uimm16    = ifieldUIMM16(theInstr);
   7879 
   7880    Int    simm16 = extend_s_16to32(uimm16);
   7881    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   7882    IRTemp EA     = newTemp(ty);
   7883    IRTemp rA     = newTemp(ty);
   7884    IRTemp rB     = newTemp(ty);
   7885    IRTemp iHi    = newTemp(Ity_I32);
   7886    IRTemp iLo    = newTemp(Ity_I32);
   7887 
   7888    assign( rA, getIReg(rA_addr) );
   7889    assign( rB, getIReg(rB_addr) );
   7890 
   7891    /* These are completely straightforward from a rounding and status
   7892       bits perspective: no rounding involved and no funny status or CR
   7893       bits affected. */
   7894 
   7895    switch (opc1) {
   7896    case 0x30: // lfs (Load Float Single, PPC32 p441)
   7897       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7898       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7899       putFReg( frD_addr,
   7900                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7901       break;
   7902 
   7903    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
   7904       if (rA_addr == 0)
   7905          return False;
   7906       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7907       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7908       putFReg( frD_addr,
   7909                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7910       putIReg( rA_addr, mkexpr(EA) );
   7911       break;
   7912 
   7913    case 0x32: // lfd (Load Float Double, PPC32 p437)
   7914       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7915       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   7916       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7917       break;
   7918 
   7919    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
   7920       if (rA_addr == 0)
   7921          return False;
   7922       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
   7923       assign( EA, ea_rA_simm(rA_addr, simm16) );
   7924       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7925       putIReg( rA_addr, mkexpr(EA) );
   7926       break;
   7927 
   7928    case 0x1F:
   7929       if (b0 != 0) {
   7930          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
   7931          return False;
   7932       }
   7933 
   7934       switch(opc2) {
   7935       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
   7936          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7937          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7938          putFReg( frD_addr, unop( Iop_F32toF64,
   7939                                   load(Ity_F32, mkexpr(EA))) );
   7940          break;
   7941 
   7942       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
   7943          if (rA_addr == 0)
   7944             return False;
   7945          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7946          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7947          putFReg( frD_addr,
   7948                   unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
   7949          putIReg( rA_addr, mkexpr(EA) );
   7950          break;
   7951 
   7952       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
   7953          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7954          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   7955          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7956          break;
   7957 
   7958       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
   7959          if (rA_addr == 0)
   7960             return False;
   7961          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7962          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   7963          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
   7964          putIReg( rA_addr, mkexpr(EA) );
   7965          break;
   7966 
   7967       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
   7968          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7969          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7970          assign( iLo, load(Ity_I32, mkexpr(EA)) );
   7971          assign( iHi, binop(Iop_Sub32,
   7972                             mkU32(0),
   7973                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
   7974          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
   7975                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
   7976          break;
   7977 
   7978       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
   7979       {
   7980          IRTemp dw = newTemp( Ity_I64 );
   7981          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
   7982          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   7983          assign( iLo, load(Ity_I32, mkexpr(EA)) );
   7984          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
   7985          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
   7986          break;
   7987       }
   7988 
   7989       default:
   7990          vex_printf("dis_fp_load(ppc)(opc2)\n");
   7991          return False;
   7992       }
   7993       break;
   7994 
   7995    default:
   7996       vex_printf("dis_fp_load(ppc)(opc1)\n");
   7997       return False;
   7998    }
   7999    return True;
   8000 }
   8001 
   8002 
   8003 
   8004 /*
   8005   Floating Point Store Instructions
   8006 */
   8007 static Bool dis_fp_store ( UInt theInstr )
   8008 {
   8009    /* X-Form, D-Form */
   8010    UChar opc1      = ifieldOPC(theInstr);
   8011    UChar frS_addr  = ifieldRegDS(theInstr);
   8012    UChar rA_addr   = ifieldRegA(theInstr);
   8013    UChar rB_addr   = ifieldRegB(theInstr);
   8014    UInt  opc2      = ifieldOPClo10(theInstr);
   8015    UChar b0        = ifieldBIT0(theInstr);
   8016    Int   uimm16    = ifieldUIMM16(theInstr);
   8017 
   8018    Int    simm16 = extend_s_16to32(uimm16);
   8019    IRTemp frS    = newTemp(Ity_F64);
   8020    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
   8021    IRTemp EA     = newTemp(ty);
   8022    IRTemp rA     = newTemp(ty);
   8023    IRTemp rB     = newTemp(ty);
   8024 
   8025    assign( frS, getFReg(frS_addr) );
   8026    assign( rA,  getIReg(rA_addr) );
   8027    assign( rB,  getIReg(rB_addr) );
   8028 
   8029    /* These are straightforward from a status bits perspective: no
   8030       funny status or CR bits affected.  For single precision stores,
   8031       the values are truncated and denormalised (not rounded) to turn
   8032       them into single precision values. */
   8033 
   8034    switch (opc1) {
   8035 
   8036    case 0x34: // stfs (Store Float Single, PPC32 p518)
   8037       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   8038       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   8039       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
   8040          the value to be stored in the correct way, without any
   8041          rounding. */
   8042       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   8043       break;
   8044 
   8045    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
   8046       if (rA_addr == 0)
   8047          return False;
   8048       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   8049       assign( EA, ea_rA_simm(rA_addr, simm16) );
   8050       /* See comment for stfs */
   8051       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   8052       putIReg( rA_addr, mkexpr(EA) );
   8053       break;
   8054 
   8055    case 0x36: // stfd (Store Float Double, PPC32 p513)
   8056       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   8057       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
   8058       store( mkexpr(EA), mkexpr(frS) );
   8059       break;
   8060 
   8061    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
   8062       if (rA_addr == 0)
   8063          return False;
   8064       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
   8065       assign( EA, ea_rA_simm(rA_addr, simm16) );
   8066       store( mkexpr(EA), mkexpr(frS) );
   8067       putIReg( rA_addr, mkexpr(EA) );
   8068       break;
   8069 
   8070    case 0x1F:
   8071       if (b0 != 0) {
   8072          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
   8073          return False;
   8074       }
   8075       switch(opc2) {
   8076       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
   8077          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   8078          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   8079          /* See note for stfs */
   8080          store( mkexpr(EA),
   8081                 unop(Iop_TruncF64asF32, mkexpr(frS)) );
   8082          break;
   8083 
   8084       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
   8085          if (rA_addr == 0)
   8086             return False;
   8087          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   8088          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   8089          /* See note for stfs */
   8090          store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
   8091          putIReg( rA_addr, mkexpr(EA) );
   8092          break;
   8093 
   8094       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
   8095          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   8096          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   8097          store( mkexpr(EA), mkexpr(frS) );
   8098          break;
   8099 
   8100       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
   8101          if (rA_addr == 0)
   8102             return False;
   8103          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   8104          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
   8105          store( mkexpr(EA), mkexpr(frS) );
   8106          putIReg( rA_addr, mkexpr(EA) );
   8107          break;
   8108 
   8109       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
   8110          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8111          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
   8112          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   8113          store( mkexpr(EA),
   8114                 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
   8115          break;
   8116 
   8117       default:
   8118          vex_printf("dis_fp_store(ppc)(opc2)\n");
   8119          return False;
   8120       }
   8121       break;
   8122 
   8123    default:
   8124       vex_printf("dis_fp_store(ppc)(opc1)\n");
   8125       return False;
   8126    }
   8127    return True;
   8128 }
   8129 
   8130 
   8131 
   8132 /*
   8133   Floating Point Arith Instructions
   8134 */
   8135 static Bool dis_fp_arith ( UInt theInstr )
   8136 {
   8137    /* A-Form */
   8138    UChar opc1     = ifieldOPC(theInstr);
   8139    UChar frD_addr = ifieldRegDS(theInstr);
   8140    UChar frA_addr = ifieldRegA(theInstr);
   8141    UChar frB_addr = ifieldRegB(theInstr);
   8142    UChar frC_addr = ifieldRegC(theInstr);
   8143    UChar opc2     = ifieldOPClo5(theInstr);
   8144    UChar flag_rC  = ifieldBIT0(theInstr);
   8145 
   8146    IRTemp  frD = newTemp(Ity_F64);
   8147    IRTemp  frA = newTemp(Ity_F64);
   8148    IRTemp  frB = newTemp(Ity_F64);
   8149    IRTemp  frC = newTemp(Ity_F64);
   8150    IRExpr* rm  = get_IR_roundingmode();
   8151 
   8152    /* By default, we will examine the results of the operation and set
   8153       fpscr[FPRF] accordingly. */
   8154    Bool set_FPRF = True;
   8155 
   8156    /* By default, if flag_RC is set, we will clear cr1 after the
   8157       operation.  In reality we should set cr1 to indicate the
   8158       exception status of the operation, but since we're not
   8159       simulating exceptions, the exception status will appear to be
   8160       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8161    Bool clear_CR1 = True;
   8162 
   8163    assign( frA, getFReg(frA_addr));
   8164    assign( frB, getFReg(frB_addr));
   8165    assign( frC, getFReg(frC_addr));
   8166 
   8167    switch (opc1) {
   8168    case 0x3B:
   8169       switch (opc2) {
   8170       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
   8171          if (frC_addr != 0)
   8172             return False;
   8173          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8174              frD_addr, frA_addr, frB_addr);
   8175          assign( frD, triop( Iop_DivF64r32,
   8176                              rm, mkexpr(frA), mkexpr(frB) ));
   8177          break;
   8178 
   8179       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
   8180          if (frC_addr != 0)
   8181             return False;
   8182          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8183              frD_addr, frA_addr, frB_addr);
   8184          assign( frD, triop( Iop_SubF64r32,
   8185                              rm, mkexpr(frA), mkexpr(frB) ));
   8186          break;
   8187 
   8188       case 0x15: // fadds (Floating Add Single, PPC32 p401)
   8189          if (frC_addr != 0)
   8190             return False;
   8191          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8192              frD_addr, frA_addr, frB_addr);
   8193          assign( frD, triop( Iop_AddF64r32,
   8194                              rm, mkexpr(frA), mkexpr(frB) ));
   8195          break;
   8196 
   8197       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
   8198          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   8199          if (frA_addr != 0 || frC_addr != 0)
   8200             return False;
   8201          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
   8202              frD_addr, frB_addr);
   8203          // however illogically, on ppc970 this insn behaves identically
   8204          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
   8205          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
   8206          break;
   8207 
   8208       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
   8209          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8210          if (frA_addr != 0 || frC_addr != 0)
   8211             return False;
   8212          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
   8213              frD_addr, frB_addr);
   8214          { IRExpr* ieee_one
   8215               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   8216            assign( frD, triop( Iop_DivF64r32,
   8217                                rm,
   8218                                ieee_one, mkexpr(frB) ));
   8219          }
   8220          break;
   8221 
   8222       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
   8223          if (frB_addr != 0)
   8224             return False;
   8225          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8226              frD_addr, frA_addr, frC_addr);
   8227          assign( frD, triop( Iop_MulF64r32,
   8228                              rm, mkexpr(frA), mkexpr(frC) ));
   8229          break;
   8230 
   8231       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
   8232          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8233          // Undocumented instruction?
   8234          if (frA_addr != 0 || frC_addr != 0)
   8235             return False;
   8236          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
   8237              frD_addr, frB_addr);
   8238          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
   8239          break;
   8240 
   8241       default:
   8242          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
   8243          return False;
   8244       }
   8245       break;
   8246 
   8247    case 0x3F:
   8248       switch (opc2) {
   8249       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
   8250          if (frC_addr != 0)
   8251             return False;
   8252          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8253              frD_addr, frA_addr, frB_addr);
   8254          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
   8255          break;
   8256 
   8257       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
   8258          if (frC_addr != 0)
   8259             return False;
   8260          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8261              frD_addr, frA_addr, frB_addr);
   8262          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
   8263          break;
   8264 
   8265       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
   8266          if (frC_addr != 0)
   8267             return False;
   8268          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8269              frD_addr, frA_addr, frB_addr);
   8270          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
   8271          break;
   8272 
   8273       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
   8274          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
   8275          if (frA_addr != 0 || frC_addr != 0)
   8276             return False;
   8277          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
   8278              frD_addr, frB_addr);
   8279          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
   8280          break;
   8281 
   8282       case 0x17: { // fsel (Floating Select, PPC32 p426)
   8283          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8284          IRTemp cc    = newTemp(Ity_I32);
   8285          IRTemp cc_b0 = newTemp(Ity_I32);
   8286 
   8287          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8288              frD_addr, frA_addr, frC_addr, frB_addr);
   8289 
   8290          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
   8291          // => GT|EQ == (cc & 0x1 == 0)
   8292          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
   8293                                        IRExpr_Const(IRConst_F64(0))) );
   8294          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
   8295 
   8296          // frD = (frA >= 0.0) ? frC : frB
   8297          //     = (cc_b0 == 0) ? frC : frB
   8298          assign( frD,
   8299                  IRExpr_ITE(
   8300                     binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
   8301                     mkexpr(frC),
   8302                     mkexpr(frB) ));
   8303 
   8304          /* One of the rare ones which don't mess with FPRF */
   8305          set_FPRF = False;
   8306          break;
   8307       }
   8308 
   8309       case 0x18: // fre (Floating Reciprocal Estimate)
   8310          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8311          // Note: unclear whether this insn really exists or not
   8312          // ppc970 doesn't have it, but POWER5 does
   8313          if (frA_addr != 0 || frC_addr != 0)
   8314             return False;
   8315          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
   8316              frD_addr, frB_addr);
   8317          { IRExpr* ieee_one
   8318               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   8319            assign( frD, triop( Iop_DivF64,
   8320                                rm,
   8321                                ieee_one, mkexpr(frB) ));
   8322          }
   8323          break;
   8324 
   8325       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
   8326          if (frB_addr != 0)
   8327             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
   8328          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8329              frD_addr, frA_addr, frC_addr);
   8330          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
   8331          break;
   8332 
   8333       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
   8334          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
   8335          if (frA_addr != 0 || frC_addr != 0)
   8336             return False;
   8337          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
   8338              frD_addr, frB_addr);
   8339          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
   8340          break;
   8341 
   8342       default:
   8343          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
   8344          return False;
   8345       }
   8346       break;
   8347 
   8348    default:
   8349       vex_printf("dis_fp_arith(ppc)(opc1)\n");
   8350       return False;
   8351    }
   8352 
   8353    putFReg( frD_addr, mkexpr(frD) );
   8354 
   8355    if (set_FPRF) {
   8356       // XXX XXX XXX FIXME
   8357       // set FPRF from frD
   8358    }
   8359 
   8360    if (flag_rC && clear_CR1) {
   8361       putCR321( 1, mkU8(0) );
   8362       putCR0( 1, mkU8(0) );
   8363    }
   8364 
   8365    return True;
   8366 }
   8367 
   8368 
   8369 
   8370 /*
   8371   Floating Point Mult-Add Instructions
   8372 */
   8373 static Bool dis_fp_multadd ( UInt theInstr )
   8374 {
   8375    /* A-Form */
   8376    UChar opc1     = ifieldOPC(theInstr);
   8377    UChar frD_addr = ifieldRegDS(theInstr);
   8378    UChar frA_addr = ifieldRegA(theInstr);
   8379    UChar frB_addr = ifieldRegB(theInstr);
   8380    UChar frC_addr = ifieldRegC(theInstr);
   8381    UChar opc2     = ifieldOPClo5(theInstr);
   8382    UChar flag_rC  = ifieldBIT0(theInstr);
   8383 
   8384    IRTemp  frD = newTemp(Ity_F64);
   8385    IRTemp  frA = newTemp(Ity_F64);
   8386    IRTemp  frB = newTemp(Ity_F64);
   8387    IRTemp  frC = newTemp(Ity_F64);
   8388    IRTemp  rmt = newTemp(Ity_I32);
   8389    IRTemp  tmp = newTemp(Ity_F64);
   8390    IRTemp  sign_tmp = newTemp(Ity_I64);
   8391    IRTemp  nan_mask = newTemp(Ity_I32);
   8392    IRExpr* rm;
   8393 
   8394    /* By default, we will examine the results of the operation and set
   8395       fpscr[FPRF] accordingly. */
   8396    Bool set_FPRF = True;
   8397 
   8398    /* By default, if flag_RC is set, we will clear cr1 after the
   8399       operation.  In reality we should set cr1 to indicate the
   8400       exception status of the operation, but since we're not
   8401       simulating exceptions, the exception status will appear to be
   8402       zero.  Hence cr1 should be cleared if this is a . form insn. */
   8403    Bool clear_CR1 = True;
   8404 
   8405    /* Bind the rounding mode expression to a temp; there's no
   8406       point in creating gratuitous CSEs, as we know we'll need
   8407       to use it twice. */
   8408    assign( rmt, get_IR_roundingmode() );
   8409    rm = mkexpr(rmt);
   8410 
   8411    assign( frA, getFReg(frA_addr));
   8412    assign( frB, getFReg(frB_addr));
   8413    assign( frC, getFReg(frC_addr));
   8414 
   8415    /* The rounding in this is all a bit dodgy.  The idea is to only do
   8416       one rounding.  That clearly isn't achieveable without dedicated
   8417       four-input IR primops, although in the single precision case we
   8418       can sort-of simulate it by doing the inner multiply in double
   8419       precision.
   8420 
   8421       In the negated cases, the negation happens after rounding. */
   8422 
   8423    switch (opc1) {
   8424    case 0x3B:
   8425       switch (opc2) {
   8426       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
   8427          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8428              frD_addr, frA_addr, frC_addr, frB_addr);
   8429          assign( frD, qop( Iop_MSubF64r32, rm,
   8430                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8431          break;
   8432 
   8433       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
   8434          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8435              frD_addr, frA_addr, frC_addr, frB_addr);
   8436          assign( frD, qop( Iop_MAddF64r32, rm,
   8437                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8438          break;
   8439 
   8440       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
   8441       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
   8442 
   8443          if (opc2 == 0x1E) {
   8444             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8445                      frD_addr, frA_addr, frC_addr, frB_addr);
   8446             assign( tmp, qop( Iop_MSubF64r32, rm,
   8447                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8448          } else {
   8449             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8450                      frD_addr, frA_addr, frC_addr, frB_addr);
   8451             assign( tmp, qop( Iop_MAddF64r32, rm,
   8452                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8453          }
   8454 
   8455          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8456                                       mkU32( NANmaskSingle ) ) );
   8457          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8458                                                mkexpr( nan_mask ) ) );
   8459          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8460          break;
   8461 
   8462       default:
   8463          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
   8464          return False;
   8465       }
   8466       break;
   8467 
   8468    case 0x3F:
   8469       switch (opc2) {
   8470       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
   8471          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8472              frD_addr, frA_addr, frC_addr, frB_addr);
   8473          assign( frD, qop( Iop_MSubF64, rm,
   8474                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8475          break;
   8476 
   8477       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
   8478          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8479              frD_addr, frA_addr, frC_addr, frB_addr);
   8480          assign( frD, qop( Iop_MAddF64, rm,
   8481                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8482          break;
   8483 
   8484       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
   8485       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
   8486 
   8487          if (opc2 == 0x1E) {
   8488             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8489                      frD_addr, frA_addr, frC_addr, frB_addr);
   8490             assign( tmp, qop( Iop_MSubF64, rm,
   8491                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
   8492          } else {
   8493             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
   8494                      frD_addr, frA_addr, frC_addr, frB_addr);
   8495             assign( tmp, qop( Iop_MAddF64, rm,
   8496                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
   8497          }
   8498 
   8499          assign( nan_mask, Check_NaN( mkexpr( tmp ),
   8500                                       mkU32( NANmaskDouble ) ) );
   8501          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
   8502                                                mkexpr( nan_mask ) ) );
   8503          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
   8504          break;
   8505 
   8506       default:
   8507          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
   8508          return False;
   8509       }
   8510       break;
   8511 
   8512    default:
   8513       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
   8514       return False;
   8515    }
   8516 
   8517    putFReg( frD_addr, mkexpr(frD) );
   8518 
   8519    if (set_FPRF) {
   8520       // XXX XXX XXX FIXME
   8521       // set FPRF from frD
   8522    }
   8523 
   8524    if (flag_rC && clear_CR1) {
   8525       putCR321( 1, mkU8(0) );
   8526       putCR0( 1, mkU8(0) );
   8527    }
   8528 
   8529    return True;
   8530 }
   8531 
   8532 /*
   8533  * fe_flag is set to 1 if any of the following conditions occurs:
   8534  *  - The floating-point operand in register FRB is a Zero, a
   8535  *    NaN, an Infinity, or a negative value.
   8536  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
   8537  *  Otherwise fe_flag is set to 0.
   8538  *
   8539  * fg_flag is set to 1 if either of the following conditions occurs.
   8540  *   - The floating-point operand in register FRB is a Zero, an
   8541  *     Infinity, or a denormalized value.
   8542  *  Otherwise fg_flag is set to 0.
   8543  *
   8544  */
   8545 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8546 {
   8547    // The following temps are for holding intermediate results
   8548    IRTemp e_b = newTemp(Ity_I32);
   8549    IRExpr * fe_flag,  * fg_flag;
   8550    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8551    UInt bias = sp? 127 : 1023;
   8552    IRExpr * frbNaN, * frbDenorm, * frBNeg;
   8553    IRExpr * eb_LTE;
   8554    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8555    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8556    *fe_flag_tmp = newTemp(Ity_I32);
   8557    *fg_flag_tmp = newTemp(Ity_I32);
   8558    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
   8559    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8560 
   8561    //////////////////  fe_flag tests BEGIN //////////////////////
   8562    /* We first do all tests that may result in setting fe_flag to '1'.
   8563     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
   8564     * for details.)
   8565     */
   8566    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
   8567    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
   8568    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
   8569    {
   8570       // Test_value = -970 for double precision
   8571       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
   8572       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
   8573    }
   8574    frBNeg = binop( Iop_CmpEQ32,
   8575                    binop( Iop_Shr32,
   8576                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
   8577                           mkU8( 31 ) ),
   8578                    mkU32( 1 ) );
   8579    //////////////////  fe_flag tests END //////////////////////
   8580 
   8581    //////////////////  fg_flag tests BEGIN //////////////////////
   8582    /*
   8583     * The following tests were already performed above in the fe_flag
   8584     * tests.  So these conditions will result in both fe_ and fg_ flags
   8585     * being set.
   8586     *   - Test if FRB is Zero
   8587     *   - Test if FRB is an Infinity
   8588     */
   8589 
   8590    /*
   8591     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8592     * the exp is 0 and the fraction is non-zero.
   8593     */
   8594    if (sp) {
   8595       IRTemp frac_part = newTemp(Ity_I32);
   8596       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
   8597       frbDenorm
   8598                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8599                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
   8600    } else {
   8601       IRExpr * hi32, * low32, * fraction_is_nonzero;
   8602       IRTemp frac_part = newTemp(Ity_I64);
   8603 
   8604       assign( frac_part, FP_FRAC_PART(frB_Int) );
   8605       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8606       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8607       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8608                                                 mkU32( 0 ) );
   8609       frbDenorm
   8610                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
   8611                          fraction_is_nonzero );
   8612    }
   8613    //////////////////  fg_flag tests END //////////////////////
   8614 
   8615    /////////////////////////
   8616    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
   8617                     mkOR1( frbNaN,
   8618                            mkOR1( mkexpr( frbInf_tmp ),
   8619                                   mkOR1( frBNeg, eb_LTE ) ) ) );
   8620 
   8621    fe_flag = unop(Iop_1Uto32, fe_flag);
   8622 
   8623    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
   8624                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
   8625    fg_flag = unop(Iop_1Uto32, fg_flag);
   8626    assign (*fg_flag_tmp, fg_flag);
   8627    assign (*fe_flag_tmp, fe_flag);
   8628 }
   8629 /*
   8630  * fe_flag is set to 1 if any of the following conditions occurs:
   8631  *  - The double-precision floating-point operand in register FRA is a NaN or an
   8632  *    Infinity.
   8633  *  - The double-precision floating-point operand in register FRB is a Zero, a
   8634  *    NaN, or an Infinity.
   8635  *  - e_b is less than or equal to -1022.
   8636  *  - e_b is greater than or equal to 1021.
   8637  *  - The double-precision floating-point operand in register FRA is not a zero
   8638  *    and the difference, e_a - e_b, is greater than or equal to 1023.
   8639  *  - The double-precision floating-point operand in register FRA is not a zero
   8640  *    and the difference, e_a - e_b, is less than or equal to -1021.
   8641  *  - The double-precision floating-point operand in register FRA is not a zero
   8642  *    and e_a is less than or equal to -970
   8643  *  Otherwise fe_flag is set to 0.
   8644  *
   8645  * fg_flag is set to 1 if either of the following conditions occurs.
   8646  *   - The double-precision floating-point operand in register FRA is an Infinity.
   8647  *   - The double-precision floating-point operand in register FRB is a Zero, an
   8648  *     Infinity, or a denormalized value.
   8649  *  Otherwise fg_flag is set to 0.
   8650  *
   8651  */
   8652 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
   8653 {
   8654    // The following temps are for holding intermediate results
   8655    IRTemp e_a = newTemp(Ity_I32);
   8656    IRTemp e_b = newTemp(Ity_I32);
   8657    IRTemp frA_exp_shR = newTemp(Ity_I32);
   8658    IRTemp frB_exp_shR = newTemp(Ity_I32);
   8659 
   8660    UInt bias = sp? 127 : 1023;
   8661    *fe_flag_tmp = newTemp(Ity_I32);
   8662    *fg_flag_tmp = newTemp(Ity_I32);
   8663 
   8664    /* The following variables hold boolean results from tests
   8665     * that are OR'ed together for setting the fe_ and fg_ flags.
   8666     * For some cases, the booleans are used more than once, so
   8667     * I make those IRTemp's instead of IRExpr's.
   8668     */
   8669    IRExpr * fraNaN, * frbNaN, * frbDenorm;
   8670    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
   8671    IRTemp  fraInf_tmp = newTemp(Ity_I1);
   8672    IRTemp  frbZero_tmp = newTemp(Ity_I1);
   8673    IRTemp  frbInf_tmp = newTemp(Ity_I1);
   8674    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
   8675 
   8676 /* The following are the flags that are set by OR'ing the results of
   8677  * all the tests done for tdiv.  These flags are the input to the specified CR.
   8678  */
   8679    IRExpr * fe_flag, * fg_flag;
   8680 
   8681    // Create temps that will be used throughout the following tests.
   8682    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
   8683    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
   8684    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
   8685    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
   8686    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
   8687 
   8688 
   8689    //////////////////  fe_flag tests BEGIN //////////////////////
   8690    /* We first do all tests that may result in setting fe_flag to '1'. */
   8691 
   8692    /*
   8693     * Test if the double-precision floating-point operand in register FRA is
   8694     * a NaN:
   8695     */
   8696    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
   8697    /*
   8698     * Test if the double-precision floating-point operand in register FRA is
   8699     * an Infinity.
   8700     */
   8701    assign(fraInf_tmp, is_Inf(frA_int, sp));
   8702 
   8703    /*
   8704     * Test if the double-precision floating-point operand in register FRB is
   8705     * a NaN:
   8706     */
   8707    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
   8708    /*
   8709     * Test if the double-precision floating-point operand in register FRB is
   8710     * an Infinity.
   8711     */
   8712    assign( frbInf_tmp, is_Inf(frB_int, sp) );
   8713    /*
   8714     * Test if the double-precision floating-point operand in register FRB is
   8715     * a Zero.
   8716     */
   8717    assign( frbZero_tmp, is_Zero(frB_int, sp) );
   8718 
   8719    /*
   8720     * Test if e_b <= -1022 for double precision;
   8721     * or e_b <= -126 for single precision
   8722     */
   8723    {
   8724       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
   8725       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
   8726    }
   8727 
   8728    /*
   8729     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
   8730     * or e_b >= -125 (125 < e_b) for single precision
   8731     */
   8732    {
   8733       Int test_value = sp ? 125 : 1021;
   8734       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
   8735    }
   8736 
   8737    /*
   8738     * Test if FRA != Zero and (e_a - e_b) >= bias
   8739     */
   8740    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
   8741    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8742                        binop( Iop_CmpLT32S, mkU32( bias ),
   8743                               binop( Iop_Sub32, mkexpr( e_a ),
   8744                                      mkexpr( e_b ) ) ) );
   8745 
   8746    /*
   8747     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
   8748     */
   8749    {
   8750       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
   8751 
   8752       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
   8753                           binop( Iop_CmpLE32S,
   8754                                  binop( Iop_Sub32,
   8755                                         mkexpr( e_a ),
   8756                                         mkexpr( e_b ) ),
   8757                                         mkU32( test_value ) ) );
   8758    }
   8759 
   8760    /*
   8761     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
   8762     */
   8763    {
   8764       UInt test_value = 0xfffffc36;  //Int test_value = -970;
   8765 
   8766       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
   8767                                                         mkexpr( e_a ),
   8768                                                         mkU32( test_value ) ) );
   8769    }
   8770    //////////////////  fe_flag tests END //////////////////////
   8771 
   8772    //////////////////  fg_flag tests BEGIN //////////////////////
   8773    /*
   8774     * The following tests were already performed above in the fe_flag
   8775     * tests.  So these conditions will result in both fe_ and fg_ flags
   8776     * being set.
   8777     *   - Test if FRA is an Infinity
   8778     *   - Test if FRB ix Zero
   8779     *   - Test if FRB is an Infinity
   8780     */
   8781 
   8782    /*
   8783     * Test if FRB holds a denormalized value.  A denormalized value is one where
   8784     * the exp is 0 and the fraction is non-zero.
   8785     */
   8786    {
   8787       IRExpr * fraction_is_nonzero;
   8788 
   8789       if (sp) {
   8790          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
   8791                                       mkU32( 0 ) );
   8792       } else {
   8793          IRExpr * hi32, * low32;
   8794          IRTemp frac_part = newTemp(Ity_I64);
   8795          assign( frac_part, FP_FRAC_PART(frB_int) );
   8796 
   8797          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
   8798          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
   8799          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
   8800                                       mkU32( 0 ) );
   8801       }
   8802       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
   8803                                  mkU32( 0x0 ) ), fraction_is_nonzero );
   8804 
   8805    }
   8806    //////////////////  fg_flag tests END //////////////////////
   8807 
   8808    fe_flag
   8809    = mkOR1(
   8810             fraNaN,
   8811             mkOR1(
   8812                    mkexpr( fraInf_tmp ),
   8813                    mkOR1(
   8814                           mkexpr( frbZero_tmp ),
   8815                           mkOR1(
   8816                                  frbNaN,
   8817                                  mkOR1(
   8818                                         mkexpr( frbInf_tmp ),
   8819                                         mkOR1( eb_LTE,
   8820                                                mkOR1( eb_GTE,
   8821                                                       mkOR1( ea_eb_GTE,
   8822                                                              mkOR1( ea_eb_LTE,
   8823                                                                     ea_LTE ) ) ) ) ) ) ) ) );
   8824 
   8825    fe_flag = unop(Iop_1Uto32, fe_flag);
   8826 
   8827    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
   8828                                                  mkOR1( mkexpr( frbInf_tmp ),
   8829                                                         frbDenorm ) ) );
   8830    fg_flag = unop(Iop_1Uto32, fg_flag);
   8831    assign(*fe_flag_tmp, fe_flag);
   8832    assign(*fg_flag_tmp, fg_flag);
   8833 }
   8834 
   8835 /* See description for _do_fp_tdiv() above. */
   8836 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
   8837 {
   8838    IRTemp  fe_flag, fg_flag;
   8839    /////////////////////////
   8840    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8841     * where fl_flag == 1 on ppc64.
   8842     */
   8843    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
   8844    fe_flag = fg_flag = IRTemp_INVALID;
   8845    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
   8846    return binop( Iop_Or32,
   8847                  binop( Iop_Or32,
   8848                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
   8849                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8850                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
   8851 }
   8852 
   8853 static Bool dis_fp_tests ( UInt theInstr )
   8854 {
   8855    UChar opc1     = ifieldOPC(theInstr);
   8856    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8857    UChar frB_addr = ifieldRegB(theInstr);
   8858    UChar b0       = ifieldBIT0(theInstr);
   8859    UInt  opc2     = ifieldOPClo10(theInstr);
   8860    IRTemp frB_I64     = newTemp(Ity_I64);
   8861 
   8862    if (opc1 != 0x3F || b0 != 0 ){
   8863       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8864       return False;
   8865    }
   8866    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
   8867 
   8868    switch (opc2) {
   8869       case 0x080: // ftdiv
   8870       {
   8871          UChar frA_addr = ifieldRegA(theInstr);
   8872          IRTemp frA_I64     = newTemp(Ity_I64);
   8873          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8874          if (b21to22 != 0 ) {
   8875             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
   8876             return False;
   8877          }
   8878 
   8879          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
   8880          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   8881 
   8882          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   8883          break;
   8884       }
   8885       case 0x0A0: // ftsqrt
   8886       {
   8887          IRTemp flags = newTemp(Ity_I32);
   8888          IRTemp  fe_flag, fg_flag;
   8889          fe_flag = fg_flag = IRTemp_INVALID;
   8890          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
   8891          if ( b18to22 != 0) {
   8892             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
   8893             return False;
   8894          }
   8895          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
   8896          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
   8897          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   8898           * where fl_flag == 1 on ppc64.
   8899           */
   8900          assign( flags,
   8901                  binop( Iop_Or32,
   8902                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   8903                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   8904                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   8905          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   8906          break;
   8907       }
   8908 
   8909       default:
   8910          vex_printf("dis_fp_tests(ppc)(opc2)\n");
   8911          return False;
   8912 
   8913    }
   8914    return True;
   8915 }
   8916 
   8917 /*
   8918   Floating Point Compare Instructions
   8919 */
   8920 static Bool dis_fp_cmp ( UInt theInstr )
   8921 {
   8922    /* X-Form */
   8923    UChar opc1     = ifieldOPC(theInstr);
   8924    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   8925    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
   8926    UChar frA_addr = ifieldRegA(theInstr);
   8927    UChar frB_addr = ifieldRegB(theInstr);
   8928    UInt  opc2     = ifieldOPClo10(theInstr);
   8929    UChar b0       = ifieldBIT0(theInstr);
   8930 
   8931    IRTemp ccIR    = newTemp(Ity_I32);
   8932    IRTemp ccPPC32 = newTemp(Ity_I32);
   8933 
   8934    IRTemp frA     = newTemp(Ity_F64);
   8935    IRTemp frB     = newTemp(Ity_F64);
   8936 
   8937    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
   8938       vex_printf("dis_fp_cmp(ppc)(instr)\n");
   8939       return False;
   8940    }
   8941 
   8942    assign( frA, getFReg(frA_addr));
   8943    assign( frB, getFReg(frB_addr));
   8944 
   8945    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
   8946 
   8947    /* Map compare result from IR to PPC32 */
   8948    /*
   8949      FP cmp result | PPC | IR
   8950      --------------------------
   8951      UN            | 0x1 | 0x45
   8952      EQ            | 0x2 | 0x40
   8953      GT            | 0x4 | 0x00
   8954      LT            | 0x8 | 0x01
   8955    */
   8956 
   8957    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
   8958    //                    | ((ccIR ^ (ccIR>>6)) & 1)
   8959    assign(
   8960       ccPPC32,
   8961       binop(
   8962          Iop_Shl32,
   8963          mkU32(1),
   8964          unop(
   8965             Iop_32to8,
   8966             binop(
   8967                Iop_Or32,
   8968                binop(
   8969                   Iop_And32,
   8970                   unop(
   8971                      Iop_Not32,
   8972                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
   8973                   ),
   8974                   mkU32(2)
   8975                ),
   8976                binop(
   8977                   Iop_And32,
   8978                   binop(
   8979                      Iop_Xor32,
   8980                      mkexpr(ccIR),
   8981                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
   8982                   ),
   8983                   mkU32(1)
   8984                )
   8985             )
   8986          )
   8987       )
   8988    );
   8989 
   8990    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   8991 
   8992    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
   8993       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
   8994    */
   8995    // XXX XXX XXX FIXME
   8996    // Also write the result into FPRF (it's not entirely clear how)
   8997 
   8998    /* Note: Differences between fcmpu and fcmpo are only in exception
   8999       flag settings, which aren't supported anyway. */
   9000    switch (opc2) {
   9001    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
   9002       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   9003       break;
   9004    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
   9005       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
   9006       break;
   9007    default:
   9008       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
   9009       return False;
   9010    }
   9011    return True;
   9012 }
   9013 
   9014 
   9015 
   9016 /*
   9017   Floating Point Rounding/Conversion Instructions
   9018 */
   9019 static Bool dis_fp_round ( UInt theInstr )
   9020 {
   9021    /* X-Form */
   9022    UChar opc1     = ifieldOPC(theInstr);
   9023    UChar b16to20  = ifieldRegA(theInstr);
   9024    UChar frD_addr = ifieldRegDS(theInstr);
   9025    UChar frB_addr = ifieldRegB(theInstr);
   9026    UInt  opc2     = ifieldOPClo10(theInstr);
   9027    UChar flag_rC  = ifieldBIT0(theInstr);
   9028 
   9029    IRTemp  frD     = newTemp(Ity_F64);
   9030    IRTemp  frB     = newTemp(Ity_F64);
   9031    IRTemp  r_tmp32 = newTemp(Ity_I32);
   9032    IRTemp  r_tmp64 = newTemp(Ity_I64);
   9033    IRExpr* rm      = get_IR_roundingmode();
   9034 
   9035    /* By default, we will examine the results of the operation and set
   9036       fpscr[FPRF] accordingly. */
   9037    Bool set_FPRF = True;
   9038 
   9039    /* By default, if flag_RC is set, we will clear cr1 after the
   9040       operation.  In reality we should set cr1 to indicate the
   9041       exception status of the operation, but since we're not
   9042       simulating exceptions, the exception status will appear to be
   9043       zero.  Hence cr1 should be cleared if this is a . form insn. */
   9044    Bool clear_CR1 = True;
   9045    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
   9046       vex_printf("dis_fp_round(ppc)(instr)\n");
   9047       return False;
   9048    }
   9049 
   9050    assign( frB, getFReg(frB_addr));
   9051    if (opc1 == 0x3B) {
   9052       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
   9053        * they're very similar to the other instructions handled here, but have
   9054        * a different primary opcode.
   9055        */
   9056       switch (opc2) {
   9057          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
   9058             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9059             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9060             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
   9061                                                               mkexpr( r_tmp64 ) ) ) );
   9062             goto putFR;
   9063 
   9064          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
   9065             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9066             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9067             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
   9068             goto putFR;
   9069       }
   9070    }
   9071 
   9072 
   9073    switch (opc2) {
   9074    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
   9075       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9076       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
   9077       break;
   9078 
   9079    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
   9080       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9081       assign( r_tmp32,
   9082               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
   9083       assign( frD, unop( Iop_ReinterpI64asF64,
   9084                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   9085       /* FPRF is undefined after fctiw.  Leave unchanged. */
   9086       set_FPRF = False;
   9087       break;
   9088 
   9089    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
   9090       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9091       assign( r_tmp32,
   9092               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
   9093       assign( frD, unop( Iop_ReinterpI64asF64,
   9094                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   9095       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   9096       set_FPRF = False;
   9097       break;
   9098 
   9099    case 0x08F: case 0x08E: // fctiwu[z]
   9100       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
   9101                flag_rC ? ".":"", frD_addr, frB_addr);
   9102       assign( r_tmp32,
   9103               binop( Iop_F64toI32U,
   9104                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
   9105                      mkexpr( frB ) ) );
   9106       assign( frD, unop( Iop_ReinterpI64asF64,
   9107                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
   9108       /* FPRF is undefined after fctiwz.  Leave unchanged. */
   9109       set_FPRF = False;
   9110       break;
   9111 
   9112 
   9113    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
   9114       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9115       assign( r_tmp64,
   9116               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
   9117       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   9118       /* FPRF is undefined after fctid.  Leave unchanged. */
   9119       set_FPRF = False;
   9120       break;
   9121 
   9122    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
   9123       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9124       assign( r_tmp64,
   9125               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   9126       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   9127       /* FPRF is undefined after fctidz.  Leave unchanged. */
   9128       set_FPRF = False;
   9129       break;
   9130 
   9131    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
   9132    {
   9133       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
   9134                flag_rC ? ".":"", frD_addr, frB_addr);
   9135       assign( r_tmp64,
   9136               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
   9137       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
   9138       /* FPRF is undefined after fctidz.  Leave unchanged. */
   9139       set_FPRF = False;
   9140       break;
   9141    }
   9142    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
   9143       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9144       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9145       assign( frD,
   9146               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
   9147       break;
   9148 
   9149    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
   9150       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9151       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
   9152       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
   9153       break;
   9154 
   9155    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
   9156       switch(opc2) {
   9157       case 0x188: // frin (Floating Round to Integer Nearest)
   9158          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9159          assign( r_tmp64,
   9160                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
   9161          break;
   9162       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
   9163          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9164          assign( r_tmp64,
   9165                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
   9166          break;
   9167       case 0x1C8: // frip (Floating Round to Integer Plus)
   9168          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9169          assign( r_tmp64,
   9170                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
   9171          break;
   9172       case 0x1E8: // frim (Floating Round to Integer Minus)
   9173          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9174          assign( r_tmp64,
   9175                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
   9176          break;
   9177       }
   9178 
   9179       /* don't use the rounded integer if frB is outside -9e18..9e18 */
   9180       /* F64 has only log10(2**52) significant digits anyway */
   9181       /* need to preserve sign of zero */
   9182       /*   frD = (fabs(frB) > 9e18) ? frB :
   9183                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
   9184       assign(frD, IRExpr_ITE(
   9185                      binop(Iop_CmpNE8,
   9186                            unop(Iop_32to8,
   9187                                 binop(Iop_CmpF64,
   9188                                       IRExpr_Const(IRConst_F64(9e18)),
   9189                                       unop(Iop_AbsF64, mkexpr(frB)))),
   9190                            mkU8(0)),
   9191                      mkexpr(frB),
   9192                      IRExpr_ITE(
   9193                         binop(Iop_CmpNE32,
   9194                               binop(Iop_Shr32,
   9195                                     unop(Iop_64HIto32,
   9196                                          unop(Iop_ReinterpF64asI64,
   9197                                               mkexpr(frB))),
   9198                                     mkU8(31)),
   9199                               mkU32(0)),
   9200                         unop(Iop_NegF64,
   9201                              unop( Iop_AbsF64,
   9202                                    binop(Iop_I64StoF64, mkU32(0),
   9203                                          mkexpr(r_tmp64)) )),
   9204                         binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
   9205                      )
   9206       ));
   9207       break;
   9208 
   9209    default:
   9210       vex_printf("dis_fp_round(ppc)(opc2)\n");
   9211       return False;
   9212    }
   9213 putFR:
   9214    putFReg( frD_addr, mkexpr(frD) );
   9215 
   9216    if (set_FPRF) {
   9217       // XXX XXX XXX FIXME
   9218       // set FPRF from frD
   9219    }
   9220 
   9221    if (flag_rC && clear_CR1) {
   9222       putCR321( 1, mkU8(0) );
   9223       putCR0( 1, mkU8(0) );
   9224    }
   9225 
   9226    return True;
   9227 }
   9228 
   9229 /*
   9230   Floating Point Pair Instructions
   9231 */
   9232 static Bool dis_fp_pair ( UInt theInstr )
   9233 {
   9234    /* X-Form/DS-Form */
   9235    UChar  opc1         = ifieldOPC(theInstr);
   9236    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
   9237    UChar  frT_lo_addr  = frT_hi_addr + 1;
   9238    UChar  rA_addr      = ifieldRegA(theInstr);
   9239    UChar  rB_addr      = ifieldRegB(theInstr);
   9240    UInt  uimm16        = ifieldUIMM16(theInstr);
   9241    Int    simm16       = extend_s_16to32(uimm16);
   9242    UInt   opc2         = ifieldOPClo10(theInstr);
   9243    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   9244    IRTemp EA_hi        = newTemp(ty);
   9245    IRTemp EA_lo        = newTemp(ty);
   9246    IRTemp frT_hi       = newTemp(Ity_F64);
   9247    IRTemp frT_lo       = newTemp(Ity_F64);
   9248    UChar b0            = ifieldBIT0(theInstr);
   9249    Bool is_load        = 0;
   9250 
   9251    if ((frT_hi_addr %2) != 0) {
   9252       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
   9253       return False;
   9254    }
   9255 
   9256    switch (opc1) {
   9257    case 0x1F: // register offset
   9258       switch(opc2) {
   9259       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
   9260          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   9261          is_load = 1;
   9262          break;
   9263       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
   9264          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
   9265          break;
   9266       default:
   9267          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
   9268          return False;
   9269       }
   9270 
   9271       if (b0 != 0) {
   9272          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
   9273          return False;
   9274       }
   9275       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
   9276       break;
   9277    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
   9278       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   9279       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   9280       is_load = 1;
   9281       break;
   9282    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
   9283       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
   9284       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
   9285       break;
   9286    default:   // immediate offset
   9287       vex_printf("dis_fp_pair(ppc)(instr)\n");
   9288       return False;
   9289    }
   9290 
   9291    if (mode64)
   9292       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
   9293    else
   9294       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
   9295 
   9296    assign( frT_hi, getFReg(frT_hi_addr) );
   9297    assign( frT_lo, getFReg(frT_lo_addr) );
   9298 
   9299    if (is_load) {
   9300       putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
   9301       putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
   9302    } else {
   9303       store( mkexpr(EA_hi), mkexpr(frT_hi) );
   9304       store( mkexpr(EA_lo), mkexpr(frT_lo) );
   9305    }
   9306 
   9307    return True;
   9308 }
   9309 
   9310 
   9311 /*
   9312   Floating Point Merge Instructions
   9313 */
   9314 static Bool dis_fp_merge ( UInt theInstr )
   9315 {
   9316    /* X-Form */
   9317    UInt  opc2     = ifieldOPClo10(theInstr);
   9318    UChar frD_addr = ifieldRegDS(theInstr);
   9319    UChar frA_addr = ifieldRegA(theInstr);
   9320    UChar frB_addr = ifieldRegB(theInstr);
   9321 
   9322    IRTemp frD = newTemp(Ity_F64);
   9323    IRTemp frA = newTemp(Ity_F64);
   9324    IRTemp frB = newTemp(Ity_F64);
   9325 
   9326    assign( frA, getFReg(frA_addr));
   9327    assign( frB, getFReg(frB_addr));
   9328 
   9329    switch (opc2) {
   9330    case 0x3c6: // fmrgew floating merge even word
   9331       DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   9332 
   9333       assign( frD, unop( Iop_ReinterpI64asF64,
   9334                          binop( Iop_32HLto64,
   9335                                 unop( Iop_64HIto32,
   9336                                       unop( Iop_ReinterpF64asI64,
   9337                                             mkexpr(frA) ) ),
   9338                                 unop( Iop_64HIto32,
   9339                                       unop( Iop_ReinterpF64asI64,
   9340                                             mkexpr(frB) ) ) ) ) );
   9341    break;
   9342 
   9343    case 0x346: // fmrgow floating merge odd word
   9344       DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
   9345 
   9346       assign( frD, unop( Iop_ReinterpI64asF64,
   9347                          binop( Iop_32HLto64,
   9348                                 unop( Iop_64to32,
   9349                                       unop( Iop_ReinterpF64asI64,
   9350                                             mkexpr(frA) ) ),
   9351                                 unop( Iop_64to32,
   9352                                       unop( Iop_ReinterpF64asI64,
   9353                                             mkexpr(frB) ) ) ) ) );
   9354    break;
   9355 
   9356    default:
   9357       vex_printf("dis_fp_merge(ppc)(opc2)\n");
   9358       return False;
   9359    }
   9360 
   9361    putFReg( frD_addr, mkexpr(frD) );
   9362    return True;
   9363 }
   9364 
   9365 /*
   9366   Floating Point Move Instructions
   9367 */
   9368 static Bool dis_fp_move ( UInt theInstr )
   9369 {
   9370    /* X-Form */
   9371    UChar opc1     = ifieldOPC(theInstr);
   9372    UChar frD_addr = ifieldRegDS(theInstr);
   9373    UChar frA_addr = ifieldRegA(theInstr);
   9374    UChar frB_addr = ifieldRegB(theInstr);
   9375    UInt  opc2     = ifieldOPClo10(theInstr);
   9376    UChar flag_rC  = ifieldBIT0(theInstr);
   9377 
   9378    IRTemp frD = newTemp(Ity_F64);
   9379    IRTemp frB = newTemp(Ity_F64);
   9380    IRTemp itmpB = newTemp(Ity_F64);
   9381    IRTemp frA;
   9382    IRTemp signA;
   9383    IRTemp hiD;
   9384 
   9385    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
   9386       vex_printf("dis_fp_move(ppc)(instr)\n");
   9387       return False;
   9388    }
   9389 
   9390    assign( frB, getFReg(frB_addr));
   9391 
   9392    switch (opc2) {
   9393    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
   9394       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
   9395           frB_addr);
   9396       signA = newTemp(Ity_I32);
   9397       hiD = newTemp(Ity_I32);
   9398       itmpB = newTemp(Ity_I64);
   9399       frA = newTemp(Ity_F64);
   9400       assign( frA, getFReg(frA_addr) );
   9401 
   9402       /* get A's sign bit */
   9403       assign(signA, binop(Iop_And32,
   9404                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
   9405                                                   mkexpr(frA))),
   9406                           mkU32(0x80000000)) );
   9407 
   9408       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
   9409 
   9410       /* mask off B's sign bit and or in A's sign bit */
   9411       assign(hiD, binop(Iop_Or32,
   9412                         binop(Iop_And32,
   9413                               unop(Iop_64HIto32,
   9414                                    mkexpr(itmpB)),  /* frB's high 32 bits */
   9415                               mkU32(0x7fffffff)),
   9416                         mkexpr(signA)) );
   9417 
   9418       /* combine hiD/loB into frD */
   9419       assign( frD, unop(Iop_ReinterpI64asF64,
   9420                         binop(Iop_32HLto64,
   9421                               mkexpr(hiD),
   9422                               unop(Iop_64to32,
   9423                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
   9424       break;
   9425 
   9426    case 0x028: // fneg (Floating Negate, PPC32 p416)
   9427       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9428       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
   9429       break;
   9430 
   9431    case 0x048: // fmr (Floating Move Register, PPC32 p410)
   9432       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9433       assign( frD, mkexpr(frB) );
   9434       break;
   9435 
   9436    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
   9437       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9438       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
   9439       break;
   9440 
   9441    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
   9442       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
   9443       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
   9444       break;
   9445 
   9446    default:
   9447       vex_printf("dis_fp_move(ppc)(opc2)\n");
   9448       return False;
   9449    }
   9450 
   9451    putFReg( frD_addr, mkexpr(frD) );
   9452 
   9453    /* None of these change FPRF.  cr1 is set in the usual way though,
   9454       if flag_rC is set. */
   9455 
   9456    if (flag_rC) {
   9457       putCR321( 1, mkU8(0) );
   9458       putCR0( 1, mkU8(0) );
   9459    }
   9460 
   9461    return True;
   9462 }
   9463 
   9464 
   9465 
   9466 /*
   9467   Floating Point Status/Control Register Instructions
   9468 */
   9469 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
   9470 {
   9471    /* Many forms - see each switch case */
   9472    UChar opc1    = ifieldOPC(theInstr);
   9473    UInt  opc2    = ifieldOPClo10(theInstr);
   9474    UChar flag_rC = ifieldBIT0(theInstr);
   9475 
   9476    if (opc1 != 0x3F) {
   9477       vex_printf("dis_fp_scr(ppc)(instr)\n");
   9478       return False;
   9479    }
   9480 
   9481    switch (opc2) {
   9482    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
   9483       // Bit crbD of the FPSCR is set.
   9484       UChar crbD    = ifieldRegDS(theInstr);
   9485       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9486 
   9487       if (b11to20 != 0) {
   9488          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
   9489          return False;
   9490       }
   9491       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
   9492       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
   9493 		     1ULL << ( 31 - crbD ) );
   9494       break;
   9495    }
   9496 
   9497    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
   9498       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
   9499       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
   9500       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
   9501       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
   9502       IRTemp  tmp     = newTemp(Ity_I32);
   9503       IRExpr* fpscr_all;
   9504       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
   9505          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
   9506          return False;
   9507       }
   9508       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
   9509       vassert(crfD < 8);
   9510       vassert(crfS < 8);
   9511       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9512       assign( tmp, binop(Iop_And32,
   9513                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
   9514                         mkU32(0xF)) );
   9515       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
   9516       break;
   9517    }
   9518 
   9519    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
   9520       // Bit crbD of the FPSCR is cleared.
   9521       UChar crbD    = ifieldRegDS(theInstr);
   9522       UInt  b11to20 = IFIELD(theInstr, 11, 10);
   9523 
   9524       if (b11to20 != 0) {
   9525          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
   9526          return False;
   9527       }
   9528       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
   9529       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
   9530       break;
   9531    }
   9532 
   9533    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
   9534       UInt crfD     = IFIELD( theInstr, 23, 3 );
   9535       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
   9536       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
   9537       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
   9538       UChar Wbit;
   9539 
   9540       if (b16to22 != 0 || b11 != 0) {
   9541          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
   9542          return False;
   9543       }
   9544       DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM);
   9545       if (GX_level) {
   9546          /* This implies that Decimal Floating Point is supported, and the
   9547           * FPSCR must be managed as a 64-bit register.
   9548           */
   9549          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9550       } else {
   9551          Wbit = 0;
   9552       }
   9553       crfD = crfD + (8 * (1 - Wbit) );
   9554       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
   9555       break;
   9556    }
   9557 
   9558    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
   9559       UChar   frD_addr  = ifieldRegDS(theInstr);
   9560       UInt    b11to20   = IFIELD(theInstr, 11, 10);
   9561       IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
   9562       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
   9563                                                  MASK_FPSCR_DRN );
   9564 
   9565       if (b11to20 != 0) {
   9566          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
   9567          return False;
   9568       }
   9569       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
   9570       putFReg( frD_addr,
   9571           unop( Iop_ReinterpI64asF64,
   9572                 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
   9573       break;
   9574    }
   9575 
   9576    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
   9577       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
   9578       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
   9579       UChar frB_addr = ifieldRegB(theInstr);
   9580       IRTemp frB   = newTemp(Ity_F64);
   9581       IRTemp rB_64 = newTemp( Ity_I64 );
   9582       Int i;
   9583       ULong mask;
   9584       UChar Wbit;
   9585 #define BFP_MASK_SEED 0x3000000000000000ULL
   9586 #define DFP_MASK_SEED 0x7000000000000000ULL
   9587 
   9588       if (GX_level) {
   9589          /* This implies that Decimal Floating Point is supported, and the
   9590           * FPSCR must be managed as a 64-bit register.
   9591           */
   9592          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
   9593       } else {
   9594          Wbit = 0;
   9595       }
   9596 
   9597       if (b25 == 1) {
   9598          /* new 64 bit move variant for power 6.  If L field (bit 25) is
   9599           * a one do a full 64 bit move.  Note, the FPSCR is not really
   9600           * properly modeled.  This instruciton only changes the value of
   9601           * the rounding mode.  The HW exception bits do not get set in
   9602           * the simulator.  1/12/09
   9603           */
   9604          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
   9605          mask = 0xFF;
   9606 
   9607       } else {
   9608          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
   9609          // Build 32bit mask from FM:
   9610          mask = 0;
   9611          for (i=0; i<8; i++) {
   9612             if ((FM & (1<<(7-i))) == 1) {
   9613                /* FPSCR field k is set to the contents of the corresponding
   9614                 * field of register FRB, where k = i+8x(1-W).  In the Power
   9615                 * ISA, register field numbering is from left to right, so field
   9616                 * 15 is the least significant field in a 64-bit register.  To
   9617                 * generate the mask, we set all the appropriate rounding mode
   9618                 * bits in the highest order nibble (field 0) and shift right
   9619                 * 'k x nibble length'.
   9620                 */
   9621                if (Wbit)
   9622                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9623                else
   9624                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
   9625             }
   9626          }
   9627       }
   9628       assign( frB, getFReg(frB_addr));
   9629       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   9630       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
   9631       break;
   9632    }
   9633 
   9634    default:
   9635       vex_printf("dis_fp_scr(ppc)(opc2)\n");
   9636       return False;
   9637    }
   9638    return True;
   9639 }
   9640 
   9641 /*------------------------------------------------------------*/
   9642 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
   9643 /*------------------------------------------------------------*/
   9644 #define DFP_LONG  1
   9645 #define DFP_EXTND 2
   9646 #define DFP_LONG_BIAS   398
   9647 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
   9648 #define DFP_EXTND_BIAS  6176
   9649 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
   9650 #define DFP_LONG_EXP_MSK   0XFF
   9651 #define DFP_EXTND_EXP_MSK  0XFFF
   9652 
   9653 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
   9654 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
   9655 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
   9656 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
   9657 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
   9658 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
   9659 #define DFP_LONG_EXP_MAX          369      // biased max
   9660 #define DFP_LONG_EXP_MIN          0        // biased min
   9661 #define DFP_EXTND_EXP_MAX         6111     // biased max
   9662 #define DFP_EXTND_EXP_MIN         0        // biased min
   9663 #define DFP_LONG_MAX_SIG_DIGITS   16
   9664 #define DFP_EXTND_MAX_SIG_DIGITS  34
   9665 #define MAX_DIGITS_IN_STRING      8
   9666 
   9667 
   9668 #define  AND(x, y) binop( Iop_And32, x, y )
   9669 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
   9670 #define   OR(x, y) binop( Iop_Or32,  x, y )
   9671 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
   9672 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
   9673 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
   9674 
   9675 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
   9676 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
   9677 
   9678 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
   9679    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
   9680     ((_b1) << 1) | ((_b0) << 0))
   9681 
   9682 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
   9683 {
   9684    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9685    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
   9686    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
   9687    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
   9688    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
   9689    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
   9690    IRTemp lmd_07_val    = newTemp( Ity_I32 );
   9691    IRTemp lmd_8_val     = newTemp( Ity_I32 );
   9692    IRTemp lmd_9_val     = newTemp( Ity_I32 );
   9693 
   9694    /* The encodig is as follows:
   9695     * lmd - left most digit
   9696     * lme - left most 2-bits of the exponent
   9697     *
   9698     *    lmd
   9699     *   0 - 7    (lmexp << 3) | lmd
   9700     *     8      0b11000 (24 decimal) if lme=0b00;
   9701     *            0b11010 (26 decimal) if lme=0b01;
   9702     *            0b11100 (28 decimal) if lme=0b10;
   9703     *     9      0b11001 (25 decimal) if lme=0b00;
   9704     *            0b11011 (27 decimal) if lme=0b01;
   9705     *            0b11101 (29 decimal) if lme=0b10;
   9706     */
   9707 
   9708    /* Generate the masks for each condition */
   9709    assign( lmd_07_mask,
   9710            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
   9711    assign( lmd_8_mask,
   9712            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
   9713    assign( lmd_9_mask,
   9714            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
   9715    assign( lmexp_00_mask,
   9716            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
   9717    assign( lmexp_01_mask,
   9718            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
   9719    assign( lmexp_10_mask,
   9720            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
   9721 
   9722    /* Generate the values for each LMD condition, assuming the condition
   9723     * is TRUE.
   9724     */
   9725    assign( lmd_07_val,
   9726            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
   9727    assign( lmd_8_val,
   9728            binop( Iop_Or32,
   9729                   binop( Iop_Or32,
   9730                          binop( Iop_And32,
   9731                                 mkexpr( lmexp_00_mask ),
   9732                                 mkU32( 24 ) ),
   9733                          binop( Iop_And32,
   9734                                 mkexpr( lmexp_01_mask ),
   9735                                 mkU32( 26 ) ) ),
   9736                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
   9737    assign( lmd_9_val,
   9738            binop( Iop_Or32,
   9739                   binop( Iop_Or32,
   9740                          binop( Iop_And32,
   9741                                 mkexpr( lmexp_00_mask ),
   9742                                 mkU32( 25 ) ),
   9743                          binop( Iop_And32,
   9744                                 mkexpr( lmexp_01_mask ),
   9745                                 mkU32( 27 ) ) ),
   9746                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
   9747 
   9748    /* generate the result from the possible LMD values */
   9749    return binop( Iop_Or32,
   9750                  binop( Iop_Or32,
   9751                         binop( Iop_And32,
   9752                                mkexpr( lmd_07_mask ),
   9753                                mkexpr( lmd_07_val ) ),
   9754                         binop( Iop_And32,
   9755                                mkexpr( lmd_8_mask ),
   9756                                mkexpr( lmd_8_val ) ) ),
   9757                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
   9758 }
   9759 
   9760 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
   9761 {
   9762    /* Extract the exponent and the left most digit of the mantissa
   9763     * from the G field bits [0:4].
   9764     */
   9765    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
   9766    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
   9767    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
   9768    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
   9769    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
   9770    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
   9771    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
   9772 
   9773    IRTemp lmd_07_val = newTemp( Ity_I32 );
   9774    IRTemp lmd_8_val  = newTemp( Ity_I32 );
   9775    IRTemp lmd_9_val  = newTemp( Ity_I32 );
   9776 
   9777    /* The left most digit (LMD) encoding is as follows:
   9778     *    lmd
   9779     *   0 - 7    (lmexp << 3) | lmd
   9780     *     8      0b11000 (24 decimal) if lme=0b00;
   9781     *            0b11010 (26 decimal) if lme=0b01;
   9782     *            0b11100 (28 decimal) if lme=0b10
   9783     *     9      0b11001 (25 decimal) if lme=0b00;
   9784     *            0b11011 (27 decimal) if lme=0b01;
   9785     *            0b11101 (29 decimal) if lme=0b10;
   9786     */
   9787 
   9788    /* Generate the masks for each condition of LMD and exponent bits */
   9789    assign( lmd_07_mask,
   9790            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
   9791                                     gfield_0_4,
   9792                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
   9793    assign( lmd_8_00_mask,
   9794            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9795                                     gfield_0_4,
   9796                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
   9797    assign( lmd_8_01_mask,
   9798            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9799                                     gfield_0_4,
   9800                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
   9801    assign( lmd_8_10_mask,
   9802            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9803                                     gfield_0_4,
   9804                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
   9805    assign( lmd_9_00_mask,
   9806            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9807                                     gfield_0_4,
   9808                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
   9809    assign( lmd_9_01_mask,
   9810            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9811                                     gfield_0_4,
   9812                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
   9813    assign( lmd_9_10_mask,
   9814            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
   9815                                     gfield_0_4,
   9816                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
   9817 
   9818    /* Generate the values for each LMD condition, assuming the condition
   9819     * is TRUE.
   9820     */
   9821    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
   9822    assign( lmd_8_val, mkU32( 0x8 ) );
   9823    assign( lmd_9_val, mkU32( 0x9 ) );
   9824 
   9825    assign( *lmd,
   9826            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
   9827                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
   9828                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
   9829                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
   9830                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
   9831                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
   9832                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
   9833                      ) ) );
   9834 }
   9835 
   9836 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
   9837 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
   9838 #define DIGIT3_SHR 12
   9839 #define DIGIT4_SHR 16
   9840 #define DIGIT5_SHR 20
   9841 #define DIGIT6_SHR 24
   9842 #define DIGIT7_SHR 28
   9843 
   9844 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
   9845 {
   9846    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
   9847     * digit is a valid BCD number, i.e. less then 9.
   9848     */
   9849    IRTemp valid = newTemp( Ity_I32 );
   9850 
   9851    assign( valid,
   9852            AND4( AND4 ( unop( Iop_1Sto32,
   9853                               binop( Iop_CmpLE32U,
   9854                                      binop( Iop_And32,
   9855                                             bcd_l,
   9856                                             mkU32 ( 0xF ) ),
   9857                                       mkU32( 0x9 ) ) ),
   9858                         unop( Iop_1Sto32,
   9859                               binop( Iop_CmpLE32U,
   9860                                      binop( Iop_And32,
   9861                                             binop( Iop_Shr32,
   9862                                                    bcd_l,
   9863                                                    mkU8 ( DIGIT1_SHR ) ),
   9864                                              mkU32 ( 0xF ) ),
   9865                                       mkU32( 0x9 ) ) ),
   9866                         unop( Iop_1Sto32,
   9867                               binop( Iop_CmpLE32U,
   9868                                      binop( Iop_And32,
   9869                                             binop( Iop_Shr32,
   9870                                                    bcd_l,
   9871                                                    mkU8 ( DIGIT2_SHR ) ),
   9872                                             mkU32 ( 0xF ) ),
   9873                                       mkU32( 0x9 ) ) ),
   9874                         unop( Iop_1Sto32,
   9875                               binop( Iop_CmpLE32U,
   9876                                      binop( Iop_And32,
   9877                                             binop( Iop_Shr32,
   9878                                                    bcd_l,
   9879                                                    mkU8 ( DIGIT3_SHR ) ),
   9880                                              mkU32 ( 0xF ) ),
   9881                                       mkU32( 0x9 ) ) ) ),
   9882                  AND4 ( unop( Iop_1Sto32,
   9883                               binop( Iop_CmpLE32U,
   9884                                      binop( Iop_And32,
   9885                                             binop( Iop_Shr32,
   9886                                                    bcd_l,
   9887                                                    mkU8 ( DIGIT4_SHR ) ),
   9888                                             mkU32 ( 0xF ) ),
   9889                                      mkU32( 0x9 ) ) ),
   9890                         unop( Iop_1Sto32,
   9891                               binop( Iop_CmpLE32U,
   9892                                      binop( Iop_And32,
   9893                                             binop( Iop_Shr32,
   9894                                                    bcd_l,
   9895                                                    mkU8 ( DIGIT5_SHR ) ),
   9896                                             mkU32 ( 0xF ) ),
   9897                                      mkU32( 0x9 ) ) ),
   9898                         unop( Iop_1Sto32,
   9899                               binop( Iop_CmpLE32U,
   9900                                      binop( Iop_And32,
   9901                                             binop( Iop_Shr32,
   9902                                                    bcd_l,
   9903                                                    mkU8 ( DIGIT6_SHR ) ),
   9904                                             mkU32 ( 0xF ) ),
   9905                                      mkU32( 0x9 ) ) ),
   9906                         unop( Iop_1Sto32,
   9907                               binop( Iop_CmpLE32U,
   9908                                      binop( Iop_And32,
   9909                                             binop( Iop_Shr32,
   9910                                                    bcd_l,
   9911                                                    mkU8 ( DIGIT7_SHR ) ),
   9912                                             mkU32 ( 0xF ) ),
   9913                                      mkU32( 0x9 ) ) ) ),
   9914                  AND4( unop( Iop_1Sto32,
   9915                              binop( Iop_CmpLE32U,
   9916                                     binop( Iop_And32,
   9917                                            bcd_u,
   9918                                            mkU32 ( 0xF ) ),
   9919                                     mkU32( 0x9 ) ) ),
   9920                        unop( Iop_1Sto32,
   9921                              binop( Iop_CmpLE32U,
   9922                                     binop( Iop_And32,
   9923                                            binop( Iop_Shr32,
   9924                                                   bcd_u,
   9925                                                   mkU8 ( DIGIT1_SHR ) ),
   9926                                            mkU32 ( 0xF ) ),
   9927                                     mkU32( 0x9 ) ) ),
   9928                        unop( Iop_1Sto32,
   9929                              binop( Iop_CmpLE32U,
   9930                                     binop( Iop_And32,
   9931                                            binop( Iop_Shr32,
   9932                                                   bcd_u,
   9933                                                   mkU8 ( DIGIT2_SHR ) ),
   9934                                            mkU32 ( 0xF ) ),
   9935                                     mkU32( 0x9 ) ) ),
   9936                        unop( Iop_1Sto32,
   9937                              binop( Iop_CmpLE32U,
   9938                                     binop( Iop_And32,
   9939                                            binop( Iop_Shr32,
   9940                                                   bcd_u,
   9941                                                   mkU8 ( DIGIT3_SHR ) ),
   9942                                            mkU32 ( 0xF ) ),
   9943                                     mkU32( 0x9 ) ) ) ),
   9944                  AND4( unop( Iop_1Sto32,
   9945                              binop( Iop_CmpLE32U,
   9946                                     binop( Iop_And32,
   9947                                            binop( Iop_Shr32,
   9948                                                   bcd_u,
   9949                                                   mkU8 ( DIGIT4_SHR ) ),
   9950                                            mkU32 ( 0xF ) ),
   9951                                     mkU32( 0x9 ) ) ),
   9952                        unop( Iop_1Sto32,
   9953                              binop( Iop_CmpLE32U,
   9954                                     binop( Iop_And32,
   9955                                            binop( Iop_Shr32,
   9956                                                   bcd_u,
   9957                                                   mkU8 ( DIGIT5_SHR ) ),
   9958                                            mkU32 ( 0xF ) ),
   9959                                     mkU32( 0x9 ) ) ),
   9960                        unop( Iop_1Sto32,
   9961                              binop( Iop_CmpLE32U,
   9962                                     binop( Iop_And32,
   9963                                            binop( Iop_Shr32,
   9964                                                   bcd_u,
   9965                                                   mkU8 ( DIGIT6_SHR ) ),
   9966                                            mkU32 ( 0xF ) ),
   9967                                     mkU32( 0x9 ) ) ),
   9968                        unop( Iop_1Sto32,
   9969                              binop( Iop_CmpLE32U,
   9970                                     binop( Iop_And32,
   9971                                            binop( Iop_Shr32,
   9972                                                   bcd_u,
   9973                                                   mkU8 ( DIGIT7_SHR ) ),
   9974                                            mkU32 ( 0xF ) ),
   9975                                     mkU32( 0x9 ) ) ) ) ) );
   9976 
   9977    return unop( Iop_Not32, mkexpr( valid ) );
   9978 }
   9979 #undef DIGIT1_SHR
   9980 #undef DIGIT2_SHR
   9981 #undef DIGIT3_SHR
   9982 #undef DIGIT4_SHR
   9983 #undef DIGIT5_SHR
   9984 #undef DIGIT6_SHR
   9985 #undef DIGIT7_SHR
   9986 
   9987 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
   9988 {
   9989    return binop( Iop_Or32,
   9990                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
   9991                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
   9992                );
   9993 }
   9994 
   9995 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
   9996 {
   9997    return binop( Iop_Or32,
   9998                  binop( Iop_Or32,
   9999                         unop( Iop_1Sto32,
   10000                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
   10001                         unop( Iop_1Sto32,
   10002                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
   10003                  binop( Iop_Or32,
   10004                         unop( Iop_1Sto32,
   10005                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
   10006                         unop( Iop_1Sto32,
   10007                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
   10008 }
   10009 
   10010 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
   10011                                    IRExpr * neg_sign_mask )
   10012 {
   10013    return binop( Iop_Or32,
   10014                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
   10015                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
   10016 }
   10017 
   10018 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
   10019                                    IRExpr * pos_sign_mask,
   10020                                    IRExpr * neg_sign_mask )
   10021 /* first argument is all 1's if the BCD string had an invalid digit in it. */
   10022 {
   10023    return binop( Iop_Or32,
   10024                  invalid_bcd_mask,
   10025                  unop( Iop_1Sto32,
   10026                        binop( Iop_CmpEQ32,
   10027                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
   10028                               mkU32( 0x0 ) ) ) );
   10029 }
   10030 
   10031 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
   10032                                          IRTemp * top_12_l, IRTemp * mid_60_u,
   10033                                          IRTemp * mid_60_l, IRTemp * low_60_u,
   10034                                          IRTemp * low_60_l)
   10035 {
   10036    IRTemp tmplow60 = newTemp( Ity_I64 );
   10037    IRTemp tmpmid60 = newTemp( Ity_I64 );
   10038    IRTemp tmptop12 = newTemp( Ity_I64 );
   10039    IRTemp low_50   = newTemp( Ity_I64 );
   10040    IRTemp mid_50   = newTemp( Ity_I64 );
   10041    IRTemp top_10   = newTemp( Ity_I64 );
   10042    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
   10043 
   10044    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
   10045 
   10046    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
   10047    assign( low_50,
   10048            binop( Iop_32HLto64,
   10049                   binop( Iop_And32,
   10050                          unop( Iop_64HIto32, frBI64_lo ),
   10051                          mkU32( 0x3FFFF ) ),
   10052                          unop( Iop_64to32, frBI64_lo ) ) );
   10053 
   10054    /* Convert the 50 bit densely packed BCD string to a 60 bit
   10055     * BCD string.
   10056     */
   10057    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
   10058    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
   10059    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
   10060 
   10061    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
   10062     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
   10063     */
   10064    assign( mid_50,
   10065            binop( Iop_32HLto64,
   10066                   binop( Iop_Or32,
   10067                          binop( Iop_Shl32,
   10068                                 binop( Iop_And32,
   10069                                        unop( Iop_64HIto32, frBI64_hi ),
   10070                                        mkU32( 0xF ) ),
   10071                                 mkU8( 14 ) ),
   10072                          binop( Iop_Shr32,
   10073                                 unop( Iop_64to32, frBI64_hi ),
   10074                                 mkU8( 18 ) ) ),
   10075                   binop( Iop_Or32,
   10076                          binop( Iop_Shl32,
   10077                                 unop( Iop_64to32, frBI64_hi ),
   10078                                 mkU8( 14 ) ),
   10079                          binop( Iop_Shr32,
   10080                                 unop( Iop_64HIto32, frBI64_lo ),
   10081                                 mkU8( 18 ) ) ) ) );
   10082 
   10083    /* Convert the 50 bit densely packed BCD string to a 60 bit
   10084     * BCD string.
   10085     */
   10086    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
   10087    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
   10088    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
   10089 
   10090    /* top_10[49:0] = frBI64_hi[45:36]) |  */
   10091    assign( top_10,
   10092            binop( Iop_32HLto64,
   10093                   mkU32( 0 ),
   10094                   binop( Iop_And32,
   10095                          binop( Iop_Shr32,
   10096                                 unop( Iop_64HIto32, frBI64_hi ),
   10097                                 mkU8( 4 ) ),
   10098                          mkU32( 0x3FF ) ) ) );
   10099 
   10100    /* Convert the 10 bit densely packed BCD string to a 12 bit
   10101     * BCD string.
   10102     */
   10103    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
   10104    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
   10105    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
   10106 }
   10107 
   10108 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
   10109                          IRTemp * final_cnt, IRTemp * final_flag,
   10110                          IRExpr * string )
   10111 {
   10112    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
   10113    int digits = MAX_DIGITS_IN_STRING;
   10114    int i;
   10115 
   10116    cnt[start-1] = newTemp( Ity_I8 );
   10117    flag[start-1] = newTemp( Ity_I8 );
   10118    assign( cnt[start-1], init_cnt);
   10119    assign( flag[start-1], init_flag);
   10120 
   10121    for ( i = start; i <= digits; i++) {
   10122       cnt[i] = newTemp( Ity_I8 );
   10123       flag[i] = newTemp( Ity_I8 );
   10124       assign( cnt[i],
   10125               binop( Iop_Add8,
   10126                      mkexpr( cnt[i-1] ),
   10127                      binop(Iop_And8,
   10128                            unop( Iop_1Uto8,
   10129                                  binop(Iop_CmpEQ32,
   10130                                        binop(Iop_And32,
   10131                                              string,
   10132                                              mkU32( 0xF <<
   10133                                                     ( ( digits - i ) * 4) ) ),
   10134                                        mkU32( 0 ) ) ),
   10135                            binop( Iop_Xor8, /* complement flag */
   10136                                   mkexpr( flag[i - 1] ),
   10137                                   mkU8( 0xFF ) ) ) ) );
   10138 
   10139       /* set flag to 1 if digit was not a zero */
   10140       assign( flag[i],
   10141               binop(Iop_Or8,
   10142                     unop( Iop_1Sto8,
   10143                           binop(Iop_CmpNE32,
   10144                                 binop(Iop_And32,
   10145                                       string,
   10146                                       mkU32( 0xF <<
   10147                                              ( (digits - i) * 4) ) ),
   10148                                 mkU32( 0 ) ) ),
   10149                     mkexpr( flag[i - 1] ) ) );
   10150    }
   10151 
   10152    *final_cnt = cnt[digits];
   10153    *final_flag = flag[digits];
   10154 }
   10155 
   10156 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
   10157                                         IRExpr * low_32 )
   10158 {
   10159    IRTemp num_lmd    = newTemp( Ity_I8 );
   10160    IRTemp num_upper  = newTemp( Ity_I8 );
   10161    IRTemp num_low    = newTemp( Ity_I8 );
   10162    IRTemp lmd_flag   = newTemp( Ity_I8 );
   10163    IRTemp upper_flag = newTemp( Ity_I8 );
   10164    IRTemp low_flag   = newTemp( Ity_I8 );
   10165 
   10166    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   10167    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   10168 
   10169    Count_zeros( 2,
   10170                 mkexpr( num_lmd ),
   10171                 mkexpr( lmd_flag ),
   10172                 &num_upper,
   10173                 &upper_flag,
   10174                 upper_28 );
   10175 
   10176    Count_zeros( 1,
   10177                 mkexpr( num_upper ),
   10178                 mkexpr( upper_flag ),
   10179                 &num_low,
   10180                 &low_flag,
   10181                 low_32 );
   10182 
   10183    return mkexpr( num_low );
   10184 }
   10185 
   10186 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
   10187                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
   10188                                          IRExpr * low_60_u, IRExpr * low_60_l)
   10189 {
   10190    IRTemp num_lmd   = newTemp( Ity_I8 );
   10191    IRTemp num_top   = newTemp( Ity_I8 );
   10192    IRTemp num_mid_u = newTemp( Ity_I8 );
   10193    IRTemp num_mid_l = newTemp( Ity_I8 );
   10194    IRTemp num_low_u = newTemp( Ity_I8 );
   10195    IRTemp num_low_l = newTemp( Ity_I8 );
   10196 
   10197    IRTemp lmd_flag   = newTemp( Ity_I8 );
   10198    IRTemp top_flag   = newTemp( Ity_I8 );
   10199    IRTemp mid_u_flag = newTemp( Ity_I8 );
   10200    IRTemp mid_l_flag = newTemp( Ity_I8 );
   10201    IRTemp low_u_flag = newTemp( Ity_I8 );
   10202    IRTemp low_l_flag = newTemp( Ity_I8 );
   10203 
   10204    /* Check the LMD, digit 16, to see if it is zero. */
   10205    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
   10206 
   10207    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
   10208 
   10209    Count_zeros( 6,
   10210                 mkexpr( num_lmd ),
   10211                 mkexpr( lmd_flag ),
   10212                 &num_top,
   10213                 &top_flag,
   10214                 top_12_l );
   10215 
   10216    Count_zeros( 1,
   10217                 mkexpr( num_top ),
   10218                 mkexpr( top_flag ),
   10219                 &num_mid_u,
   10220                 &mid_u_flag,
   10221                 binop( Iop_Or32,
   10222                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
   10223                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
   10224 
   10225    Count_zeros( 2,
   10226                 mkexpr( num_mid_u ),
   10227                 mkexpr( mid_u_flag ),
   10228                 &num_mid_l,
   10229                 &mid_l_flag,
   10230                 mid_60_l );
   10231 
   10232    Count_zeros( 1,
   10233                 mkexpr( num_mid_l ),
   10234                 mkexpr( mid_l_flag ),
   10235                 &num_low_u,
   10236                 &low_u_flag,
   10237                 binop( Iop_Or32,
   10238                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
   10239                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
   10240 
   10241    Count_zeros( 2,
   10242                 mkexpr( num_low_u ),
   10243                 mkexpr( low_u_flag ),
   10244                 &num_low_l,
   10245                 &low_l_flag,
   10246                 low_60_l );
   10247 
   10248    return mkexpr( num_low_l );
   10249 }
   10250 
   10251 static IRExpr * Check_unordered(IRExpr * val)
   10252 {
   10253    IRTemp gfield0to5 = newTemp( Ity_I32 );
   10254 
   10255    /* Extract G[0:4] */
   10256    assign( gfield0to5,
   10257            binop( Iop_And32,
   10258                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
   10259                   mkU32( 0x1F ) ) );
   10260 
   10261    /* Check for unordered, return all 1'x if true */
   10262    return binop( Iop_Or32, /* QNaN check */
   10263                  unop( Iop_1Sto32,
   10264                        binop( Iop_CmpEQ32,
   10265                               mkexpr( gfield0to5 ),
   10266                               mkU32( 0x1E ) ) ),
   10267                               unop( Iop_1Sto32, /* SNaN check */
   10268                                     binop( Iop_CmpEQ32,
   10269                                            mkexpr( gfield0to5 ),
   10270                                            mkU32( 0x1F ) ) ) );
   10271 }
   10272 
   10273 #undef AND
   10274 #undef AND4
   10275 #undef OR
   10276 #undef OR3
   10277 #undef OR4
   10278 #undef NOT
   10279 #undef SHR
   10280 #undef SHL
   10281 #undef BITS5
   10282 
   10283 /*------------------------------------------------------------*/
   10284 /*--- Decimal Floating Point (DFP) instruction translation ---*/
   10285 /*------------------------------------------------------------*/
   10286 
   10287 /* DFP Arithmetic instructions */
   10288 static Bool dis_dfp_arith(UInt theInstr)
   10289 {
   10290    UInt opc2 = ifieldOPClo10( theInstr );
   10291    UChar frS_addr = ifieldRegDS( theInstr );
   10292    UChar frA_addr = ifieldRegA( theInstr );
   10293    UChar frB_addr = ifieldRegB( theInstr );
   10294    UChar flag_rC = ifieldBIT0( theInstr );
   10295 
   10296    IRTemp frA = newTemp( Ity_D64 );
   10297    IRTemp frB = newTemp( Ity_D64 );
   10298    IRTemp frS = newTemp( Ity_D64 );
   10299    IRExpr* round = get_IR_roundingmode_DFP();
   10300 
   10301    /* By default, if flag_RC is set, we will clear cr1 after the
   10302     * operation.  In reality we should set cr1 to indicate the
   10303     * exception status of the operation, but since we're not
   10304     * simulating exceptions, the exception status will appear to be
   10305     * zero.  Hence cr1 should be cleared if this is a . form insn.
   10306     */
   10307    Bool clear_CR1 = True;
   10308 
   10309    assign( frA, getDReg( frA_addr ) );
   10310    assign( frB, getDReg( frB_addr ) );
   10311 
   10312    switch (opc2) {
   10313    case 0x2: // dadd
   10314       DIP( "dadd%s fr%u,fr%u,fr%u\n",
   10315            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10316       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10317       break;
   10318    case 0x202: // dsub
   10319       DIP( "dsub%s fr%u,fr%u,fr%u\n",
   10320            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10321       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10322       break;
   10323    case 0x22: // dmul
   10324       DIP( "dmul%s fr%u,fr%u,fr%u\n",
   10325            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10326       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10327       break;
   10328    case 0x222: // ddiv
   10329       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
   10330            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10331       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
   10332       break;
   10333    }
   10334 
   10335    putDReg( frS_addr, mkexpr( frS ) );
   10336 
   10337    if (flag_rC && clear_CR1) {
   10338       putCR321( 1, mkU8( 0 ) );
   10339       putCR0( 1, mkU8( 0 ) );
   10340    }
   10341 
   10342    return True;
   10343 }
   10344 
   10345 /* Quad DFP Arithmetic instructions */
   10346 static Bool dis_dfp_arithq(UInt theInstr)
   10347 {
   10348    UInt opc2 = ifieldOPClo10( theInstr );
   10349    UChar frS_addr = ifieldRegDS( theInstr );
   10350    UChar frA_addr = ifieldRegA( theInstr );
   10351    UChar frB_addr = ifieldRegB( theInstr );
   10352    UChar flag_rC = ifieldBIT0( theInstr );
   10353 
   10354    IRTemp frA = newTemp( Ity_D128 );
   10355    IRTemp frB = newTemp( Ity_D128 );
   10356    IRTemp frS = newTemp( Ity_D128 );
   10357    IRExpr* round = get_IR_roundingmode_DFP();
   10358 
   10359    /* By default, if flag_RC is set, we will clear cr1 after the
   10360     * operation.  In reality we should set cr1 to indicate the
   10361     * exception status of the operation, but since we're not
   10362     * simulating exceptions, the exception status will appear to be
   10363     * zero.  Hence cr1 should be cleared if this is a . form insn.
   10364     */
   10365    Bool clear_CR1 = True;
   10366 
   10367    assign( frA, getDReg_pair( frA_addr ) );
   10368    assign( frB, getDReg_pair( frB_addr ) );
   10369 
   10370    switch (opc2) {
   10371    case 0x2: // daddq
   10372       DIP( "daddq%s fr%u,fr%u,fr%u\n",
   10373            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10374       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10375       break;
   10376    case 0x202: // dsubq
   10377       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
   10378            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10379       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10380       break;
   10381    case 0x22: // dmulq
   10382       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
   10383            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10384       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10385       break;
   10386    case 0x222: // ddivq
   10387       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
   10388            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10389       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
   10390       break;
   10391    }
   10392 
   10393    putDReg_pair( frS_addr, mkexpr( frS ) );
   10394 
   10395    if (flag_rC && clear_CR1) {
   10396       putCR321( 1, mkU8( 0 ) );
   10397       putCR0( 1, mkU8( 0 ) );
   10398    }
   10399 
   10400    return True;
   10401 }
   10402 
   10403 /* DFP 64-bit logical shift instructions  */
   10404 static Bool dis_dfp_shift(UInt theInstr) {
   10405    UInt opc2       = ifieldOPClo9( theInstr );
   10406    UChar frS_addr  = ifieldRegDS( theInstr );
   10407    UChar frA_addr  = ifieldRegA( theInstr );
   10408    UChar shift_val = IFIELD(theInstr, 10, 6);
   10409    UChar flag_rC   = ifieldBIT0( theInstr );
   10410 
   10411    IRTemp frA = newTemp( Ity_D64 );
   10412    IRTemp frS = newTemp( Ity_D64 );
   10413    Bool clear_CR1 = True;
   10414 
   10415    assign( frA, getDReg( frA_addr ) );
   10416 
   10417    switch (opc2) {
   10418    case 0x42: // dscli
   10419       DIP( "dscli%s fr%u,fr%u,%u\n",
   10420            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10421       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
   10422       break;
   10423    case 0x62: // dscri
   10424       DIP( "dscri%s fr%u,fr%u,%u\n",
   10425            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10426       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
   10427       break;
   10428    }
   10429 
   10430    putDReg( frS_addr, mkexpr( frS ) );
   10431 
   10432    if (flag_rC && clear_CR1) {
   10433       putCR321( 1, mkU8( 0 ) );
   10434       putCR0( 1, mkU8( 0 ) );
   10435    }
   10436 
   10437    return True;
   10438 }
   10439 
   10440 /* Quad DFP  logical shift instructions  */
   10441 static Bool dis_dfp_shiftq(UInt theInstr) {
   10442    UInt opc2       = ifieldOPClo9( theInstr );
   10443    UChar frS_addr  = ifieldRegDS( theInstr );
   10444    UChar frA_addr  = ifieldRegA( theInstr );
   10445    UChar shift_val = IFIELD(theInstr, 10, 6);
   10446    UChar flag_rC   = ifieldBIT0( theInstr );
   10447 
   10448    IRTemp frA = newTemp( Ity_D128 );
   10449    IRTemp frS = newTemp( Ity_D128 );
   10450    Bool clear_CR1 = True;
   10451 
   10452    assign( frA, getDReg_pair( frA_addr ) );
   10453 
   10454    switch (opc2) {
   10455    case 0x42: // dscliq
   10456       DIP( "dscliq%s fr%u,fr%u,%u\n",
   10457            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10458       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10459       break;
   10460    case 0x62: // dscriq
   10461       DIP( "dscriq%s fr%u,fr%u,%u\n",
   10462            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
   10463       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
   10464       break;
   10465    }
   10466 
   10467    putDReg_pair( frS_addr, mkexpr( frS ) );
   10468 
   10469    if (flag_rC && clear_CR1) {
   10470       putCR321( 1, mkU8( 0 ) );
   10471       putCR0( 1, mkU8( 0 ) );
   10472    }
   10473 
   10474    return True;
   10475 }
   10476 
   10477 /* DFP 64-bit format conversion instructions */
   10478 static Bool dis_dfp_fmt_conv(UInt theInstr) {
   10479    UInt opc2      = ifieldOPClo10( theInstr );
   10480    UChar frS_addr = ifieldRegDS( theInstr );
   10481    UChar frB_addr = ifieldRegB( theInstr );
   10482    IRExpr* round  = get_IR_roundingmode_DFP();
   10483    UChar flag_rC  = ifieldBIT0( theInstr );
   10484    IRTemp frB;
   10485    IRTemp frS;
   10486    Bool clear_CR1 = True;
   10487 
   10488    switch (opc2) {
   10489    case 0x102: //dctdp
   10490       DIP( "dctdp%s fr%u,fr%u\n",
   10491            flag_rC ? ".":"", frS_addr, frB_addr );
   10492 
   10493       frB = newTemp( Ity_D32 );
   10494       frS = newTemp( Ity_D64 );
   10495       assign( frB, getDReg32( frB_addr ) );
   10496       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
   10497       putDReg( frS_addr, mkexpr( frS ) );
   10498       break;
   10499    case 0x302: // drsp
   10500       DIP( "drsp%s fr%u,fr%u\n",
   10501            flag_rC ? ".":"", frS_addr, frB_addr );
   10502       frB = newTemp( Ity_D64 );
   10503       frS = newTemp( Ity_D32 );
   10504       assign( frB, getDReg( frB_addr ) );
   10505       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
   10506       putDReg32( frS_addr, mkexpr( frS ) );
   10507       break;
   10508    case 0x122: // dctfix
   10509       {
   10510          IRTemp tmp = newTemp( Ity_I64 );
   10511 
   10512          DIP( "dctfix%s fr%u,fr%u\n",
   10513               flag_rC ? ".":"", frS_addr, frB_addr );
   10514          frB = newTemp( Ity_D64 );
   10515          frS = newTemp( Ity_D64 );
   10516          assign( frB, getDReg( frB_addr ) );
   10517          assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
   10518          assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10519          putDReg( frS_addr, mkexpr( frS ) );
   10520       }
   10521       break;
   10522    case 0x322: // dcffix
   10523       DIP( "dcffix%s fr%u,fr%u\n",
   10524            flag_rC ? ".":"", frS_addr, frB_addr );
   10525       frB = newTemp( Ity_D64 );
   10526       frS = newTemp( Ity_D64 );
   10527       assign( frB, getDReg( frB_addr ) );
   10528       assign( frS, binop( Iop_I64StoD64,
   10529                           round,
   10530                           unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
   10531       putDReg( frS_addr, mkexpr( frS ) );
   10532       break;
   10533    }
   10534 
   10535    if (flag_rC && clear_CR1) {
   10536       putCR321( 1, mkU8( 0 ) );
   10537       putCR0( 1, mkU8( 0 ) );
   10538    }
   10539 
   10540    return True;
   10541 }
   10542 
   10543 /* Quad DFP format conversion instructions */
   10544 static Bool dis_dfp_fmt_convq(UInt theInstr) {
   10545    UInt opc2      = ifieldOPClo10( theInstr );
   10546    UChar frS_addr = ifieldRegDS( theInstr );
   10547    UChar frB_addr = ifieldRegB( theInstr );
   10548    IRExpr* round  = get_IR_roundingmode_DFP();
   10549    IRTemp frB64   = newTemp( Ity_D64 );
   10550    IRTemp frB128  = newTemp( Ity_D128 );
   10551    IRTemp frS64   = newTemp( Ity_D64 );
   10552    IRTemp frS128  = newTemp( Ity_D128 );
   10553    UChar flag_rC  = ifieldBIT0( theInstr );
   10554    Bool clear_CR1 = True;
   10555 
   10556    switch (opc2) {
   10557    case 0x102: // dctqpq
   10558       DIP( "dctqpq%s fr%u,fr%u\n",
   10559            flag_rC ? ".":"", frS_addr, frB_addr );
   10560       assign( frB64, getDReg( frB_addr ) );
   10561       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
   10562       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10563       break;
   10564    case 0x122: // dctfixq
   10565       {
   10566          IRTemp tmp = newTemp( Ity_I64 );
   10567 
   10568          DIP( "dctfixq%s fr%u,fr%u\n",
   10569               flag_rC ? ".":"", frS_addr, frB_addr );
   10570          assign( frB128, getDReg_pair( frB_addr ) );
   10571          assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
   10572          assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10573          putDReg( frS_addr, mkexpr( frS64 ) );
   10574       }
   10575       break;
   10576    case 0x302: //drdpq
   10577       DIP( "drdpq%s fr%u,fr%u\n",
   10578            flag_rC ? ".":"", frS_addr, frB_addr );
   10579       assign( frB128, getDReg_pair( frB_addr ) );
   10580       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
   10581       putDReg( frS_addr, mkexpr( frS64 ) );
   10582       break;
   10583    case 0x322: // dcffixq
   10584      {
   10585       /* Have to introduce an IOP for this instruction so it will work
   10586        * on POWER 6 because emulating the instruction requires a POWER 7
   10587        * DFP instruction in the emulation code.
   10588        */
   10589       DIP( "dcffixq%s fr%u,fr%u\n",
   10590            flag_rC ? ".":"", frS_addr, frB_addr );
   10591       assign( frB64, getDReg( frB_addr ) );
   10592       assign( frS128, unop( Iop_I64StoD128,
   10593                             unop( Iop_ReinterpD64asI64,
   10594                                   mkexpr( frB64 ) ) ) );
   10595       putDReg_pair( frS_addr, mkexpr( frS128 ) );
   10596       break;
   10597      }
   10598    }
   10599 
   10600    if (flag_rC && clear_CR1) {
   10601       putCR321( 1, mkU8( 0 ) );
   10602       putCR0( 1, mkU8( 0 ) );
   10603    }
   10604 
   10605    return True;
   10606 }
   10607 
   10608 static Bool dis_dfp_round( UInt theInstr ) {
   10609    UChar frS_addr = ifieldRegDS(theInstr);
   10610    UChar R        = IFIELD(theInstr, 16, 1);
   10611    UChar RMC      = IFIELD(theInstr, 9, 2);
   10612    UChar frB_addr = ifieldRegB( theInstr );
   10613    UChar flag_rC  = ifieldBIT0( theInstr );
   10614    IRTemp frB     = newTemp( Ity_D64 );
   10615    IRTemp frS     = newTemp( Ity_D64 );
   10616    UInt opc2      = ifieldOPClo8( theInstr );
   10617    Bool clear_CR1 = True;
   10618 
   10619    switch (opc2) {
   10620    /* drintn, is the same as drintx.  The only difference is this
   10621     * instruction does not generate an exception for an inexact operation.
   10622     * Currently not supporting inexact exceptions.
   10623     */
   10624    case 0x63: // drintx
   10625    case 0xE3: // drintn
   10626       DIP( "drintx/drintn%s fr%u,fr%u\n",
   10627            flag_rC ? ".":"", frS_addr, frB_addr );
   10628 
   10629       /* NOTE, this instruction takes a DFP value and rounds to the
   10630        * neares floating point integer value, i.e. fractional part
   10631        * is zero.  The result is a floating point number.
   10632        */
   10633       /* pass the value of R and RMC in the same field */
   10634       assign( frB, getDReg( frB_addr ) );
   10635       assign( frS, binop( Iop_RoundD64toInt,
   10636                           mkU32( ( R << 3 ) | RMC ),
   10637                           mkexpr( frB ) ) );
   10638       putDReg( frS_addr, mkexpr( frS ) );
   10639       break;
   10640    default:
   10641       vex_printf("dis_dfp_round(ppc)(opc2)\n");
   10642       return False;
   10643    }
   10644 
   10645    if (flag_rC && clear_CR1) {
   10646       putCR321( 1, mkU8( 0 ) );
   10647       putCR0( 1, mkU8( 0 ) );
   10648    }
   10649 
   10650    return True;
   10651 }
   10652 
   10653 static Bool dis_dfp_roundq(UInt theInstr) {
   10654    UChar frS_addr = ifieldRegDS( theInstr );
   10655    UChar frB_addr = ifieldRegB( theInstr );
   10656    UChar R = IFIELD(theInstr, 16, 1);
   10657    UChar RMC = IFIELD(theInstr, 9, 2);
   10658    UChar flag_rC = ifieldBIT0( theInstr );
   10659    IRTemp frB = newTemp( Ity_D128 );
   10660    IRTemp frS = newTemp( Ity_D128 );
   10661    Bool clear_CR1 = True;
   10662    UInt opc2 = ifieldOPClo8( theInstr );
   10663 
   10664    switch (opc2) {
   10665    /* drintnq, is the same as drintxq.  The only difference is this
   10666     * instruction does not generate an exception for an inexact operation.
   10667     * Currently not supporting inexact exceptions.
   10668     */
   10669    case 0x63: // drintxq
   10670    case 0xE3: // drintnq
   10671       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
   10672            flag_rC ? ".":"", frS_addr, frB_addr );
   10673 
   10674       /* pass the value of R and RMC in the same field */
   10675       assign( frB, getDReg_pair( frB_addr ) );
   10676       assign( frS, binop( Iop_RoundD128toInt,
   10677                           mkU32( ( R << 3 ) | RMC ),
   10678                           mkexpr( frB ) ) );
   10679       putDReg_pair( frS_addr, mkexpr( frS ) );
   10680       break;
   10681    default:
   10682       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
   10683       return False;
   10684    }
   10685 
   10686    if (flag_rC && clear_CR1) {
   10687       putCR321( 1, mkU8( 0 ) );
   10688       putCR0( 1, mkU8( 0 ) );
   10689    }
   10690 
   10691    return True;
   10692 }
   10693 
   10694 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
   10695    UInt opc2 = ifieldOPClo8( theInstr );
   10696    UChar frS_addr = ifieldRegDS( theInstr );
   10697    UChar frA_addr = ifieldRegA( theInstr );
   10698    UChar frB_addr = ifieldRegB( theInstr );
   10699    UChar flag_rC = ifieldBIT0( theInstr );
   10700    UInt TE_value = IFIELD(theInstr, 16, 4);
   10701    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10702    UInt RMC = IFIELD(theInstr, 9, 2);
   10703    IRTemp frA = newTemp( Ity_D64 );
   10704    IRTemp frB = newTemp( Ity_D64 );
   10705    IRTemp frS = newTemp( Ity_D64 );
   10706    Bool clear_CR1 = True;
   10707 
   10708    assign( frB, getDReg( frB_addr ) );
   10709 
   10710    switch (opc2) {
   10711    case 0x43: // dquai
   10712       DIP( "dquai%s fr%u,fr%u,fr%u\n",
   10713            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10714       IRTemp TE_I64 = newTemp( Ity_I64 );
   10715 
   10716       /* Generate a reference DFP value frA with the desired exponent
   10717        * given by TE using significand from frB.  Need to add the bias
   10718        * 398 to TE.  TE is stored as a 2's complement number.
   10719        */
   10720       if (TE_sign == 1) {
   10721          /* Take 2's complement of the 5-bit value and subtract from bias.
   10722           *  Bias is adjusted for the +1 required when taking 2's complement.
   10723           */
   10724          assign( TE_I64,
   10725                  unop( Iop_32Uto64,
   10726                        binop( Iop_Sub32, mkU32( 397 ),
   10727                               binop( Iop_And32, mkU32( 0xF ),
   10728                                      unop( Iop_Not32, mkU32( TE_value ) )
   10729                                      ) ) ) );
   10730 
   10731       } else {
   10732           assign( TE_I64,
   10733                   unop( Iop_32Uto64,
   10734                         binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
   10735                         ) );
   10736       }
   10737 
   10738       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
   10739                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
   10740 
   10741       assign( frS, triop( Iop_QuantizeD64,
   10742                           mkU32( RMC ),
   10743                           mkexpr( frA ),
   10744                           mkexpr( frB ) ) );
   10745       break;
   10746 
   10747    case 0x3: // dqua
   10748       DIP( "dqua%s fr%u,fr%u,fr%u\n",
   10749            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10750       assign( frA, getDReg( frA_addr ) );
   10751       assign( frS, triop( Iop_QuantizeD64,
   10752                           mkU32( RMC ),
   10753                           mkexpr( frA ),
   10754                           mkexpr( frB ) ) );
   10755       break;
   10756    case 0x23: // drrnd
   10757       {
   10758          IRTemp tmp = newTemp( Ity_I8 );
   10759 
   10760          DIP( "drrnd%s fr%u,fr%u,fr%u\n",
   10761               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10762          assign( frA, getDReg( frA_addr ) );
   10763          /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
   10764          assign( tmp, unop( Iop_32to8,
   10765                             unop( Iop_64to32,
   10766                                   unop( Iop_ReinterpD64asI64,
   10767                                         mkexpr( frA ) ) ) ) );
   10768          assign( frS, triop( Iop_SignificanceRoundD64,
   10769                              mkU32( RMC ),
   10770                              mkexpr( tmp ),
   10771                              mkexpr( frB ) ) );
   10772       }
   10773       break;
   10774    default:
   10775       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
   10776       return False;
   10777    }
   10778    putDReg( frS_addr, mkexpr( frS ) );
   10779 
   10780    if (flag_rC && clear_CR1) {
   10781       putCR321( 1, mkU8( 0 ) );
   10782       putCR0( 1, mkU8( 0 ) );
   10783    }
   10784 
   10785    return True;
   10786 }
   10787 
   10788 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
   10789    UInt opc2 = ifieldOPClo8( theInstr );
   10790    UChar frS_addr = ifieldRegDS( theInstr );
   10791    UChar frA_addr = ifieldRegA( theInstr );
   10792    UChar frB_addr = ifieldRegB( theInstr );
   10793    UChar flag_rC = ifieldBIT0( theInstr );
   10794    UInt TE_value = IFIELD(theInstr, 16, 4);
   10795    UInt TE_sign  = IFIELD(theInstr, 20, 1);
   10796    UInt RMC = IFIELD(theInstr, 9, 2);
   10797    IRTemp frA = newTemp( Ity_D128 );
   10798    IRTemp frB = newTemp( Ity_D128 );
   10799    IRTemp frS = newTemp( Ity_D128 );
   10800    Bool clear_CR1 = True;
   10801 
   10802    assign( frB, getDReg_pair( frB_addr ) );
   10803 
   10804    switch (opc2) {
   10805    case 0x43: // dquaiq
   10806       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10807            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10808       IRTemp TE_I64 = newTemp( Ity_I64 );
   10809 
   10810       /* Generate a reference DFP value frA with the desired exponent
   10811        * given by TE using significand of 1.  Need to add the bias
   10812        * 6176 to TE.
   10813        */
   10814       if (TE_sign == 1) {
   10815          /* Take 2's complement of the 5-bit value and subtract from bias.
   10816           *  Bias adjusted for the +1 required when taking 2's complement.
   10817           */
   10818          assign( TE_I64,
   10819                  unop( Iop_32Uto64,
   10820                        binop( Iop_Sub32, mkU32( 6175 ),
   10821                               binop( Iop_And32, mkU32( 0xF ),
   10822                                      unop( Iop_Not32, mkU32( TE_value ) )
   10823                                      ) ) ) );
   10824 
   10825       } else {
   10826          assign( TE_I64,
   10827                  unop( Iop_32Uto64,
   10828                        binop( Iop_Add32,
   10829                              mkU32( 6176 ),
   10830                              mkU32( TE_value ) ) ) );
   10831       }
   10832 
   10833       assign( frA,
   10834               binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
   10835                      unop( Iop_D64toD128,
   10836                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
   10837       assign( frS, triop( Iop_QuantizeD128,
   10838                           mkU32( RMC ),
   10839                           mkexpr( frA ),
   10840                           mkexpr( frB ) ) );
   10841       break;
   10842    case 0x3: // dquaq
   10843       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
   10844            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10845       assign( frA, getDReg_pair( frA_addr ) );
   10846       assign( frS, triop( Iop_QuantizeD128,
   10847                           mkU32( RMC ),
   10848                           mkexpr( frA ),
   10849                           mkexpr( frB ) ) );
   10850       break;
   10851    case 0x23: // drrndq
   10852       {
   10853          IRTemp tmp = newTemp( Ity_I8 );
   10854 
   10855          DIP( "drrndq%s fr%u,fr%u,fr%u\n",
   10856               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10857          assign( frA, getDReg_pair( frA_addr ) );
   10858          assign( tmp, unop( Iop_32to8,
   10859                             unop( Iop_64to32,
   10860                                   unop( Iop_ReinterpD64asI64,
   10861                                         unop( Iop_D128HItoD64,
   10862                                               mkexpr( frA ) ) ) ) ) );
   10863          assign( frS, triop( Iop_SignificanceRoundD128,
   10864                              mkU32( RMC ),
   10865                              mkexpr( tmp ),
   10866                              mkexpr( frB ) ) );
   10867       }
   10868       break;
   10869    default:
   10870       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
   10871       return False;
   10872    }
   10873    putDReg_pair( frS_addr, mkexpr( frS ) );
   10874 
   10875    if (flag_rC && clear_CR1) {
   10876       putCR321( 1, mkU8( 0 ) );
   10877       putCR0( 1, mkU8( 0 ) );
   10878    }
   10879 
   10880    return True;
   10881 }
   10882 
   10883 static Bool dis_dfp_extract_insert(UInt theInstr) {
   10884    UInt opc2 = ifieldOPClo10( theInstr );
   10885    UChar frS_addr = ifieldRegDS( theInstr );
   10886    UChar frA_addr = ifieldRegA( theInstr );
   10887    UChar frB_addr = ifieldRegB( theInstr );
   10888    UChar flag_rC = ifieldBIT0( theInstr );
   10889    Bool clear_CR1 = True;
   10890 
   10891    IRTemp frA = newTemp( Ity_D64 );
   10892    IRTemp frB = newTemp( Ity_D64 );
   10893    IRTemp frS = newTemp( Ity_D64 );
   10894    IRTemp tmp = newTemp( Ity_I64 );
   10895 
   10896    assign( frA, getDReg( frA_addr ) );
   10897    assign( frB, getDReg( frB_addr ) );
   10898 
   10899    switch (opc2) {
   10900    case 0x162: // dxex
   10901       DIP( "dxex%s fr%u,fr%u,fr%u\n",
   10902            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10903       assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
   10904       assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10905       break;
   10906    case 0x362: // diex
   10907       DIP( "diex%s fr%u,fr%u,fr%u\n",
   10908            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10909       assign( frS, binop( Iop_InsertExpD64,
   10910                           unop( Iop_ReinterpD64asI64,
   10911                                 mkexpr( frA ) ),
   10912                           mkexpr( frB ) ) );
   10913       break;
   10914    default:
   10915       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
   10916       return False;
   10917    }
   10918 
   10919    putDReg( frS_addr, mkexpr( frS ) );
   10920 
   10921    if (flag_rC && clear_CR1) {
   10922       putCR321( 1, mkU8( 0 ) );
   10923       putCR0( 1, mkU8( 0 ) );
   10924    }
   10925 
   10926    return True;
   10927 }
   10928 
   10929 static Bool dis_dfp_extract_insertq(UInt theInstr) {
   10930    UInt opc2 = ifieldOPClo10( theInstr );
   10931    UChar frS_addr = ifieldRegDS( theInstr );
   10932    UChar frA_addr = ifieldRegA( theInstr );
   10933    UChar frB_addr = ifieldRegB( theInstr );
   10934    UChar flag_rC = ifieldBIT0( theInstr );
   10935 
   10936    IRTemp frA   = newTemp( Ity_D64 );
   10937    IRTemp frB   = newTemp( Ity_D128 );
   10938    IRTemp frS64 = newTemp( Ity_D64 );
   10939    IRTemp frS   = newTemp( Ity_D128 );
   10940    IRTemp tmp   = newTemp( Ity_I64 );
   10941    Bool clear_CR1 = True;
   10942 
   10943    assign( frB, getDReg_pair( frB_addr ) );
   10944 
   10945    switch (opc2) {
   10946    case 0x162:  // dxexq
   10947       DIP( "dxexq%s fr%u,fr%u\n",
   10948            flag_rC ? ".":"", frS_addr,  frB_addr );
   10949       /* Instruction actually returns a 64-bit result.  So as to be
   10950        * consistent and not have to add a new struct, the emulation returns
   10951        * the 64-bit result in the upper and lower register.
   10952        */
   10953       assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
   10954       assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
   10955       putDReg( frS_addr, mkexpr( frS64 ) );
   10956       break;
   10957    case 0x362:  // diexq
   10958       DIP( "diexq%s fr%u,fr%u,fr%u\n",
   10959            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
   10960       assign( frA, getDReg( frA_addr ) );
   10961       assign( frS, binop( Iop_InsertExpD128,
   10962                           unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
   10963                           mkexpr( frB ) ) );
   10964       putDReg_pair( frS_addr, mkexpr( frS ) );
   10965       break;
   10966    default:
   10967       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
   10968       return False;
   10969    }
   10970 
   10971    if (flag_rC && clear_CR1) {
   10972       putCR321( 1, mkU8( 0 ) );
   10973       putCR0( 1, mkU8( 0 ) );
   10974    }
   10975 
   10976    return True;
   10977 }
   10978 
   10979 /* DFP 64-bit comparison instructions */
   10980 static Bool dis_dfp_compare(UInt theInstr) {
   10981    /* X-Form */
   10982    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   10983    UChar frA_addr = ifieldRegA( theInstr );
   10984    UChar frB_addr = ifieldRegB( theInstr );
   10985    UInt opc1 = ifieldOPC( theInstr );
   10986    IRTemp frA;
   10987    IRTemp frB;
   10988 
   10989    IRTemp ccIR = newTemp( Ity_I32 );
   10990    IRTemp ccPPC32 = newTemp( Ity_I32 );
   10991 
   10992 
   10993    /* Note: Differences between dcmpu and dcmpo are only in exception
   10994     flag settings, which aren't supported anyway. */
   10995    switch (opc1) {
   10996    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
   10997       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   10998       frA = newTemp( Ity_D64 );
   10999       frB = newTemp( Ity_D64 );
   11000 
   11001       assign( frA, getDReg( frA_addr ) );
   11002       assign( frB, getDReg( frB_addr ) );
   11003 
   11004       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
   11005       break;
   11006    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
   11007       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
   11008       frA = newTemp( Ity_D128 );
   11009       frB = newTemp( Ity_D128 );
   11010 
   11011       assign( frA, getDReg_pair( frA_addr ) );
   11012       assign( frB, getDReg_pair( frB_addr ) );
   11013       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
   11014       break;
   11015    default:
   11016       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
   11017       return False;
   11018    }
   11019 
   11020    /* Map compare result from IR to PPC32 */
   11021    /*
   11022     FP cmp result | PPC | IR
   11023     --------------------------
   11024     UN            | 0x1 | 0x45
   11025     EQ            | 0x2 | 0x40
   11026     GT            | 0x4 | 0x00
   11027     LT            | 0x8 | 0x01
   11028     */
   11029 
   11030    assign( ccPPC32,
   11031            binop( Iop_Shl32,
   11032                   mkU32( 1 ),
   11033                   unop( Iop_32to8,
   11034                         binop( Iop_Or32,
   11035                                binop( Iop_And32,
   11036                                       unop( Iop_Not32,
   11037                                             binop( Iop_Shr32,
   11038                                                    mkexpr( ccIR ),
   11039                                                    mkU8( 5 ) ) ),
   11040                                       mkU32( 2 ) ),
   11041                                binop( Iop_And32,
   11042                                       binop( Iop_Xor32,
   11043                                              mkexpr( ccIR ),
   11044                                              binop( Iop_Shr32,
   11045                                                     mkexpr( ccIR ),
   11046                                                     mkU8( 6 ) ) ),
   11047                                       mkU32( 1 ) ) ) ) ) );
   11048 
   11049    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
   11050    return True;
   11051 }
   11052 
   11053 /* Test class/group/exponent/significance instructions. */
   11054 static Bool dis_dfp_exponent_test ( UInt theInstr )
   11055 {
   11056    UChar frA_addr   = ifieldRegA( theInstr );
   11057    UChar frB_addr   = ifieldRegB( theInstr );
   11058    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
   11059    IRTemp frA       = newTemp( Ity_D64 );
   11060    IRTemp frB       = newTemp( Ity_D64 );
   11061    IRTemp frA128    = newTemp( Ity_D128 );
   11062    IRTemp frB128    = newTemp( Ity_D128 );
   11063    UInt opc1        = ifieldOPC( theInstr );
   11064    IRTemp gfield_A  = newTemp( Ity_I32 );
   11065    IRTemp gfield_B  = newTemp( Ity_I32 );
   11066    IRTemp gfield_mask   = newTemp( Ity_I32 );
   11067    IRTemp exponent_A    = newTemp( Ity_I32 );
   11068    IRTemp exponent_B    = newTemp( Ity_I32 );
   11069    IRTemp A_NaN_true    = newTemp( Ity_I32 );
   11070    IRTemp B_NaN_true    = newTemp( Ity_I32 );
   11071    IRTemp A_inf_true    = newTemp( Ity_I32 );
   11072    IRTemp B_inf_true    = newTemp( Ity_I32 );
   11073    IRTemp A_equals_B    = newTemp( Ity_I32 );
   11074    IRTemp finite_number = newTemp( Ity_I32 );
   11075    IRTemp cc0 = newTemp( Ity_I32 );
   11076    IRTemp cc1 = newTemp( Ity_I32 );
   11077    IRTemp cc2 = newTemp( Ity_I32 );
   11078    IRTemp cc3 = newTemp( Ity_I32 );
   11079 
   11080    /* The dtstex and dtstexg instructions only differ in the size of the
   11081     * exponent field.  The following switch statement takes care of the size
   11082     * specific setup.  Once the value of the exponents, the G-field shift
   11083     * and mask is setup the remaining code is identical.
   11084     */
   11085    switch (opc1) {
   11086    case 0x3b: // dtstex       Extended instruction setup
   11087       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   11088       assign( frA, getDReg( frA_addr ) );
   11089       assign( frB, getDReg( frB_addr ) );
   11090       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   11091       assign(exponent_A, unop( Iop_64to32,
   11092                                unop( Iop_ExtractExpD64,
   11093                                      mkexpr( frA ) ) ) );
   11094       assign(exponent_B, unop( Iop_64to32,
   11095                                unop( Iop_ExtractExpD64,
   11096                                      mkexpr( frB ) ) ) );
   11097       break;
   11098 
   11099    case 0x3F: //  dtstexq      Quad instruction setup
   11100       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
   11101       assign( frA128, getDReg_pair( frA_addr ) );
   11102       assign( frB128, getDReg_pair( frB_addr ) );
   11103       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
   11104       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
   11105       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   11106       assign( exponent_A, unop( Iop_64to32,
   11107                                 unop( Iop_ExtractExpD128,
   11108                                       mkexpr( frA128 ) ) ) );
   11109       assign( exponent_B, unop( Iop_64to32,
   11110                                 unop( Iop_ExtractExpD128,
   11111                                       mkexpr( frB128 ) ) ) );
   11112       break;
   11113    default:
   11114       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
   11115       return False;
   11116    }
   11117 
   11118    /* Extract the Gfield */
   11119    assign( gfield_A, binop( Iop_And32,
   11120                             mkexpr( gfield_mask ),
   11121                             unop( Iop_64HIto32,
   11122                                   unop( Iop_ReinterpD64asI64,
   11123                                         mkexpr(frA) ) ) ) );
   11124 
   11125    assign( gfield_B, binop( Iop_And32,
   11126                             mkexpr( gfield_mask ),
   11127                             unop( Iop_64HIto32,
   11128                                   unop( Iop_ReinterpD64asI64,
   11129                                         mkexpr(frB) ) ) ) );
   11130 
   11131    /* check for NAN */
   11132    assign( A_NaN_true, binop(Iop_Or32,
   11133                              unop( Iop_1Sto32,
   11134                                    binop( Iop_CmpEQ32,
   11135                                           mkexpr( gfield_A ),
   11136                                           mkU32( 0x7C000000 ) ) ),
   11137                              unop( Iop_1Sto32,
   11138                                    binop( Iop_CmpEQ32,
   11139                                           mkexpr( gfield_A ),
   11140                                           mkU32( 0x7E000000 ) )
   11141                                    ) ) );
   11142    assign( B_NaN_true, binop(Iop_Or32,
   11143                              unop( Iop_1Sto32,
   11144                                    binop( Iop_CmpEQ32,
   11145                                           mkexpr( gfield_B ),
   11146                                           mkU32( 0x7C000000 ) ) ),
   11147                              unop( Iop_1Sto32,
   11148                                    binop( Iop_CmpEQ32,
   11149                                           mkexpr( gfield_B ),
   11150                                           mkU32( 0x7E000000 ) )
   11151                              ) ) );
   11152 
   11153    /* check for infinity */
   11154    assign( A_inf_true,
   11155            unop( Iop_1Sto32,
   11156                  binop( Iop_CmpEQ32,
   11157                         mkexpr( gfield_A ),
   11158                         mkU32( 0x78000000 ) ) ) );
   11159 
   11160    assign( B_inf_true,
   11161            unop( Iop_1Sto32,
   11162                  binop( Iop_CmpEQ32,
   11163                         mkexpr( gfield_B ),
   11164                         mkU32( 0x78000000 ) ) ) );
   11165 
   11166    assign( finite_number,
   11167            unop( Iop_Not32,
   11168                  binop( Iop_Or32,
   11169                         binop( Iop_Or32,
   11170                                mkexpr( A_NaN_true ),
   11171                                mkexpr( B_NaN_true ) ),
   11172                         binop( Iop_Or32,
   11173                                mkexpr( A_inf_true ),
   11174                                mkexpr( B_inf_true ) ) ) ) );
   11175 
   11176    /* Calculate the condition code bits
   11177     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
   11178     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
   11179     * cc0, cc1 and cc0 reflect the results of the comparisons.
   11180     */
   11181    assign( A_equals_B,
   11182            binop( Iop_Or32,
   11183                   unop( Iop_1Uto32,
   11184                   binop( Iop_CmpEQ32,
   11185                          mkexpr( exponent_A ),
   11186                          mkexpr( exponent_B ) ) ),
   11187                   binop( Iop_Or32,
   11188                          binop( Iop_And32,
   11189                                 mkexpr( A_inf_true ),
   11190                                 mkexpr( B_inf_true ) ),
   11191                          binop( Iop_And32,
   11192                                 mkexpr( A_NaN_true ),
   11193                                 mkexpr( B_NaN_true ) ) ) ) );
   11194 
   11195    assign( cc0, binop( Iop_And32,
   11196                        mkexpr( finite_number ),
   11197                        binop( Iop_Shl32,
   11198                               unop( Iop_1Uto32,
   11199                                     binop( Iop_CmpLT32U,
   11200                                            mkexpr( exponent_A ),
   11201                                            mkexpr( exponent_B ) ) ),
   11202                                            mkU8( 3 ) ) ) );
   11203 
   11204    assign( cc1, binop( Iop_And32,
   11205                        mkexpr( finite_number ),
   11206                        binop( Iop_Shl32,
   11207                               unop( Iop_1Uto32,
   11208                                     binop( Iop_CmpLT32U,
   11209                                            mkexpr( exponent_B ),
   11210                                            mkexpr( exponent_A ) ) ),
   11211                                            mkU8( 2 ) ) ) );
   11212 
   11213    assign( cc2, binop( Iop_Shl32,
   11214                        binop( Iop_And32,
   11215                               mkexpr( A_equals_B ),
   11216                               mkU32( 1 ) ),
   11217                               mkU8( 1 ) ) );
   11218 
   11219    assign( cc3, binop( Iop_And32,
   11220                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
   11221                        binop( Iop_And32,
   11222                               mkU32( 0x1 ),
   11223                               binop( Iop_Or32,
   11224                                      binop( Iop_Or32,
   11225                                             mkexpr ( A_inf_true ),
   11226                                             mkexpr ( B_inf_true ) ),
   11227                                             binop( Iop_Or32,
   11228                                                    mkexpr ( A_NaN_true ),
   11229                                                    mkexpr ( B_NaN_true ) ) )
   11230                               ) ) );
   11231 
   11232    /* store the condition code */
   11233    putGST_field( PPC_GST_CR,
   11234                  binop( Iop_Or32,
   11235                         mkexpr( cc0 ),
   11236                         binop( Iop_Or32,
   11237                                mkexpr( cc1 ),
   11238                                binop( Iop_Or32,
   11239                                       mkexpr( cc2 ),
   11240                                       mkexpr( cc3 ) ) ) ),
   11241                  crfD );
   11242    return True;
   11243 }
   11244 
   11245 /* Test class/group/exponent/significance instructions. */
   11246 static Bool dis_dfp_class_test ( UInt theInstr )
   11247 {
   11248    UChar frA_addr   = ifieldRegA( theInstr );
   11249    IRTemp frA       = newTemp( Ity_D64 );
   11250    IRTemp abs_frA   = newTemp( Ity_D64 );
   11251    IRTemp frAI64_hi = newTemp( Ity_I64 );
   11252    IRTemp frAI64_lo = newTemp( Ity_I64 );
   11253    UInt opc1        = ifieldOPC( theInstr );
   11254    UInt opc2        = ifieldOPClo9( theInstr );
   11255    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
   11256    UInt DCM         = IFIELD( theInstr, 10, 6 );
   11257    IRTemp DCM_calc  = newTemp( Ity_I32 );
   11258    UInt max_exp     = 0;
   11259    UInt min_exp     = 0;
   11260    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
   11261    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
   11262    IRTemp significand64  = newTemp( Ity_D64 );
   11263    IRTemp significand128 = newTemp( Ity_D128 );
   11264    IRTemp exp_min_normal = newTemp( Ity_I64 );
   11265    IRTemp exponent       = newTemp( Ity_I32 );
   11266 
   11267    IRTemp infinity_true  = newTemp( Ity_I32 );
   11268    IRTemp SNaN_true      = newTemp( Ity_I32 );
   11269    IRTemp QNaN_true      = newTemp( Ity_I32 );
   11270    IRTemp subnormal_true = newTemp( Ity_I32 );
   11271    IRTemp normal_true    = newTemp( Ity_I32 );
   11272    IRTemp extreme_true   = newTemp( Ity_I32 );
   11273    IRTemp lmd            = newTemp( Ity_I32 );
   11274    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
   11275    IRTemp zero_true      = newTemp( Ity_I32 );
   11276    IRTemp sign           = newTemp( Ity_I32 );
   11277    IRTemp field          = newTemp( Ity_I32 );
   11278    IRTemp ccIR_zero      = newTemp( Ity_I32 );
   11279    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
   11280 
   11281    /* UInt size     = DFP_LONG;  JRS:unused */
   11282    IRTemp gfield = newTemp( Ity_I32 );
   11283    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
   11284    IRTemp gfield_mask       = newTemp( Ity_I32 );
   11285    IRTemp dcm0 = newTemp( Ity_I32 );
   11286    IRTemp dcm1 = newTemp( Ity_I32 );
   11287    IRTemp dcm2 = newTemp( Ity_I32 );
   11288    IRTemp dcm3 = newTemp( Ity_I32 );
   11289    IRTemp dcm4 = newTemp( Ity_I32 );
   11290    IRTemp dcm5 = newTemp( Ity_I32 );
   11291 
   11292    /* The only difference between the dtstdc and dtstdcq instructions is
   11293     * size of the T and G fields.  The calculation of the 4 bit field
   11294     * is the same.  Setup the parameters and values that are DFP size
   11295     * specific.  The rest of the code is independent of the DFP size.
   11296     *
   11297     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
   11298     * The interpretation of the ccIR values is as follows:
   11299     *
   11300     *    DFP cmp result | IR
   11301     * --------------------------
   11302     *	 UN             | 0x45
   11303     *	 EQ             | 0x40
   11304     *	 GT             | 0x00
   11305     *	 LT             | 0x01
   11306     */
   11307 
   11308    assign( frA, getDReg( frA_addr ) );
   11309    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
   11310 
   11311    assign( abs_frA, unop( Iop_ReinterpI64asD64,
   11312                           binop( Iop_And64,
   11313                                  unop( Iop_ReinterpD64asI64,
   11314                                        mkexpr( frA ) ),
   11315                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
   11316    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
   11317    switch (opc1) {
   11318    case 0x3b: // dtstdc, dtstdg
   11319       DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
   11320                crfD, frA_addr, DCM);
   11321       /* setup the parameters for the long format of the two instructions */
   11322       assign( frAI64_lo, mkU64( 0 ) );
   11323       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
   11324       max_exp = DFP_LONG_EXP_MAX;
   11325       min_exp = DFP_LONG_EXP_MIN;
   11326 
   11327       assign( exponent, unop( Iop_64to32,
   11328                               unop( Iop_ExtractExpD64,
   11329                                     mkexpr( frA ) ) ) );
   11330       assign( significand64,
   11331               unop( Iop_ReinterpI64asD64,
   11332                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
   11333       assign( exp_min_normal,mkU64( 398 - 383 ) );
   11334       assign( min_subnormalD64,
   11335               binop( Iop_InsertExpD64,
   11336                      mkexpr( exp_min_normal ),
   11337                      mkexpr( significand64 ) ) );
   11338 
   11339       assign( ccIR_subnormal,
   11340               binop( Iop_CmpD64,
   11341                      mkexpr( abs_frA ),
   11342                      mkexpr( min_subnormalD64 ) ) );
   11343 
   11344       /* compare absolute value of frA with zero */
   11345       assign( ccIR_zero,
   11346               binop( Iop_CmpD64,
   11347                      mkexpr( abs_frA ),
   11348                      unop( Iop_ReinterpI64asD64,
   11349                            mkU64( 0x2238000000000000ULL ) ) ) );
   11350 
   11351       /* size = DFP_LONG; JRS: unused */
   11352       break;
   11353 
   11354    case 0x3F:   // dtstdcq, dtstdgq
   11355       DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
   11356                crfD, frA_addr, DCM);
   11357       /* setup the parameters for the extended format of the
   11358        * two instructions
   11359        */
   11360       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
   11361                                getDReg( frA_addr+1 ) ) );
   11362 
   11363       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
   11364       max_exp = DFP_EXTND_EXP_MAX;
   11365       min_exp = DFP_EXTND_EXP_MIN;
   11366       assign( exponent, unop( Iop_64to32,
   11367                               unop( Iop_ExtractExpD128,
   11368                                     getDReg_pair( frA_addr) ) ) );
   11369 
   11370       /* create quand exponent for minimum normal number */
   11371       assign( exp_min_normal, mkU64( 6176 - 6143 ) );
   11372       assign( significand128,
   11373               unop( Iop_D64toD128,
   11374                     unop( Iop_ReinterpI64asD64,
   11375                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
   11376 
   11377       assign( min_subnormalD128,
   11378               binop( Iop_InsertExpD128,
   11379                      mkexpr( exp_min_normal ),
   11380                      mkexpr( significand128 ) ) );
   11381 
   11382       assign( ccIR_subnormal,
   11383               binop( Iop_CmpD128,
   11384                      binop( Iop_D64HLtoD128,
   11385                             unop( Iop_ReinterpI64asD64,
   11386                                   binop( Iop_And64,
   11387                                          unop( Iop_ReinterpD64asI64,
   11388                                                mkexpr( frA ) ),
   11389                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
   11390                             getDReg( frA_addr+1 ) ),
   11391                      mkexpr( min_subnormalD128 ) ) );
   11392       assign( ccIR_zero,
   11393               binop( Iop_CmpD128,
   11394                      binop( Iop_D64HLtoD128,
   11395                             mkexpr( abs_frA ),
   11396                             getDReg( frA_addr+1 ) ),
   11397                      unop( Iop_D64toD128,
   11398                            unop( Iop_ReinterpI64asD64,
   11399                                  mkU64( 0x0ULL ) ) ) ) );
   11400 
   11401       /* size = DFP_EXTND; JRS:unused */
   11402       break;
   11403    default:
   11404       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
   11405       return False;
   11406    }
   11407 
   11408    /* The G-field is in the upper 32-bits.  The I64 logical operations
   11409     * do not seem to be supported in 32-bit mode so keep things as 32-bit
   11410     * operations.
   11411     */
   11412    assign( gfield, binop( Iop_And32,
   11413                           mkexpr( gfield_mask ),
   11414                           unop( Iop_64HIto32,
   11415                                 mkexpr(frAI64_hi) ) ) );
   11416 
   11417    /* There is a lot of code that is the same to do the class and group
   11418     * instructions.  Later there is an if statement to handle the specific
   11419     * instruction.
   11420     *
   11421     * Will be using I32 values, compares, shifts and logical operations for
   11422     * this code as the 64-bit compare, shifts, logical operations are not
   11423     * supported in 32-bit mode.
   11424     */
   11425 
   11426    /* Check the bits for Infinity, QNaN or Signaling NaN */
   11427    assign( infinity_true,
   11428            unop( Iop_1Sto32,
   11429                  binop( Iop_CmpEQ32,
   11430                         binop( Iop_And32,
   11431                                mkU32( 0x7C000000 ),
   11432                                mkexpr( gfield ) ),
   11433                         mkU32( 0x78000000 ) ) ) );
   11434 
   11435    assign( SNaN_true,
   11436            unop( Iop_1Sto32,
   11437                  binop( Iop_CmpEQ32,
   11438                         binop( Iop_And32,
   11439                                mkU32( 0x7E000000 ),
   11440                                mkexpr( gfield ) ),
   11441                         mkU32( 0x7E000000 ) ) ) );
   11442 
   11443    assign( QNaN_true,
   11444            binop( Iop_And32,
   11445                   unop( Iop_1Sto32,
   11446                        binop( Iop_CmpEQ32,
   11447                               binop( Iop_And32,
   11448                                      mkU32( 0x7E000000 ),
   11449                                      mkexpr( gfield ) ),
   11450                               mkU32( 0x7C000000 ) ) ),
   11451                   unop( Iop_Not32,
   11452                         mkexpr( SNaN_true ) ) ) );
   11453 
   11454    assign( zero_true,
   11455            binop( Iop_And32,
   11456                   unop(Iop_1Sto32,
   11457                        binop( Iop_CmpEQ32,
   11458                               mkexpr( ccIR_zero ),
   11459                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
   11460                   unop( Iop_Not32,
   11461                         binop( Iop_Or32,
   11462                                mkexpr( infinity_true ),
   11463                                binop( Iop_Or32,
   11464                                       mkexpr( QNaN_true ),
   11465                                       mkexpr( SNaN_true ) ) ) ) ) );
   11466 
   11467    /* Do compare of frA the minimum normal value.  Comparison is size
   11468     * depenent and was done above to get the ccIR value.
   11469     */
   11470    assign( subnormal_true,
   11471            binop( Iop_And32,
   11472                   binop( Iop_Or32,
   11473                          unop( Iop_1Sto32,
   11474                                binop( Iop_CmpEQ32,
   11475                                       mkexpr( ccIR_subnormal ),
   11476                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
   11477                          unop( Iop_1Sto32,
   11478                                binop( Iop_CmpEQ32,
   11479                                       mkexpr( ccIR_subnormal ),
   11480                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
   11481            unop( Iop_Not32,
   11482                  binop( Iop_Or32,
   11483                         binop( Iop_Or32,
   11484                                mkexpr( infinity_true ),
   11485                                mkexpr( zero_true) ),
   11486                         binop( Iop_Or32,
   11487                                mkexpr( QNaN_true ),
   11488                                mkexpr( SNaN_true ) ) ) ) ) );
   11489 
   11490    /* Normal number is not subnormal, infinity, NaN or Zero */
   11491    assign( normal_true,
   11492            unop( Iop_Not32,
   11493                  binop( Iop_Or32,
   11494                         binop( Iop_Or32,
   11495                                mkexpr( infinity_true ),
   11496                                mkexpr( zero_true ) ),
   11497                         binop( Iop_Or32,
   11498                                mkexpr( subnormal_true ),
   11499                                binop( Iop_Or32,
   11500                                       mkexpr( QNaN_true ),
   11501                                       mkexpr( SNaN_true ) ) ) ) ) );
   11502 
   11503    /* Calculate the DCM bit field based on the tests for the specific
   11504     * instruction
   11505     */
   11506    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
   11507       /* DCM[0:5] Bit   Data Class definition
   11508        *   0   Zero
   11509        *   1   Subnormal
   11510        *   2   Normal
   11511        *   3   Infinity
   11512        *   4   Quiet NaN
   11513        *   5   Signaling NaN
   11514        */
   11515 
   11516       assign( dcm0, binop( Iop_Shl32,
   11517                            mkexpr( zero_true ),
   11518                            mkU8( 5 ) ) );
   11519       assign( dcm1, binop( Iop_Shl32,
   11520                            binop( Iop_And32,
   11521                                   mkexpr( subnormal_true ),
   11522                                   mkU32( 1 ) ),
   11523                            mkU8( 4 ) ) );
   11524       assign( dcm2, binop( Iop_Shl32,
   11525                            binop( Iop_And32,
   11526                                   mkexpr( normal_true ),
   11527                                   mkU32( 1 ) ),
   11528                            mkU8( 3 ) ) );
   11529       assign( dcm3, binop( Iop_Shl32,
   11530                            binop( Iop_And32,
   11531                                   mkexpr( infinity_true),
   11532                                   mkU32( 1 ) ),
   11533                            mkU8( 2 ) ) );
   11534       assign( dcm4, binop( Iop_Shl32,
   11535                            binop( Iop_And32,
   11536                                   mkexpr( QNaN_true ),
   11537                                   mkU32( 1 ) ),
   11538                            mkU8( 1 ) ) );
   11539       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
   11540 
   11541    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
   11542       /* check if the exponent is extreme */
   11543       assign( extreme_true, binop( Iop_Or32,
   11544                                    unop( Iop_1Sto32,
   11545                                          binop( Iop_CmpEQ32,
   11546                                                 mkexpr( exponent ),
   11547                                                 mkU32( max_exp ) ) ),
   11548                                    unop( Iop_1Sto32,
   11549                                          binop( Iop_CmpEQ32,
   11550                                                 mkexpr( exponent ),
   11551                                                 mkU32( min_exp ) ) ) ) );
   11552 
   11553       /* Check if LMD is zero */
   11554       Get_lmd( &lmd, binop( Iop_Shr32,
   11555                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
   11556 
   11557       assign( lmd_zero_true, unop( Iop_1Sto32,
   11558                                    binop( Iop_CmpEQ32,
   11559                                           mkexpr( lmd ),
   11560                                           mkU32( 0 ) ) ) );
   11561 
   11562       /* DCM[0:5] Bit   Data Class definition
   11563        *  0   Zero with non-extreme exponent
   11564        *  1   Zero with extreme exponent
   11565        *  2   Subnormal or (Normal with extreme exponent)
   11566        *  3   Normal with non-extreme exponent and
   11567        *      leftmost zero digit in significand
   11568        *  4   Normal with non-extreme exponent and
   11569        *      leftmost nonzero digit in significand
   11570        *  5   Special symbol (Infinity, QNaN, or SNaN)
   11571        */
   11572       assign( dcm0, binop( Iop_Shl32,
   11573                            binop( Iop_And32,
   11574                                   binop( Iop_And32,
   11575                                          unop( Iop_Not32,
   11576                                                mkexpr( extreme_true ) ),
   11577                                          mkexpr( zero_true ) ),
   11578                                   mkU32( 0x1 ) ),
   11579                            mkU8( 5 ) ) );
   11580 
   11581       assign( dcm1, binop( Iop_Shl32,
   11582                            binop( Iop_And32,
   11583                                   binop( Iop_And32,
   11584                                          mkexpr( extreme_true ),
   11585                                          mkexpr( zero_true ) ),
   11586                                   mkU32( 0x1 ) ),
   11587                            mkU8( 4 ) ) );
   11588 
   11589       assign( dcm2, binop( Iop_Shl32,
   11590                            binop( Iop_And32,
   11591                                   binop( Iop_Or32,
   11592                                          binop( Iop_And32,
   11593                                                 mkexpr( extreme_true ),
   11594                                                 mkexpr( normal_true ) ),
   11595                                          mkexpr( subnormal_true ) ),
   11596                                   mkU32( 0x1 ) ),
   11597                            mkU8( 3 ) ) );
   11598 
   11599       assign( dcm3, binop( Iop_Shl32,
   11600                            binop( Iop_And32,
   11601                                   binop( Iop_And32,
   11602                                          binop( Iop_And32,
   11603                                                 unop( Iop_Not32,
   11604                                                       mkexpr( extreme_true ) ),
   11605                                                       mkexpr( normal_true ) ),
   11606                                          unop( Iop_1Sto32,
   11607                                                binop( Iop_CmpEQ32,
   11608                                                       mkexpr( lmd ),
   11609                                                       mkU32( 0 ) ) ) ),
   11610                                   mkU32( 0x1 ) ),
   11611                            mkU8( 2 ) ) );
   11612 
   11613       assign( dcm4, binop( Iop_Shl32,
   11614                            binop( Iop_And32,
   11615                                   binop( Iop_And32,
   11616                                          binop( Iop_And32,
   11617                                                 unop( Iop_Not32,
   11618                                                       mkexpr( extreme_true ) ),
   11619                                                 mkexpr( normal_true ) ),
   11620                                           unop( Iop_1Sto32,
   11621                                                 binop( Iop_CmpNE32,
   11622                                                        mkexpr( lmd ),
   11623                                                        mkU32( 0 ) ) ) ),
   11624                                   mkU32( 0x1 ) ),
   11625                            mkU8( 1 ) ) );
   11626 
   11627       assign( dcm5, binop( Iop_And32,
   11628                            binop( Iop_Or32,
   11629                                   mkexpr( SNaN_true),
   11630                                   binop( Iop_Or32,
   11631                                          mkexpr( QNaN_true),
   11632                                          mkexpr( infinity_true) ) ),
   11633                            mkU32( 0x1 ) ) );
   11634    }
   11635 
   11636    /* create DCM field */
   11637    assign( DCM_calc,
   11638            binop( Iop_Or32,
   11639                   mkexpr( dcm0 ),
   11640                   binop( Iop_Or32,
   11641                          mkexpr( dcm1 ),
   11642                          binop( Iop_Or32,
   11643                                 mkexpr( dcm2 ),
   11644                                 binop( Iop_Or32,
   11645                                        mkexpr( dcm3 ),
   11646                                        binop( Iop_Or32,
   11647                                               mkexpr( dcm4 ),
   11648                                               mkexpr( dcm5 ) ) ) ) ) ) );
   11649 
   11650    /* Get the sign of the DFP number, ignore sign for QNaN */
   11651    assign( sign,
   11652            unop( Iop_1Uto32,
   11653                  binop( Iop_CmpEQ32,
   11654                         binop( Iop_Shr32,
   11655                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
   11656                                mkU8( 63 - 32 ) ),
   11657                         mkU32( 1 ) ) ) );
   11658 
   11659    /* This instruction generates a four bit field to be stored in the
   11660     * condition code register.  The condition code register consists of 7
   11661     * fields.  The field to be written to is specified by the BF (AKA crfD)
   11662     * field.
   11663     *
   11664     * The field layout is as follows:
   11665     *
   11666     *      Field          Meaning
   11667     *      0000           Operand positive with no match
   11668     *      0100           Operand positive with at least one match
   11669     *      0001           Operand negative with no match
   11670     *      0101           Operand negative with at least one match
   11671     */
   11672    assign( field, binop( Iop_Or32,
   11673                          binop( Iop_Shl32,
   11674                                 mkexpr( sign ),
   11675                                 mkU8( 3 ) ),
   11676                                 binop( Iop_Shl32,
   11677                                        unop( Iop_1Uto32,
   11678                                              binop( Iop_CmpNE32,
   11679                                                     binop( Iop_And32,
   11680                                                            mkU32( DCM ),
   11681                                                            mkexpr( DCM_calc ) ),
   11682                                                      mkU32( 0 ) ) ),
   11683                                        mkU8( 1 ) ) ) );
   11684 
   11685    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
   11686    return True;
   11687 }
   11688 
   11689 static Bool dis_dfp_bcd(UInt theInstr) {
   11690    UInt opc2        = ifieldOPClo10( theInstr );
   11691    ULong sp         = IFIELD(theInstr, 19, 2);
   11692    ULong s          = IFIELD(theInstr, 20, 1);
   11693    UChar frT_addr   = ifieldRegDS( theInstr );
   11694    UChar frB_addr   = ifieldRegB( theInstr );
   11695    IRTemp frB       = newTemp( Ity_D64 );
   11696    IRTemp frBI64    = newTemp( Ity_I64 );
   11697    IRTemp result    = newTemp( Ity_I64 );
   11698    IRTemp resultD64 = newTemp( Ity_D64 );
   11699    IRTemp bcd64     = newTemp( Ity_I64 );
   11700    IRTemp bcd_u     = newTemp( Ity_I32 );
   11701    IRTemp bcd_l     = newTemp( Ity_I32 );
   11702    IRTemp dbcd_u    = newTemp( Ity_I32 );
   11703    IRTemp dbcd_l    = newTemp( Ity_I32 );
   11704    IRTemp lmd       = newTemp( Ity_I32 );
   11705 
   11706    assign( frB, getDReg( frB_addr ) );
   11707    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   11708 
   11709    switch ( opc2 ) {
   11710    case 0x142: // ddedpd   DFP Decode DPD to BCD
   11711       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11712 
   11713          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   11714          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
   11715          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
   11716 
   11717       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11718          /* Unsigned BCD string */
   11719          Get_lmd( &lmd,
   11720                   binop( Iop_Shr32,
   11721                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11722                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
   11723 
   11724          assign( result,
   11725                  binop( Iop_32HLto64,
   11726                         binop( Iop_Or32,
   11727                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
   11728                                mkexpr( bcd_u ) ),
   11729                         mkexpr( bcd_l ) ) );
   11730 
   11731       } else {
   11732          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   11733           * the positive and negative values are encoded in the least
   11734           * significant bits.
   11735           */
   11736          IRTemp sign = newTemp( Ity_I32 );
   11737 
   11738          if (sp == 2) {
   11739             /* Positive sign = 0xC, negative sign = 0xD */
   11740 
   11741             assign( sign,
   11742                     binop( Iop_Or32,
   11743                            binop( Iop_Shr32,
   11744                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11745                                   mkU8( 31 ) ),
   11746                            mkU32( 0xC ) ) );
   11747 
   11748          } else if ( sp == 3 ) {
   11749             /* Positive sign = 0xF, negative sign = 0xD */
   11750             IRTemp tmp32 = newTemp( Ity_I32 );
   11751 
   11752             /* Complement sign bit then OR into bit position 1 */
   11753             assign( tmp32,
   11754                     binop( Iop_Xor32,
   11755                            binop( Iop_Shr32,
   11756                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11757                                   mkU8( 30 ) ),
   11758                            mkU32( 0x2 ) ) );
   11759 
   11760             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   11761 
   11762          } else {
   11763             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   11764          }
   11765 
   11766          /* Put sign in bottom 4 bits, move most significant 4-bits from
   11767           * bcd_l to bcd_u.
   11768           */
   11769          assign( result,
   11770                  binop( Iop_32HLto64,
   11771                         binop( Iop_Or32,
   11772                                binop( Iop_Shr32,
   11773                                       mkexpr( bcd_l ),
   11774                                       mkU8( 28 ) ),
   11775                                binop( Iop_Shl32,
   11776                                       mkexpr( bcd_u ),
   11777                                       mkU8( 4 ) ) ),
   11778                         binop( Iop_Or32,
   11779                                       mkexpr( sign ),
   11780                                binop( Iop_Shl32,
   11781                                       mkexpr( bcd_l ),
   11782                                       mkU8( 4 ) ) ) ) );
   11783       }
   11784 
   11785       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
   11786       break;
   11787 
   11788    case 0x342: // denbcd   DFP Encode BCD to DPD
   11789    {
   11790       IRTemp valid_mask   = newTemp( Ity_I32 );
   11791       IRTemp invalid_mask = newTemp( Ity_I32 );
   11792       IRTemp without_lmd  = newTemp( Ity_I64 );
   11793       IRTemp tmp64        = newTemp( Ity_I64 );
   11794       IRTemp dbcd64       = newTemp( Ity_I64 );
   11795       IRTemp left_exp     = newTemp( Ity_I32 );
   11796       IRTemp g0_4         = newTemp( Ity_I32 );
   11797 
   11798       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   11799 
   11800       if ( s == 0 ) {
   11801          /* Unsigned BCD string */
   11802          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
   11803          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
   11804          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
   11805 
   11806          assign( lmd,
   11807                  binop( Iop_Shr32,
   11808                         binop( Iop_And32,
   11809                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11810                                mkU32( 0xF0000000 ) ),
   11811                         mkU8( 28 ) ) );
   11812 
   11813          assign( invalid_mask,
   11814                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   11815                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
   11816          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11817 
   11818          assign( without_lmd,
   11819                  unop( Iop_ReinterpD64asI64,
   11820                        binop( Iop_InsertExpD64,
   11821                               mkU64( DFP_LONG_BIAS ),
   11822                               unop( Iop_ReinterpI64asD64,
   11823                                     binop( Iop_32HLto64,
   11824                                            mkexpr( dbcd_u ),
   11825                                            mkexpr( dbcd_l ) ) ) ) ) );
   11826          assign( left_exp,
   11827                  binop( Iop_Shr32,
   11828                         binop( Iop_And32,
   11829                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
   11830                                mkU32( 0x60000000 ) ),
   11831                         mkU8( 29 ) ) );
   11832 
   11833          assign( g0_4,
   11834                  binop( Iop_Shl32,
   11835                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
   11836                         mkU8( 26 ) ) );
   11837 
   11838          assign( tmp64,
   11839                  binop( Iop_32HLto64,
   11840                         binop( Iop_Or32,
   11841                                binop( Iop_And32,
   11842                                       unop( Iop_64HIto32,
   11843                                             mkexpr( without_lmd ) ),
   11844                                       mkU32( 0x83FFFFFF ) ),
   11845                                mkexpr( g0_4 ) ),
   11846                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
   11847 
   11848       } else if ( s == 1 ) {
   11849          IRTemp sign = newTemp( Ity_I32 );
   11850          IRTemp sign_bit = newTemp( Ity_I32 );
   11851          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   11852          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   11853          IRTemp tmp = newTemp( Ity_I64 );
   11854 
   11855          /* Signed BCD string, least significant 4 bits are sign bits
   11856           * positive sign = 0xC, negative sign = 0xD
   11857           */
   11858          assign( tmp, unop( Iop_BCDtoDPB,
   11859                             binop( Iop_32HLto64,
   11860                                    binop( Iop_Shr32,
   11861                                           unop( Iop_64HIto32,
   11862                                                 mkexpr( frBI64 ) ),
   11863                                                 mkU8( 4 ) ),
   11864                                    binop( Iop_Or32,
   11865                                           binop( Iop_Shr32,
   11866                                                  unop( Iop_64to32,
   11867                                                        mkexpr( frBI64 ) ),
   11868                                                   mkU8( 4 ) ),
   11869                                           binop( Iop_Shl32,
   11870                                                  unop( Iop_64HIto32,
   11871                                                        mkexpr( frBI64 ) ),
   11872                                                        mkU8( 28 ) ) ) ) ) );
   11873 
   11874          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
   11875          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
   11876 
   11877          /* Get the sign of the BCD string. */
   11878          assign( sign,
   11879                  binop( Iop_And32,
   11880                         unop( Iop_64to32, mkexpr( frBI64 ) ),
   11881                         mkU32( 0xF ) ) );
   11882 
   11883          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   11884          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   11885          assign( sign_bit,
   11886                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   11887                                     mkexpr( neg_sign_mask ) ) );
   11888 
   11889          /* Check for invalid sign and BCD digit.  Don't check the bottom
   11890           * four bits of bcd_l as that is the sign value.
   11891           */
   11892          assign( invalid_mask,
   11893                  Generate_inv_mask(
   11894                                    bcd_digit_inval( unop( Iop_64HIto32,
   11895                                                           mkexpr( frBI64 ) ),
   11896                                                     binop( Iop_Shr32,
   11897                                                            unop( Iop_64to32,
   11898                                                                  mkexpr( frBI64 ) ),
   11899                                                            mkU8( 4 ) ) ),
   11900                                    mkexpr( pos_sign_mask ),
   11901                                    mkexpr( neg_sign_mask ) ) );
   11902 
   11903          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   11904 
   11905          /* Generate the result assuming the sign value was valid. */
   11906          assign( tmp64,
   11907                  unop( Iop_ReinterpD64asI64,
   11908                        binop( Iop_InsertExpD64,
   11909                               mkU64( DFP_LONG_BIAS ),
   11910                               unop( Iop_ReinterpI64asD64,
   11911                                     binop( Iop_32HLto64,
   11912                                            binop( Iop_Or32,
   11913                                                   mkexpr( dbcd_u ),
   11914                                                   mkexpr( sign_bit ) ),
   11915                                            mkexpr( dbcd_l ) ) ) ) ) );
   11916       }
   11917 
   11918       /* Generate the value to store depending on the validity of the
   11919        * sign value and the validity of the BCD digits.
   11920        */
   11921       assign( resultD64,
   11922               unop( Iop_ReinterpI64asD64,
   11923                     binop( Iop_32HLto64,
   11924                            binop( Iop_Or32,
   11925                                   binop( Iop_And32,
   11926                                          mkexpr( valid_mask ),
   11927                                          unop( Iop_64HIto32,
   11928                                                mkexpr( tmp64 ) ) ),
   11929                                   binop( Iop_And32,
   11930                                          mkU32( 0x7C000000 ),
   11931                                          mkexpr( invalid_mask ) ) ),
   11932                            binop( Iop_Or32,
   11933                                   binop( Iop_And32,
   11934                                          mkexpr( valid_mask ),
   11935                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
   11936                                   binop( Iop_And32,
   11937                                          mkU32( 0x0 ),
   11938                                          mkexpr( invalid_mask ) ) ) ) ) );
   11939       putDReg( frT_addr, mkexpr( resultD64 ) );
   11940    }
   11941    break;
   11942    default:
   11943       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
   11944       return False;
   11945    }
   11946    return True;
   11947 }
   11948 
   11949 static Bool dis_dfp_bcdq( UInt theInstr )
   11950 {
   11951    UInt opc2        = ifieldOPClo10( theInstr );
   11952    ULong sp         = IFIELD(theInstr, 19, 2);
   11953    ULong s          = IFIELD(theInstr, 20, 1);
   11954    IRTemp frB_hi    = newTemp( Ity_D64 );
   11955    IRTemp frB_lo    = newTemp( Ity_D64 );
   11956    IRTemp frBI64_hi = newTemp( Ity_I64 );
   11957    IRTemp frBI64_lo = newTemp( Ity_I64 );
   11958    UChar frT_addr   = ifieldRegDS( theInstr );
   11959    UChar frB_addr   = ifieldRegB( theInstr );
   11960 
   11961    IRTemp lmd       = newTemp( Ity_I32 );
   11962    IRTemp result_hi = newTemp( Ity_I64 );
   11963    IRTemp result_lo = newTemp( Ity_I64 );
   11964 
   11965    assign( frB_hi, getDReg( frB_addr ) );
   11966    assign( frB_lo, getDReg( frB_addr + 1 ) );
   11967    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   11968    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   11969 
   11970    switch ( opc2 ) {
   11971    case 0x142: // ddedpdq   DFP Decode DPD to BCD
   11972    {
   11973       IRTemp low_60_u = newTemp( Ity_I32 );
   11974       IRTemp low_60_l = newTemp( Ity_I32 );
   11975       IRTemp mid_60_u = newTemp( Ity_I32 );
   11976       IRTemp mid_60_l = newTemp( Ity_I32 );
   11977       IRTemp top_12_l = newTemp( Ity_I32 );
   11978 
   11979       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
   11980 
   11981       /* Note, instruction only stores the lower 32 BCD digits in
   11982        * the result
   11983        */
   11984       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   11985                                    mkexpr( frBI64_lo ),
   11986                                    &top_12_l,
   11987                                    &mid_60_u,
   11988                                    &mid_60_l,
   11989                                    &low_60_u,
   11990                                    &low_60_l );
   11991 
   11992       if ( ( sp == 0 ) || ( sp == 1 ) ) {
   11993          /* Unsigned BCD string */
   11994          assign( result_hi,
   11995                  binop( Iop_32HLto64,
   11996                         binop( Iop_Or32,
   11997                                binop( Iop_Shl32,
   11998                                       mkexpr( top_12_l ),
   11999                                       mkU8( 24 ) ),
   12000                                binop( Iop_Shr32,
   12001                                       mkexpr( mid_60_u ),
   12002                                       mkU8( 4 ) ) ),
   12003                         binop( Iop_Or32,
   12004                                binop( Iop_Shl32,
   12005                                       mkexpr( mid_60_u ),
   12006                                       mkU8( 28 ) ),
   12007                                binop( Iop_Shr32,
   12008                                       mkexpr( mid_60_l ),
   12009                                       mkU8( 4 ) ) ) ) );
   12010 
   12011          assign( result_lo,
   12012                  binop( Iop_32HLto64,
   12013                         binop( Iop_Or32,
   12014                                binop( Iop_Shl32,
   12015                                       mkexpr( mid_60_l ),
   12016                                       mkU8( 28 ) ),
   12017                                mkexpr( low_60_u ) ),
   12018                         mkexpr( low_60_l ) ) );
   12019 
   12020       } else {
   12021          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
   12022           * the positive and negative values are encoded in the least
   12023           * significant bits.
   12024           */
   12025          IRTemp sign = newTemp( Ity_I32 );
   12026 
   12027          if ( sp == 2 ) {
   12028             /* Positive sign = 0xC, negative sign = 0xD */
   12029             assign( sign,
   12030                     binop( Iop_Or32,
   12031                            binop( Iop_Shr32,
   12032                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12033                                   mkU8( 31 ) ),
   12034                            mkU32( 0xC ) ) );
   12035 
   12036          } else if ( sp == 3 ) {
   12037             IRTemp tmp32 = newTemp( Ity_I32 );
   12038 
   12039             /* Positive sign = 0xF, negative sign = 0xD.
   12040              * Need to complement sign bit then OR into bit position 1.
   12041              */
   12042             assign( tmp32,
   12043                     binop( Iop_Xor32,
   12044                            binop( Iop_Shr32,
   12045                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12046                                   mkU8( 30 ) ),
   12047                            mkU32( 0x2 ) ) );
   12048 
   12049             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
   12050 
   12051          } else {
   12052             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
   12053          }
   12054 
   12055          assign( result_hi,
   12056                  binop( Iop_32HLto64,
   12057                         binop( Iop_Or32,
   12058                                binop( Iop_Shl32,
   12059                                       mkexpr( top_12_l ),
   12060                                       mkU8( 28 ) ),
   12061                                mkexpr( mid_60_u ) ),
   12062                         mkexpr( mid_60_l ) ) );
   12063 
   12064          assign( result_lo,
   12065                  binop( Iop_32HLto64,
   12066                         binop( Iop_Or32,
   12067                                binop( Iop_Shl32,
   12068                                       mkexpr( low_60_u ),
   12069                                       mkU8( 4 ) ),
   12070                                binop( Iop_Shr32,
   12071                                       mkexpr( low_60_l ),
   12072                                       mkU8( 28 ) ) ),
   12073                         binop( Iop_Or32,
   12074                                binop( Iop_Shl32,
   12075                                       mkexpr( low_60_l ),
   12076                                       mkU8( 4 ) ),
   12077                                mkexpr( sign ) ) ) );
   12078       }
   12079 
   12080       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   12081       putDReg( frT_addr + 1,
   12082                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   12083    }
   12084    break;
   12085    case 0x342: // denbcdq   DFP Encode BCD to DPD
   12086    {
   12087       IRTemp valid_mask      = newTemp( Ity_I32 );
   12088       IRTemp invalid_mask    = newTemp( Ity_I32 );
   12089       IRTemp result128       = newTemp( Ity_D128 );
   12090       IRTemp dfp_significand = newTemp( Ity_D128 );
   12091       IRTemp tmp_hi          = newTemp( Ity_I64 );
   12092       IRTemp tmp_lo          = newTemp( Ity_I64 );
   12093       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
   12094       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
   12095       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
   12096       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
   12097       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
   12098       IRTemp bcd_top_8       = newTemp( Ity_I64 );
   12099       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
   12100       IRTemp bcd_low_60      = newTemp( Ity_I64 );
   12101       IRTemp sign_bit        = newTemp( Ity_I32 );
   12102       IRTemp tmptop10        = newTemp( Ity_I64 );
   12103       IRTemp tmpmid50        = newTemp( Ity_I64 );
   12104       IRTemp tmplow50        = newTemp( Ity_I64 );
   12105       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
   12106 
   12107       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
   12108 
   12109       if ( s == 0 ) {
   12110          /* Unsigned BCD string */
   12111          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
   12112 
   12113          assign( bcd_top_8,
   12114                  binop( Iop_32HLto64,
   12115                         mkU32( 0 ),
   12116                         binop( Iop_And32,
   12117                                binop( Iop_Shr32,
   12118                                       unop( Iop_64HIto32,
   12119                                             mkexpr( frBI64_hi ) ),
   12120                                       mkU8( 24 ) ),
   12121                                mkU32( 0xFF ) ) ) );
   12122          assign( bcd_mid_60,
   12123                  binop( Iop_32HLto64,
   12124                         binop( Iop_Or32,
   12125                                binop( Iop_Shr32,
   12126                                       unop( Iop_64to32,
   12127                                             mkexpr( frBI64_hi ) ),
   12128                                       mkU8( 28 ) ),
   12129                                binop( Iop_Shl32,
   12130                                       unop( Iop_64HIto32,
   12131                                             mkexpr( frBI64_hi ) ),
   12132                                       mkU8( 4 ) ) ),
   12133                         binop( Iop_Or32,
   12134                                binop( Iop_Shl32,
   12135                                       unop( Iop_64to32,
   12136                                             mkexpr( frBI64_hi ) ),
   12137                                       mkU8( 4 ) ),
   12138                                binop( Iop_Shr32,
   12139                                       unop( Iop_64HIto32,
   12140                                             mkexpr( frBI64_lo ) ),
   12141                                       mkU8( 28 ) ) ) ) );
   12142 
   12143          /* Note, the various helper functions ignores top 4-bits */
   12144          assign( bcd_low_60, mkexpr( frBI64_lo ) );
   12145 
   12146          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
   12147          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   12148 
   12149          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
   12150          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   12151          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   12152 
   12153          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   12154          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   12155          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   12156 
   12157          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
   12158           * value is not part of the final result. Only the right most
   12159           * BCD digits are stored.
   12160           */
   12161          assign( lmd, mkU32( 0 ) );
   12162 
   12163          assign( invalid_mask,
   12164                  binop( Iop_Or32,
   12165                         bcd_digit_inval( mkU32( 0 ),
   12166                                          unop( Iop_64to32,
   12167                                                mkexpr( bcd_top_8 ) ) ),
   12168                         binop( Iop_Or32,
   12169                                bcd_digit_inval( unop( Iop_64HIto32,
   12170                                                       mkexpr( bcd_mid_60 ) ),
   12171                                                 unop( Iop_64to32,
   12172                                                       mkexpr( bcd_mid_60 ) ) ),
   12173                                bcd_digit_inval( unop( Iop_64HIto32,
   12174                                                       mkexpr( bcd_low_60 ) ),
   12175                                                 unop( Iop_64to32,
   12176                                                       mkexpr( bcd_low_60 ) )
   12177                                                 ) ) ) );
   12178 
   12179       } else if ( s == 1 ) {
   12180          IRTemp sign          = newTemp( Ity_I32 );
   12181          IRTemp zero          = newTemp( Ity_I32 );
   12182          IRTemp pos_sign_mask = newTemp( Ity_I32 );
   12183          IRTemp neg_sign_mask = newTemp( Ity_I32 );
   12184 
   12185          /* The sign of the BCD string is stored in lower 4 bits */
   12186          assign( sign,
   12187                  binop( Iop_And32,
   12188                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
   12189                         mkU32( 0xF ) ) );
   12190          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
   12191          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
   12192          assign( sign_bit,
   12193                  Generate_sign_bit( mkexpr( pos_sign_mask ),
   12194                                     mkexpr( neg_sign_mask ) ) );
   12195 
   12196          /* Generate the value assuminig the sign and BCD digits are vaild */
   12197          assign( bcd_top_8,
   12198                  binop( Iop_32HLto64,
   12199                         mkU32( 0x0 ),
   12200                         binop( Iop_Shr32,
   12201                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12202                                mkU8( 28 ) ) ) );
   12203 
   12204          /* The various helper routines ignore the upper 4-bits */
   12205          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
   12206 
   12207          /* Remove bottom four sign bits */
   12208          assign( bcd_low_60,
   12209                  binop( Iop_32HLto64,
   12210                         binop( Iop_Shr32,
   12211                                unop( Iop_64HIto32,
   12212                                      mkexpr( frBI64_lo ) ),
   12213                                mkU8( 4 ) ),
   12214                                binop( Iop_Or32,
   12215                                       binop( Iop_Shl32,
   12216                                              unop( Iop_64HIto32,
   12217                                                    mkexpr( frBI64_lo ) ),
   12218                                              mkU8( 28 ) ),
   12219                                       binop( Iop_Shr32,
   12220                                              unop( Iop_64to32,
   12221                                                    mkexpr( frBI64_lo ) ),
   12222                                              mkU8( 4 ) ) ) ) );
   12223          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
   12224          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
   12225 
   12226          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
   12227          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
   12228          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
   12229 
   12230          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
   12231          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
   12232          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
   12233 
   12234          /* The entire BCD string fits in lower 110-bits.  The LMD value
   12235           * is not stored in the final result for the DFP Long instruction.
   12236           */
   12237          assign( lmd, mkU32( 0 ) );
   12238 
   12239          /* Check for invalid sign and invalid BCD digit.  Don't check the
   12240           *  bottom four bits of frBI64_lo as that is the sign value.
   12241           */
   12242          assign( zero, mkU32( 0 ) );
   12243          assign( inval_bcd_digit_mask,
   12244                  binop( Iop_Or32,
   12245                         bcd_digit_inval( mkexpr( zero ),
   12246                                          unop( Iop_64to32,
   12247                                                mkexpr( bcd_top_8 ) ) ),
   12248                         binop( Iop_Or32,
   12249                                bcd_digit_inval( unop( Iop_64HIto32,
   12250                                                      mkexpr( bcd_mid_60 ) ),
   12251                                                unop( Iop_64to32,
   12252                                                      mkexpr( bcd_mid_60 ) ) ),
   12253                                bcd_digit_inval( unop( Iop_64HIto32,
   12254                                                      mkexpr( frBI64_lo ) ),
   12255                                                binop( Iop_Shr32,
   12256                                                       unop( Iop_64to32,
   12257                                                             mkexpr( frBI64_lo ) ),
   12258                                                         mkU8( 4 ) ) ) ) ) );
   12259          assign( invalid_mask,
   12260                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
   12261                                     mkexpr( pos_sign_mask ),
   12262                                     mkexpr( neg_sign_mask ) ) );
   12263 
   12264       }
   12265 
   12266       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
   12267 
   12268       /* Calculate the value of the result assuming sign and BCD digits
   12269        * are all valid.
   12270        */
   12271       assign( dfp_significand,
   12272               binop( Iop_D64HLtoD128,
   12273                      unop( Iop_ReinterpI64asD64,
   12274                            binop( Iop_32HLto64,
   12275                                   binop( Iop_Or32,
   12276                                          mkexpr( sign_bit ),
   12277                                          mkexpr( dbcd_top_l ) ),
   12278                                   binop( Iop_Or32,
   12279                                          binop( Iop_Shl32,
   12280                                                 mkexpr( dbcd_mid_u ),
   12281                                                 mkU8( 18 ) ),
   12282                                          binop( Iop_Shr32,
   12283                                                 mkexpr( dbcd_mid_l ),
   12284                                                 mkU8( 14 ) ) ) ) ),
   12285                      unop( Iop_ReinterpI64asD64,
   12286                            binop( Iop_32HLto64,
   12287                                   binop( Iop_Or32,
   12288                                          mkexpr( dbcd_low_u ),
   12289                                          binop( Iop_Shl32,
   12290                                                 mkexpr( dbcd_mid_l ),
   12291                                                 mkU8( 18 ) ) ),
   12292                                   mkexpr( dbcd_low_l ) ) ) ) );
   12293 
   12294       /* Break the result back down to 32-bit chunks and replace chunks.
   12295        * If there was an invalid BCD digit or invalid sign value, replace
   12296        * the calculated result with the invalid bit string.
   12297        */
   12298       assign( result128,
   12299               binop( Iop_InsertExpD128,
   12300                      mkU64( DFP_EXTND_BIAS ),
   12301                      mkexpr( dfp_significand ) ) );
   12302 
   12303       assign( tmp_hi,
   12304               unop( Iop_ReinterpD64asI64,
   12305                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
   12306 
   12307       assign( tmp_lo,
   12308               unop( Iop_ReinterpD64asI64,
   12309                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
   12310 
   12311       assign( result_hi,
   12312               binop( Iop_32HLto64,
   12313                      binop( Iop_Or32,
   12314                             binop( Iop_And32,
   12315                                    mkexpr( valid_mask ),
   12316                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
   12317                             binop( Iop_And32,
   12318                                    mkU32( 0x7C000000 ),
   12319                                    mkexpr( invalid_mask ) ) ),
   12320                      binop( Iop_Or32,
   12321                             binop( Iop_And32,
   12322                                    mkexpr( valid_mask ),
   12323                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
   12324                             binop( Iop_And32,
   12325                                    mkU32( 0x0 ),
   12326                                    mkexpr( invalid_mask ) ) ) ) );
   12327 
   12328       assign( result_lo,
   12329               binop( Iop_32HLto64,
   12330                      binop( Iop_Or32,
   12331                             binop( Iop_And32,
   12332                                    mkexpr( valid_mask ),
   12333                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
   12334                             binop( Iop_And32,
   12335                                    mkU32( 0x0 ),
   12336                                    mkexpr( invalid_mask ) ) ),
   12337                      binop( Iop_Or32,
   12338                             binop( Iop_And32,
   12339                                    mkexpr( valid_mask ),
   12340                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
   12341                             binop( Iop_And32,
   12342                                    mkU32( 0x0 ),
   12343                                    mkexpr( invalid_mask ) ) ) ) );
   12344 
   12345       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
   12346       putDReg( frT_addr + 1,
   12347                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
   12348 
   12349    }
   12350    break;
   12351    default:
   12352       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
   12353       break;
   12354    }
   12355    return True;
   12356 }
   12357 
   12358 static Bool dis_dfp_significant_digits( UInt theInstr )
   12359 {
   12360    UChar frA_addr = ifieldRegA( theInstr );
   12361    UChar frB_addr = ifieldRegB( theInstr );
   12362    IRTemp frA     = newTemp( Ity_D64 );
   12363    UInt opc1      = ifieldOPC( theInstr );
   12364    IRTemp B_sig   = newTemp( Ity_I8 );
   12365    IRTemp K       = newTemp( Ity_I8 );
   12366    IRTemp lmd_B   = newTemp( Ity_I32 );
   12367    IRTemp field   = newTemp( Ity_I32 );
   12368    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
   12369    IRTemp Unordered_true     = newTemp( Ity_I32 );
   12370    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
   12371    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
   12372    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
   12373    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
   12374    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
   12375 
   12376    /* Get the reference singificance stored in frA */
   12377    assign( frA, getDReg( frA_addr ) );
   12378 
   12379    /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
   12380     * supported in 32-bit mode.
   12381     */
   12382    assign( K, unop( Iop_32to8,
   12383                     binop( Iop_And32,
   12384                            unop( Iop_64to32,
   12385                                  unop( Iop_ReinterpD64asI64,
   12386                                        mkexpr( frA ) ) ),
   12387                            mkU32( 0x3F ) ) ) );
   12388 
   12389    switch ( opc1 ) {
   12390    case 0x3b: // dtstsf   DFP Test Significance
   12391    {
   12392       IRTemp frB     = newTemp( Ity_D64 );
   12393       IRTemp frBI64  = newTemp( Ity_I64 );
   12394       IRTemp B_bcd_u = newTemp( Ity_I32 );
   12395       IRTemp B_bcd_l = newTemp( Ity_I32 );
   12396       IRTemp tmp64   = newTemp( Ity_I64 );
   12397 
   12398       DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   12399 
   12400       assign( frB, getDReg( frB_addr ) );
   12401       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
   12402 
   12403       /* Get the BCD string for the value stored in a series of I32 values.
   12404        * Count the number of leading zeros.  Subtract the number of leading
   12405        * zeros from 16 (maximum number of significant digits in DFP
   12406        * Long).
   12407        */
   12408       Get_lmd( &lmd_B,
   12409                binop( Iop_Shr32,
   12410                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
   12411                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   12412 
   12413       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
   12414       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
   12415       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
   12416 
   12417       assign( B_sig,
   12418               binop( Iop_Sub8,
   12419                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
   12420                      Count_leading_zeros_60( mkexpr( lmd_B ),
   12421                                              mkexpr( B_bcd_u ),
   12422                                              mkexpr( B_bcd_l ) ) ) );
   12423       assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
   12424    }
   12425    break;
   12426    case 0x3F: // dtstsfq     DFP Test Significance
   12427    {
   12428       IRTemp frB_hi     = newTemp( Ity_D64 );
   12429       IRTemp frB_lo     = newTemp( Ity_D64 );
   12430       IRTemp frBI64_hi  = newTemp( Ity_I64 );
   12431       IRTemp frBI64_lo  = newTemp( Ity_I64 );
   12432       IRTemp B_low_60_u = newTemp( Ity_I32 );
   12433       IRTemp B_low_60_l = newTemp( Ity_I32 );
   12434       IRTemp B_mid_60_u = newTemp( Ity_I32 );
   12435       IRTemp B_mid_60_l = newTemp( Ity_I32 );
   12436       IRTemp B_top_12_l = newTemp( Ity_I32 );
   12437 
   12438       DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
   12439 
   12440       assign( frB_hi, getDReg( frB_addr ) );
   12441       assign( frB_lo, getDReg( frB_addr + 1 ) );
   12442 
   12443       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
   12444       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
   12445 
   12446       /* Get the BCD string for the value stored in a series of I32 values.
   12447        * Count the number of leading zeros.  Subtract the number of leading
   12448        * zeros from 32 (maximum number of significant digits in DFP
   12449        * extended).
   12450        */
   12451       Get_lmd( &lmd_B,
   12452                binop( Iop_Shr32,
   12453                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
   12454                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
   12455 
   12456       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
   12457                                    mkexpr( frBI64_lo ),
   12458                                    &B_top_12_l,
   12459                                    &B_mid_60_u,
   12460                                    &B_mid_60_l,
   12461                                    &B_low_60_u,
   12462                                    &B_low_60_l );
   12463 
   12464       assign( B_sig,
   12465               binop( Iop_Sub8,
   12466                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
   12467                      Count_leading_zeros_128( mkexpr( lmd_B ),
   12468                                               mkexpr( B_top_12_l ),
   12469                                               mkexpr( B_mid_60_u ),
   12470                                               mkexpr( B_mid_60_l ),
   12471                                               mkexpr( B_low_60_u ),
   12472                                               mkexpr( B_low_60_l ) ) ) );
   12473 
   12474       assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
   12475    }
   12476    break;
   12477    }
   12478 
   12479    /* Compare (16 - cnt[0]) against K and set the condition code field
   12480     * accordingly.
   12481     *
   12482     * The field layout is as follows:
   12483     *
   12484     * bit[3:0]    Description
   12485     *    3     K != 0 and K < Number of significant digits if FRB
   12486     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
   12487     *    1     K != 0 and K = Number of significant digits if FRB
   12488     *    0     K ? Number of significant digits if FRB
   12489     */
   12490    assign( Eq_true_mask,
   12491            unop( Iop_1Sto32,
   12492                  binop( Iop_CmpEQ32,
   12493                         unop( Iop_8Uto32, mkexpr( K ) ),
   12494                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12495    assign( Lt_true_mask,
   12496            unop( Iop_1Sto32,
   12497                  binop( Iop_CmpLT32U,
   12498                         unop( Iop_8Uto32, mkexpr( K ) ),
   12499                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
   12500    assign( Gt_true_mask,
   12501            unop( Iop_1Sto32,
   12502                  binop( Iop_CmpLT32U,
   12503                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
   12504                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
   12505 
   12506    assign( KisZero_true_mask,
   12507            unop( Iop_1Sto32,
   12508                  binop( Iop_CmpEQ32,
   12509                         unop( Iop_8Uto32, mkexpr( K ) ),
   12510                         mkU32( 0 ) ) ) );
   12511    assign( KisZero_false_mask,
   12512            unop( Iop_1Sto32,
   12513                  binop( Iop_CmpNE32,
   12514                         unop( Iop_8Uto32, mkexpr( K ) ),
   12515                         mkU32( 0 ) ) ) );
   12516 
   12517    assign( field,
   12518            binop( Iop_Or32,
   12519                   binop( Iop_And32,
   12520                          mkexpr( KisZero_false_mask ),
   12521                          binop( Iop_Or32,
   12522                                 binop( Iop_And32,
   12523                                        mkexpr( Lt_true_mask ),
   12524                                        mkU32( 0x8 ) ),
   12525                                 binop( Iop_Or32,
   12526                                        binop( Iop_And32,
   12527                                               mkexpr( Gt_true_mask ),
   12528                                               mkU32( 0x4 ) ),
   12529                                        binop( Iop_And32,
   12530                                               mkexpr( Eq_true_mask ),
   12531                                               mkU32( 0x2 ) ) ) ) ),
   12532                   binop( Iop_And32,
   12533                          mkexpr( KisZero_true_mask ),
   12534                          mkU32( 0x4 ) ) ) );
   12535 
   12536    putGST_field( PPC_GST_CR,
   12537                  binop( Iop_Or32,
   12538                         binop( Iop_And32,
   12539                                mkexpr( Unordered_true ),
   12540                                mkU32( 0x1 ) ),
   12541                         binop( Iop_And32,
   12542                                unop( Iop_Not32, mkexpr( Unordered_true ) ),
   12543                                mkexpr( field ) ) ),
   12544                  crfD );
   12545 
   12546    return True;
   12547 }
   12548 
   12549 /*------------------------------------------------------------*/
   12550 /*--- AltiVec Instruction Translation                      ---*/
   12551 /*------------------------------------------------------------*/
   12552 
   12553 /*
   12554   Altivec Cache Control Instructions (Data Streams)
   12555 */
   12556 static Bool dis_av_datastream ( UInt theInstr )
   12557 {
   12558    /* X-Form */
   12559    UChar opc1     = ifieldOPC(theInstr);
   12560    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
   12561    UChar flag_A   = flag_T;
   12562    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
   12563    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
   12564    UChar rA_addr  = ifieldRegA(theInstr);
   12565    UChar rB_addr  = ifieldRegB(theInstr);
   12566    UInt  opc2     = ifieldOPClo10(theInstr);
   12567    UChar b0       = ifieldBIT0(theInstr);
   12568 
   12569    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
   12570       vex_printf("dis_av_datastream(ppc)(instr)\n");
   12571       return False;
   12572    }
   12573 
   12574    switch (opc2) {
   12575    case 0x156: // dst (Data Stream Touch, AV p115)
   12576       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12577                                 rA_addr, rB_addr, STRM);
   12578       break;
   12579 
   12580    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
   12581       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
   12582                                   rA_addr, rB_addr, STRM);
   12583       break;
   12584 
   12585    case 0x336: // dss (Data Stream Stop, AV p114)
   12586       if (rA_addr != 0 || rB_addr != 0) {
   12587          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
   12588          return False;
   12589       }
   12590       if (flag_A == 0) {
   12591          DIP("dss %d\n", STRM);
   12592       } else {
   12593          DIP("dssall\n");
   12594       }
   12595       break;
   12596 
   12597    default:
   12598       vex_printf("dis_av_datastream(ppc)(opc2)\n");
   12599       return False;
   12600    }
   12601    return True;
   12602 }
   12603 
   12604 /*
   12605   AltiVec Processor Control Instructions
   12606 */
   12607 static Bool dis_av_procctl ( UInt theInstr )
   12608 {
   12609    /* VX-Form */
   12610    UChar opc1    = ifieldOPC(theInstr);
   12611    UChar vD_addr = ifieldRegDS(theInstr);
   12612    UChar vA_addr = ifieldRegA(theInstr);
   12613    UChar vB_addr = ifieldRegB(theInstr);
   12614    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   12615 
   12616    if (opc1 != 0x4) {
   12617       vex_printf("dis_av_procctl(ppc)(instr)\n");
   12618       return False;
   12619    }
   12620 
   12621    switch (opc2) {
   12622    case 0x604: // mfvscr (Move from VSCR, AV p129)
   12623       if (vA_addr != 0 || vB_addr != 0) {
   12624          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12625          return False;
   12626       }
   12627       DIP("mfvscr v%d\n", vD_addr);
   12628       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
   12629       break;
   12630 
   12631    case 0x644: { // mtvscr (Move to VSCR, AV p130)
   12632       IRTemp vB = newTemp(Ity_V128);
   12633       if (vD_addr != 0 || vA_addr != 0) {
   12634          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
   12635          return False;
   12636       }
   12637       DIP("mtvscr v%d\n", vB_addr);
   12638       assign( vB, getVReg(vB_addr));
   12639       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
   12640       break;
   12641    }
   12642    default:
   12643       vex_printf("dis_av_procctl(ppc)(opc2)\n");
   12644       return False;
   12645    }
   12646    return True;
   12647 }
   12648 
   12649 /*
   12650  * VSX scalar and vector convert instructions
   12651  */
   12652 static Bool
   12653 dis_vx_conv ( UInt theInstr, UInt opc2 )
   12654 {
   12655    /* XX2-Form */
   12656    UChar opc1 = ifieldOPC( theInstr );
   12657    UChar XT = ifieldRegXT( theInstr );
   12658    UChar XB = ifieldRegXB( theInstr );
   12659    IRTemp xB, xB2;
   12660    IRTemp b3, b2, b1, b0;
   12661    xB = xB2 = IRTemp_INVALID;
   12662 
   12663    if (opc1 != 0x3C) {
   12664       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
   12665       return False;
   12666    }
   12667 
   12668    /* Create and assign temps only as needed for the given instruction. */
   12669    switch (opc2) {
   12670       // scalar double-precision floating point argument
   12671       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
   12672          xB = newTemp(Ity_F64);
   12673          assign( xB,
   12674                  unop( Iop_ReinterpI64asF64,
   12675                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12676          break;
   12677       // vector double-precision floating point arguments
   12678       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
   12679 
   12680          xB = newTemp(Ity_F64);
   12681          xB2 = newTemp(Ity_F64);
   12682          assign( xB,
   12683                  unop( Iop_ReinterpI64asF64,
   12684                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12685          assign( xB2,
   12686                  unop( Iop_ReinterpI64asF64,
   12687                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
   12688          break;
   12689       // vector single precision or [un]signed integer word arguments
   12690       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
   12691       case 0x1f0: case 0x1d0:
   12692          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   12693          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
   12694          break;
   12695          // vector [un]signed integer doubleword argument
   12696       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
   12697          xB = newTemp(Ity_I64);
   12698          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12699          xB2 = newTemp(Ity_I64);
   12700          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
   12701          break;
   12702       // scalar [un]signed integer doubleword argument
   12703       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
   12704          xB = newTemp(Ity_I64);
   12705          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   12706          break;
   12707       // scalar single precision argument
   12708       case 0x292: // xscvspdp
   12709          xB  = newTemp(Ity_I32);
   12710 
   12711          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
   12712                                                   unop( Iop_V128HIto64,
   12713                                                         getVSReg( XB ) ) ) ) );
   12714          break;
   12715       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
   12716          xB = newTemp(Ity_I32);
   12717          assign( xB,
   12718                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
   12719          break;
   12720 
   12721       /* Certain instructions have their complete implementation in the main switch statement
   12722        * that follows this one; thus we have a "do nothing" case for those instructions here.
   12723        */
   12724       case 0x170: case 0x150:
   12725          break; // do nothing
   12726 
   12727       default:
   12728          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   12729          return False;
   12730    }
   12731 
   12732 
   12733    switch (opc2) {
   12734       case 0x2B0:
   12735          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
   12736          //             to Signed Integer Doubleword format with Saturate)
   12737          DIP("xscvdpsxds v%u,v%u\n", XT, XB);
   12738          putVSReg( XT,
   12739                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
   12740                                                  mkU32( Irrm_ZERO ),
   12741                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
   12742          break;
   12743       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
   12744                   //             Convert to Signed Integer Word format with Saturate)
   12745          DIP("xscvdpsxws v%u,v%u\n", XT, XB);
   12746          putVSReg( XT,
   12747                    binop( Iop_64HLtoV128,
   12748                           unop( Iop_32Sto64,
   12749                                 binop( Iop_F64toI32S,
   12750                                        mkU32( Irrm_ZERO ),
   12751                                        mkexpr( xB ) ) ),
   12752                                        mkU64( 0ULL ) ) );
   12753          break;
   12754       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
   12755                   //             to Unsigned Integer Doubleword format with Saturate)
   12756          DIP("xscvdpuxds v%u,v%u\n", XT, XB);
   12757          putVSReg( XT,
   12758                    binop( Iop_64HLtoV128,
   12759                           binop( Iop_F64toI64U,
   12760                                  mkU32( Irrm_ZERO ),
   12761                                  mkexpr( xB ) ),
   12762                                  mkU64( 0ULL ) ) );
   12763          break;
   12764       case 0x270:
   12765          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
   12766          //             to Single-Precision format)
   12767          DIP("xscvsxdsp v%u,v%u\n", XT, XB);
   12768          putVSReg( XT,
   12769                    binop( Iop_64HLtoV128,
   12770                           unop( Iop_ReinterpF64asI64,
   12771                                 binop( Iop_RoundF64toF32,
   12772                                        get_IR_roundingmode(),
   12773                                        binop( Iop_I64StoF64,
   12774                                               get_IR_roundingmode(),
   12775                                               mkexpr( xB ) ) ) ),
   12776                           mkU64( 0 ) ) );
   12777          break;
   12778       case 0x2F0:
   12779          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
   12780          //            Double-Precision format)
   12781          DIP("xscvsxddp v%u,v%u\n", XT, XB);
   12782          putVSReg( XT,
   12783                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12784                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   12785                                                        mkexpr( xB ) ) ),
   12786                                                        mkU64( 0 ) ) );
   12787          break;
   12788       case 0x250:
   12789          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
   12790          //            Doubleword to Singel-Precision format)
   12791          DIP("xscvuxdsp v%u,v%u\n", XT, XB);
   12792          putVSReg( XT,
   12793                    binop( Iop_64HLtoV128,
   12794                           unop( Iop_ReinterpF64asI64,
   12795                                 binop( Iop_RoundF64toF32,
   12796                                        get_IR_roundingmode(),
   12797                                        binop( Iop_I64UtoF64,
   12798                                               get_IR_roundingmode(),
   12799                                               mkexpr( xB ) ) ) ),
   12800                           mkU64( 0 ) ) );
   12801          break;
   12802       case 0x2D0:
   12803          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
   12804          //            Double-Precision format)
   12805          DIP("xscvuxddp v%u,v%u\n", XT, XB);
   12806          putVSReg( XT,
   12807                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   12808                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   12809                                                        mkexpr( xB ) ) ),
   12810                                                        mkU64( 0 ) ) );
   12811          break;
   12812       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
   12813                   //             to Signed Integer Word format with Saturate)
   12814       {
   12815          IRTemp hiResult_32 = newTemp(Ity_I32);
   12816          IRTemp loResult_32 = newTemp(Ity_I32);
   12817          IRExpr* rmZero = mkU32(Irrm_ZERO);
   12818 
   12819          DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
   12820          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
   12821          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
   12822          putVSReg( XT,
   12823                    binop( Iop_64HLtoV128,
   12824                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
   12825                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
   12826          break;
   12827       }
   12828       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
   12829          //  (VSX Vector truncate Single-Precision to integer and
   12830          //   Convert to [Un]signed Integer Word format with Saturate)
   12831       {
   12832          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
   12833          IRTemp tempResult = newTemp(Ity_V128);
   12834          IRTemp res0 = newTemp(Ity_I32);
   12835          IRTemp res1 = newTemp(Ity_I32);
   12836          IRTemp res2 = newTemp(Ity_I32);
   12837          IRTemp res3 = newTemp(Ity_I32);
   12838          IRTemp hi64 = newTemp(Ity_I64);
   12839          IRTemp lo64 = newTemp(Ity_I64);
   12840          Bool un_signed = (opc2 == 0x110);
   12841          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
   12842 
   12843          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
   12844          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
   12845           * then result is set to 0x80000000.  */
   12846          assign(tempResult, unop(op, getVSReg(XB)));
   12847          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
   12848          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
   12849          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
   12850          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
   12851          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
   12852          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
   12853 
   12854          b3_result = IRExpr_ITE(is_NaN_32(b3),
   12855                                 // then: result is 0x{8|0}80000000
   12856                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12857                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12858                                 mkexpr(res3));
   12859          b2_result = IRExpr_ITE(is_NaN_32(b2),
   12860                                 // then: result is 0x{8|0}80000000
   12861                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12862                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12863                                 mkexpr(res2));
   12864          b1_result = IRExpr_ITE(is_NaN_32(b1),
   12865                                 // then: result is 0x{8|0}80000000
   12866                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12867                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12868                                 mkexpr(res1));
   12869          b0_result = IRExpr_ITE(is_NaN_32(b0),
   12870                                 // then: result is 0x{8|0}80000000
   12871                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
   12872                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
   12873                                 mkexpr(res0));
   12874 
   12875          putVSReg( XT,
   12876                    binop( Iop_64HLtoV128,
   12877                           binop( Iop_32HLto64, b3_result, b2_result ),
   12878                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
   12879          break;
   12880       }
   12881       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
   12882                   //           Convert to Single-Precision format
   12883          DIP("xscvdpsp v%u,v%u\n", XT, XB);
   12884          putVSReg( XT,
   12885                    binop( Iop_64HLtoV128,
   12886                           binop( Iop_32HLto64,
   12887                                  unop( Iop_ReinterpF32asI32,
   12888                                        unop( Iop_TruncF64asF32,
   12889                                              binop( Iop_RoundF64toF32,
   12890                                                     get_IR_roundingmode(),
   12891                                                     mkexpr( xB ) ) ) ),
   12892                                  mkU32( 0 ) ),
   12893                           mkU64( 0ULL ) ) );
   12894          break;
   12895       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
   12896                               vector Single-Precision non-signalling */
   12897          DIP("xscvdpspn v%u,v%u\n", XT, XB);
   12898          putVSReg( XT,
   12899                    binop( Iop_64HLtoV128,
   12900                           binop( Iop_32HLto64,
   12901                                  unop( Iop_ReinterpF32asI32,
   12902                                        unop( Iop_TruncF64asF32,
   12903                                              mkexpr( xB ) ) ),
   12904                                  mkU32( 0 ) ),
   12905                           mkU64( 0ULL ) ) );
   12906          break;
   12907       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
   12908                   //             and Convert to Unsigned Integer Word format with Saturate)
   12909          DIP("xscvdpuxws v%u,v%u\n", XT, XB);
   12910          putVSReg( XT,
   12911                    binop( Iop_64HLtoV128,
   12912                           binop( Iop_32HLto64,
   12913                                  mkU32( 0 ),
   12914                                  binop( Iop_F64toI32U,
   12915                                         mkU32( Irrm_ZERO ),
   12916                                         mkexpr( xB ) ) ),
   12917                           mkU64( 0ULL ) ) );
   12918          break;
   12919       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
   12920          DIP("xscvspdp v%u,v%u\n", XT, XB);
   12921          putVSReg( XT,
   12922                    binop( Iop_64HLtoV128,
   12923                           unop( Iop_ReinterpF64asI64,
   12924                                 unop( Iop_F32toF64,
   12925                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12926                           mkU64( 0ULL ) ) );
   12927          break;
   12928       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
   12929          DIP("xscvspdpn v%u,v%u\n", XT, XB);
   12930          putVSReg( XT,
   12931                    binop( Iop_64HLtoV128,
   12932                           unop( Iop_ReinterpF64asI64,
   12933                                 unop( Iop_F32toF64,
   12934                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
   12935                                       mkU64( 0ULL ) ) );
   12936          break;
   12937       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
   12938                   //           and Convert to Single-Precision format)
   12939          DIP("xvcvdpsp v%u,v%u\n", XT, XB);
   12940          putVSReg( XT,
   12941                    binop( Iop_64HLtoV128,
   12942                           binop( Iop_32HLto64,
   12943                                  unop( Iop_ReinterpF32asI32,
   12944                                        unop( Iop_TruncF64asF32,
   12945                                              binop( Iop_RoundF64toF32,
   12946                                                     get_IR_roundingmode(),
   12947                                                     mkexpr( xB ) ) ) ),
   12948                                  mkU32( 0 ) ),
   12949                           binop( Iop_32HLto64,
   12950                                  unop( Iop_ReinterpF32asI32,
   12951                                        unop( Iop_TruncF64asF32,
   12952                                              binop( Iop_RoundF64toF32,
   12953                                                     get_IR_roundingmode(),
   12954                                                     mkexpr( xB2 ) ) ) ),
   12955                                  mkU32( 0 ) ) ) );
   12956          break;
   12957       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
   12958                   //             and Convert to Unsigned Integer Doubleword format
   12959                   //             with Saturate)
   12960          DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
   12961          putVSReg( XT,
   12962                    binop( Iop_64HLtoV128,
   12963                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   12964                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   12965          break;
   12966       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
   12967                   //             Convert to Unsigned Integer Word format with Saturate)
   12968          DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
   12969          putVSReg( XT,
   12970                    binop( Iop_64HLtoV128,
   12971                           binop( Iop_32HLto64,
   12972                                  binop( Iop_F64toI32U,
   12973                                         mkU32( Irrm_ZERO ),
   12974                                         mkexpr( xB ) ),
   12975                                  mkU32( 0 ) ),
   12976                           binop( Iop_32HLto64,
   12977                                  binop( Iop_F64toI32U,
   12978                                         mkU32( Irrm_ZERO ),
   12979                                         mkexpr( xB2 ) ),
   12980                                  mkU32( 0 ) ) ) );
   12981          break;
   12982       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
   12983          DIP("xvcvspdp v%u,v%u\n", XT, XB);
   12984          putVSReg( XT,
   12985                    binop( Iop_64HLtoV128,
   12986                           unop( Iop_ReinterpF64asI64,
   12987                                 unop( Iop_F32toF64,
   12988                                       unop( Iop_ReinterpI32asF32,
   12989                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
   12990                           unop( Iop_ReinterpF64asI64,
   12991                                 unop( Iop_F32toF64,
   12992                                       unop( Iop_ReinterpI32asF32,
   12993                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
   12994          break;
   12995       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
   12996                   //           Convert to Signed Integer Doubleword format with Saturate)
   12997          DIP("xvcvspsxds v%u,v%u\n", XT, XB);
   12998          putVSReg( XT,
   12999                    binop( Iop_64HLtoV128,
   13000                           binop( Iop_F64toI64S,
   13001                                  mkU32( Irrm_ZERO ),
   13002                                  unop( Iop_F32toF64,
   13003                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   13004                           binop( Iop_F64toI64S,
   13005                                  mkU32( Irrm_ZERO ),
   13006                                  unop( Iop_F32toF64,
   13007                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   13008          break;
   13009       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
   13010                   //            Convert to Unsigned Integer Doubleword format with Saturate)
   13011          DIP("xvcvspuxds v%u,v%u\n", XT, XB);
   13012          putVSReg( XT,
   13013                    binop( Iop_64HLtoV128,
   13014                           binop( Iop_F64toI64U,
   13015                                  mkU32( Irrm_ZERO ),
   13016                                  unop( Iop_F32toF64,
   13017                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
   13018                           binop( Iop_F64toI64U,
   13019                                  mkU32( Irrm_ZERO ),
   13020                                  unop( Iop_F32toF64,
   13021                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
   13022          break;
   13023       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
   13024                   //             Convert to Signed Integer Doubleword format with Saturate)
   13025          DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
   13026          putVSReg( XT,
   13027                    binop( Iop_64HLtoV128,
   13028                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
   13029                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
   13030          break;
   13031       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
   13032                   //            to Double-Precision format)
   13033          DIP("xvcvsxddp v%u,v%u\n", XT, XB);
   13034          putVSReg( XT,
   13035                    binop( Iop_64HLtoV128,
   13036                           unop( Iop_ReinterpF64asI64,
   13037                                 binop( Iop_I64StoF64,
   13038                                        get_IR_roundingmode(),
   13039                                        mkexpr( xB ) ) ),
   13040                           unop( Iop_ReinterpF64asI64,
   13041                                 binop( Iop_I64StoF64,
   13042                                        get_IR_roundingmode(),
   13043                                        mkexpr( xB2 ) ) ) ) );
   13044          break;
   13045       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
   13046                   //            to Double-Precision format)
   13047          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
   13048          putVSReg( XT,
   13049                    binop( Iop_64HLtoV128,
   13050                           unop( Iop_ReinterpF64asI64,
   13051                                 binop( Iop_I64UtoF64,
   13052                                        get_IR_roundingmode(),
   13053                                        mkexpr( xB ) ) ),
   13054                           unop( Iop_ReinterpF64asI64,
   13055                                 binop( Iop_I64UtoF64,
   13056                                        get_IR_roundingmode(),
   13057                                        mkexpr( xB2 ) ) ) ) );
   13058 
   13059          break;
   13060       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
   13061                   //            to Single-Precision format)
   13062          DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
   13063          putVSReg( XT,
   13064                    binop( Iop_64HLtoV128,
   13065                           binop( Iop_32HLto64,
   13066                                  unop( Iop_ReinterpF32asI32,
   13067                                        unop( Iop_TruncF64asF32,
   13068                                              binop( Iop_RoundF64toF32,
   13069                                                     get_IR_roundingmode(),
   13070                                                     binop( Iop_I64StoF64,
   13071                                                            get_IR_roundingmode(),
   13072                                                            mkexpr( xB ) ) ) ) ),
   13073                                  mkU32( 0 ) ),
   13074                           binop( Iop_32HLto64,
   13075                                  unop( Iop_ReinterpF32asI32,
   13076                                        unop( Iop_TruncF64asF32,
   13077                                              binop( Iop_RoundF64toF32,
   13078                                                     get_IR_roundingmode(),
   13079                                                     binop( Iop_I64StoF64,
   13080                                                            get_IR_roundingmode(),
   13081                                                            mkexpr( xB2 ) ) ) ) ),
   13082                                  mkU32( 0 ) ) ) );
   13083          break;
   13084       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
   13085                   //            to Single-Precision format)
   13086          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
   13087          putVSReg( XT,
   13088                    binop( Iop_64HLtoV128,
   13089                           binop( Iop_32HLto64,
   13090                                  unop( Iop_ReinterpF32asI32,
   13091                                        unop( Iop_TruncF64asF32,
   13092                                              binop( Iop_RoundF64toF32,
   13093                                                     get_IR_roundingmode(),
   13094                                                     binop( Iop_I64UtoF64,
   13095                                                            get_IR_roundingmode(),
   13096                                                            mkexpr( xB ) ) ) ) ),
   13097                                  mkU32( 0 ) ),
   13098                           binop( Iop_32HLto64,
   13099                                  unop( Iop_ReinterpF32asI32,
   13100                                        unop( Iop_TruncF64asF32,
   13101                                              binop( Iop_RoundF64toF32,
   13102                                                     get_IR_roundingmode(),
   13103                                                     binop( Iop_I64UtoF64,
   13104                                                            get_IR_roundingmode(),
   13105                                                            mkexpr( xB2 ) ) ) ) ),
   13106                                  mkU32( 0 ) ) ) );
   13107          break;
   13108 
   13109       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
   13110          DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
   13111          putVSReg( XT,
   13112                    binop( Iop_64HLtoV128,
   13113                           unop( Iop_ReinterpF64asI64,
   13114                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   13115                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
   13116                           unop( Iop_ReinterpF64asI64,
   13117                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
   13118                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
   13119          break;
   13120       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
   13121          DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
   13122          putVSReg( XT,
   13123                    binop( Iop_64HLtoV128,
   13124                           unop( Iop_ReinterpF64asI64,
   13125                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   13126                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
   13127                           unop( Iop_ReinterpF64asI64,
   13128                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
   13129                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
   13130          break;
   13131       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
   13132          DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
   13133          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
   13134          break;
   13135       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
   13136          DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
   13137          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
   13138          break;
   13139 
   13140       default:
   13141          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
   13142          return False;
   13143    }
   13144    return True;
   13145 }
   13146 
   13147 /*
   13148  * VSX vector Double Precision Floating Point Arithmetic Instructions
   13149  */
   13150 static Bool
   13151 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
   13152 {
   13153    /* XX3-Form */
   13154    UChar opc1 = ifieldOPC( theInstr );
   13155    UChar XT = ifieldRegXT( theInstr );
   13156    UChar XA = ifieldRegXA( theInstr );
   13157    UChar XB = ifieldRegXB( theInstr );
   13158    IRExpr* rm = get_IR_roundingmode();
   13159    IRTemp frA = newTemp(Ity_F64);
   13160    IRTemp frB = newTemp(Ity_F64);
   13161    IRTemp frA2 = newTemp(Ity_F64);
   13162    IRTemp frB2 = newTemp(Ity_F64);
   13163 
   13164    if (opc1 != 0x3C) {
   13165       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
   13166       return False;
   13167    }
   13168 
   13169    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   13170    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   13171    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
   13172    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
   13173 
   13174    switch (opc2) {
   13175       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
   13176       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
   13177       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
   13178       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
   13179       {
   13180          IROp mOp;
   13181          const HChar * oper_name;
   13182          switch (opc2) {
   13183             case 0x1E0:
   13184                mOp = Iop_DivF64;
   13185                oper_name = "div";
   13186                break;
   13187             case 0x1C0:
   13188                mOp = Iop_MulF64;
   13189                oper_name = "mul";
   13190                break;
   13191             case 0x180:
   13192                mOp = Iop_AddF64;
   13193                oper_name = "add";
   13194                break;
   13195             case 0x1A0:
   13196                mOp = Iop_SubF64;
   13197                oper_name = "sub";
   13198                break;
   13199 
   13200             default:
   13201                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
   13202          }
   13203          IRTemp hiResult = newTemp(Ity_I64);
   13204          IRTemp loResult = newTemp(Ity_I64);
   13205          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
   13206 
   13207          assign( hiResult,
   13208                  unop( Iop_ReinterpF64asI64,
   13209                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
   13210          assign( loResult,
   13211                  unop( Iop_ReinterpF64asI64,
   13212                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
   13213          putVSReg( XT,
   13214                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   13215          break;
   13216       }
   13217       case 0x196: // xvsqrtdp
   13218       {
   13219          IRTemp hiResult = newTemp(Ity_I64);
   13220          IRTemp loResult = newTemp(Ity_I64);
   13221          DIP("xvsqrtdp v%d,v%d\n", XT, XB);
   13222 
   13223          assign( hiResult,
   13224                  unop( Iop_ReinterpF64asI64,
   13225                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
   13226          assign( loResult,
   13227                  unop( Iop_ReinterpF64asI64,
   13228                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
   13229          putVSReg( XT,
   13230                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   13231          break;
   13232       }
   13233       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
   13234       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
   13235       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
   13236       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
   13237       {
   13238          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
   13239           *    XT == FRC
   13240           *    XA == FRA
   13241           *    XB == FRB
   13242           *
   13243           * and for xvm{add|sub}adp . . .
   13244           *    XT == FRB
   13245           *    XA == FRA
   13246           *    XB == FRC
   13247           */
   13248          Bool negate;
   13249          IROp mOp = Iop_INVALID;
   13250          const HChar * oper_name = NULL;
   13251          Bool mdp = False;
   13252 
   13253          switch (opc2) {
   13254             case 0x184: case 0x1A4:
   13255             case 0x384: case 0x3A4:
   13256                mOp = Iop_MAddF64;
   13257                oper_name = "add";
   13258                mdp = (opc2 & 0x0FF) == 0x0A4;
   13259                break;
   13260 
   13261             case 0x1C4: case 0x1E4:
   13262             case 0x3C4: case 0x3E4:
   13263                mOp = Iop_MSubF64;
   13264                oper_name = "sub";
   13265                mdp = (opc2 & 0x0FF) == 0x0E4;
   13266                break;
   13267 
   13268             default:
   13269                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   13270          }
   13271 
   13272          switch (opc2) {
   13273             case 0x384: case 0x3A4:
   13274             case 0x3C4: case 0x3E4:
   13275                negate = True;
   13276                break;
   13277             default:
   13278                negate = False;
   13279          }
   13280          IRTemp hiResult = newTemp(Ity_I64);
   13281          IRTemp loResult = newTemp(Ity_I64);
   13282          IRTemp frT = newTemp(Ity_F64);
   13283          IRTemp frT2 = newTemp(Ity_F64);
   13284          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
   13285              XT, XA, XB);
   13286          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
   13287          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
   13288 
   13289          assign( hiResult,
   13290                  unop( Iop_ReinterpF64asI64,
   13291                        qop( mOp,
   13292                             rm,
   13293                             mkexpr( frA ),
   13294                             mkexpr( mdp ? frT : frB ),
   13295                             mkexpr( mdp ? frB : frT ) ) ) );
   13296          assign( loResult,
   13297                  unop( Iop_ReinterpF64asI64,
   13298                        qop( mOp,
   13299                             rm,
   13300                             mkexpr( frA2 ),
   13301                             mkexpr( mdp ? frT2 : frB2 ),
   13302                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
   13303          putVSReg( XT,
   13304                    binop( Iop_64HLtoV128,
   13305                           mkexpr( negate ? getNegatedResult( hiResult )
   13306                                          : hiResult ),
   13307                           mkexpr( negate ? getNegatedResult( loResult )
   13308                                          : loResult ) ) );
   13309          break;
   13310       }
   13311       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   13312       {
   13313          IRTemp frBHi_I64 = newTemp(Ity_I64);
   13314          IRTemp frBLo_I64 = newTemp(Ity_I64);
   13315          IRTemp flagsHi = newTemp(Ity_I32);
   13316          IRTemp flagsLo = newTemp(Ity_I32);
   13317          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13318          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   13319          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   13320 
   13321          DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
   13322          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   13323          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   13324          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
   13325          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
   13326          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13327           * where fl_flag == 1 on ppc64.
   13328           */
   13329          assign( flagsHi,
   13330                  binop( Iop_Or32,
   13331                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13332                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   13333                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   13334          assign( flagsLo,
   13335                  binop( Iop_Or32,
   13336                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13337                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   13338                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   13339          putGST_field( PPC_GST_CR,
   13340                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   13341                        crfD );
   13342          break;
   13343       }
   13344       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
   13345       {
   13346          IRTemp frBHi_I64 = newTemp(Ity_I64);
   13347          IRTemp frBLo_I64 = newTemp(Ity_I64);
   13348          IRTemp frAHi_I64 = newTemp(Ity_I64);
   13349          IRTemp frALo_I64 = newTemp(Ity_I64);
   13350          IRTemp flagsHi = newTemp(Ity_I32);
   13351          IRTemp flagsLo = newTemp(Ity_I32);
   13352          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13353          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
   13354          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
   13355 
   13356          DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
   13357          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
   13358          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
   13359          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   13360          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
   13361 
   13362          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
   13363          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
   13364          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13365           * where fl_flag == 1 on ppc64.
   13366           */
   13367          assign( flagsHi,
   13368                  binop( Iop_Or32,
   13369                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13370                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
   13371                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
   13372          assign( flagsLo,
   13373                  binop( Iop_Or32,
   13374                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13375                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
   13376                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
   13377          putGST_field( PPC_GST_CR,
   13378                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
   13379                        crfD );
   13380          break;
   13381       }
   13382 
   13383       default:
   13384          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
   13385          return False;
   13386    }
   13387    return True;
   13388 }
   13389 
   13390 /*
   13391  * VSX vector Single Precision Floating Point Arithmetic Instructions
   13392  */
   13393 static Bool
   13394 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
   13395 {
   13396    /* XX3-Form */
   13397    UChar opc1 = ifieldOPC( theInstr );
   13398    UChar XT = ifieldRegXT( theInstr );
   13399    UChar XA = ifieldRegXA( theInstr );
   13400    UChar XB = ifieldRegXB( theInstr );
   13401    IRExpr* rm = get_IR_roundingmode();
   13402    IRTemp a3, a2, a1, a0;
   13403    IRTemp b3, b2, b1, b0;
   13404    IRTemp res0 = newTemp(Ity_I32);
   13405    IRTemp res1 = newTemp(Ity_I32);
   13406    IRTemp res2 = newTemp(Ity_I32);
   13407    IRTemp res3 = newTemp(Ity_I32);
   13408 
   13409    a3 = a2 = a1 = a0 = IRTemp_INVALID;
   13410    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   13411 
   13412    if (opc1 != 0x3C) {
   13413       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
   13414       return False;
   13415    }
   13416 
   13417    switch (opc2) {
   13418       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
   13419          DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
   13420          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
   13421          putVSReg( XT, triop(Iop_Add32Fx4, rm,
   13422                              getVSReg( XA ), getVSReg( XB )) );
   13423          break;
   13424 
   13425       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
   13426          DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
   13427          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
   13428          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
   13429                              getVSReg( XA ), getVSReg( XB )) );
   13430          break;
   13431 
   13432       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
   13433          DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
   13434          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
   13435          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
   13436                              getVSReg( XA ), getVSReg( XB )) );
   13437          break;
   13438 
   13439       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
   13440       {
   13441          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
   13442           * So there are two choices:
   13443           *   1. Implement the xvdivsp with a native insn; or
   13444           *   2. Extract the 4 single precision floats from each vector
   13445           *      register inputs and perform fdivs on each pair
   13446           * I will do the latter, due to the general philosophy of
   13447           * reusing existing implementations when practical.
   13448           */
   13449          DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
   13450          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13451          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13452 
   13453          assign( res0,
   13454               unop( Iop_ReinterpF32asI32,
   13455                     unop( Iop_TruncF64asF32,
   13456                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
   13457          assign( res1,
   13458                  unop( Iop_ReinterpF32asI32,
   13459                        unop( Iop_TruncF64asF32,
   13460                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
   13461          assign( res2,
   13462                  unop( Iop_ReinterpF32asI32,
   13463                        unop( Iop_TruncF64asF32,
   13464                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
   13465          assign( res3,
   13466                  unop( Iop_ReinterpF32asI32,
   13467                        unop( Iop_TruncF64asF32,
   13468                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
   13469 
   13470          putVSReg( XT,
   13471                    binop( Iop_64HLtoV128,
   13472                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13473                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13474          break;
   13475       }
   13476       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
   13477       {
   13478          DIP("xvsqrtsp v%d,v%d\n", XT, XB);
   13479          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13480          /* Note: The native xvsqrtsp insruction does not always give the same precision
   13481           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
   13482           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
   13483           * to the actual instruction.
   13484           */
   13485 
   13486          assign( res0,
   13487                  unop( Iop_ReinterpF32asI32,
   13488                        unop( Iop_TruncF64asF32,
   13489                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
   13490          assign( res1,
   13491                  unop( Iop_ReinterpF32asI32,
   13492                        unop( Iop_TruncF64asF32,
   13493                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
   13494          assign( res2,
   13495                  unop( Iop_ReinterpF32asI32,
   13496                        unop( Iop_TruncF64asF32,
   13497                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
   13498          assign( res3,
   13499                  unop( Iop_ReinterpF32asI32,
   13500                        unop( Iop_TruncF64asF32,
   13501                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
   13502 
   13503          putVSReg( XT,
   13504                    binop( Iop_64HLtoV128,
   13505                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   13506                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   13507          break;
   13508       }
   13509 
   13510       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
   13511       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
   13512       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
   13513       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
   13514       {
   13515          IRTemp t3, t2, t1, t0;
   13516          Bool msp = False;
   13517          Bool negate;
   13518          const HChar * oper_name = NULL;
   13519          IROp mOp = Iop_INVALID;
   13520          switch (opc2) {
   13521             case 0x104: case 0x124:
   13522             case 0x304: case 0x324:
   13523                msp = (opc2 & 0x0FF) == 0x024;
   13524                mOp = Iop_MAddF64r32;
   13525                oper_name = "madd";
   13526                break;
   13527 
   13528             case 0x144: case 0x164:
   13529             case 0x344: case 0x364:
   13530                msp = (opc2 & 0x0FF) == 0x064;
   13531                mOp = Iop_MSubF64r32;
   13532                oper_name = "sub";
   13533                break;
   13534 
   13535             default:
   13536                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
   13537          }
   13538 
   13539          switch (opc2) {
   13540             case 0x304: case 0x324:
   13541             case 0x344: case 0x364:
   13542                negate = True;
   13543                break;
   13544 
   13545             default:
   13546                negate = False;
   13547          }
   13548 
   13549          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
   13550              msp ? "msp" : "asp", XT, XA, XB);
   13551 
   13552          t3 = t2 = t1 = t0 = IRTemp_INVALID;
   13553          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13554          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13555          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
   13556 
   13557          assign( res0,
   13558                  unop( Iop_ReinterpF32asI32,
   13559                        unop( Iop_TruncF64asF32,
   13560                              qop( mOp,
   13561                                   rm,
   13562                                   mkexpr( a0 ),
   13563                                   mkexpr( msp ? t0 : b0 ),
   13564                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
   13565          assign( res1,
   13566                  unop( Iop_ReinterpF32asI32,
   13567                        unop( Iop_TruncF64asF32,
   13568                              qop( mOp,
   13569                                   rm,
   13570                                   mkexpr( a1 ),
   13571                                   mkexpr( msp ? t1 : b1 ),
   13572                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
   13573          assign( res2,
   13574                  unop( Iop_ReinterpF32asI32,
   13575                        unop( Iop_TruncF64asF32,
   13576                              qop( mOp,
   13577                                   rm,
   13578                                   mkexpr( a2 ),
   13579                                   mkexpr( msp ? t2 : b2 ),
   13580                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
   13581          assign( res3,
   13582                  unop( Iop_ReinterpF32asI32,
   13583                        unop( Iop_TruncF64asF32,
   13584                              qop( mOp,
   13585                                   rm,
   13586                                   mkexpr( a3 ),
   13587                                   mkexpr( msp ? t3 : b3 ),
   13588                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
   13589 
   13590          putVSReg( XT,
   13591                    binop( Iop_64HLtoV128,
   13592                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
   13593                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
   13594                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
   13595                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
   13596 
   13597          break;
   13598       }
   13599       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
   13600       {
   13601          IRTemp flags0 = newTemp(Ity_I32);
   13602          IRTemp flags1 = newTemp(Ity_I32);
   13603          IRTemp flags2 = newTemp(Ity_I32);
   13604          IRTemp flags3 = newTemp(Ity_I32);
   13605          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13606          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13607          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13608          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13609          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13610          DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
   13611 
   13612          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13613          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13614          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13615          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13616          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13617 
   13618          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13619           * where fl_flag == 1 on ppc64.
   13620           */
   13621          assign( flags0,
   13622                  binop( Iop_Or32,
   13623                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13624                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13625                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13626          assign( flags1,
   13627                  binop( Iop_Or32,
   13628                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13629                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13630                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13631          assign( flags2,
   13632                  binop( Iop_Or32,
   13633                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13634                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13635                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13636          assign( flags3,
   13637                  binop( Iop_Or32,
   13638                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13639                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13640                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13641          putGST_field( PPC_GST_CR,
   13642                        binop( Iop_Or32,
   13643                               mkexpr( flags0 ),
   13644                               binop( Iop_Or32,
   13645                                      mkexpr( flags1 ),
   13646                                      binop( Iop_Or32,
   13647                                             mkexpr( flags2 ),
   13648                                             mkexpr( flags3 ) ) ) ),
   13649                        crfD );
   13650 
   13651          break;
   13652       }
   13653       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
   13654       {
   13655          IRTemp flags0 = newTemp(Ity_I32);
   13656          IRTemp flags1 = newTemp(Ity_I32);
   13657          IRTemp flags2 = newTemp(Ity_I32);
   13658          IRTemp flags3 = newTemp(Ity_I32);
   13659          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   13660          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
   13661          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
   13662          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
   13663          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
   13664          DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
   13665 
   13666          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   13667          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   13668          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
   13669          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
   13670          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
   13671          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
   13672 
   13673          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   13674           * where fl_flag == 1 on ppc64.
   13675           */
   13676          assign( flags0,
   13677                  binop( Iop_Or32,
   13678                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13679                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
   13680                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
   13681          assign( flags1,
   13682                  binop( Iop_Or32,
   13683                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13684                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
   13685                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
   13686          assign( flags2,
   13687                  binop( Iop_Or32,
   13688                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13689                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
   13690                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
   13691          assign( flags3,
   13692                  binop( Iop_Or32,
   13693                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   13694                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
   13695                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
   13696          putGST_field( PPC_GST_CR,
   13697                        binop( Iop_Or32,
   13698                               mkexpr( flags0 ),
   13699                               binop( Iop_Or32,
   13700                                      mkexpr( flags1 ),
   13701                                      binop( Iop_Or32,
   13702                                             mkexpr( flags2 ),
   13703                                             mkexpr( flags3 ) ) ) ),
   13704                        crfD );
   13705 
   13706          break;
   13707       }
   13708 
   13709       default:
   13710          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
   13711          return False;
   13712    }
   13713    return True;
   13714 }
   13715 
   13716 /*
   13717  * Vector Population Count/bit matrix transpose
   13718  */
   13719 static Bool
   13720 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
   13721 {
   13722    UChar vRB_addr = ifieldRegB(theInstr);
   13723    UChar vRT_addr = ifieldRegDS(theInstr);
   13724    UChar opc1 = ifieldOPC( theInstr );
   13725    IRTemp vB = newTemp(Ity_V128);
   13726    assign( vB, getVReg(vRB_addr));
   13727 
   13728    if (opc1 != 0x4) {
   13729       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
   13730       return False;
   13731    }
   13732 
   13733    switch (opc2) {
   13734       case 0x702:    // vclzb
   13735          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
   13736          putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
   13737          break;
   13738 
   13739       case 0x742:    // vclzh
   13740          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
   13741          putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
   13742          break;
   13743 
   13744       case 0x782:    // vclzw
   13745          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
   13746          putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
   13747          break;
   13748 
   13749       case 0x7C2:    // vclzd
   13750          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
   13751          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
   13752          break;
   13753 
   13754       case 0x703:    // vpopcntb
   13755       {
   13756          /* Break vector into 32-bit words and do the population count
   13757           * on byte in the words
   13758           */
   13759          IRType ty = Ity_I32;
   13760          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13761          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13762          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13763          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13764 
   13765          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
   13766          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13767          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
   13768          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
   13769          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
   13770          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
   13771 
   13772          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13773                                          cnt_bits32_63, cnt_bits0_31) );
   13774          break;
   13775       }
   13776 
   13777       case 0x743:    // vpopcnth
   13778       {
   13779          /* Break vector into 32-bit words and do the population count
   13780           * for each half word
   13781           */
   13782          IRType ty = Ity_I32;
   13783          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13784          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13785          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13786          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13787 
   13788          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
   13789          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13790 
   13791          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
   13792          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
   13793          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
   13794          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
   13795 
   13796          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13797                                          cnt_bits32_63, cnt_bits0_31) );
   13798          break;
   13799       }
   13800 
   13801       case 0x783:    // vpopcntw
   13802       {
   13803          /* Break vector into 32-bit words and do the population count
   13804           * on each word.
   13805           */
   13806          IRType ty = Ity_I32;
   13807          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13808          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13809          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
   13810          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
   13811 
   13812          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
   13813          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13814 
   13815          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
   13816          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
   13817          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
   13818          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
   13819 
   13820          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
   13821                                          cnt_bits32_63, cnt_bits0_31) );
   13822          break;
   13823       }
   13824 
   13825       case 0x7C3:    // vpopcntd
   13826       {
   13827          if (mode64) {
   13828             /* Break vector into 64-bit double words and do the population count
   13829              * on each double word.
   13830              */
   13831             IRType ty = Ity_I64;
   13832             IRTemp bits0_63   = newTemp(Ity_I64);
   13833             IRTemp bits64_127 = newTemp(Ity_I64);
   13834             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13835             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
   13836 
   13837             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13838 
   13839             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
   13840             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
   13841             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
   13842             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
   13843 
   13844             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13845                                       mkexpr( cnt_bits64_127 ),
   13846                                       mkexpr( cnt_bits0_63 ) ) );
   13847          } else {
   13848             /* Break vector into 32-bit words and do the population count
   13849              * on each doubleword.
   13850              */
   13851             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
   13852             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
   13853             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
   13854             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
   13855 
   13856             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
   13857             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
   13858 
   13859             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
   13860             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
   13861 
   13862             putVReg( vRT_addr, binop( Iop_64HLtoV128,
   13863                                       mkexpr( cnt_bits64_127 ),
   13864                                       mkexpr( cnt_bits0_63 ) ) );
   13865          }
   13866          break;
   13867       }
   13868 
   13869       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
   13870          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
   13871          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
   13872          break;
   13873 
   13874       default:
   13875          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
   13876          return False;
   13877       break;
   13878    }
   13879    return True;
   13880 }
   13881 
   13882 typedef enum {
   13883    PPC_CMP_EQ = 2,
   13884    PPC_CMP_GT = 4,
   13885    PPC_CMP_GE = 6,
   13886    PPC_CMP_LT = 8
   13887 } ppc_cmp_t;
   13888 
   13889 
   13890 /*
   13891   This helper function takes as input the IRExpr returned
   13892   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
   13893   in IR form.  This helper function converts it to PPC form.
   13894 
   13895   Map compare result from IR to PPC
   13896 
   13897   FP cmp result | PPC | IR
   13898   --------------------------
   13899   UN            | 0x1 | 0x45
   13900   EQ            | 0x2 | 0x40
   13901   GT            | 0x4 | 0x00
   13902   LT            | 0x8 | 0x01
   13903 
   13904  condcode = Shl(1, (~(ccIR>>5) & 2)
   13905                     | ((ccIR ^ (ccIR>>6)) & 1)
   13906 */
   13907 static IRTemp
   13908 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
   13909 {
   13910    IRTemp condcode = newTemp( Ity_I32 );
   13911    IRTemp ccIR = newTemp( Ity_I32 );
   13912 
   13913    assign(ccIR, ccIR_expr);
   13914    assign( condcode,
   13915            binop( Iop_Shl32,
   13916                   mkU32( 1 ),
   13917                   unop( Iop_32to8,
   13918                         binop( Iop_Or32,
   13919                                binop( Iop_And32,
   13920                                       unop( Iop_Not32,
   13921                                             binop( Iop_Shr32,
   13922                                                    mkexpr( ccIR ),
   13923                                                    mkU8( 5 ) ) ),
   13924                                       mkU32( 2 ) ),
   13925                                binop( Iop_And32,
   13926                                       binop( Iop_Xor32,
   13927                                              mkexpr( ccIR ),
   13928                                              binop( Iop_Shr32,
   13929                                                     mkexpr( ccIR ),
   13930                                                     mkU8( 6 ) ) ),
   13931                                       mkU32( 1 ) ) ) ) ) );
   13932    return condcode;
   13933 }
   13934 
   13935 /*
   13936  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
   13937  * following these special rules:
   13938  *   - The max/min of a QNaN and any value is that value
   13939  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
   13940  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
   13941  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
   13942  */
   13943 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
   13944 {
   13945    IRTemp frA_isNaN = newTemp(Ity_I1);
   13946    IRTemp frB_isNaN = newTemp(Ity_I1);
   13947    IRTemp frA_isSNaN = newTemp(Ity_I1);
   13948    IRTemp frB_isSNaN = newTemp(Ity_I1);
   13949    IRTemp frA_isQNaN = newTemp(Ity_I1);
   13950    IRTemp frB_isQNaN = newTemp(Ity_I1);
   13951 
   13952    assign( frA_isNaN, is_NaN( frA_I64 ) );
   13953    assign( frB_isNaN, is_NaN( frB_I64 ) );
   13954    // If operand is a NAN and bit 12 is '0', then it's an SNaN
   13955    assign( frA_isSNaN,
   13956            mkAND1( mkexpr(frA_isNaN),
   13957                    binop( Iop_CmpEQ32,
   13958                           binop( Iop_And32,
   13959                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
   13960                                  mkU32( 0x00080000 ) ),
   13961                           mkU32( 0 ) ) ) );
   13962    assign( frB_isSNaN,
   13963            mkAND1( mkexpr(frB_isNaN),
   13964                    binop( Iop_CmpEQ32,
   13965                           binop( Iop_And32,
   13966                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
   13967                                  mkU32( 0x00080000 ) ),
   13968                           mkU32( 0 ) ) ) );
   13969    assign( frA_isQNaN,
   13970            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
   13971    assign( frB_isQNaN,
   13972            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
   13973 
   13974    /* Based on the rules specified in the function prologue, the algorithm is as follows:
   13975     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13976     *   if frA is a SNaN
   13977     *     result = frA converted to QNaN
   13978     *   else if frB is a SNaN
   13979     *     result = frB converted to QNaN
   13980     *   else if frB is a QNaN
   13981     *     result = frA
   13982     *   // One of frA or frB was a NaN in order for this function to be called, so
   13983     *   // if we get to this point, we KNOW that frA must be a QNaN.
   13984     *   else // frA is a QNaN
   13985     *     result = frB
   13986     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
   13987     */
   13988 
   13989 #define SNAN_MASK 0x0008000000000000ULL
   13990    return
   13991    IRExpr_ITE(mkexpr(frA_isSNaN),
   13992               /* then: result = frA converted to QNaN */
   13993               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
   13994               /* else:  if frB is a SNaN */
   13995               IRExpr_ITE(mkexpr(frB_isSNaN),
   13996                          /* then: result = frB converted to QNaN */
   13997                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
   13998                          /* else:  if frB is a QNaN */
   13999                          IRExpr_ITE(mkexpr(frB_isQNaN),
   14000                                     /* then: result = frA */
   14001                                     mkexpr(frA_I64),
   14002                                     /* else:  frA is a QNaN, so result = frB */
   14003                                     mkexpr(frB_I64))));
   14004 }
   14005 
   14006 /*
   14007  * Helper function for get_max_min_fp.
   14008  */
   14009 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
   14010 {
   14011    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   14012                                                   unop( Iop_ReinterpI64asF64,
   14013                                                         mkexpr( src1 ) ),
   14014                                                   unop( Iop_ReinterpI64asF64,
   14015                                                         mkexpr( src2 ) ) ) );
   14016 
   14017    return IRExpr_ITE( binop( Iop_CmpEQ32,
   14018                                mkexpr( src1cmpsrc2 ),
   14019                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
   14020                       /* then: use src1 */
   14021                       mkexpr( src1 ),
   14022                       /* else: use src2 */
   14023                       mkexpr( src2 ) );
   14024 }
   14025 
   14026 /*
   14027  * Helper function for "Maximum/Minimum Double Precision" operations.
   14028  * Arguments: frA and frb are Ity_I64
   14029  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
   14030  */
   14031 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
   14032 {
   14033    /* There are three special cases where get_fp_cmp_CR_val is not helpful
   14034     * for ascertaining the maximum between two doubles:
   14035     *   1. The max/min of +0 and -0 is +0.
   14036     *   2. The max/min of a QNaN and any value is that value.
   14037     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
   14038     * We perform the check for [+/-]0 here in this function and use the
   14039     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
   14040     * to do the standard comparison function.
   14041     */
   14042    IRTemp anyNaN = newTemp(Ity_I1);
   14043    IRTemp frA_isZero = newTemp(Ity_I1);
   14044    IRTemp frB_isZero = newTemp(Ity_I1);
   14045    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
   14046    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
   14047    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
   14048 #define MINUS_ZERO 0x8000000000000000ULL
   14049 
   14050    return IRExpr_ITE( /* If both arguments are zero . . . */
   14051                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
   14052                      /* then: if frA is -0 and isMin==True, return -0;
   14053                       *     else if frA is +0 and isMin==False; return +0;
   14054                       *     otherwise, simply return frB. */
   14055                      IRExpr_ITE( binop( Iop_CmpEQ32,
   14056                                         unop( Iop_64HIto32,
   14057                                               mkexpr( frA_I64 ) ),
   14058                                         mkU32( isMin ? 0x80000000 : 0 ) ),
   14059                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
   14060                                  mkexpr( frB_I64 ) ),
   14061                      /* else: check if either input is a NaN*/
   14062                      IRExpr_ITE( mkexpr( anyNaN ),
   14063                                  /* then: use "NaN helper" */
   14064                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
   14065                                  /* else: use "comparison helper" */
   14066                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
   14067 }
   14068 
   14069 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
   14070 {
   14071    switch (opc2 & 0x7F) {
   14072       case 0x72:
   14073          return "m";
   14074       case 0x52:
   14075          return "p";
   14076       case 0x56:
   14077          return "c";
   14078       case 0x32:
   14079          return "z";
   14080       case 0x12:
   14081          return "";
   14082 
   14083       default: // Impossible to get here
   14084          vex_printf("Unrecognized opcode %x\n", opc2);
   14085          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
   14086    }
   14087 }
   14088 
   14089 /*
   14090  * Helper function for vector/scalar double precision fp round to integer instructions.
   14091  */
   14092 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
   14093 {
   14094 
   14095    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
   14096    IRTemp frB = newTemp(Ity_F64);
   14097    IRTemp frD = newTemp(Ity_F64);
   14098    IRTemp intermediateResult = newTemp(Ity_I64);
   14099    IRTemp is_SNAN = newTemp(Ity_I1);
   14100    IRExpr * hi32;
   14101    IRExpr * rxpi_rm;
   14102    switch (opc2 & 0x7F) {
   14103       case 0x72:
   14104          rxpi_rm = mkU32(Irrm_NegINF);
   14105          break;
   14106       case 0x52:
   14107          rxpi_rm = mkU32(Irrm_PosINF);
   14108          break;
   14109       case 0x56:
   14110          rxpi_rm = get_IR_roundingmode();
   14111          break;
   14112       case 0x32:
   14113          rxpi_rm = mkU32(Irrm_ZERO);
   14114          break;
   14115       case 0x12:
   14116          rxpi_rm = mkU32(Irrm_NEAREST);
   14117          break;
   14118 
   14119       default: // Impossible to get here
   14120          vex_printf("Unrecognized opcode %x\n", opc2);
   14121          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
   14122    }
   14123    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
   14124    assign( intermediateResult,
   14125            binop( Iop_F64toI64S, rxpi_rm,
   14126                   mkexpr( frB ) ) );
   14127 
   14128    /* don't use the rounded integer if frB is outside -9e18..9e18 */
   14129    /* F64 has only log10(2**52) significant digits anyway */
   14130    /* need to preserve sign of zero */
   14131    /*   frD = (fabs(frB) > 9e18) ? frB :
   14132             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
   14133    assign( frD,
   14134            IRExpr_ITE(
   14135               binop( Iop_CmpNE8,
   14136                      unop( Iop_32to8,
   14137                            binop( Iop_CmpF64,
   14138                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
   14139                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
   14140                      mkU8(0) ),
   14141               mkexpr( frB ),
   14142               IRExpr_ITE(
   14143                  binop( Iop_CmpNE32,
   14144                         binop( Iop_Shr32,
   14145                                unop( Iop_64HIto32,
   14146                                      mkexpr( frB_I64 ) ),
   14147                                mkU8( 31 ) ),
   14148                         mkU32(0) ),
   14149                  unop( Iop_NegF64,
   14150                        unop( Iop_AbsF64,
   14151                              binop( Iop_I64StoF64,
   14152                                     mkU32( 0 ),
   14153                                     mkexpr( intermediateResult ) ) ) ),
   14154                  binop( Iop_I64StoF64,
   14155                         mkU32( 0 ),
   14156                         mkexpr( intermediateResult ) )
   14157               )
   14158            )
   14159    );
   14160 
   14161    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
   14162     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
   14163     */
   14164 #define SNAN_MASK 0x0008000000000000ULL
   14165    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
   14166    assign( is_SNAN,
   14167            mkAND1( is_NaN( frB_I64 ),
   14168                    binop( Iop_CmpEQ32,
   14169                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
   14170                           mkU32( 0 ) ) ) );
   14171 
   14172    return IRExpr_ITE( mkexpr( is_SNAN ),
   14173                         unop( Iop_ReinterpI64asF64,
   14174                               binop( Iop_Xor64,
   14175                                      mkU64( SNAN_MASK ),
   14176                                      mkexpr( frB_I64 ) ) ),
   14177                       mkexpr( frD ));
   14178 }
   14179 
   14180 /*
   14181  * Miscellaneous VSX vector instructions
   14182  */
   14183 static Bool
   14184 dis_vxv_misc ( UInt theInstr, UInt opc2 )
   14185 {
   14186    /* XX3-Form */
   14187    UChar opc1 = ifieldOPC( theInstr );
   14188    UChar XT = ifieldRegXT( theInstr );
   14189    UChar XB = ifieldRegXB( theInstr );
   14190 
   14191    if (opc1 != 0x3C) {
   14192       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
   14193       return False;
   14194    }
   14195 
   14196    switch (opc2) {
   14197       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
   14198       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
   14199                    //             Double-Precision)
   14200       {
   14201          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14202          IRExpr* rm  = get_IR_roundingmode();
   14203          IRTemp frB = newTemp(Ity_I64);
   14204          IRTemp frB2 = newTemp(Ity_I64);
   14205          Bool redp = opc2 == 0x1B4;
   14206          IRTemp sqrtHi = newTemp(Ity_F64);
   14207          IRTemp sqrtLo = newTemp(Ity_F64);
   14208          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14209          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14210 
   14211          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
   14212          if (!redp) {
   14213             assign( sqrtHi,
   14214                     binop( Iop_SqrtF64,
   14215                            rm,
   14216                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
   14217             assign( sqrtLo,
   14218                     binop( Iop_SqrtF64,
   14219                            rm,
   14220                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
   14221          }
   14222          putVSReg( XT,
   14223                    binop( Iop_64HLtoV128,
   14224                           unop( Iop_ReinterpF64asI64,
   14225                                 triop( Iop_DivF64,
   14226                                        rm,
   14227                                        ieee_one,
   14228                                        redp ? unop( Iop_ReinterpI64asF64,
   14229                                                     mkexpr( frB ) )
   14230                                             : mkexpr( sqrtHi ) ) ),
   14231                           unop( Iop_ReinterpF64asI64,
   14232                                 triop( Iop_DivF64,
   14233                                        rm,
   14234                                        ieee_one,
   14235                                        redp ? unop( Iop_ReinterpI64asF64,
   14236                                                     mkexpr( frB2 ) )
   14237                                             : mkexpr( sqrtLo ) ) ) ) );
   14238          break;
   14239 
   14240       }
   14241       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
   14242       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
   14243       {
   14244          IRTemp b3, b2, b1, b0;
   14245          IRTemp res0 = newTemp(Ity_I32);
   14246          IRTemp res1 = newTemp(Ity_I32);
   14247          IRTemp res2 = newTemp(Ity_I32);
   14248          IRTemp res3 = newTemp(Ity_I32);
   14249          IRTemp sqrt3 = newTemp(Ity_F64);
   14250          IRTemp sqrt2 = newTemp(Ity_F64);
   14251          IRTemp sqrt1 = newTemp(Ity_F64);
   14252          IRTemp sqrt0 = newTemp(Ity_F64);
   14253          IRExpr* rm  = get_IR_roundingmode();
   14254          Bool resp = opc2 == 0x134;
   14255 
   14256          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   14257 
   14258          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   14259          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
   14260          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   14261 
   14262          if (!resp) {
   14263             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
   14264             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
   14265             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
   14266             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
   14267          }
   14268 
   14269          assign( res0,
   14270                  unop( Iop_ReinterpF32asI32,
   14271                        unop( Iop_TruncF64asF32,
   14272                              triop( Iop_DivF64r32,
   14273                                     rm,
   14274                                     ieee_one,
   14275                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
   14276          assign( res1,
   14277                  unop( Iop_ReinterpF32asI32,
   14278                        unop( Iop_TruncF64asF32,
   14279                              triop( Iop_DivF64r32,
   14280                                     rm,
   14281                                     ieee_one,
   14282                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
   14283          assign( res2,
   14284                  unop( Iop_ReinterpF32asI32,
   14285                        unop( Iop_TruncF64asF32,
   14286                              triop( Iop_DivF64r32,
   14287                                     rm,
   14288                                     ieee_one,
   14289                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
   14290          assign( res3,
   14291                  unop( Iop_ReinterpF32asI32,
   14292                        unop( Iop_TruncF64asF32,
   14293                              triop( Iop_DivF64r32,
   14294                                     rm,
   14295                                     ieee_one,
   14296                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
   14297          putVSReg( XT,
   14298                    binop( Iop_64HLtoV128,
   14299                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   14300                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   14301          break;
   14302       }
   14303       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
   14304       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
   14305       {
   14306          UChar XA = ifieldRegXA( theInstr );
   14307          IRTemp a3, a2, a1, a0;
   14308          IRTemp b3, b2, b1, b0;
   14309          IRTemp res0 = newTemp( Ity_I32 );
   14310          IRTemp res1 = newTemp( Ity_I32 );
   14311          IRTemp res2 = newTemp( Ity_I32 );
   14312          IRTemp res3 = newTemp( Ity_I32 );
   14313          IRTemp a0_I64 = newTemp( Ity_I64 );
   14314          IRTemp a1_I64 = newTemp( Ity_I64 );
   14315          IRTemp a2_I64 = newTemp( Ity_I64 );
   14316          IRTemp a3_I64 = newTemp( Ity_I64 );
   14317          IRTemp b0_I64 = newTemp( Ity_I64 );
   14318          IRTemp b1_I64 = newTemp( Ity_I64 );
   14319          IRTemp b2_I64 = newTemp( Ity_I64 );
   14320          IRTemp b3_I64 = newTemp( Ity_I64 );
   14321 
   14322          Bool isMin = opc2 == 0x320 ? True : False;
   14323 
   14324          a3 = a2 = a1 = a0 = IRTemp_INVALID;
   14325          b3 = b2 = b1 = b0 = IRTemp_INVALID;
   14326          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
   14327          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
   14328          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
   14329          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
   14330          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
   14331          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
   14332          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
   14333          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
   14334          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
   14335          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
   14336          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
   14337          assign( res0,
   14338                  unop( Iop_ReinterpF32asI32,
   14339                        unop( Iop_TruncF64asF32,
   14340                              unop( Iop_ReinterpI64asF64,
   14341                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
   14342          assign( res1,
   14343                  unop( Iop_ReinterpF32asI32,
   14344                        unop( Iop_TruncF64asF32,
   14345                              unop( Iop_ReinterpI64asF64,
   14346                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
   14347          assign( res2,
   14348                  unop( Iop_ReinterpF32asI32,
   14349                        unop( Iop_TruncF64asF32,
   14350                              unop( Iop_ReinterpI64asF64,
   14351                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
   14352          assign( res3,
   14353                  unop( Iop_ReinterpF32asI32,
   14354                        unop( Iop_TruncF64asF32,
   14355                              unop( Iop_ReinterpI64asF64,
   14356                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
   14357          putVSReg( XT,
   14358                    binop( Iop_64HLtoV128,
   14359                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
   14360                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
   14361          break;
   14362       }
   14363       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
   14364       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
   14365       {
   14366          UChar XA = ifieldRegXA( theInstr );
   14367          IRTemp frA = newTemp(Ity_I64);
   14368          IRTemp frB = newTemp(Ity_I64);
   14369          IRTemp frA2 = newTemp(Ity_I64);
   14370          IRTemp frB2 = newTemp(Ity_I64);
   14371          Bool isMin = opc2 == 0x3A0 ? True : False;
   14372 
   14373          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   14374          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14375          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   14376          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14377          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
   14378          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
   14379 
   14380          break;
   14381       }
   14382       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
   14383       {
   14384          UChar XA = ifieldRegXA( theInstr );
   14385          IRTemp frA = newTemp(Ity_I64);
   14386          IRTemp frB = newTemp(Ity_I64);
   14387          IRTemp frA2 = newTemp(Ity_I64);
   14388          IRTemp frB2 = newTemp(Ity_I64);
   14389          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
   14390          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
   14391          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
   14392          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
   14393 
   14394          DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
   14395          putVSReg( XT,
   14396                    binop( Iop_64HLtoV128,
   14397                           binop( Iop_Or64,
   14398                                  binop( Iop_And64,
   14399                                         mkexpr( frA ),
   14400                                         mkU64( SIGN_BIT ) ),
   14401                                  binop( Iop_And64,
   14402                                         mkexpr( frB ),
   14403                                         mkU64( SIGN_MASK ) ) ),
   14404                           binop( Iop_Or64,
   14405                                  binop( Iop_And64,
   14406                                         mkexpr( frA2 ),
   14407                                         mkU64( SIGN_BIT ) ),
   14408                                  binop( Iop_And64,
   14409                                         mkexpr( frB2 ),
   14410                                         mkU64( SIGN_MASK ) ) ) ) );
   14411          break;
   14412       }
   14413       case 0x340: // xvcpsgnsp
   14414       {
   14415          UChar XA = ifieldRegXA( theInstr );
   14416          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
   14417          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
   14418          IRTemp resHi = newTemp(Ity_I64);
   14419          IRTemp resLo = newTemp(Ity_I64);
   14420 
   14421          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
   14422          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
   14423          DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
   14424          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
   14425          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
   14426 
   14427          assign( resHi,
   14428                  binop( Iop_32HLto64,
   14429                         binop( Iop_Or32,
   14430                                binop( Iop_And32,
   14431                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
   14432                                       mkU32( SIGN_BIT32 ) ),
   14433                                binop( Iop_And32,
   14434                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
   14435                                       mkU32( SIGN_MASK32) ) ),
   14436 
   14437                         binop( Iop_Or32,
   14438                                binop( Iop_And32,
   14439                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
   14440                                       mkU32( SIGN_BIT32 ) ),
   14441                                binop( Iop_And32,
   14442                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
   14443                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14444          assign( resLo,
   14445                  binop( Iop_32HLto64,
   14446                         binop( Iop_Or32,
   14447                                binop( Iop_And32,
   14448                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
   14449                                       mkU32( SIGN_BIT32 ) ),
   14450                                binop( Iop_And32,
   14451                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
   14452                                       mkU32( SIGN_MASK32 ) ) ),
   14453 
   14454                         binop( Iop_Or32,
   14455                                binop( Iop_And32,
   14456                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
   14457                                       mkU32( SIGN_BIT32 ) ),
   14458                                binop( Iop_And32,
   14459                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
   14460                                       mkU32( SIGN_MASK32 ) ) ) ) );
   14461          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
   14462          break;
   14463       }
   14464       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
   14465       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
   14466       {
   14467          IRTemp frB = newTemp(Ity_F64);
   14468          IRTemp frB2 = newTemp(Ity_F64);
   14469          IRTemp abs_resultHi = newTemp(Ity_F64);
   14470          IRTemp abs_resultLo = newTemp(Ity_F64);
   14471          Bool make_negative = (opc2 == 0x3D2) ? True : False;
   14472          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14473          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14474 
   14475          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
   14476          if (make_negative) {
   14477             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
   14478             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
   14479 
   14480          } else {
   14481             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
   14482             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
   14483          }
   14484          putVSReg( XT, binop( Iop_64HLtoV128,
   14485                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
   14486                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
   14487          break;
   14488       }
   14489       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
   14490       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
   14491       {
   14492          /*
   14493           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
   14494           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
   14495           * of this function is so easy using shifts, I choose to emulate this instruction that
   14496           * way versus a native instruction method of implementation.
   14497           */
   14498          Bool make_negative = (opc2 == 0x352) ? True : False;
   14499          IRTemp shiftVector = newTemp(Ity_V128);
   14500          IRTemp absVal_vector = newTemp(Ity_V128);
   14501          assign( shiftVector,
   14502                  binop( Iop_64HLtoV128,
   14503                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
   14504                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
   14505          assign( absVal_vector,
   14506                    binop( Iop_Shr32x4,
   14507                           binop( Iop_Shl32x4,
   14508                                  getVSReg( XB ),
   14509                                  mkexpr( shiftVector ) ),
   14510                           mkexpr( shiftVector ) ) );
   14511          if (make_negative) {
   14512             IRTemp signBit_vector = newTemp(Ity_V128);
   14513             assign( signBit_vector,
   14514                     binop( Iop_64HLtoV128,
   14515                            binop( Iop_32HLto64,
   14516                                   mkU32( 0x80000000 ),
   14517                                   mkU32( 0x80000000 ) ),
   14518                            binop( Iop_32HLto64,
   14519                                   mkU32( 0x80000000 ),
   14520                                   mkU32( 0x80000000 ) ) ) );
   14521             putVSReg( XT,
   14522                       binop( Iop_OrV128,
   14523                              mkexpr( absVal_vector ),
   14524                              mkexpr( signBit_vector ) ) );
   14525          } else {
   14526             putVSReg( XT, mkexpr( absVal_vector ) );
   14527          }
   14528          break;
   14529       }
   14530       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
   14531       {
   14532          IRTemp frB = newTemp(Ity_F64);
   14533          IRTemp frB2 = newTemp(Ity_F64);
   14534          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14535          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
   14536          DIP("xvnegdp v%d,v%d\n",  XT, XB);
   14537          putVSReg( XT,
   14538                    binop( Iop_64HLtoV128,
   14539                           unop( Iop_ReinterpF64asI64,
   14540                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
   14541                           unop( Iop_ReinterpF64asI64,
   14542                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
   14543          break;
   14544       }
   14545       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
   14546       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
   14547       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
   14548       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
   14549       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
   14550       {
   14551          IRTemp frBHi_I64 = newTemp(Ity_I64);
   14552          IRTemp frBLo_I64 = newTemp(Ity_I64);
   14553          IRExpr * frD_fp_roundHi = NULL;
   14554          IRExpr * frD_fp_roundLo = NULL;
   14555 
   14556          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
   14557          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
   14558          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
   14559          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
   14560 
   14561          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
   14562          putVSReg( XT,
   14563                    binop( Iop_64HLtoV128,
   14564                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
   14565                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
   14566          break;
   14567       }
   14568       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
   14569       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
   14570       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
   14571       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
   14572       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
   14573       {
   14574          const HChar * insn_suffix = NULL;
   14575          IROp op;
   14576          if (opc2 != 0x156) {
   14577             // Use pre-defined IRop's for vrfi{m|n|p|z}
   14578             switch (opc2) {
   14579                case 0x112:
   14580                   insn_suffix = "";
   14581                   op = Iop_RoundF32x4_RN;
   14582                   break;
   14583                case 0x172:
   14584                   insn_suffix = "m";
   14585                   op = Iop_RoundF32x4_RM;
   14586                   break;
   14587                case 0x152:
   14588                   insn_suffix = "p";
   14589                   op = Iop_RoundF32x4_RP;
   14590                   break;
   14591                case 0x132:
   14592                   insn_suffix = "z";
   14593                   op = Iop_RoundF32x4_RZ;
   14594                   break;
   14595 
   14596                default:
   14597                   vex_printf("Unrecognized opcode %x\n", opc2);
   14598                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
   14599             }
   14600             DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
   14601             putVSReg( XT, unop( op, getVSReg(XB) ) );
   14602          } else {
   14603             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
   14604             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
   14605             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
   14606             IRTemp b3_I64 = newTemp(Ity_I64);
   14607             IRTemp b2_I64 = newTemp(Ity_I64);
   14608             IRTemp b1_I64 = newTemp(Ity_I64);
   14609             IRTemp b0_I64 = newTemp(Ity_I64);
   14610 
   14611             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
   14612             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
   14613             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
   14614             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
   14615             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
   14616             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
   14617             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
   14618             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
   14619                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
   14620             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
   14621                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
   14622             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
   14623                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
   14624             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
   14625                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
   14626             DIP("xvrspic v%d,v%d\n", XT, XB);
   14627             putVSReg( XT,
   14628                       binop( Iop_64HLtoV128,
   14629                              binop( Iop_32HLto64,
   14630                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
   14631                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
   14632                              binop( Iop_32HLto64,
   14633                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
   14634                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
   14635          }
   14636          break;
   14637       }
   14638 
   14639       default:
   14640          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
   14641          return False;
   14642    }
   14643    return True;
   14644 }
   14645 
   14646 
   14647 /*
   14648  * VSX Scalar Floating Point Arithmetic Instructions
   14649  */
   14650 static Bool
   14651 dis_vxs_arith ( UInt theInstr, UInt opc2 )
   14652 {
   14653    /* XX3-Form */
   14654    UChar opc1 = ifieldOPC( theInstr );
   14655    UChar XT = ifieldRegXT( theInstr );
   14656    UChar XA = ifieldRegXA( theInstr );
   14657    UChar XB = ifieldRegXB( theInstr );
   14658    IRExpr* rm = get_IR_roundingmode();
   14659    IRTemp frA = newTemp(Ity_F64);
   14660    IRTemp frB = newTemp(Ity_F64);
   14661 
   14662    if (opc1 != 0x3C) {
   14663       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
   14664       return False;
   14665    }
   14666 
   14667    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14668    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14669 
   14670    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
   14671     * of VSX[XT] are undefined after the operation; therefore, we can simply set
   14672     * element to zero where it makes sense to do so.
   14673     */
   14674    switch (opc2) {
   14675       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
   14676          DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
   14677          putVSReg( XT, binop( Iop_64HLtoV128,
   14678                               unop( Iop_ReinterpF64asI64,
   14679                                     binop( Iop_RoundF64toF32, rm,
   14680                                            triop( Iop_AddF64, rm,
   14681                                                   mkexpr( frA ),
   14682                                                   mkexpr( frB ) ) ) ),
   14683                               mkU64( 0 ) ) );
   14684          break;
   14685       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
   14686          DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
   14687          putVSReg( XT, binop( Iop_64HLtoV128,
   14688                               unop( Iop_ReinterpF64asI64,
   14689                                     binop( Iop_RoundF64toF32, rm,
   14690                                            triop( Iop_SubF64, rm,
   14691                                                   mkexpr( frA ),
   14692                                                   mkexpr( frB ) ) ) ),
   14693                               mkU64( 0 ) ) );
   14694          break;
   14695       case 0x080: // xsadddp (VSX scalar add double-precision)
   14696          DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
   14697          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14698                                                     triop( Iop_AddF64, rm,
   14699                                                            mkexpr( frA ),
   14700                                                            mkexpr( frB ) ) ),
   14701                               mkU64( 0 ) ) );
   14702          break;
   14703       case 0x060: // xsdivsp (VSX scalar divide single-precision)
   14704          DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
   14705          putVSReg( XT, binop( Iop_64HLtoV128,
   14706                               unop( Iop_ReinterpF64asI64,
   14707                                     binop( Iop_RoundF64toF32, rm,
   14708                                            triop( Iop_DivF64, rm,
   14709                                                   mkexpr( frA ),
   14710                                                   mkexpr( frB ) ) ) ),
   14711                                mkU64( 0 ) ) );
   14712          break;
   14713       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
   14714          DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
   14715          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14716                                                     triop( Iop_DivF64, rm,
   14717                                                            mkexpr( frA ),
   14718                                                            mkexpr( frB ) ) ),
   14719                               mkU64( 0 ) ) );
   14720          break;
   14721       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
   14722                                * single-precision)
   14723                                */
   14724       {
   14725          IRTemp frT = newTemp(Ity_F64);
   14726          Bool mdp = opc2 == 0x024;
   14727          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14728          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14729                                                         getVSReg( XT ) ) ) );
   14730          putVSReg( XT,
   14731                    binop( Iop_64HLtoV128,
   14732                           unop( Iop_ReinterpF64asI64,
   14733                                 binop( Iop_RoundF64toF32, rm,
   14734                                        qop( Iop_MAddF64, rm,
   14735                                             mkexpr( frA ),
   14736                                             mkexpr( mdp ? frT : frB ),
   14737                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14738                           mkU64( 0 ) ) );
   14739          break;
   14740       }
   14741       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
   14742       {
   14743          IRTemp frT = newTemp(Ity_F64);
   14744          Bool mdp = opc2 == 0x0A4;
   14745          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14746          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14747                                                         getVSReg( XT ) ) ) );
   14748          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14749                                                     qop( Iop_MAddF64, rm,
   14750                                                          mkexpr( frA ),
   14751                                                          mkexpr( mdp ? frT : frB ),
   14752                                                          mkexpr( mdp ? frB : frT ) ) ),
   14753                               mkU64( 0 ) ) );
   14754          break;
   14755       }
   14756       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
   14757                                * multiply-subtract single-precision)
   14758 			       */
   14759       {
   14760          IRTemp frT = newTemp(Ity_F64);
   14761          Bool mdp = opc2 == 0x064;
   14762          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14763          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14764                                                         getVSReg( XT ) ) ) );
   14765          putVSReg( XT,
   14766                    binop( Iop_64HLtoV128,
   14767                           unop( Iop_ReinterpF64asI64,
   14768                                 binop( Iop_RoundF64toF32, rm,
   14769                                        qop( Iop_MSubF64, rm,
   14770                                             mkexpr( frA ),
   14771                                             mkexpr( mdp ? frT : frB ),
   14772                                             mkexpr( mdp ? frB : frT ) ) ) ),
   14773                           mkU64( 0 ) ) );
   14774          break;
   14775       }
   14776       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
   14777       {
   14778          IRTemp frT = newTemp(Ity_F64);
   14779          Bool mdp = opc2 == 0x0E4;
   14780          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14781          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14782                                                         getVSReg( XT ) ) ) );
   14783          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14784                                                     qop( Iop_MSubF64, rm,
   14785                                                          mkexpr( frA ),
   14786                                                          mkexpr( mdp ? frT : frB ),
   14787                                                          mkexpr( mdp ? frB : frT ) ) ),
   14788                               mkU64( 0 ) ) );
   14789          break;
   14790       }
   14791       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
   14792       {
   14793          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
   14794           * of fnmadd and use pretty much the same code. However, that code has a bug in the
   14795           * way it blindly negates the signbit, even if the floating point result is a NaN.
   14796           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
   14797           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
   14798           * bit for NaN result.
   14799           */
   14800          Bool mdp = opc2 == 0x2A4;
   14801          IRTemp frT = newTemp(Ity_F64);
   14802          IRTemp maddResult = newTemp(Ity_I64);
   14803 
   14804          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14805          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14806                                                         getVSReg( XT ) ) ) );
   14807          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
   14808                                                               mkexpr( frA ),
   14809                                                               mkexpr( mdp ? frT : frB ),
   14810                                                               mkexpr( mdp ? frB : frT ) ) ) );
   14811 
   14812          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
   14813                               mkU64( 0 ) ) );
   14814          break;
   14815       }
   14816       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
   14817                                * multiply-add single-precision)
   14818                                */
   14819       {
   14820          Bool mdp = opc2 == 0x224;
   14821          IRTemp frT = newTemp(Ity_F64);
   14822          IRTemp maddResult = newTemp(Ity_I64);
   14823 
   14824          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14825          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14826                                                         getVSReg( XT ) ) ) );
   14827          assign( maddResult,
   14828                  unop( Iop_ReinterpF64asI64,
   14829                        binop( Iop_RoundF64toF32, rm,
   14830                               qop( Iop_MAddF64, rm,
   14831                                    mkexpr( frA ),
   14832                                    mkexpr( mdp ? frT : frB ),
   14833                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14834 
   14835          putVSReg( XT, binop( Iop_64HLtoV128,
   14836                               mkexpr( getNegatedResult(maddResult) ),
   14837                               mkU64( 0 ) ) );
   14838          break;
   14839       }
   14840       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
   14841                                * Multiply-Subtract Single-Precision)
   14842                                */
   14843       {
   14844          IRTemp frT = newTemp(Ity_F64);
   14845          Bool mdp = opc2 == 0x264;
   14846          IRTemp msubResult = newTemp(Ity_I64);
   14847 
   14848          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14849          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14850                                                         getVSReg( XT ) ) ) );
   14851          assign( msubResult,
   14852                  unop( Iop_ReinterpF64asI64,
   14853                        binop( Iop_RoundF64toF32, rm,
   14854                               qop( Iop_MSubF64, rm,
   14855                                    mkexpr( frA ),
   14856                                    mkexpr( mdp ? frT : frB ),
   14857                                    mkexpr( mdp ? frB : frT ) ) ) ) );
   14858 
   14859          putVSReg( XT, binop( Iop_64HLtoV128,
   14860                               mkexpr( getNegatedResult(msubResult) ),
   14861                               mkU64( 0 ) ) );
   14862 
   14863          break;
   14864       }
   14865 
   14866       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
   14867       {
   14868          IRTemp frT = newTemp(Ity_F64);
   14869          Bool mdp = opc2 == 0x2E4;
   14870          IRTemp msubResult = newTemp(Ity_I64);
   14871 
   14872          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
   14873          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
   14874                                                         getVSReg( XT ) ) ) );
   14875          assign(msubResult, unop( Iop_ReinterpF64asI64,
   14876                                       qop( Iop_MSubF64,
   14877                                            rm,
   14878                                            mkexpr( frA ),
   14879                                            mkexpr( mdp ? frT : frB ),
   14880                                            mkexpr( mdp ? frB : frT ) ) ));
   14881 
   14882          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
   14883 
   14884          break;
   14885       }
   14886 
   14887       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
   14888          DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
   14889          putVSReg( XT, binop( Iop_64HLtoV128,
   14890                               unop( Iop_ReinterpF64asI64,
   14891                                     binop( Iop_RoundF64toF32, rm,
   14892                                            triop( Iop_MulF64, rm,
   14893                                                    mkexpr( frA ),
   14894                                                    mkexpr( frB ) ) ) ),
   14895                               mkU64( 0 ) ) );
   14896          break;
   14897 
   14898       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
   14899          DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
   14900          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14901                                                     triop( Iop_MulF64, rm,
   14902                                                            mkexpr( frA ),
   14903                                                            mkexpr( frB ) ) ),
   14904                               mkU64( 0 ) ) );
   14905          break;
   14906       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
   14907          DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
   14908          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14909                                                     triop( Iop_SubF64, rm,
   14910                                                            mkexpr( frA ),
   14911                                                            mkexpr( frB ) ) ),
   14912                               mkU64( 0 ) ) );
   14913          break;
   14914 
   14915       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
   14916          DIP("xssqrtsp v%d,v%d\n", XT, XB);
   14917          putVSReg( XT,
   14918                    binop( Iop_64HLtoV128,
   14919                           unop( Iop_ReinterpF64asI64,
   14920                                 binop( Iop_RoundF64toF32, rm,
   14921                                        binop( Iop_SqrtF64, rm,
   14922                                               mkexpr( frB ) ) ) ),
   14923                           mkU64( 0 ) ) );
   14924          break;
   14925 
   14926       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
   14927          DIP("xssqrtdp v%d,v%d\n", XT, XB);
   14928          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
   14929                                                      binop( Iop_SqrtF64, rm,
   14930                                                             mkexpr( frB ) ) ),
   14931                                mkU64( 0 ) ) );
   14932          break;
   14933 
   14934       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
   14935       {
   14936          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14937          IRTemp frA_I64 = newTemp(Ity_I64);
   14938          IRTemp frB_I64 = newTemp(Ity_I64);
   14939          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
   14940          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
   14941          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
   14942          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
   14943          break;
   14944       }
   14945       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
   14946       {
   14947          IRTemp frB_I64 = newTemp(Ity_I64);
   14948          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14949          IRTemp flags = newTemp(Ity_I32);
   14950          IRTemp  fe_flag, fg_flag;
   14951          fe_flag = fg_flag = IRTemp_INVALID;
   14952          DIP("xstsqrtdp v%d,v%d\n", XT, XB);
   14953          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
   14954          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
   14955          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
   14956           * where fl_flag == 1 on ppc64.
   14957           */
   14958          assign( flags,
   14959                  binop( Iop_Or32,
   14960                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
   14961                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
   14962                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
   14963          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
   14964          break;
   14965       }
   14966 
   14967       default:
   14968          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
   14969          return False;
   14970    }
   14971 
   14972    return True;
   14973 }
   14974 
   14975 
   14976 /*
   14977  * VSX Floating Point Compare Instructions
   14978  */
   14979 static Bool
   14980 dis_vx_cmp( UInt theInstr, UInt opc2 )
   14981 {
   14982    /* XX3-Form and XX2-Form */
   14983    UChar opc1 = ifieldOPC( theInstr );
   14984    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
   14985    IRTemp ccPPC32;
   14986    UChar XA       = ifieldRegXA ( theInstr );
   14987    UChar XB       = ifieldRegXB ( theInstr );
   14988    IRTemp frA     = newTemp(Ity_F64);
   14989    IRTemp frB     = newTemp(Ity_F64);
   14990 
   14991    if (opc1 != 0x3C) {
   14992       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
   14993       return False;
   14994    }
   14995 
   14996    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
   14997    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
   14998    switch (opc2) {
   14999       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   15000          /* Note: Differences between xscmpudp and xscmpodp are only in
   15001           * exception flag settings, which aren't supported anyway. */
   15002          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
   15003                                            crfD, XA, XB);
   15004          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
   15005          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
   15006          break;
   15007 
   15008       default:
   15009          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
   15010          return False;
   15011    }
   15012    return True;
   15013 }
   15014 
   15015 static void
   15016 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
   15017                  ppc_cmp_t cmp_type )
   15018 {
   15019    IRTemp frA_hi     = newTemp(Ity_F64);
   15020    IRTemp frB_hi     = newTemp(Ity_F64);
   15021    IRTemp frA_lo     = newTemp(Ity_F64);
   15022    IRTemp frB_lo     = newTemp(Ity_F64);
   15023    IRTemp ccPPC32    = newTemp(Ity_I32);
   15024    IRTemp ccIR_hi;
   15025    IRTemp ccIR_lo;
   15026 
   15027    IRTemp hiResult = newTemp(Ity_I64);
   15028    IRTemp loResult = newTemp(Ity_I64);
   15029    IRTemp hiEQlo = newTemp(Ity_I1);
   15030    IRTemp all_elem_true = newTemp(Ity_I32);
   15031    IRTemp all_elem_false = newTemp(Ity_I32);
   15032 
   15033    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
   15034    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
   15035    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
   15036    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
   15037 
   15038    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   15039                                        mkexpr( frA_hi ),
   15040                                        mkexpr( frB_hi ) ) );
   15041    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
   15042                                        mkexpr( frA_lo ),
   15043                                        mkexpr( frB_lo ) ) );
   15044 
   15045    if (cmp_type != PPC_CMP_GE) {
   15046       assign( hiResult,
   15047               unop( Iop_1Sto64,
   15048                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
   15049       assign( loResult,
   15050               unop( Iop_1Sto64,
   15051                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
   15052    } else {
   15053       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
   15054       // the other element compare may return "2" (for "equal to").
   15055       IRTemp lo_GE = newTemp(Ity_I1);
   15056       IRTemp hi_GE = newTemp(Ity_I1);
   15057 
   15058       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
   15059                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
   15060       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
   15061 
   15062       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
   15063                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
   15064       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
   15065    }
   15066 
   15067    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
   15068    assign( hiEQlo,
   15069            binop( Iop_CmpEQ32,
   15070                   unop( Iop_64to32, mkexpr( hiResult ) ),
   15071                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
   15072    putVSReg( XT,
   15073              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
   15074 
   15075    assign( all_elem_true,
   15076            unop( Iop_1Uto32,
   15077                  mkAND1( mkexpr( hiEQlo ),
   15078                          binop( Iop_CmpEQ32,
   15079                                 mkU32( 0xffffffff ),
   15080                                 unop( Iop_64to32,
   15081                                 mkexpr( hiResult ) ) ) ) ) );
   15082 
   15083    assign( all_elem_false,
   15084            unop( Iop_1Uto32,
   15085                  mkAND1( mkexpr( hiEQlo ),
   15086                          binop( Iop_CmpEQ32,
   15087                                 mkU32( 0 ),
   15088                                 unop( Iop_64to32,
   15089                                 mkexpr( hiResult ) ) ) ) ) );
   15090    assign( ccPPC32,
   15091            binop( Iop_Or32,
   15092                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
   15093                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
   15094 
   15095    if (flag_rC) {
   15096       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
   15097    }
   15098 }
   15099 
   15100 /*
   15101  * VSX Vector Compare Instructions
   15102  */
   15103 static Bool
   15104 dis_vvec_cmp( UInt theInstr, UInt opc2 )
   15105 {
   15106    /* XX3-Form */
   15107    UChar opc1 = ifieldOPC( theInstr );
   15108    UChar XT = ifieldRegXT ( theInstr );
   15109    UChar XA = ifieldRegXA ( theInstr );
   15110    UChar XB = ifieldRegXB ( theInstr );
   15111    UChar flag_rC  = ifieldBIT10(theInstr);
   15112    IRTemp vA = newTemp( Ity_V128 );
   15113    IRTemp vB = newTemp( Ity_V128 );
   15114 
   15115    if (opc1 != 0x3C) {
   15116       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
   15117       return False;
   15118    }
   15119 
   15120    assign( vA, getVSReg( XA ) );
   15121    assign( vB, getVSReg( XB ) );
   15122 
   15123    switch (opc2) {
   15124       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
   15125       {
   15126          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15127              XT, XA, XB);
   15128          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
   15129          break;
   15130       }
   15131 
   15132       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
   15133       {
   15134          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15135              XT, XA, XB);
   15136          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
   15137          break;
   15138       }
   15139 
   15140       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
   15141       {
   15142          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15143              XT, XA, XB);
   15144          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
   15145          break;
   15146       }
   15147 
   15148       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
   15149       {
   15150          IRTemp vD = newTemp(Ity_V128);
   15151 
   15152          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15153              XT, XA, XB);
   15154          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   15155          putVSReg( XT, mkexpr(vD) );
   15156          if (flag_rC) {
   15157             set_AV_CR6( mkexpr(vD), True );
   15158          }
   15159          break;
   15160       }
   15161 
   15162       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
   15163       {
   15164          IRTemp vD = newTemp(Ity_V128);
   15165 
   15166          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15167              XT, XA, XB);
   15168          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   15169          putVSReg( XT, mkexpr(vD) );
   15170          if (flag_rC) {
   15171             set_AV_CR6( mkexpr(vD), True );
   15172          }
   15173          break;
   15174       }
   15175 
   15176       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
   15177       {
   15178          IRTemp vD = newTemp(Ity_V128);
   15179 
   15180          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
   15181              XT, XA, XB);
   15182          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   15183          putVSReg( XT, mkexpr(vD) );
   15184          if (flag_rC) {
   15185             set_AV_CR6( mkexpr(vD), True );
   15186          }
   15187          break;
   15188       }
   15189 
   15190       default:
   15191          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
   15192          return False;
   15193    }
   15194    return True;
   15195 }
   15196 /*
   15197  * Miscellaneous VSX Scalar Instructions
   15198  */
   15199 static Bool
   15200 dis_vxs_misc( UInt theInstr, UInt opc2 )
   15201 {
   15202 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
   15203    /* XX3-Form and XX2-Form */
   15204    UChar opc1 = ifieldOPC( theInstr );
   15205    UChar XT = ifieldRegXT ( theInstr );
   15206    UChar XA = ifieldRegXA ( theInstr );
   15207    UChar XB = ifieldRegXB ( theInstr );
   15208    IRTemp vA = newTemp( Ity_V128 );
   15209    IRTemp vB = newTemp( Ity_V128 );
   15210 
   15211    if (opc1 != 0x3C) {
   15212       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
   15213       return False;
   15214    }
   15215 
   15216    assign( vA, getVSReg( XA ) );
   15217    assign( vB, getVSReg( XB ) );
   15218 
   15219    /* For all the VSX move instructions, the contents of doubleword element 1
   15220     * of VSX[XT] are undefined after the operation; therefore, we can simply
   15221     * move the entire array element where it makes sense to do so.
   15222     */
   15223 
   15224    switch (opc2) {
   15225       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
   15226       {
   15227          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
   15228          IRTemp absVal = newTemp(Ity_V128);
   15229          if (host_endness == VexEndnessLE) {
   15230             IRTemp hi64 = newTemp(Ity_I64);
   15231             IRTemp lo64 = newTemp(Ity_I64);
   15232             assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
   15233             assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
   15234             assign( absVal, binop( Iop_64HLtoV128,
   15235                                    binop( Iop_And64, mkexpr(hi64),
   15236                                           mkU64(VG_PPC_SIGN_MASK) ),
   15237                                    mkexpr(lo64) ) );
   15238          } else {
   15239             assign(absVal, binop(Iop_ShrV128,
   15240                                  binop(Iop_ShlV128, mkexpr(vB),
   15241                                        mkU8(1)), mkU8(1)));
   15242          }
   15243          DIP("xsabsdp v%d,v%d\n", XT, XB);
   15244          putVSReg(XT, mkexpr(absVal));
   15245          break;
   15246       }
   15247       case 0x2C0: // xscpsgndp
   15248       {
   15249          /* Scalar copy sign double-precision */
   15250          IRTemp vecA_signed = newTemp(Ity_I64);
   15251          IRTemp vecB_unsigned = newTemp(Ity_I64);
   15252          IRTemp vec_result = newTemp(Ity_V128);
   15253          DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
   15254          assign( vecA_signed, binop( Iop_And64,
   15255                                      unop( Iop_V128HIto64,
   15256                                            mkexpr(vA)),
   15257                                            mkU64(~VG_PPC_SIGN_MASK) ) );
   15258          assign( vecB_unsigned, binop( Iop_And64,
   15259                                        unop( Iop_V128HIto64,
   15260                                              mkexpr(vB) ),
   15261                                              mkU64(VG_PPC_SIGN_MASK) ) );
   15262          assign( vec_result, binop( Iop_64HLtoV128,
   15263                                     binop( Iop_Or64,
   15264                                            mkexpr(vecA_signed),
   15265                                            mkexpr(vecB_unsigned) ),
   15266                                     mkU64(0x0ULL)));
   15267          putVSReg(XT, mkexpr(vec_result));
   15268          break;
   15269       }
   15270       case 0x2D2: // xsnabsdp
   15271       {
   15272          /* Scalar negative absolute value double-precision */
   15273          IRTemp BHi_signed = newTemp(Ity_I64);
   15274          DIP("xsnabsdp v%d,v%d\n", XT, XB);
   15275          assign( BHi_signed, binop( Iop_Or64,
   15276                                     unop( Iop_V128HIto64,
   15277                                           mkexpr(vB) ),
   15278                                           mkU64(~VG_PPC_SIGN_MASK) ) );
   15279          putVSReg(XT, binop( Iop_64HLtoV128,
   15280                              mkexpr(BHi_signed), mkU64(0x0ULL) ) );
   15281          break;
   15282       }
   15283       case 0x2F2: // xsnegdp
   15284       {
   15285          /* Scalar negate double-precision */
   15286          IRTemp BHi_signed = newTemp(Ity_I64);
   15287          IRTemp BHi_unsigned = newTemp(Ity_I64);
   15288          IRTemp BHi_negated = newTemp(Ity_I64);
   15289          IRTemp BHi_negated_signbit = newTemp(Ity_I1);
   15290          IRTemp vec_result = newTemp(Ity_V128);
   15291          DIP("xsnabsdp v%d,v%d\n", XT, XB);
   15292          assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
   15293          assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
   15294                                       mkU64(VG_PPC_SIGN_MASK) ) );
   15295          assign( BHi_negated_signbit,
   15296                  unop( Iop_Not1,
   15297                        unop( Iop_32to1,
   15298                              binop( Iop_Shr32,
   15299                                     unop( Iop_64HIto32,
   15300                                           binop( Iop_And64,
   15301                                                  mkexpr(BHi_signed),
   15302                                                  mkU64(~VG_PPC_SIGN_MASK) )
   15303                                           ),
   15304                                     mkU8(31) ) ) ) );
   15305          assign( BHi_negated,
   15306                  binop( Iop_Or64,
   15307                         binop( Iop_32HLto64,
   15308                                binop( Iop_Shl32,
   15309                                       unop( Iop_1Uto32,
   15310                                             mkexpr(BHi_negated_signbit) ),
   15311                                       mkU8(31) ),
   15312                                mkU32(0) ),
   15313                         mkexpr(BHi_unsigned) ) );
   15314          assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
   15315                                     mkU64(0x0ULL)));
   15316          putVSReg( XT, mkexpr(vec_result));
   15317          break;
   15318       }
   15319       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
   15320       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
   15321       {
   15322          IRTemp frA     = newTemp(Ity_I64);
   15323          IRTemp frB     = newTemp(Ity_I64);
   15324          Bool isMin = opc2 == 0x2A0 ? True : False;
   15325          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
   15326 
   15327          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
   15328          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
   15329          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
   15330 
   15331          break;
   15332       }
   15333       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
   15334       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
   15335       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
   15336       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
   15337       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
   15338       {
   15339          IRTemp frB_I64 = newTemp(Ity_I64);
   15340          IRExpr * frD_fp_round = NULL;
   15341 
   15342          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
   15343          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
   15344 
   15345          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
   15346          putVSReg( XT,
   15347                    binop( Iop_64HLtoV128,
   15348                           unop( Iop_ReinterpF64asI64, frD_fp_round),
   15349                           mkU64( 0 ) ) );
   15350          break;
   15351       }
   15352       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
   15353       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
   15354                    * single-Precision)
   15355                    */
   15356       {
   15357          IRTemp frB = newTemp(Ity_F64);
   15358          IRTemp sqrt = newTemp(Ity_F64);
   15359          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   15360          IRExpr* rm  = get_IR_roundingmode();
   15361          Bool redp = opc2 == 0x034;
   15362          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
   15363              XB);
   15364 
   15365          assign( frB,
   15366                  unop( Iop_ReinterpI64asF64,
   15367                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15368 
   15369          if (!redp)
   15370             assign( sqrt,
   15371                     binop( Iop_SqrtF64,
   15372                            rm,
   15373                            mkexpr(frB) ) );
   15374          putVSReg( XT,
   15375                       binop( Iop_64HLtoV128,
   15376                              unop( Iop_ReinterpF64asI64,
   15377                                    binop( Iop_RoundF64toF32, rm,
   15378                                           triop( Iop_DivF64,
   15379                                                  rm,
   15380                                                  ieee_one,
   15381                                                  redp ? mkexpr( frB ) :
   15382                                                         mkexpr( sqrt ) ) ) ),
   15383                              mkU64( 0 ) ) );
   15384          break;
   15385       }
   15386 
   15387       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
   15388       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
   15389 
   15390       {
   15391          IRTemp frB = newTemp(Ity_F64);
   15392          IRTemp sqrt = newTemp(Ity_F64);
   15393          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
   15394          IRExpr* rm  = get_IR_roundingmode();
   15395          Bool redp = opc2 == 0x0B4;
   15396          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
   15397          assign( frB,
   15398                  unop( Iop_ReinterpI64asF64,
   15399                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15400 
   15401          if (!redp)
   15402             assign( sqrt,
   15403                     binop( Iop_SqrtF64,
   15404                            rm,
   15405                            mkexpr(frB) ) );
   15406          putVSReg( XT,
   15407                       binop( Iop_64HLtoV128,
   15408                              unop( Iop_ReinterpF64asI64,
   15409                                    triop( Iop_DivF64,
   15410                                           rm,
   15411                                           ieee_one,
   15412                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
   15413                              mkU64( 0 ) ) );
   15414          break;
   15415       }
   15416 
   15417       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
   15418       {
   15419          IRTemp frB = newTemp(Ity_F64);
   15420          IRExpr* rm  = get_IR_roundingmode();
   15421          DIP("xsrsp v%d, v%d\n", XT, XB);
   15422          assign( frB,
   15423                  unop( Iop_ReinterpI64asF64,
   15424                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
   15425 
   15426          putVSReg( XT, binop( Iop_64HLtoV128,
   15427                               unop( Iop_ReinterpF64asI64,
   15428                                     binop( Iop_RoundF64toF32,
   15429                                            rm,
   15430                                            mkexpr( frB ) ) ),
   15431                               mkU64( 0 ) ) );
   15432          break;
   15433       }
   15434 
   15435       default:
   15436          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
   15437          return False;
   15438    }
   15439    return True;
   15440 }
   15441 
   15442 /*
   15443  * VSX Logical Instructions
   15444  */
   15445 static Bool
   15446 dis_vx_logic ( UInt theInstr, UInt opc2 )
   15447 {
   15448    /* XX3-Form */
   15449    UChar opc1 = ifieldOPC( theInstr );
   15450    UChar XT = ifieldRegXT ( theInstr );
   15451    UChar XA = ifieldRegXA ( theInstr );
   15452    UChar XB = ifieldRegXB ( theInstr );
   15453    IRTemp vA = newTemp( Ity_V128 );
   15454    IRTemp vB = newTemp( Ity_V128 );
   15455 
   15456    if (opc1 != 0x3C) {
   15457       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
   15458       return False;
   15459    }
   15460 
   15461    assign( vA, getVSReg( XA ) );
   15462    assign( vB, getVSReg( XB ) );
   15463 
   15464    switch (opc2) {
   15465       case 0x268: // xxlxor
   15466          DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
   15467          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
   15468          break;
   15469       case 0x248: // xxlor
   15470          DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
   15471          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
   15472          break;
   15473       case 0x288: // xxlnor
   15474          DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
   15475          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
   15476                                                  mkexpr( vB ) ) ) );
   15477          break;
   15478       case 0x208: // xxland
   15479          DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
   15480          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
   15481          break;
   15482       case 0x228: //xxlandc
   15483          DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
   15484          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
   15485                                                                mkexpr( vB ) ) ) );
   15486          break;
   15487       case 0x2A8: // xxlorc (VSX Logical OR with complement)
   15488          DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
   15489          putVSReg( XT, binop( Iop_OrV128,
   15490                               mkexpr( vA ),
   15491                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
   15492          break;
   15493       case 0x2C8: // xxlnand (VSX Logical NAND)
   15494          DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
   15495          putVSReg( XT, unop( Iop_NotV128,
   15496                              binop( Iop_AndV128, mkexpr( vA ),
   15497                                     mkexpr( vB ) ) ) );
   15498          break;
   15499       case 0x2E8: // xxleqv (VSX Logical Equivalence)
   15500          DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
   15501          putVSReg( XT, unop( Iop_NotV128,
   15502                              binop( Iop_XorV128,
   15503                              mkexpr( vA ), mkexpr( vB ) ) ) );
   15504          break;
   15505       default:
   15506          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
   15507          return False;
   15508    }
   15509    return True;
   15510 }
   15511 
   15512 /*
   15513  * VSX Load Instructions
   15514  * NOTE: VSX supports word-aligned storage access.
   15515  */
   15516 static Bool
   15517 dis_vx_load ( UInt theInstr )
   15518 {
   15519    /* XX1-Form */
   15520    UChar opc1 = ifieldOPC( theInstr );
   15521    UChar XT = ifieldRegXT ( theInstr );
   15522    UChar rA_addr = ifieldRegA( theInstr );
   15523    UChar rB_addr = ifieldRegB( theInstr );
   15524    UInt opc2 = ifieldOPClo10( theInstr );
   15525 
   15526    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15527    IRTemp EA = newTemp( ty );
   15528 
   15529    if (opc1 != 0x1F) {
   15530       vex_printf( "dis_vx_load(ppc)(instr)\n" );
   15531       return False;
   15532    }
   15533 
   15534    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15535 
   15536    switch (opc2) {
   15537    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
   15538    {
   15539       IRExpr * exp;
   15540       DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15541 
   15542       if (host_endness == VexEndnessLE)
   15543          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   15544       else
   15545          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   15546 
   15547       putVSReg( XT, binop( Iop_64HLtoV128,
   15548                            unop( Iop_32Uto64, exp),
   15549                            mkU64(0) ) );
   15550       break;
   15551    }
   15552    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
   15553    {
   15554       IRExpr * exp;
   15555       DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15556 
   15557       if (host_endness == VexEndnessLE)
   15558          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
   15559       else
   15560          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
   15561 
   15562       putVSReg( XT, binop( Iop_64HLtoV128,
   15563                            unop( Iop_32Sto64, exp),
   15564                            mkU64(0) ) );
   15565       break;
   15566    }
   15567    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
   15568    {
   15569       IRExpr * exp;
   15570       DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15571       /* Take 32-bit floating point value in the upper half of the fetched
   15572        * 64-bit value, convert to 64-bit floating point value and load into
   15573        * top word of V128.
   15574        */
   15575       exp = unop( Iop_ReinterpF64asI64,
   15576                   unop( Iop_F32toF64,
   15577                         unop( Iop_ReinterpI32asF32,
   15578                               load( Ity_I32, mkexpr( EA ) ) ) ) );
   15579 
   15580       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
   15581       break;
   15582    }
   15583    case 0x24C: // lxsdx
   15584    {
   15585       IRExpr * exp;
   15586       DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15587       exp = load( Ity_I64, mkexpr( EA ) );
   15588       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
   15589       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
   15590       // are undefined after this operation, we can just do a splat op.
   15591       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
   15592       break;
   15593    }
   15594    case 0x34C: // lxvd2x
   15595    {
   15596       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
   15597       IRExpr * high, *low;
   15598       ULong ea_off = 8;
   15599       IRExpr* high_addr;
   15600       DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15601       high = load( Ity_I64, mkexpr( EA ) );
   15602       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
   15603             : mkU32( ea_off ) );
   15604       low = load( Ity_I64, high_addr );
   15605       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
   15606       break;
   15607    }
   15608    case 0x14C: // lxvdsx
   15609    {
   15610       IRTemp data = newTemp(Ity_I64);
   15611       DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15612       assign( data, load( Ity_I64, mkexpr( EA ) ) );
   15613       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
   15614       break;
   15615    }
   15616    case 0x30C:
   15617    {
   15618       IRExpr *t0;
   15619 
   15620       DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
   15621 
   15622       /* The load will result in the data being in BE order. */
   15623       if (host_endness == VexEndnessLE) {
   15624          IRExpr *t0_BE;
   15625          IRTemp perm_LE = newTemp(Ity_V128);
   15626 
   15627          t0_BE = load( Ity_V128, mkexpr( EA ) );
   15628 
   15629          /*  Permute the data to LE format */
   15630          assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
   15631                                  mkU64(0x0405060700010203ULL)));
   15632 
   15633          t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
   15634       } else {
   15635          t0 = load( Ity_V128, mkexpr( EA ) );
   15636       }
   15637 
   15638       putVSReg( XT, t0 );
   15639       break;
   15640    }
   15641    default:
   15642       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
   15643       return False;
   15644    }
   15645    return True;
   15646 }
   15647 
   15648 /*
   15649  * VSX Store Instructions
   15650  * NOTE: VSX supports word-aligned storage access.
   15651  */
   15652 static Bool
   15653 dis_vx_store ( UInt theInstr )
   15654 {
   15655    /* XX1-Form */
   15656    UChar opc1 = ifieldOPC( theInstr );
   15657    UChar XS = ifieldRegXS( theInstr );
   15658    UChar rA_addr = ifieldRegA( theInstr );
   15659    UChar rB_addr = ifieldRegB( theInstr );
   15660    IRTemp vS = newTemp( Ity_V128 );
   15661    UInt opc2 = ifieldOPClo10( theInstr );
   15662 
   15663    IRType ty = mode64 ? Ity_I64 : Ity_I32;
   15664    IRTemp EA = newTemp( ty );
   15665 
   15666    if (opc1 != 0x1F) {
   15667       vex_printf( "dis_vx_store(ppc)(instr)\n" );
   15668       return False;
   15669    }
   15670 
   15671    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
   15672    assign( vS, getVSReg( XS ) );
   15673 
   15674    switch (opc2) {
   15675    case 0x08C:
   15676    {
   15677      /* Need the next to the most significant 32-bit word from
   15678       * the 128-bit vector.
   15679       */
   15680       IRExpr * high64, * low32;
   15681       DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   15682       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15683       low32  = unop( Iop_64to32, high64 );
   15684       store( mkexpr( EA ), low32 );
   15685       break;
   15686    }
   15687    case 0x28C:
   15688    {
   15689       IRTemp high64 = newTemp(Ity_F64);
   15690       IRTemp val32  = newTemp(Ity_I32);
   15691       DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   15692       assign(high64, unop( Iop_ReinterpI64asF64,
   15693                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
   15694       assign(val32, unop( Iop_ReinterpF32asI32,
   15695                           unop( Iop_TruncF64asF32,
   15696                                 mkexpr(high64) ) ) );
   15697       store( mkexpr( EA ), mkexpr( val32 ) );
   15698       break;
   15699    }
   15700    case 0x2CC:
   15701    {
   15702       IRExpr * high64;
   15703       DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   15704       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15705       store( mkexpr( EA ), high64 );
   15706       break;
   15707    }
   15708    case 0x3CC:
   15709    {
   15710       IRExpr * high64, *low64;
   15711       DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   15712       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
   15713       low64 = unop( Iop_V128to64, mkexpr( vS ) );
   15714       store( mkexpr( EA ), high64 );
   15715       store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15716                     ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
   15717       break;
   15718    }
   15719    case 0x38C:
   15720    {
   15721       UInt ea_off = 0;
   15722       IRExpr* irx_addr;
   15723       IRTemp hi64 = newTemp( Ity_I64 );
   15724       IRTemp lo64 = newTemp( Ity_I64 );
   15725 
   15726       DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
   15727 
   15728       // This instruction supports word-aligned stores, so EA may not be
   15729       // quad-word aligned.  Therefore, do 4 individual word-size stores.
   15730       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
   15731       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
   15732       store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
   15733       ea_off += 4;
   15734       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15735                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15736       store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
   15737       ea_off += 4;
   15738       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15739                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15740       store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
   15741       ea_off += 4;
   15742       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
   15743                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
   15744       store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
   15745 
   15746       break;
   15747    }
   15748    default:
   15749       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
   15750       return False;
   15751    }
   15752    return True;
   15753 }
   15754 
   15755 /*
   15756  * VSX permute and other miscealleous instructions
   15757  */
   15758 static Bool
   15759 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
   15760 {
   15761    /* XX3-Form */
   15762    UChar opc1 = ifieldOPC( theInstr );
   15763    UChar XT = ifieldRegXT ( theInstr );
   15764    UChar XA = ifieldRegXA ( theInstr );
   15765    UChar XB = ifieldRegXB ( theInstr );
   15766    IRTemp vT = newTemp( Ity_V128 );
   15767    IRTemp vA = newTemp( Ity_V128 );
   15768    IRTemp vB = newTemp( Ity_V128 );
   15769 
   15770    if (opc1 != 0x3C) {
   15771       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
   15772       return False;
   15773    }
   15774 
   15775    assign( vA, getVSReg( XA ) );
   15776    assign( vB, getVSReg( XB ) );
   15777 
   15778    switch (opc2) {
   15779       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
   15780       {
   15781          UChar SHW = ifieldSHW ( theInstr );
   15782          IRTemp result = newTemp(Ity_V128);
   15783          if ( SHW != 0 ) {
   15784              IRTemp hi = newTemp(Ity_V128);
   15785              IRTemp lo = newTemp(Ity_V128);
   15786              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
   15787              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
   15788              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
   15789          } else
   15790              assign ( result, mkexpr(vA) );
   15791          DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
   15792          putVSReg( XT, mkexpr(result) );
   15793          break;
   15794       }
   15795       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
   15796       {
   15797          UChar DM = ifieldDM ( theInstr );
   15798          IRTemp hi = newTemp(Ity_I64);
   15799          IRTemp lo = newTemp(Ity_I64);
   15800 
   15801          if (DM & 0x2)
   15802            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
   15803          else
   15804            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
   15805 
   15806          if (DM & 0x1)
   15807            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
   15808          else
   15809            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
   15810 
   15811          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
   15812 
   15813          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
   15814          putVSReg( XT, mkexpr( vT ) );
   15815          break;
   15816       }
   15817       case 0x48: // xxmrghw (VSX Merge High Word)
   15818       case 0xc8: // xxmrglw (VSX Merge Low Word)
   15819       {
   15820          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
   15821          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
   15822          IRTemp a64 = newTemp(Ity_I64);
   15823          IRTemp ahi32 = newTemp(Ity_I32);
   15824          IRTemp alo32 = newTemp(Ity_I32);
   15825          IRTemp b64 = newTemp(Ity_I64);
   15826          IRTemp bhi32 = newTemp(Ity_I32);
   15827          IRTemp blo32 = newTemp(Ity_I32);
   15828 
   15829          assign( a64, unop(word_op, mkexpr(vA)) );
   15830          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
   15831          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
   15832 
   15833          assign( b64, unop(word_op, mkexpr(vB)) );
   15834          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
   15835          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
   15836 
   15837          assign( vT, binop(Iop_64HLtoV128,
   15838                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
   15839                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
   15840 
   15841          DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
   15842          putVSReg( XT, mkexpr( vT ) );
   15843          break;
   15844       }
   15845       case 0x018: // xxsel (VSX Select)
   15846       {
   15847          UChar XC = ifieldRegXC(theInstr);
   15848          IRTemp vC = newTemp( Ity_V128 );
   15849          assign( vC, getVSReg( XC ) );
   15850          DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
   15851          /* vD = (vA & ~vC) | (vB & vC) */
   15852          putVSReg( XT, binop(Iop_OrV128,
   15853             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   15854             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   15855          break;
   15856       }
   15857       case 0x148: // xxspltw (VSX Splat Word)
   15858       {
   15859          UChar UIM   = ifieldRegA(theInstr) & 3;
   15860          UChar sh_uim = (3 - (UIM)) * 32;
   15861          DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
   15862          putVSReg( XT,
   15863                    unop( Iop_Dup32x4,
   15864                          unop( Iop_V128to32,
   15865                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
   15866          break;
   15867       }
   15868 
   15869       default:
   15870          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
   15871          return False;
   15872    }
   15873    return True;
   15874 }
   15875 
   15876 /*
   15877   AltiVec Load Instructions
   15878 */
   15879 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
   15880 {
   15881    /* X-Form */
   15882    UChar opc1     = ifieldOPC(theInstr);
   15883    UChar vD_addr  = ifieldRegDS(theInstr);
   15884    UChar rA_addr  = ifieldRegA(theInstr);
   15885    UChar rB_addr  = ifieldRegB(theInstr);
   15886    UInt  opc2     = ifieldOPClo10(theInstr);
   15887    UChar b0       = ifieldBIT0(theInstr);
   15888 
   15889    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
   15890    IRTemp EA         = newTemp(ty);
   15891    IRTemp EA_align16 = newTemp(ty);
   15892 
   15893    if (opc1 != 0x1F || b0 != 0) {
   15894       vex_printf("dis_av_load(ppc)(instr)\n");
   15895       return False;
   15896    }
   15897 
   15898    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   15899    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
   15900 
   15901    switch (opc2) {
   15902 
   15903    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
   15904       IRDirty* d;
   15905       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15906       IRExpr** args_be = mkIRExprVec_5(
   15907                          IRExpr_BBPTR(),
   15908                          mkU32(vD_off),
   15909                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15910                                           mkU32(0xF)),
   15911                          mkU32(0)/*left*/,
   15912                          mkU32(1)/*Big Endian*/);
   15913       IRExpr** args_le = mkIRExprVec_5(
   15914                          IRExpr_BBPTR(),
   15915                          mkU32(vD_off),
   15916                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15917                                           mkU32(0xF)),
   15918                          mkU32(0)/*left*/,
   15919                          mkU32(0)/*Little Endian*/);
   15920       if (!mode64) {
   15921          d = unsafeIRDirty_0_N (
   15922                         0/*regparms*/,
   15923                         "ppc32g_dirtyhelper_LVS",
   15924                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15925                         args_be );
   15926       } else {
   15927          if (host_endness == VexEndnessBE)
   15928             d = unsafeIRDirty_0_N (
   15929                            0/*regparms*/,
   15930                            "ppc64g_dirtyhelper_LVS",
   15931                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15932                            args_be );
   15933          else
   15934             d = unsafeIRDirty_0_N (
   15935                            0/*regparms*/,
   15936                            "ppc64g_dirtyhelper_LVS",
   15937                            &ppc64g_dirtyhelper_LVS,
   15938                            args_le );
   15939       }
   15940       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15941       /* declare guest state effects */
   15942       d->nFxState = 1;
   15943       vex_bzero(&d->fxState, sizeof(d->fxState));
   15944       d->fxState[0].fx     = Ifx_Write;
   15945       d->fxState[0].offset = vD_off;
   15946       d->fxState[0].size   = sizeof(U128);
   15947 
   15948       /* execute the dirty call, side-effecting guest state */
   15949       stmt( IRStmt_Dirty(d) );
   15950       break;
   15951    }
   15952    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
   15953       IRDirty* d;
   15954       UInt vD_off = vectorGuestRegOffset(vD_addr);
   15955       IRExpr** args_be = mkIRExprVec_5(
   15956                              IRExpr_BBPTR(),
   15957                              mkU32(vD_off),
   15958                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15959                                               mkU32(0xF)),
   15960                              mkU32(1)/*right*/,
   15961                              mkU32(1)/*Big Endian*/);
   15962       IRExpr** args_le = mkIRExprVec_5(
   15963                              IRExpr_BBPTR(),
   15964                              mkU32(vD_off),
   15965                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
   15966                                               mkU32(0xF)),
   15967                              mkU32(1)/*right*/,
   15968                              mkU32(0)/*Little Endian*/);
   15969 
   15970       if (!mode64) {
   15971          d = unsafeIRDirty_0_N (
   15972                         0/*regparms*/,
   15973                         "ppc32g_dirtyhelper_LVS",
   15974                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
   15975                         args_be );
   15976       } else {
   15977          if (host_endness == VexEndnessBE)
   15978             d = unsafeIRDirty_0_N (
   15979                            0/*regparms*/,
   15980                            "ppc64g_dirtyhelper_LVS",
   15981                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
   15982                            args_be );
   15983          else
   15984             d = unsafeIRDirty_0_N (
   15985                            0/*regparms*/,
   15986                            "ppc64g_dirtyhelper_LVS",
   15987                            &ppc64g_dirtyhelper_LVS,
   15988                            args_le );
   15989       }
   15990       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   15991       /* declare guest state effects */
   15992       d->nFxState = 1;
   15993       vex_bzero(&d->fxState, sizeof(d->fxState));
   15994       d->fxState[0].fx     = Ifx_Write;
   15995       d->fxState[0].offset = vD_off;
   15996       d->fxState[0].size   = sizeof(U128);
   15997 
   15998       /* execute the dirty call, side-effecting guest state */
   15999       stmt( IRStmt_Dirty(d) );
   16000       break;
   16001    }
   16002    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
   16003       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   16004       /* loads addressed byte into vector[EA[0:3]
   16005          since all other destination bytes are undefined,
   16006          can simply load entire vector from 16-aligned EA */
   16007       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   16008       break;
   16009 
   16010    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
   16011       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   16012       /* see note for lvebx */
   16013       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   16014       break;
   16015 
   16016    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
   16017       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   16018       /* see note for lvebx */
   16019       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   16020       break;
   16021 
   16022    case 0x067: // lvx (Load Vector Indexed, AV p127)
   16023       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   16024       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   16025       break;
   16026 
   16027    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
   16028       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
   16029       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
   16030       break;
   16031 
   16032    default:
   16033       vex_printf("dis_av_load(ppc)(opc2)\n");
   16034       return False;
   16035    }
   16036    return True;
   16037 }
   16038 
   16039 /*
   16040   AltiVec Store Instructions
   16041 */
   16042 static Bool dis_av_store ( UInt theInstr )
   16043 {
   16044    /* X-Form */
   16045    UChar opc1     = ifieldOPC(theInstr);
   16046    UChar vS_addr  = ifieldRegDS(theInstr);
   16047    UChar rA_addr  = ifieldRegA(theInstr);
   16048    UChar rB_addr  = ifieldRegB(theInstr);
   16049    UInt  opc2     = ifieldOPClo10(theInstr);
   16050    UChar b0       = ifieldBIT0(theInstr);
   16051 
   16052    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
   16053    IRTemp EA           = newTemp(ty);
   16054    IRTemp addr_aligned = newTemp(ty);
   16055    IRTemp vS           = newTemp(Ity_V128);
   16056    IRTemp eb           = newTemp(Ity_I8);
   16057    IRTemp idx          = newTemp(Ity_I8);
   16058 
   16059    if (opc1 != 0x1F || b0 != 0) {
   16060       vex_printf("dis_av_store(ppc)(instr)\n");
   16061       return False;
   16062    }
   16063 
   16064    assign( vS, getVReg(vS_addr));
   16065    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
   16066 
   16067    switch (opc2) {
   16068    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
   16069       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   16070       assign( eb, binop(Iop_And8, mkU8(0xF),
   16071                         unop(Iop_32to8,
   16072                              mkNarrowTo32(ty, mkexpr(EA)) )) );
   16073      if (host_endness == VexEndnessLE) {
   16074          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   16075       } else {
   16076          assign( idx, binop(Iop_Shl8,
   16077                             binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
   16078                             mkU8(3)) );
   16079       }
   16080       store( mkexpr(EA),
   16081              unop( Iop_32to8, unop(Iop_V128to32,
   16082                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   16083       break;
   16084    }
   16085    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
   16086       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   16087       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
   16088       assign( eb, binop(Iop_And8, mkU8(0xF),
   16089                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   16090       if (host_endness == VexEndnessLE) {
   16091           assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   16092       } else {
   16093          assign( idx, binop(Iop_Shl8,
   16094                             binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
   16095                             mkU8(3)) );
   16096       }
   16097       store( mkexpr(addr_aligned),
   16098              unop( Iop_32to16, unop(Iop_V128to32,
   16099                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
   16100       break;
   16101    }
   16102    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
   16103       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   16104       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
   16105       assign( eb, binop(Iop_And8, mkU8(0xF),
   16106                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
   16107       if (host_endness == VexEndnessLE) {
   16108          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
   16109       } else {
   16110          assign( idx, binop(Iop_Shl8,
   16111                             binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
   16112                             mkU8(3)) );
   16113       }
   16114       store( mkexpr( addr_aligned),
   16115              unop( Iop_V128to32,
   16116                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
   16117       break;
   16118    }
   16119 
   16120    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
   16121       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   16122       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   16123       break;
   16124 
   16125    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
   16126       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
   16127       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
   16128       break;
   16129 
   16130    default:
   16131       vex_printf("dis_av_store(ppc)(opc2)\n");
   16132       return False;
   16133    }
   16134    return True;
   16135 }
   16136 
   16137 /*
   16138   AltiVec Arithmetic Instructions
   16139 */
   16140 static Bool dis_av_arith ( UInt theInstr )
   16141 {
   16142    /* VX-Form */
   16143    UChar opc1     = ifieldOPC(theInstr);
   16144    UChar vD_addr  = ifieldRegDS(theInstr);
   16145    UChar vA_addr  = ifieldRegA(theInstr);
   16146    UChar vB_addr  = ifieldRegB(theInstr);
   16147    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   16148 
   16149    IRTemp vA = newTemp(Ity_V128);
   16150    IRTemp vB = newTemp(Ity_V128);
   16151    IRTemp z3 = newTemp(Ity_I64);
   16152    IRTemp z2 = newTemp(Ity_I64);
   16153    IRTemp z1 = newTemp(Ity_I64);
   16154    IRTemp z0 = newTemp(Ity_I64);
   16155    IRTemp aEvn, aOdd;
   16156    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
   16157    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
   16158    IRTemp b3, b2, b1, b0;
   16159 
   16160    aEvn = aOdd = IRTemp_INVALID;
   16161    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
   16162    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
   16163    b3 = b2 = b1 = b0 = IRTemp_INVALID;
   16164 
   16165    assign( vA, getVReg(vA_addr));
   16166    assign( vB, getVReg(vB_addr));
   16167 
   16168    if (opc1 != 0x4) {
   16169       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
   16170       return False;
   16171    }
   16172 
   16173    switch (opc2) {
   16174    /* Add */
   16175    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
   16176       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16177       /* unsigned_ov(x+y) = (y >u not(x)) */
   16178       putVReg( vD_addr, binop(Iop_ShrN32x4,
   16179                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
   16180                                     unop(Iop_NotV128, mkexpr(vA))),
   16181                               mkU8(31)) );
   16182       break;
   16183    }
   16184    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
   16185       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16186       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
   16187       break;
   16188 
   16189    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
   16190       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16191       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
   16192       break;
   16193 
   16194    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
   16195       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16196       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
   16197       break;
   16198 
   16199    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
   16200       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16201       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
   16202       break;
   16203 
   16204    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
   16205       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16206       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
   16207       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
   16208       break;
   16209 
   16210    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
   16211       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16212       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
   16213       // TODO: set VSCR[SAT]
   16214       break;
   16215 
   16216    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
   16217       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16218       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
   16219       // TODO: set VSCR[SAT]
   16220       break;
   16221 
   16222    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
   16223       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16224       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
   16225       // TODO: set VSCR[SAT]
   16226       break;
   16227 
   16228    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
   16229       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16230       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
   16231       // TODO: set VSCR[SAT]
   16232       break;
   16233 
   16234    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
   16235       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16236       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
   16237       // TODO: set VSCR[SAT]
   16238       break;
   16239 
   16240 
   16241    /* Subtract */
   16242    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
   16243       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16244       /* unsigned_ov(x-y) = (y >u x) */
   16245       putVReg( vD_addr, binop(Iop_ShrN32x4,
   16246                               unop(Iop_NotV128,
   16247                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
   16248                                          mkexpr(vA))),
   16249                               mkU8(31)) );
   16250       break;
   16251    }
   16252    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
   16253       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16254       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
   16255       break;
   16256 
   16257    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
   16258       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16259       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
   16260       break;
   16261 
   16262    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
   16263       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16264       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
   16265       break;
   16266 
   16267    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
   16268       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16269       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
   16270       break;
   16271 
   16272    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
   16273       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16274       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
   16275       // TODO: set VSCR[SAT]
   16276       break;
   16277 
   16278    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
   16279       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16280       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
   16281       // TODO: set VSCR[SAT]
   16282       break;
   16283 
   16284    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
   16285       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16286       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
   16287       // TODO: set VSCR[SAT]
   16288       break;
   16289 
   16290    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
   16291       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16292       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
   16293       // TODO: set VSCR[SAT]
   16294       break;
   16295 
   16296    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
   16297       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16298       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
   16299       // TODO: set VSCR[SAT]
   16300       break;
   16301 
   16302    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
   16303       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16304       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
   16305       // TODO: set VSCR[SAT]
   16306       break;
   16307 
   16308 
   16309    /* Maximum */
   16310    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
   16311       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16312       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
   16313       break;
   16314 
   16315    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
   16316       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16317       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
   16318       break;
   16319 
   16320    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
   16321       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16322       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
   16323       break;
   16324 
   16325    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
   16326       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16327       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
   16328       break;
   16329 
   16330    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
   16331       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16332       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
   16333       break;
   16334 
   16335    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
   16336       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16337       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
   16338       break;
   16339 
   16340    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
   16341       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16342       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
   16343       break;
   16344 
   16345    case 0x1C2: // vmaxsd (Maximum Signed Double word)
   16346       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16347       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
   16348       break;
   16349 
   16350    /* Minimum */
   16351    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
   16352       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16353       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
   16354       break;
   16355 
   16356    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
   16357       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16358       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
   16359       break;
   16360 
   16361    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
   16362       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16363       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
   16364       break;
   16365 
   16366    case 0x2C2: // vminud (Minimum Unsigned Double Word)
   16367       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16368       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
   16369       break;
   16370 
   16371    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
   16372       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16373       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
   16374       break;
   16375 
   16376    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
   16377       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16378       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
   16379       break;
   16380 
   16381    case 0x382: // vminsw (Minimum Signed Word, AV p190)
   16382       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16383       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
   16384       break;
   16385 
   16386    case 0x3C2: // vminsd (Minimum Signed Double Word)
   16387       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16388       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
   16389       break;
   16390 
   16391 
   16392    /* Average */
   16393    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
   16394       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16395       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
   16396       break;
   16397 
   16398    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
   16399       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16400       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
   16401       break;
   16402 
   16403    case 0x482: // vavguw (Average Unsigned Word, AV p154)
   16404       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16405       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
   16406       break;
   16407 
   16408    case 0x502: // vavgsb (Average Signed Byte, AV p149)
   16409       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16410       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
   16411       break;
   16412 
   16413    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
   16414       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16415       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
   16416       break;
   16417 
   16418    case 0x582: // vavgsw (Average Signed Word, AV p151)
   16419       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16420       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
   16421       break;
   16422 
   16423 
   16424    /* Multiply */
   16425    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
   16426       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16427       putVReg( vD_addr,
   16428                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
   16429       break;
   16430 
   16431    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
   16432       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16433       putVReg( vD_addr,
   16434                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
   16435       break;
   16436 
   16437    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
   16438       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16439       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
   16440       break;
   16441 
   16442    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
   16443       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16444       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
   16445       break;
   16446 
   16447    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
   16448       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16449       putVReg( vD_addr,
   16450                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
   16451       break;
   16452 
   16453    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
   16454       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16455       putVReg( vD_addr,
   16456                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
   16457       break;
   16458 
   16459    case 0x188: // vmulosw (Multiply Odd Signed Word)
   16460       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16461       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
   16462       break;
   16463 
   16464    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
   16465       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16466       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   16467       break;
   16468 
   16469    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
   16470       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16471       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   16472       break;
   16473 
   16474    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
   16475       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16476       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
   16477       break;
   16478 
   16479    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
   16480       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16481       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
   16482       break;
   16483 
   16484    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
   16485       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16486       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   16487       break;
   16488 
   16489    case 0x388: // vmulesw (Multiply Even Signed Word)
   16490       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16491       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
   16492       break;
   16493 
   16494    /* Sum Across Partial */
   16495    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
   16496       IRTemp aEE, aEO, aOE, aOO;
   16497       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   16498       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16499 
   16500       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
   16501       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   16502       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   16503       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   16504 
   16505       /* break V128 to 4xI32's, zero-extending to I64's */
   16506       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   16507       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   16508       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   16509       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   16510       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   16511 
   16512       /* add lanes */
   16513       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16514                      binop(Iop_Add64,
   16515                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   16516                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   16517       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16518                      binop(Iop_Add64,
   16519                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16520                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16521       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16522                      binop(Iop_Add64,
   16523                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16524                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16525       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16526                      binop(Iop_Add64,
   16527                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16528                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16529 
   16530       /* saturate-narrow to 32bit, and combine to V128 */
   16531       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   16532                                          mkexpr(z1), mkexpr(z0)) );
   16533       break;
   16534    }
   16535    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
   16536       IRTemp aEE, aEO, aOE, aOO;
   16537       aEE = aEO = aOE = aOO = IRTemp_INVALID;
   16538       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16539 
   16540       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
   16541       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
   16542       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
   16543       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
   16544 
   16545       /* break V128 to 4xI32's, sign-extending to I64's */
   16546       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
   16547       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
   16548       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
   16549       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
   16550       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
   16551 
   16552       /* add lanes */
   16553       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16554                      binop(Iop_Add64,
   16555                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
   16556                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
   16557       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16558                      binop(Iop_Add64,
   16559                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
   16560                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
   16561       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16562                      binop(Iop_Add64,
   16563                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
   16564                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
   16565       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16566                      binop(Iop_Add64,
   16567                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16568                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16569 
   16570       /* saturate-narrow to 32bit, and combine to V128 */
   16571       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16572                                          mkexpr(z1), mkexpr(z0)) );
   16573       break;
   16574    }
   16575    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
   16576       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16577 
   16578       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
   16579       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
   16580 
   16581       /* break V128 to 4xI32's, sign-extending to I64's */
   16582       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
   16583       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
   16584       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
   16585 
   16586       /* add lanes */
   16587       assign( z3, binop(Iop_Add64, mkexpr(b3),
   16588                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
   16589       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16590                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
   16591       assign( z1, binop(Iop_Add64, mkexpr(b1),
   16592                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
   16593       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16594                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
   16595 
   16596       /* saturate-narrow to 32bit, and combine to V128 */
   16597       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   16598                                          mkexpr(z1), mkexpr(z0)) );
   16599       break;
   16600    }
   16601    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
   16602       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16603 
   16604       /* break V128 to 4xI32's, sign-extending to I64's */
   16605       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16606       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16607 
   16608       /* add lanes */
   16609       assign( z2, binop(Iop_Add64, mkexpr(b2),
   16610                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
   16611       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16612                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
   16613 
   16614       /* saturate-narrow to 32bit, and combine to V128 */
   16615       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
   16616                                          mkU64(0), mkexpr(z0)) );
   16617       break;
   16618    }
   16619    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
   16620       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16621 
   16622       /* break V128 to 4xI32's, sign-extending to I64's */
   16623       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
   16624       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
   16625 
   16626       /* add lanes */
   16627       assign( z0, binop(Iop_Add64, mkexpr(b0),
   16628                      binop(Iop_Add64,
   16629                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
   16630                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
   16631 
   16632       /* saturate-narrow to 32bit, and combine to V128 */
   16633       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
   16634                                          mkU64(0), mkexpr(z0)) );
   16635       break;
   16636    }
   16637    default:
   16638       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
   16639       return False;
   16640    }
   16641    return True;
   16642 }
   16643 
   16644 /*
   16645   AltiVec Logic Instructions
   16646 */
   16647 static Bool dis_av_logic ( UInt theInstr )
   16648 {
   16649    /* VX-Form */
   16650    UChar opc1    = ifieldOPC(theInstr);
   16651    UChar vD_addr = ifieldRegDS(theInstr);
   16652    UChar vA_addr = ifieldRegA(theInstr);
   16653    UChar vB_addr = ifieldRegB(theInstr);
   16654    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   16655 
   16656    IRTemp vA = newTemp(Ity_V128);
   16657    IRTemp vB = newTemp(Ity_V128);
   16658    assign( vA, getVReg(vA_addr));
   16659    assign( vB, getVReg(vB_addr));
   16660 
   16661    if (opc1 != 0x4) {
   16662       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
   16663       return False;
   16664    }
   16665 
   16666    switch (opc2) {
   16667    case 0x404: // vand (And, AV p147)
   16668       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16669       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
   16670       break;
   16671 
   16672    case 0x444: // vandc (And, AV p148)
   16673       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16674       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
   16675                               unop(Iop_NotV128, mkexpr(vB))) );
   16676       break;
   16677 
   16678    case 0x484: // vor (Or, AV p217)
   16679       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16680       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
   16681       break;
   16682 
   16683    case 0x4C4: // vxor (Xor, AV p282)
   16684       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16685       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
   16686       break;
   16687 
   16688    case 0x504: // vnor (Nor, AV p216)
   16689       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16690       putVReg( vD_addr,
   16691          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
   16692       break;
   16693 
   16694    case 0x544: // vorc (vA Or'd with complement of vb)
   16695       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16696       putVReg( vD_addr, binop( Iop_OrV128,
   16697                                mkexpr( vA ),
   16698                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
   16699       break;
   16700 
   16701    case 0x584: // vnand (Nand)
   16702       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16703       putVReg( vD_addr, unop( Iop_NotV128,
   16704                               binop(Iop_AndV128, mkexpr( vA ),
   16705                               mkexpr( vB ) ) ) );
   16706       break;
   16707 
   16708    case 0x684: // veqv (complemented XOr)
   16709       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   16710       putVReg( vD_addr, unop( Iop_NotV128,
   16711                               binop( Iop_XorV128, mkexpr( vA ),
   16712                               mkexpr( vB ) ) ) );
   16713       break;
   16714 
   16715    default:
   16716       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
   16717       return False;
   16718    }
   16719    return True;
   16720 }
   16721 
   16722 /*
   16723   AltiVec Compare Instructions
   16724 */
   16725 static Bool dis_av_cmp ( UInt theInstr )
   16726 {
   16727    /* VXR-Form */
   16728    UChar opc1     = ifieldOPC(theInstr);
   16729    UChar vD_addr  = ifieldRegDS(theInstr);
   16730    UChar vA_addr  = ifieldRegA(theInstr);
   16731    UChar vB_addr  = ifieldRegB(theInstr);
   16732    UChar flag_rC  = ifieldBIT10(theInstr);
   16733    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   16734 
   16735    IRTemp vA = newTemp(Ity_V128);
   16736    IRTemp vB = newTemp(Ity_V128);
   16737    IRTemp vD = newTemp(Ity_V128);
   16738    assign( vA, getVReg(vA_addr));
   16739    assign( vB, getVReg(vB_addr));
   16740 
   16741    if (opc1 != 0x4) {
   16742       vex_printf("dis_av_cmp(ppc)(instr)\n");
   16743       return False;
   16744    }
   16745 
   16746    switch (opc2) {
   16747    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
   16748       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16749                                       vD_addr, vA_addr, vB_addr);
   16750       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
   16751       break;
   16752 
   16753    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
   16754       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16755                                       vD_addr, vA_addr, vB_addr);
   16756       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
   16757       break;
   16758 
   16759    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
   16760       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16761                                       vD_addr, vA_addr, vB_addr);
   16762       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
   16763       break;
   16764 
   16765    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
   16766       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16767                                       vD_addr, vA_addr, vB_addr);
   16768       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
   16769       break;
   16770 
   16771    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
   16772       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16773                                       vD_addr, vA_addr, vB_addr);
   16774       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
   16775       break;
   16776 
   16777    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
   16778       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16779                                       vD_addr, vA_addr, vB_addr);
   16780       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
   16781       break;
   16782 
   16783    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
   16784       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16785                                        vD_addr, vA_addr, vB_addr);
   16786       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
   16787       break;
   16788 
   16789    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
   16790       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16791                                       vD_addr, vA_addr, vB_addr);
   16792       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
   16793       break;
   16794 
   16795    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
   16796       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16797                                        vD_addr, vA_addr, vB_addr);
   16798       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
   16799       break;
   16800 
   16801    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
   16802       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16803                                       vD_addr, vA_addr, vB_addr);
   16804       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
   16805       break;
   16806 
   16807    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
   16808       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16809                                       vD_addr, vA_addr, vB_addr);
   16810       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
   16811       break;
   16812 
   16813    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
   16814       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   16815                                       vD_addr, vA_addr, vB_addr);
   16816       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
   16817       break;
   16818 
   16819    default:
   16820       vex_printf("dis_av_cmp(ppc)(opc2)\n");
   16821       return False;
   16822    }
   16823 
   16824    putVReg( vD_addr, mkexpr(vD) );
   16825 
   16826    if (flag_rC) {
   16827       set_AV_CR6( mkexpr(vD), True );
   16828    }
   16829    return True;
   16830 }
   16831 
   16832 /*
   16833   AltiVec Multiply-Sum Instructions
   16834 */
   16835 static Bool dis_av_multarith ( UInt theInstr )
   16836 {
   16837    /* VA-Form */
   16838    UChar opc1     = ifieldOPC(theInstr);
   16839    UChar vD_addr  = ifieldRegDS(theInstr);
   16840    UChar vA_addr  = ifieldRegA(theInstr);
   16841    UChar vB_addr  = ifieldRegB(theInstr);
   16842    UChar vC_addr  = ifieldRegC(theInstr);
   16843    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
   16844 
   16845    IRTemp vA    = newTemp(Ity_V128);
   16846    IRTemp vB    = newTemp(Ity_V128);
   16847    IRTemp vC    = newTemp(Ity_V128);
   16848    IRTemp zeros = newTemp(Ity_V128);
   16849    IRTemp aLo   = newTemp(Ity_V128);
   16850    IRTemp bLo   = newTemp(Ity_V128);
   16851    IRTemp cLo   = newTemp(Ity_V128);
   16852    IRTemp zLo   = newTemp(Ity_V128);
   16853    IRTemp aHi   = newTemp(Ity_V128);
   16854    IRTemp bHi   = newTemp(Ity_V128);
   16855    IRTemp cHi   = newTemp(Ity_V128);
   16856    IRTemp zHi   = newTemp(Ity_V128);
   16857    IRTemp abEvn = newTemp(Ity_V128);
   16858    IRTemp abOdd = newTemp(Ity_V128);
   16859    IRTemp z3    = newTemp(Ity_I64);
   16860    IRTemp z2    = newTemp(Ity_I64);
   16861    IRTemp z1    = newTemp(Ity_I64);
   16862    IRTemp z0    = newTemp(Ity_I64);
   16863    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
   16864    IRTemp c3, c2, c1, c0;
   16865 
   16866    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
   16867    c3 = c2 = c1 = c0 = IRTemp_INVALID;
   16868 
   16869    assign( vA, getVReg(vA_addr));
   16870    assign( vB, getVReg(vB_addr));
   16871    assign( vC, getVReg(vC_addr));
   16872    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   16873 
   16874    if (opc1 != 0x4) {
   16875       vex_printf("dis_av_multarith(ppc)(instr)\n");
   16876       return False;
   16877    }
   16878 
   16879    switch (opc2) {
   16880    /* Multiply-Add */
   16881    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
   16882       IRTemp cSigns = newTemp(Ity_V128);
   16883       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
   16884           vD_addr, vA_addr, vB_addr, vC_addr);
   16885       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
   16886       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16887       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16888       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16889       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16890       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16891       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16892 
   16893       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16894                          binop(Iop_SarN32x4,
   16895                                binop(Iop_MullEven16Sx8,
   16896                                      mkexpr(aLo), mkexpr(bLo)),
   16897                                mkU8(15))) );
   16898 
   16899       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16900                          binop(Iop_SarN32x4,
   16901                                binop(Iop_MullEven16Sx8,
   16902                                      mkexpr(aHi), mkexpr(bHi)),
   16903                                mkU8(15))) );
   16904 
   16905       putVReg( vD_addr,
   16906                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16907       break;
   16908    }
   16909    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
   16910       IRTemp zKonst = newTemp(Ity_V128);
   16911       IRTemp cSigns = newTemp(Ity_V128);
   16912       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
   16913           vD_addr, vA_addr, vB_addr, vC_addr);
   16914       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
   16915       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16916       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16917       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
   16918       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16919       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16920       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
   16921 
   16922       /* shifting our const avoids store/load version of Dup */
   16923       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
   16924                             mkU8(14)) );
   16925 
   16926       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
   16927                          binop(Iop_SarN32x4,
   16928                                binop(Iop_Add32x4, mkexpr(zKonst),
   16929                                      binop(Iop_MullEven16Sx8,
   16930                                            mkexpr(aLo), mkexpr(bLo))),
   16931                                mkU8(15))) );
   16932 
   16933       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
   16934                          binop(Iop_SarN32x4,
   16935                                binop(Iop_Add32x4, mkexpr(zKonst),
   16936                                      binop(Iop_MullEven16Sx8,
   16937                                            mkexpr(aHi), mkexpr(bHi))),
   16938                                mkU8(15))) );
   16939 
   16940       putVReg( vD_addr,
   16941                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
   16942       break;
   16943    }
   16944    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
   16945       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
   16946           vD_addr, vA_addr, vB_addr, vC_addr);
   16947       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
   16948       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
   16949       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
   16950       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
   16951       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
   16952       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
   16953       assign(zLo, binop(Iop_Add32x4,
   16954                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
   16955                      mkexpr(cLo)) );
   16956       assign(zHi, binop(Iop_Add32x4,
   16957                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
   16958                      mkexpr(cHi)));
   16959       putVReg( vD_addr,
   16960                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
   16961       break;
   16962    }
   16963 
   16964 
   16965    /* Multiply-Sum */
   16966    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
   16967       IRTemp abEE, abEO, abOE, abOO;
   16968       abEE = abEO = abOE = abOO = IRTemp_INVALID;
   16969       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
   16970           vD_addr, vA_addr, vB_addr, vC_addr);
   16971 
   16972       /* multiply vA,vB (unsigned, widening) */
   16973       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
   16974       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
   16975 
   16976       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
   16977       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
   16978       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
   16979 
   16980       putVReg( vD_addr,
   16981          binop(Iop_Add32x4, mkexpr(vC),
   16982                binop(Iop_Add32x4,
   16983                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
   16984                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
   16985       break;
   16986    }
   16987    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
   16988       IRTemp aEvn, aOdd, bEvn, bOdd;
   16989       IRTemp abEE = newTemp(Ity_V128);
   16990       IRTemp abEO = newTemp(Ity_V128);
   16991       IRTemp abOE = newTemp(Ity_V128);
   16992       IRTemp abOO = newTemp(Ity_V128);
   16993       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
   16994       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
   16995           vD_addr, vA_addr, vB_addr, vC_addr);
   16996 
   16997       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
   16998          (separating out adjacent lanes to different vectors) */
   16999       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
   17000       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
   17001 
   17002       /* multiply vA, vB, again separating adjacent lanes */
   17003       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
   17004       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
   17005       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
   17006       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
   17007 
   17008       /* add results together, + vC */
   17009       putVReg( vD_addr,
   17010          binop(Iop_QAdd32Sx4, mkexpr(vC),
   17011                binop(Iop_QAdd32Sx4,
   17012                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
   17013                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
   17014       break;
   17015    }
   17016    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
   17017       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
   17018           vD_addr, vA_addr, vB_addr, vC_addr);
   17019       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
   17020       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   17021       putVReg( vD_addr,
   17022          binop(Iop_Add32x4, mkexpr(vC),
   17023                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
   17024       break;
   17025    }
   17026    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
   17027       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
   17028           vD_addr, vA_addr, vB_addr, vC_addr);
   17029       /* widening multiply, separating lanes */
   17030       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
   17031       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
   17032 
   17033       /* break V128 to 4xI32's, zero-extending to I64's */
   17034       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   17035       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   17036       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   17037 
   17038       /* add lanes */
   17039       assign( z3, binop(Iop_Add64, mkexpr(c3),
   17040                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   17041       assign( z2, binop(Iop_Add64, mkexpr(c2),
   17042                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   17043       assign( z1, binop(Iop_Add64, mkexpr(c1),
   17044                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   17045       assign( z0, binop(Iop_Add64, mkexpr(c0),
   17046                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   17047 
   17048       /* saturate-narrow to 32bit, and combine to V128 */
   17049       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
   17050                                          mkexpr(z1), mkexpr(z0)) );
   17051 
   17052       break;
   17053    }
   17054    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
   17055       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
   17056           vD_addr, vA_addr, vB_addr, vC_addr);
   17057       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   17058       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   17059       putVReg( vD_addr,
   17060          binop(Iop_Add32x4, mkexpr(vC),
   17061                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
   17062       break;
   17063    }
   17064    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
   17065       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
   17066           vD_addr, vA_addr, vB_addr, vC_addr);
   17067       /* widening multiply, separating lanes */
   17068       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
   17069       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
   17070 
   17071       /* break V128 to 4xI32's, sign-extending to I64's */
   17072       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
   17073       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
   17074       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
   17075 
   17076       /* add lanes */
   17077       assign( z3, binop(Iop_Add64, mkexpr(c3),
   17078                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
   17079       assign( z2, binop(Iop_Add64, mkexpr(c2),
   17080                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
   17081       assign( z1, binop(Iop_Add64, mkexpr(c1),
   17082                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
   17083       assign( z0, binop(Iop_Add64, mkexpr(c0),
   17084                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
   17085 
   17086       /* saturate-narrow to 32bit, and combine to V128 */
   17087       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
   17088                                          mkexpr(z1), mkexpr(z0)) );
   17089       break;
   17090    }
   17091    default:
   17092       vex_printf("dis_av_multarith(ppc)(opc2)\n");
   17093       return False;
   17094    }
   17095    return True;
   17096 }
   17097 
   17098 /*
   17099   AltiVec Polynomial Multiply-Sum Instructions
   17100 */
   17101 static Bool dis_av_polymultarith ( UInt theInstr )
   17102 {
   17103    /* VA-Form */
   17104    UChar opc1     = ifieldOPC(theInstr);
   17105    UChar vD_addr  = ifieldRegDS(theInstr);
   17106    UChar vA_addr  = ifieldRegA(theInstr);
   17107    UChar vB_addr  = ifieldRegB(theInstr);
   17108    UChar vC_addr  = ifieldRegC(theInstr);
   17109    UInt  opc2     = IFIELD(theInstr, 0, 11);
   17110    IRTemp vA    = newTemp(Ity_V128);
   17111    IRTemp vB    = newTemp(Ity_V128);
   17112    IRTemp vC    = newTemp(Ity_V128);
   17113 
   17114    assign( vA, getVReg(vA_addr));
   17115    assign( vB, getVReg(vB_addr));
   17116    assign( vC, getVReg(vC_addr));
   17117 
   17118    if (opc1 != 0x4) {
   17119       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
   17120       return False;
   17121    }
   17122 
   17123    switch (opc2) {
   17124       /* Polynomial Multiply-Add */
   17125       case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
   17126          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17127          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
   17128                                  mkexpr(vA), mkexpr(vB)) );
   17129          break;
   17130       case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
   17131          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17132          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
   17133                                  mkexpr(vA), mkexpr(vB)) );
   17134          break;
   17135       case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
   17136          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17137          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
   17138                                  mkexpr(vA), mkexpr(vB)) );
   17139          break;
   17140       case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
   17141          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17142          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
   17143                                  mkexpr(vA), mkexpr(vB)) );
   17144          break;
   17145       default:
   17146          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
   17147          return False;
   17148    }
   17149    return True;
   17150 }
   17151 
   17152 /*
   17153   AltiVec Shift/Rotate Instructions
   17154 */
   17155 static Bool dis_av_shift ( UInt theInstr )
   17156 {
   17157    /* VX-Form */
   17158    UChar opc1    = ifieldOPC(theInstr);
   17159    UChar vD_addr = ifieldRegDS(theInstr);
   17160    UChar vA_addr = ifieldRegA(theInstr);
   17161    UChar vB_addr = ifieldRegB(theInstr);
   17162    UInt  opc2    = IFIELD( theInstr, 0, 11 );
   17163 
   17164    IRTemp vA = newTemp(Ity_V128);
   17165    IRTemp vB = newTemp(Ity_V128);
   17166    assign( vA, getVReg(vA_addr));
   17167    assign( vB, getVReg(vB_addr));
   17168 
   17169    if (opc1 != 0x4){
   17170       vex_printf("dis_av_shift(ppc)(instr)\n");
   17171       return False;
   17172    }
   17173 
   17174    switch (opc2) {
   17175    /* Rotate */
   17176    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
   17177       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17178       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
   17179       break;
   17180 
   17181    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
   17182       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17183       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
   17184       break;
   17185 
   17186    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
   17187       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17188       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
   17189       break;
   17190 
   17191    case 0x0C4: // vrld (Rotate Left Integer Double Word)
   17192       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17193       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
   17194       break;
   17195 
   17196 
   17197    /* Shift Left */
   17198    case 0x104: // vslb (Shift Left Integer B, AV p240)
   17199       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17200       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
   17201       break;
   17202 
   17203    case 0x144: // vslh (Shift Left Integer HW, AV p242)
   17204       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17205       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
   17206       break;
   17207 
   17208    case 0x184: // vslw (Shift Left Integer W, AV p244)
   17209       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17210       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
   17211       break;
   17212 
   17213    case 0x5C4: // vsld (Shift Left Integer Double Word)
   17214       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17215       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
   17216       break;
   17217 
   17218    case 0x1C4: { // vsl (Shift Left, AV p239)
   17219       IRTemp sh = newTemp(Ity_I8);
   17220       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17221       assign( sh, binop(Iop_And8, mkU8(0x7),
   17222                         unop(Iop_32to8,
   17223                              unop(Iop_V128to32, mkexpr(vB)))) );
   17224       putVReg( vD_addr,
   17225                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   17226       break;
   17227    }
   17228    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
   17229       IRTemp sh = newTemp(Ity_I8);
   17230       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17231       assign( sh, binop(Iop_And8, mkU8(0x78),
   17232                         unop(Iop_32to8,
   17233                              unop(Iop_V128to32, mkexpr(vB)))) );
   17234       putVReg( vD_addr,
   17235                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
   17236       break;
   17237    }
   17238 
   17239 
   17240    /* Shift Right */
   17241    case 0x204: // vsrb (Shift Right B, AV p256)
   17242       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17243       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
   17244       break;
   17245 
   17246    case 0x244: // vsrh (Shift Right HW, AV p257)
   17247       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17248       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
   17249       break;
   17250 
   17251    case 0x284: // vsrw (Shift Right W, AV p259)
   17252       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17253       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
   17254       break;
   17255 
   17256    case 0x2C4: { // vsr (Shift Right, AV p251)
   17257       IRTemp sh = newTemp(Ity_I8);
   17258       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17259       assign( sh, binop(Iop_And8, mkU8(0x7),
   17260                         unop(Iop_32to8,
   17261                              unop(Iop_V128to32, mkexpr(vB)))) );
   17262       putVReg( vD_addr,
   17263                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   17264       break;
   17265    }
   17266    case 0x304: // vsrab (Shift Right Alg B, AV p253)
   17267       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17268       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
   17269       break;
   17270 
   17271    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
   17272       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17273       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
   17274       break;
   17275 
   17276    case 0x384: // vsraw (Shift Right Alg W, AV p255)
   17277       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17278       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
   17279       break;
   17280 
   17281    case 0x3C4: // vsrad (Shift Right Alg Double Word)
   17282       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17283       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
   17284       break;
   17285 
   17286    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
   17287       IRTemp sh = newTemp(Ity_I8);
   17288       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17289       assign( sh, binop(Iop_And8, mkU8(0x78),
   17290                         unop(Iop_32to8,
   17291                              unop(Iop_V128to32, mkexpr(vB)))) );
   17292       putVReg( vD_addr,
   17293                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
   17294       break;
   17295    }
   17296 
   17297    case 0x6C4: // vsrd (Shift Right Double Word)
   17298       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17299       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
   17300       break;
   17301 
   17302 
   17303    default:
   17304       vex_printf("dis_av_shift(ppc)(opc2)\n");
   17305       return False;
   17306    }
   17307    return True;
   17308 }
   17309 
   17310 /*
   17311   AltiVec Permute Instructions
   17312 */
   17313 static Bool dis_av_permute ( UInt theInstr )
   17314 {
   17315    /* VA-Form, VX-Form */
   17316    UChar opc1      = ifieldOPC(theInstr);
   17317    UChar vD_addr   = ifieldRegDS(theInstr);
   17318    UChar vA_addr   = ifieldRegA(theInstr);
   17319    UChar UIMM_5    = vA_addr;
   17320    UChar vB_addr   = ifieldRegB(theInstr);
   17321    UChar vC_addr   = ifieldRegC(theInstr);
   17322    UChar b10       = ifieldBIT10(theInstr);
   17323    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
   17324    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
   17325 
   17326    UChar SIMM_8 = extend_s_5to8(UIMM_5);
   17327 
   17328    IRTemp vA = newTemp(Ity_V128);
   17329    IRTemp vB = newTemp(Ity_V128);
   17330    IRTemp vC = newTemp(Ity_V128);
   17331    assign( vA, getVReg(vA_addr));
   17332    assign( vB, getVReg(vB_addr));
   17333    assign( vC, getVReg(vC_addr));
   17334 
   17335    if (opc1 != 0x4) {
   17336       vex_printf("dis_av_permute(ppc)(instr)\n");
   17337       return False;
   17338    }
   17339 
   17340    switch (opc2) {
   17341    case 0x2A: // vsel (Conditional Select, AV p238)
   17342       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
   17343       /* vD = (vA & ~vC) | (vB & vC) */
   17344       putVReg( vD_addr, binop(Iop_OrV128,
   17345          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
   17346          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
   17347       return True;
   17348 
   17349    case 0x2B: { // vperm (Permute, AV p218)
   17350       /* limited to two args for IR, so have to play games... */
   17351       IRTemp a_perm  = newTemp(Ity_V128);
   17352       IRTemp b_perm  = newTemp(Ity_V128);
   17353       IRTemp mask    = newTemp(Ity_V128);
   17354       IRTemp vC_andF = newTemp(Ity_V128);
   17355       DIP("vperm v%d,v%d,v%d,v%d\n",
   17356           vD_addr, vA_addr, vB_addr, vC_addr);
   17357       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
   17358          IR specifies, and also to hide irrelevant bits from
   17359          memcheck */
   17360       assign( vC_andF,
   17361               binop(Iop_AndV128, mkexpr(vC),
   17362                                  unop(Iop_Dup8x16, mkU8(0xF))) );
   17363       assign( a_perm,
   17364               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
   17365       assign( b_perm,
   17366               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
   17367       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
   17368       assign( mask, binop(Iop_SarN8x16,
   17369                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
   17370                           mkU8(7)) );
   17371       // dst = (a & ~mask) | (b & mask)
   17372       putVReg( vD_addr, binop(Iop_OrV128,
   17373                               binop(Iop_AndV128, mkexpr(a_perm),
   17374                                     unop(Iop_NotV128, mkexpr(mask))),
   17375                               binop(Iop_AndV128, mkexpr(b_perm),
   17376                                     mkexpr(mask))) );
   17377       return True;
   17378    }
   17379    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
   17380       if (b10 != 0) {
   17381          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
   17382          return False;
   17383       }
   17384       DIP("vsldoi v%d,v%d,v%d,%d\n",
   17385           vD_addr, vA_addr, vB_addr, SHB_uimm4);
   17386       if (SHB_uimm4 == 0)
   17387          putVReg( vD_addr, mkexpr(vA) );
   17388       else
   17389          putVReg( vD_addr,
   17390             binop(Iop_OrV128,
   17391                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
   17392                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
   17393       return True;
   17394    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
   17395       IRTemp a_perm  = newTemp(Ity_V128);
   17396       IRTemp b_perm  = newTemp(Ity_V128);
   17397       IRTemp vrc_a   = newTemp(Ity_V128);
   17398       IRTemp vrc_b   = newTemp(Ity_V128);
   17399 
   17400       /* IBM index  is 0:7, Change index value to index 7:0 */
   17401       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
   17402                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
   17403       assign( vrc_a, binop( Iop_ShrV128,
   17404                             binop( Iop_AndV128, mkexpr( vC ),
   17405                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
   17406                             mkU8 ( 4 ) ) );
   17407       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
   17408       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
   17409       putVReg( vD_addr, binop( Iop_XorV128,
   17410                                mkexpr( a_perm ), mkexpr( b_perm) ) );
   17411       return True;
   17412    }
   17413    default:
   17414      break; // Fall through...
   17415    }
   17416 
   17417    opc2 = IFIELD( theInstr, 0, 11 );
   17418    switch (opc2) {
   17419 
   17420    /* Merge */
   17421    case 0x00C: // vmrghb (Merge High B, AV p195)
   17422       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17423       putVReg( vD_addr,
   17424                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
   17425       break;
   17426 
   17427    case 0x04C: // vmrghh (Merge High HW, AV p196)
   17428       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17429       putVReg( vD_addr,
   17430                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
   17431       break;
   17432 
   17433    case 0x08C: // vmrghw (Merge High W, AV p197)
   17434       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17435       putVReg( vD_addr,
   17436                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
   17437       break;
   17438 
   17439    case 0x10C: // vmrglb (Merge Low B, AV p198)
   17440       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17441       putVReg( vD_addr,
   17442                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
   17443       break;
   17444 
   17445    case 0x14C: // vmrglh (Merge Low HW, AV p199)
   17446       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17447       putVReg( vD_addr,
   17448                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
   17449       break;
   17450 
   17451    case 0x18C: // vmrglw (Merge Low W, AV p200)
   17452       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17453       putVReg( vD_addr,
   17454                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
   17455       break;
   17456 
   17457 
   17458    /* Splat */
   17459    case 0x20C: { // vspltb (Splat Byte, AV p245)
   17460       /* vD = Dup8x16( vB[UIMM_5] ) */
   17461       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
   17462       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17463       putVReg( vD_addr, unop(Iop_Dup8x16,
   17464            unop(Iop_32to8, unop(Iop_V128to32,
   17465                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   17466       break;
   17467    }
   17468    case 0x24C: { // vsplth (Splat Half Word, AV p246)
   17469       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
   17470       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17471       putVReg( vD_addr, unop(Iop_Dup16x8,
   17472            unop(Iop_32to16, unop(Iop_V128to32,
   17473                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
   17474       break;
   17475    }
   17476    case 0x28C: { // vspltw (Splat Word, AV p250)
   17477       /* vD = Dup32x4( vB[UIMM_5] ) */
   17478       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
   17479       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   17480       putVReg( vD_addr, unop(Iop_Dup32x4,
   17481          unop(Iop_V128to32,
   17482               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
   17483       break;
   17484    }
   17485    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
   17486       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
   17487       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
   17488       break;
   17489 
   17490    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
   17491       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
   17492       putVReg( vD_addr,
   17493                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
   17494       break;
   17495 
   17496    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
   17497       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
   17498       putVReg( vD_addr,
   17499                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
   17500       break;
   17501 
   17502    case 0x68C: // vmrgow (Merge Odd Word)
   17503      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17504       /*   VD[0] <- VA[1]
   17505            VD[1] <- VB[1]
   17506            VD[2] <- VA[3]
   17507            VD[3] <- VB[3]
   17508       */
   17509       putVReg( vD_addr,
   17510                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   17511       break;
   17512 
   17513    case 0x78C: // vmrgew (Merge Even Word)
   17514       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17515       /*   VD[0] <- VA[0]
   17516            VD[1] <- VB[0]
   17517            VD[2] <- VA[2]
   17518            VD[3] <- VB[2]
   17519       */
   17520       putVReg( vD_addr,
   17521                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
   17522       break;
   17523 
   17524    default:
   17525       vex_printf("dis_av_permute(ppc)(opc2)\n");
   17526       return False;
   17527    }
   17528    return True;
   17529 }
   17530 
   17531 /*
   17532   AltiVec Pack/Unpack Instructions
   17533 */
   17534 static Bool dis_av_pack ( UInt theInstr )
   17535 {
   17536    /* VX-Form */
   17537    UChar opc1     = ifieldOPC(theInstr);
   17538    UChar vD_addr  = ifieldRegDS(theInstr);
   17539    UChar vA_addr  = ifieldRegA(theInstr);
   17540    UChar vB_addr  = ifieldRegB(theInstr);
   17541    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17542 
   17543    IRTemp signs = IRTemp_INVALID;
   17544    IRTemp zeros = IRTemp_INVALID;
   17545    IRTemp vA    = newTemp(Ity_V128);
   17546    IRTemp vB    = newTemp(Ity_V128);
   17547    assign( vA, getVReg(vA_addr));
   17548    assign( vB, getVReg(vB_addr));
   17549 
   17550    if (opc1 != 0x4) {
   17551       vex_printf("dis_av_pack(ppc)(instr)\n");
   17552       return False;
   17553    }
   17554    switch (opc2) {
   17555    /* Packing */
   17556    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
   17557       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17558       putVReg( vD_addr,
   17559                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
   17560       return True;
   17561 
   17562    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
   17563       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17564       putVReg( vD_addr,
   17565                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
   17566       return True;
   17567 
   17568    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
   17569       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17570       putVReg( vD_addr,
   17571                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
   17572       // TODO: set VSCR[SAT]
   17573       return True;
   17574 
   17575    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
   17576       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17577       putVReg( vD_addr,
   17578                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
   17579       // TODO: set VSCR[SAT]
   17580       return True;
   17581 
   17582    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
   17583       // This insn does a signed->unsigned saturating conversion.
   17584       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17585       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
   17586       IRTemp vA_tmp = newTemp(Ity_V128);
   17587       IRTemp vB_tmp = newTemp(Ity_V128);
   17588       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17589       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17590                             unop(Iop_NotV128,
   17591                                  binop(Iop_SarN16x8,
   17592                                        mkexpr(vA), mkU8(15)))) );
   17593       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17594                             unop(Iop_NotV128,
   17595                                  binop(Iop_SarN16x8,
   17596                                        mkexpr(vB), mkU8(15)))) );
   17597       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
   17598                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17599       // TODO: set VSCR[SAT]
   17600       return True;
   17601    }
   17602    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
   17603       // This insn does a signed->unsigned saturating conversion.
   17604       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17605       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17606       IRTemp vA_tmp = newTemp(Ity_V128);
   17607       IRTemp vB_tmp = newTemp(Ity_V128);
   17608       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17609       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17610                             unop(Iop_NotV128,
   17611                                  binop(Iop_SarN32x4,
   17612                                        mkexpr(vA), mkU8(31)))) );
   17613       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17614                             unop(Iop_NotV128,
   17615                                  binop(Iop_SarN32x4,
   17616                                        mkexpr(vB), mkU8(31)))) );
   17617       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
   17618                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17619       // TODO: set VSCR[SAT]
   17620       return True;
   17621    }
   17622    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
   17623       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17624       putVReg( vD_addr,
   17625                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
   17626       // TODO: set VSCR[SAT]
   17627       return True;
   17628 
   17629    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
   17630       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17631       putVReg( vD_addr,
   17632                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
   17633       // TODO: set VSCR[SAT]
   17634       return True;
   17635 
   17636    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
   17637       /* CAB: Worth a new primop? */
   17638       /* Using shifts to compact pixel elements, then packing them */
   17639       IRTemp a1 = newTemp(Ity_V128);
   17640       IRTemp a2 = newTemp(Ity_V128);
   17641       IRTemp a3 = newTemp(Ity_V128);
   17642       IRTemp a_tmp = newTemp(Ity_V128);
   17643       IRTemp b1 = newTemp(Ity_V128);
   17644       IRTemp b2 = newTemp(Ity_V128);
   17645       IRTemp b3 = newTemp(Ity_V128);
   17646       IRTemp b_tmp = newTemp(Ity_V128);
   17647       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17648       assign( a1, binop(Iop_ShlN16x8,
   17649                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
   17650                         mkU8(10)) );
   17651       assign( a2, binop(Iop_ShlN16x8,
   17652                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
   17653                         mkU8(5)) );
   17654       assign( a3,  binop(Iop_ShrN16x8,
   17655                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
   17656                          mkU8(11)) );
   17657       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
   17658                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
   17659 
   17660       assign( b1, binop(Iop_ShlN16x8,
   17661                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
   17662                         mkU8(10)) );
   17663       assign( b2, binop(Iop_ShlN16x8,
   17664                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
   17665                         mkU8(5)) );
   17666       assign( b3,  binop(Iop_ShrN16x8,
   17667                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
   17668                          mkU8(11)) );
   17669       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
   17670                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
   17671 
   17672       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
   17673                               mkexpr(a_tmp), mkexpr(b_tmp)) );
   17674       return True;
   17675    }
   17676 
   17677    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
   17678       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17679       putVReg( vD_addr,
   17680                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
   17681       return True;
   17682 
   17683    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
   17684       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17685       putVReg( vD_addr,
   17686                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
   17687       // TODO: set VSCR[SAT]
   17688       return True;
   17689 
   17690    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
   17691       // This insn does a doubled signed->double unsigned saturating conversion
   17692       // Conversion done here, then uses unsigned->unsigned vpk insn:
   17693       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
   17694       // This is similar to the technique used for vpkswus, except done
   17695       // with double word integers versus word integers.
   17696       IRTemp vA_tmp = newTemp(Ity_V128);
   17697       IRTemp vB_tmp = newTemp(Ity_V128);
   17698       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17699       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
   17700                             unop(Iop_NotV128,
   17701                                  binop(Iop_SarN64x2,
   17702                                        mkexpr(vA), mkU8(63)))) );
   17703       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
   17704                             unop(Iop_NotV128,
   17705                                  binop(Iop_SarN64x2,
   17706                                        mkexpr(vB), mkU8(63)))) );
   17707       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
   17708                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
   17709       // TODO: set VSCR[SAT]
   17710       return True;
   17711    }
   17712 
   17713    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
   17714       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17715       putVReg( vD_addr,
   17716                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
   17717       // TODO: set VSCR[SAT]
   17718       return True;
   17719    default:
   17720       break; // Fall through...
   17721    }
   17722 
   17723 
   17724    if (vA_addr != 0) {
   17725       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
   17726       return False;
   17727    }
   17728 
   17729    signs = newTemp(Ity_V128);
   17730    zeros = newTemp(Ity_V128);
   17731    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
   17732 
   17733    switch (opc2) {
   17734    /* Unpacking */
   17735    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
   17736       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
   17737       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17738       putVReg( vD_addr,
   17739                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
   17740       break;
   17741    }
   17742    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
   17743       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
   17744       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17745       putVReg( vD_addr,
   17746                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
   17747       break;
   17748    }
   17749    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
   17750       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
   17751       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
   17752       putVReg( vD_addr,
   17753                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
   17754       break;
   17755    }
   17756    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
   17757       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
   17758       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
   17759       putVReg( vD_addr,
   17760                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
   17761       break;
   17762    }
   17763    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
   17764       /* CAB: Worth a new primop? */
   17765       /* Using shifts to isolate pixel elements, then expanding them */
   17766       IRTemp z0  = newTemp(Ity_V128);
   17767       IRTemp z1  = newTemp(Ity_V128);
   17768       IRTemp z01 = newTemp(Ity_V128);
   17769       IRTemp z2  = newTemp(Ity_V128);
   17770       IRTemp z3  = newTemp(Ity_V128);
   17771       IRTemp z23 = newTemp(Ity_V128);
   17772       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
   17773       assign( z0,  binop(Iop_ShlN16x8,
   17774                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17775                          mkU8(8)) );
   17776       assign( z1,  binop(Iop_ShrN16x8,
   17777                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17778                          mkU8(11)) );
   17779       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17780                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17781       assign( z2,  binop(Iop_ShrN16x8,
   17782                          binop(Iop_ShlN16x8,
   17783                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17784                                mkU8(11)),
   17785                          mkU8(3)) );
   17786       assign( z3,  binop(Iop_ShrN16x8,
   17787                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17788                          mkU8(11)) );
   17789       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
   17790                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17791       putVReg( vD_addr,
   17792                binop(Iop_OrV128,
   17793                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17794                      mkexpr(z23)) );
   17795       break;
   17796    }
   17797    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
   17798       /* identical to vupkhpx, except interleaving LO */
   17799       IRTemp z0  = newTemp(Ity_V128);
   17800       IRTemp z1  = newTemp(Ity_V128);
   17801       IRTemp z01 = newTemp(Ity_V128);
   17802       IRTemp z2  = newTemp(Ity_V128);
   17803       IRTemp z3  = newTemp(Ity_V128);
   17804       IRTemp z23 = newTemp(Ity_V128);
   17805       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
   17806       assign( z0,  binop(Iop_ShlN16x8,
   17807                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
   17808                          mkU8(8)) );
   17809       assign( z1,  binop(Iop_ShrN16x8,
   17810                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
   17811                          mkU8(11)) );
   17812       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17813                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
   17814       assign( z2,  binop(Iop_ShrN16x8,
   17815                          binop(Iop_ShlN16x8,
   17816                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
   17817                                mkU8(11)),
   17818                          mkU8(3)) );
   17819       assign( z3,  binop(Iop_ShrN16x8,
   17820                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
   17821                          mkU8(11)) );
   17822       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
   17823                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
   17824       putVReg( vD_addr,
   17825                binop(Iop_OrV128,
   17826                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
   17827                      mkexpr(z23)) );
   17828       break;
   17829    }
   17830    case 0x64E: { // vupkhsw (Unpack High Signed Word)
   17831       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
   17832       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17833       putVReg( vD_addr,
   17834                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
   17835       break;
   17836    }
   17837    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
   17838       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
   17839       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
   17840       putVReg( vD_addr,
   17841                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
   17842       break;
   17843    }
   17844    default:
   17845       vex_printf("dis_av_pack(ppc)(opc2)\n");
   17846       return False;
   17847    }
   17848    return True;
   17849 }
   17850 
   17851 /*
   17852   AltiVec Cipher Instructions
   17853 */
   17854 static Bool dis_av_cipher ( UInt theInstr )
   17855 {
   17856    /* VX-Form */
   17857    UChar opc1     = ifieldOPC(theInstr);
   17858    UChar vD_addr  = ifieldRegDS(theInstr);
   17859    UChar vA_addr  = ifieldRegA(theInstr);
   17860    UChar vB_addr  = ifieldRegB(theInstr);
   17861    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17862 
   17863    IRTemp vA    = newTemp(Ity_V128);
   17864    IRTemp vB    = newTemp(Ity_V128);
   17865    assign( vA, getVReg(vA_addr));
   17866    assign( vB, getVReg(vB_addr));
   17867 
   17868    if (opc1 != 0x4) {
   17869       vex_printf("dis_av_cipher(ppc)(instr)\n");
   17870       return False;
   17871    }
   17872    switch (opc2) {
   17873       case 0x508: // vcipher (Vector Inverser Cipher)
   17874          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17875          putVReg( vD_addr,
   17876                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
   17877          return True;
   17878 
   17879       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
   17880          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17881          putVReg( vD_addr,
   17882                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
   17883          return True;
   17884 
   17885       case 0x548: // vncipher (Vector Inverser Cipher)
   17886          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17887          putVReg( vD_addr,
   17888                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
   17889          return True;
   17890 
   17891       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
   17892          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   17893          putVReg( vD_addr,
   17894                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
   17895          return True;
   17896 
   17897       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
   17898        * subBytes transform)
   17899        */
   17900          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
   17901          putVReg( vD_addr,
   17902                   unop(Iop_CipherSV128, mkexpr(vA) ) );
   17903          return True;
   17904 
   17905       default:
   17906          vex_printf("dis_av_cipher(ppc)(opc2)\n");
   17907          return False;
   17908    }
   17909    return True;
   17910 }
   17911 
   17912 /*
   17913   AltiVec Secure Hash Instructions
   17914 */
   17915 static Bool dis_av_hash ( UInt theInstr )
   17916 {
   17917    /* VX-Form */
   17918    UChar opc1     = ifieldOPC(theInstr);
   17919    UChar vRT_addr = ifieldRegDS(theInstr);
   17920    UChar vRA_addr  = ifieldRegA(theInstr);
   17921    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
   17922    UChar st       = IFIELD( theInstr, 15, 1 );  // st
   17923    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
   17924    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   17925 
   17926    IRTemp vA    = newTemp(Ity_V128);
   17927    IRTemp dst    = newTemp(Ity_V128);
   17928    assign( vA, getVReg(vRA_addr));
   17929 
   17930    if (opc1 != 0x4) {
   17931       vex_printf("dis_av_hash(ppc)(instr)\n");
   17932       return False;
   17933    }
   17934 
   17935    switch (opc2) {
   17936       case 0x682:  // vshasigmaw
   17937          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17938          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
   17939          putVReg( vRT_addr, mkexpr(dst));
   17940          return True;
   17941 
   17942       case 0x6C2:  // vshasigmad,
   17943          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
   17944          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
   17945          return True;
   17946 
   17947       default:
   17948          vex_printf("dis_av_hash(ppc)(opc2)\n");
   17949          return False;
   17950    }
   17951    return True;
   17952 }
   17953 
   17954 /*
   17955  * This function is used by the Vector add/subtract [extended] modulo/carry
   17956  * instructions.
   17957  *   - For the non-extended add instructions, the cin arg is set to zero.
   17958  *   - For the extended add instructions, cin is the integer value of
   17959  *     src3.bit[127].
   17960  *   - For the non-extended subtract instructions, src1 is added to the one's
   17961  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
   17962  *     value for this operation.
   17963  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
   17964  */
   17965 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
   17966                                         IRExpr * cin, Bool modulo)
   17967 {
   17968    IRTemp _vecA_32   = IRTemp_INVALID;
   17969    IRTemp _vecB_32   = IRTemp_INVALID;
   17970    IRTemp res_32     = IRTemp_INVALID;
   17971    IRTemp result     = IRTemp_INVALID;
   17972    IRTemp tmp_result = IRTemp_INVALID;
   17973    IRTemp carry      = IRTemp_INVALID;
   17974    Int i;
   17975    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
   17976    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
   17977    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
   17978    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
   17979 
   17980    for (i = 0; i < 4; i++) {
   17981       _vecA_32 = newTemp(Ity_I32);
   17982       _vecB_32 = newTemp(Ity_I32);
   17983       res_32   = newTemp(Ity_I32);
   17984       switch (i) {
   17985       case 0:
   17986          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
   17987          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
   17988          break;
   17989       case 1:
   17990          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
   17991          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
   17992          break;
   17993       case 2:
   17994          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
   17995          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
   17996          break;
   17997       case 3:
   17998          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
   17999          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
   18000          break;
   18001       }
   18002 
   18003       assign(res_32, binop( Iop_Add32,
   18004                             binop( Iop_Add32,
   18005                                    binop ( Iop_Add32,
   18006                                            mkexpr(_vecA_32),
   18007                                            mkexpr(_vecB_32) ),
   18008                                    (i == 0) ? mkU32(0) : mkexpr(carry) ),
   18009                             (i == 0) ? cin : mkU32(0) ) );
   18010       if (modulo) {
   18011          result = newTemp(Ity_V128);
   18012          assign(result, binop( Iop_OrV128,
   18013                               (i == 0) ? binop( Iop_64HLtoV128,
   18014                                                 mkU64(0),
   18015                                                 mkU64(0) ) : mkexpr(tmp_result),
   18016                               binop( Iop_ShlV128,
   18017                                      binop( Iop_64HLtoV128,
   18018                                             mkU64(0),
   18019                                             binop( Iop_32HLto64,
   18020                                                    mkU32(0),
   18021                                                    mkexpr(res_32) ) ),
   18022                                      mkU8(i * 32) ) ) );
   18023          tmp_result = newTemp(Ity_V128);
   18024          assign(tmp_result, mkexpr(result));
   18025       }
   18026       carry = newTemp(Ity_I32);
   18027       assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
   18028                                             mkexpr(res_32),
   18029                                             mkexpr(_vecA_32 ) ) ) );
   18030    }
   18031    if (modulo)
   18032       return result;
   18033    else
   18034       return carry;
   18035 }
   18036 
   18037 
   18038 static Bool dis_av_quad ( UInt theInstr )
   18039 {
   18040    /* VX-Form */
   18041    UChar opc1     = ifieldOPC(theInstr);
   18042    UChar vRT_addr = ifieldRegDS(theInstr);
   18043    UChar vRA_addr = ifieldRegA(theInstr);
   18044    UChar vRB_addr = ifieldRegB(theInstr);
   18045    UChar vRC_addr;
   18046    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   18047 
   18048    IRTemp vA    = newTemp(Ity_V128);
   18049    IRTemp vB    = newTemp(Ity_V128);
   18050    IRTemp vC    = IRTemp_INVALID;
   18051    IRTemp cin    = IRTemp_INVALID;
   18052    assign( vA, getVReg(vRA_addr));
   18053    assign( vB, getVReg(vRB_addr));
   18054 
   18055    if (opc1 != 0x4) {
   18056       vex_printf("dis_av_quad(ppc)(instr)\n");
   18057       return False;
   18058    }
   18059 
   18060    switch (opc2) {
   18061    case 0x140:  // vaddcuq
   18062      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   18063      putVReg( vRT_addr, unop( Iop_32UtoV128,
   18064                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18065                                                                mkexpr(vB),
   18066                                                                mkU32(0), False) ) ) );
   18067      return True;
   18068    case 0x100: // vadduqm
   18069       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   18070       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18071                                                           mkexpr(vB), mkU32(0), True) ) );
   18072       return True;
   18073    case 0x540: // vsubcuq
   18074       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   18075       putVReg( vRT_addr,
   18076                unop( Iop_32UtoV128,
   18077                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18078                                                       unop( Iop_NotV128,
   18079                                                             mkexpr(vB) ),
   18080                                                       mkU32(1), False) ) ) );
   18081       return True;
   18082    case 0x500: // vsubuqm
   18083       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   18084       putVReg( vRT_addr,
   18085                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18086                                                 unop( Iop_NotV128, mkexpr(vB) ),
   18087                                                 mkU32(1), True) ) );
   18088       return True;
   18089    case 0x054C: // vbpermq
   18090    {
   18091 #define BPERMD_IDX_MASK 0x00000000000000FFULL
   18092 #define BPERMD_BIT_MASK 0x8000000000000000ULL
   18093       int i;
   18094       IRExpr * vB_expr = mkexpr(vB);
   18095       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
   18096       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
   18097       for (i = 0; i < 16; i++) {
   18098          IRTemp idx_tmp = newTemp( Ity_V128 );
   18099          IRTemp perm_bit = newTemp( Ity_V128 );
   18100          IRTemp idx = newTemp( Ity_I8 );
   18101          IRTemp idx_LT127 = newTemp( Ity_I1 );
   18102          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
   18103 
   18104          assign( idx_tmp,
   18105                  binop( Iop_AndV128,
   18106                         binop( Iop_64HLtoV128,
   18107                                mkU64(0),
   18108                                mkU64(BPERMD_IDX_MASK) ),
   18109                         vB_expr ) );
   18110          assign( idx_LT127,
   18111                  binop( Iop_CmpEQ32,
   18112                         unop ( Iop_64to32,
   18113                                unop( Iop_V128to64, binop( Iop_ShrV128,
   18114                                                           mkexpr(idx_tmp),
   18115                                                           mkU8(7) ) ) ),
   18116                         mkU32(0) ) );
   18117 
   18118          /* Below, we set idx to determine which bit of vA to use for the
   18119           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
   18120           */
   18121          assign( idx,
   18122                  binop( Iop_And8,
   18123                         unop( Iop_1Sto8,
   18124                               mkexpr(idx_LT127) ),
   18125                         unop( Iop_32to8,
   18126                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
   18127 
   18128          assign( idx_LT127_ity128,
   18129                  binop( Iop_64HLtoV128,
   18130                         mkU64(0),
   18131                         unop( Iop_32Uto64,
   18132                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
   18133          assign( perm_bit,
   18134                  binop( Iop_AndV128,
   18135                         mkexpr( idx_LT127_ity128 ),
   18136                         binop( Iop_ShrV128,
   18137                                binop( Iop_AndV128,
   18138                                       binop (Iop_64HLtoV128,
   18139                                              mkU64( BPERMD_BIT_MASK ),
   18140                                              mkU64(0)),
   18141                                       binop( Iop_ShlV128,
   18142                                              mkexpr( vA ),
   18143                                              mkexpr( idx ) ) ),
   18144                                mkU8( 127 ) ) ) );
   18145          res = binop( Iop_OrV128,
   18146                       res,
   18147                       binop( Iop_ShlV128,
   18148                              mkexpr( perm_bit ),
   18149                              mkU8( i + 64 ) ) );
   18150          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
   18151       }
   18152       putVReg( vRT_addr, res);
   18153       return True;
   18154 #undef BPERMD_IDX_MASK
   18155 #undef BPERMD_BIT_MASK
   18156    }
   18157 
   18158    default:
   18159       break;  // fall through
   18160    }
   18161 
   18162    opc2     = IFIELD( theInstr, 0, 6 );
   18163    vRC_addr = ifieldRegC(theInstr);
   18164    vC = newTemp(Ity_V128);
   18165    cin = newTemp(Ity_I32);
   18166    switch (opc2) {
   18167       case 0x3D: // vaddecuq
   18168          assign( vC, getVReg(vRC_addr));
   18169          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18170              vRC_addr);
   18171          assign(cin, binop( Iop_And32,
   18172                             unop( Iop_64to32,
   18173                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18174                             mkU32(1) ) );
   18175          putVReg( vRT_addr,
   18176                   unop( Iop_32UtoV128,
   18177                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   18178                                                          mkexpr(cin),
   18179                                                          False) ) ) );
   18180          return True;
   18181       case 0x3C: // vaddeuqm
   18182          assign( vC, getVReg(vRC_addr));
   18183          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18184              vRC_addr);
   18185          assign(cin, binop( Iop_And32,
   18186                             unop( Iop_64to32,
   18187                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18188                             mkU32(1) ) );
   18189          putVReg( vRT_addr,
   18190                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
   18191                                                    mkexpr(cin),
   18192                                                    True) ) );
   18193          return True;
   18194       case 0x3F: // vsubecuq
   18195          assign( vC, getVReg(vRC_addr));
   18196          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18197              vRC_addr);
   18198          assign(cin, binop( Iop_And32,
   18199                             unop( Iop_64to32,
   18200                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18201                             mkU32(1) ) );
   18202          putVReg( vRT_addr,
   18203                   unop( Iop_32UtoV128,
   18204                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18205                                                          unop( Iop_NotV128,
   18206                                                                mkexpr(vB) ),
   18207                                                          mkexpr(cin),
   18208                                                          False) ) ) );
   18209          return True;
   18210       case 0x3E: // vsubeuqm
   18211          assign( vC, getVReg(vRC_addr));
   18212          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
   18213              vRC_addr);
   18214          assign(cin, binop( Iop_And32,
   18215                             unop( Iop_64to32,
   18216                                   unop( Iop_V128to64, mkexpr(vC) ) ),
   18217                             mkU32(1) ) );
   18218          putVReg( vRT_addr,
   18219                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
   18220                                                    unop( Iop_NotV128, mkexpr(vB) ),
   18221                                                    mkexpr(cin),
   18222                                                    True) ) );
   18223          return True;
   18224       default:
   18225          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
   18226          return False;
   18227    }
   18228 
   18229    return True;
   18230 }
   18231 
   18232 
   18233 /*
   18234   AltiVec BCD Arithmetic instructions.
   18235   These instructions modify CR6 for various conditions in the result,
   18236   including when an overflow occurs.  We could easily detect all conditions
   18237   except when an overflow occurs.  But since we can't be 100% accurate
   18238   in our emulation of CR6, it seems best to just not support it all.
   18239 */
   18240 static Bool dis_av_bcd ( UInt theInstr )
   18241 {
   18242    /* VX-Form */
   18243    UChar opc1     = ifieldOPC(theInstr);
   18244    UChar vRT_addr = ifieldRegDS(theInstr);
   18245    UChar vRA_addr = ifieldRegA(theInstr);
   18246    UChar vRB_addr = ifieldRegB(theInstr);
   18247    UChar ps       = IFIELD( theInstr, 9, 1 );
   18248    UInt  opc2     = IFIELD( theInstr, 0, 9 );
   18249 
   18250    IRTemp vA    = newTemp(Ity_V128);
   18251    IRTemp vB    = newTemp(Ity_V128);
   18252    IRTemp dst    = newTemp(Ity_V128);
   18253    assign( vA, getVReg(vRA_addr));
   18254    assign( vB, getVReg(vRB_addr));
   18255 
   18256    if (opc1 != 0x4) {
   18257       vex_printf("dis_av_bcd(ppc)(instr)\n");
   18258       return False;
   18259    }
   18260 
   18261    switch (opc2) {
   18262    case 0x1:  // bcdadd
   18263      DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   18264      assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
   18265                          mkexpr( vB ), mkU8( ps ) ) );
   18266      putVReg( vRT_addr, mkexpr(dst));
   18267      return True;
   18268 
   18269    case 0x41:  // bcdsub
   18270      DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
   18271      assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
   18272                          mkexpr( vB ), mkU8( ps ) ) );
   18273      putVReg( vRT_addr, mkexpr(dst));
   18274      return True;
   18275 
   18276    default:
   18277       vex_printf("dis_av_bcd(ppc)(opc2)\n");
   18278       return False;
   18279    }
   18280    return True;
   18281 }
   18282 
   18283 /*
   18284   AltiVec Floating Point Arithmetic Instructions
   18285 */
   18286 static Bool dis_av_fp_arith ( UInt theInstr )
   18287 {
   18288    /* VA-Form */
   18289    UChar opc1     = ifieldOPC(theInstr);
   18290    UChar vD_addr  = ifieldRegDS(theInstr);
   18291    UChar vA_addr  = ifieldRegA(theInstr);
   18292    UChar vB_addr  = ifieldRegB(theInstr);
   18293    UChar vC_addr  = ifieldRegC(theInstr);
   18294    UInt  opc2=0;
   18295 
   18296    IRTemp vA = newTemp(Ity_V128);
   18297    IRTemp vB = newTemp(Ity_V128);
   18298    IRTemp vC = newTemp(Ity_V128);
   18299    assign( vA, getVReg(vA_addr));
   18300    assign( vB, getVReg(vB_addr));
   18301    assign( vC, getVReg(vC_addr));
   18302 
   18303    if (opc1 != 0x4) {
   18304       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
   18305       return False;
   18306    }
   18307 
   18308    IRTemp rm = newTemp(Ity_I32);
   18309    assign(rm, get_IR_roundingmode());
   18310 
   18311    opc2 = IFIELD( theInstr, 0, 6 );
   18312    switch (opc2) {
   18313    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
   18314       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
   18315           vD_addr, vA_addr, vC_addr, vB_addr);
   18316       putVReg( vD_addr,
   18317                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
   18318                      mkexpr(vB),
   18319                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18320                            mkexpr(vA), mkexpr(vC))) );
   18321       return True;
   18322 
   18323    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
   18324       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
   18325           vD_addr, vA_addr, vC_addr, vB_addr);
   18326       putVReg( vD_addr,
   18327                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   18328                      mkexpr(vB),
   18329                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18330                            mkexpr(vA), mkexpr(vC))) );
   18331       return True;
   18332    }
   18333 
   18334    default:
   18335      break; // Fall through...
   18336    }
   18337 
   18338    opc2 = IFIELD( theInstr, 0, 11 );
   18339    switch (opc2) {
   18340    case 0x00A: // vaddfp (Add FP, AV p137)
   18341       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18342       putVReg( vD_addr, triop(Iop_Add32Fx4,
   18343                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   18344       return True;
   18345 
   18346   case 0x04A: // vsubfp (Subtract FP, AV p261)
   18347       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18348       putVReg( vD_addr, triop(Iop_Sub32Fx4,
   18349                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
   18350       return True;
   18351 
   18352    case 0x40A: // vmaxfp (Maximum FP, AV p178)
   18353       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18354       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
   18355       return True;
   18356 
   18357    case 0x44A: // vminfp (Minimum FP, AV p187)
   18358       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
   18359       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
   18360       return True;
   18361 
   18362    default:
   18363       break; // Fall through...
   18364    }
   18365 
   18366 
   18367    if (vA_addr != 0) {
   18368       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
   18369       return False;
   18370    }
   18371 
   18372    switch (opc2) {
   18373    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
   18374       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
   18375       putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
   18376       return True;
   18377 
   18378    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
   18379       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
   18380       putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
   18381       return True;
   18382 
   18383    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
   18384       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
   18385       DIP(" => not implemented\n");
   18386       return False;
   18387 
   18388    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
   18389       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
   18390       DIP(" => not implemented\n");
   18391       return False;
   18392 
   18393    default:
   18394       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
   18395       return False;
   18396    }
   18397    return True;
   18398 }
   18399 
   18400 /*
   18401   AltiVec Floating Point Compare Instructions
   18402 */
   18403 static Bool dis_av_fp_cmp ( UInt theInstr )
   18404 {
   18405    /* VXR-Form */
   18406    UChar opc1     = ifieldOPC(theInstr);
   18407    UChar vD_addr  = ifieldRegDS(theInstr);
   18408    UChar vA_addr  = ifieldRegA(theInstr);
   18409    UChar vB_addr  = ifieldRegB(theInstr);
   18410    UChar flag_rC  = ifieldBIT10(theInstr);
   18411    UInt  opc2     = IFIELD( theInstr, 0, 10 );
   18412 
   18413    Bool cmp_bounds = False;
   18414 
   18415    IRTemp vA = newTemp(Ity_V128);
   18416    IRTemp vB = newTemp(Ity_V128);
   18417    IRTemp vD = newTemp(Ity_V128);
   18418    assign( vA, getVReg(vA_addr));
   18419    assign( vB, getVReg(vB_addr));
   18420 
   18421    if (opc1 != 0x4) {
   18422       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
   18423       return False;
   18424    }
   18425 
   18426    switch (opc2) {
   18427    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
   18428       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18429                                       vD_addr, vA_addr, vB_addr);
   18430       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
   18431       break;
   18432 
   18433    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
   18434       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18435                                       vD_addr, vA_addr, vB_addr);
   18436       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
   18437       break;
   18438 
   18439    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
   18440       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18441                                       vD_addr, vA_addr, vB_addr);
   18442       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
   18443       break;
   18444 
   18445    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
   18446       IRTemp gt      = newTemp(Ity_V128);
   18447       IRTemp lt      = newTemp(Ity_V128);
   18448       IRTemp zeros   = newTemp(Ity_V128);
   18449       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
   18450                                      vD_addr, vA_addr, vB_addr);
   18451       cmp_bounds = True;
   18452       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
   18453 
   18454       /* Note: making use of fact that the ppc backend for compare insns
   18455          return zero'd lanes if either of the corresponding arg lanes is
   18456          a nan.
   18457 
   18458          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
   18459          need this for the other compares too (vcmpeqfp etc)...
   18460          Better still, tighten down the spec for compare irops.
   18461        */
   18462       assign( gt, unop(Iop_NotV128,
   18463                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
   18464       assign( lt, unop(Iop_NotV128,
   18465                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
   18466                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
   18467                                    mkexpr(zeros),
   18468                                    mkexpr(vB)))) );
   18469 
   18470       // finally, just shift gt,lt to correct position
   18471       assign( vD, binop(Iop_ShlN32x4,
   18472                         binop(Iop_OrV128,
   18473                               binop(Iop_AndV128, mkexpr(gt),
   18474                                     unop(Iop_Dup32x4, mkU32(0x2))),
   18475                               binop(Iop_AndV128, mkexpr(lt),
   18476                                     unop(Iop_Dup32x4, mkU32(0x1)))),
   18477                         mkU8(30)) );
   18478       break;
   18479    }
   18480 
   18481    default:
   18482       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
   18483       return False;
   18484    }
   18485 
   18486    putVReg( vD_addr, mkexpr(vD) );
   18487 
   18488    if (flag_rC) {
   18489       set_AV_CR6( mkexpr(vD), !cmp_bounds );
   18490    }
   18491    return True;
   18492 }
   18493 
   18494 /*
   18495   AltiVec Floating Point Convert/Round Instructions
   18496 */
   18497 static Bool dis_av_fp_convert ( UInt theInstr )
   18498 {
   18499    /* VX-Form */
   18500    UChar opc1     = ifieldOPC(theInstr);
   18501    UChar vD_addr  = ifieldRegDS(theInstr);
   18502    UChar UIMM_5   = ifieldRegA(theInstr);
   18503    UChar vB_addr  = ifieldRegB(theInstr);
   18504    UInt  opc2     = IFIELD( theInstr, 0, 11 );
   18505 
   18506    IRTemp vB        = newTemp(Ity_V128);
   18507    IRTemp vScale    = newTemp(Ity_V128);
   18508    IRTemp vInvScale = newTemp(Ity_V128);
   18509 
   18510    float scale, inv_scale;
   18511 
   18512    assign( vB, getVReg(vB_addr));
   18513 
   18514    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
   18515    scale = (float)( (unsigned int) 1<<UIMM_5 );
   18516    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
   18517    inv_scale = 1/scale;
   18518    assign( vInvScale,
   18519            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
   18520 
   18521    if (opc1 != 0x4) {
   18522       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
   18523       return False;
   18524    }
   18525 
   18526    switch (opc2) {
   18527    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
   18528       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18529       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18530                               unop(Iop_I32UtoFx4, mkexpr(vB)),
   18531                               mkexpr(vInvScale)) );
   18532       return True;
   18533 
   18534    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
   18535       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18536 
   18537       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18538                               unop(Iop_I32StoFx4, mkexpr(vB)),
   18539                               mkexpr(vInvScale)) );
   18540       return True;
   18541 
   18542    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
   18543       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18544       putVReg( vD_addr,
   18545                unop(Iop_QFtoI32Ux4_RZ,
   18546                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18547                           mkexpr(vB), mkexpr(vScale))) );
   18548       return True;
   18549 
   18550    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
   18551       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
   18552       putVReg( vD_addr,
   18553                unop(Iop_QFtoI32Sx4_RZ,
   18554                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
   18555                            mkexpr(vB), mkexpr(vScale))) );
   18556       return True;
   18557 
   18558    default:
   18559      break;    // Fall through...
   18560    }
   18561 
   18562    if (UIMM_5 != 0) {
   18563       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
   18564       return False;
   18565    }
   18566 
   18567    switch (opc2) {
   18568    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
   18569       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
   18570       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
   18571       break;
   18572 
   18573    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
   18574       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
   18575       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
   18576       break;
   18577 
   18578    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
   18579       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
   18580       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
   18581       break;
   18582 
   18583    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
   18584       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
   18585       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
   18586       break;
   18587 
   18588    default:
   18589       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
   18590       return False;
   18591    }
   18592    return True;
   18593 }
   18594 
   18595 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
   18596                                        const VexAbiInfo* vbi,
   18597                                        /*OUT*/DisResult* dres,
   18598                                        Bool (*resteerOkFn)(void*,Addr),
   18599                                        void* callback_opaque )
   18600 {
   18601    UInt   opc2      = IFIELD( theInstr, 1, 10 );
   18602 
   18603    switch (opc2) {
   18604    case 0x28E: {        //tbegin.
   18605       /* The current implementation is to just fail the tbegin and execute
   18606        * the failure path.  The failure path is assumed to be functionaly
   18607        * equivalent to the transactional path with the needed data locking
   18608        * to ensure correctness.  The tend is just a noop and shouldn't
   18609        * actually get executed.
   18610        *   1) set cr0 to 0x2
   18611        *   2) Initialize TFHAR to CIA+4
   18612        *   3) Initialize TEXASR
   18613        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
   18614        *   5) Continue executing at the next instruction.
   18615        */
   18616       UInt R = IFIELD( theInstr, 21, 1 );
   18617 
   18618       ULong tm_reason;
   18619       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
   18620                                * or treclaim.
   18621                                */
   18622       UInt persistant = 1;    /* set persistant since we are always failing
   18623                                * the tbegin.
   18624                                */
   18625       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
   18626                                  as the reason for failing the trasaction */
   18627       UInt tm_exact   = 1;    /* have exact address for failure */
   18628 
   18629       DIP("tbegin. %u\n", R);
   18630 
   18631       /* Set the CR0 field to indicate the tbegin failed.  Then let
   18632        * the code do the branch to the failure path.
   18633        *
   18634        * 000 || 0  Transaction initiation successful,
   18635        *           unnested (Transaction state of
   18636        *           Non-transactional prior to tbegin.)
   18637        * 010 || 0  Transaction initiation successful, nested
   18638        *           (Transaction state of Transactional
   18639        *           prior to tbegin.)
   18640        * 001 || 0  Transaction initiation unsuccessful,
   18641        *           (Transaction state of Suspended prior
   18642        *           to tbegin.)
   18643        */
   18644       putCR321( 0, mkU8( 0x2 ) );
   18645 
   18646       tm_reason = generate_TMreason( failure_code, persistant,
   18647                                      nest_overflow, tm_exact );
   18648 
   18649       storeTMfailure( guest_CIA_curr_instr, tm_reason,
   18650                       guest_CIA_curr_instr+4 );
   18651 
   18652       return True;
   18653 
   18654       break;
   18655    }
   18656 
   18657    case 0x2AE: {        //tend.
   18658       /* The tend. is just a noop.  Do nothing */
   18659       UInt A = IFIELD( theInstr, 25, 1 );
   18660 
   18661       DIP("tend. %u\n", A);
   18662       break;
   18663    }
   18664 
   18665    case 0x2EE: {        //tsr.
   18666       /* The tsr. is just a noop.  Do nothing */
   18667       UInt L = IFIELD( theInstr, 21, 1 );
   18668 
   18669       DIP("tsr. %u\n", L);
   18670       break;
   18671    }
   18672 
   18673    case 0x2CE: {        //tcheck.
   18674       /* The tcheck. is just a noop.  Do nothing */
   18675       UInt BF = IFIELD( theInstr, 25, 1 );
   18676 
   18677       DIP("tcheck. %u\n", BF);
   18678       break;
   18679    }
   18680 
   18681    case 0x30E: {        //tbortwc.
   18682       /* The tabortwc. is just a noop.  Do nothing */
   18683       UInt TO = IFIELD( theInstr, 25, 1 );
   18684       UInt RA = IFIELD( theInstr, 16, 5 );
   18685       UInt RB = IFIELD( theInstr, 11, 5 );
   18686 
   18687       DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
   18688       break;
   18689    }
   18690 
   18691    case 0x32E: {        //tbortdc.
   18692       /* The tabortdc. is just a noop.  Do nothing */
   18693       UInt TO = IFIELD( theInstr, 25, 1 );
   18694       UInt RA = IFIELD( theInstr, 16, 5 );
   18695       UInt RB = IFIELD( theInstr, 11, 5 );
   18696 
   18697       DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
   18698       break;
   18699    }
   18700 
   18701    case 0x34E: {        //tbortwci.
   18702       /* The tabortwci. is just a noop.  Do nothing */
   18703       UInt TO = IFIELD( theInstr, 25, 1 );
   18704       UInt RA = IFIELD( theInstr, 16, 5 );
   18705       UInt SI = IFIELD( theInstr, 11, 5 );
   18706 
   18707       DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
   18708       break;
   18709    }
   18710 
   18711    case 0x36E: {        //tbortdci.
   18712       /* The tabortdci. is just a noop.  Do nothing */
   18713       UInt TO = IFIELD( theInstr, 25, 1 );
   18714       UInt RA = IFIELD( theInstr, 16, 5 );
   18715       UInt SI = IFIELD( theInstr, 11, 5 );
   18716 
   18717       DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
   18718       break;
   18719    }
   18720 
   18721    case 0x38E: {        //tbort.
   18722       /* The tabort. is just a noop.  Do nothing */
   18723       UInt RA = IFIELD( theInstr, 16, 5 );
   18724 
   18725       DIP("tabort. %u\n", RA);
   18726       break;
   18727    }
   18728 
   18729    case 0x3AE: {        //treclaim.
   18730       /* The treclaim. is just a noop.  Do nothing */
   18731       UInt RA = IFIELD( theInstr, 16, 5 );
   18732 
   18733       DIP("treclaim. %u\n", RA);
   18734       break;
   18735    }
   18736 
   18737    case 0x3EE: {        //trechkpt.
   18738       /* The trechkpt. is just a noop.  Do nothing */
   18739       DIP("trechkpt.\n");
   18740       break;
   18741    }
   18742 
   18743    default:
   18744       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
   18745       return False;
   18746    }
   18747 
   18748    return True;
   18749 }
   18750 
   18751 
   18752 /* The 0x3C primary opcode (VSX category) uses several different forms of
   18753  * extended opcodes:
   18754  *   o XX2-form:
   18755  *      - [10:2] (IBM notation [21:29])
   18756  *   o XX3-form variants:
   18757  *       - variant 1: [10:3] (IBM notation [21:28])
   18758  *       - variant 2: [9:3] (IBM notation [22:28])
   18759  *       - variant 3: [7:3] (IBM notation [24:28])
   18760  *   o XX-4 form:
   18761  *      - [10:6] (IBM notation [21:25])
   18762  *
   18763  * The XX2-form needs bit 0 masked from the standard extended opcode
   18764  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
   18765  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
   18766  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
   18767  * front end since their encoding does not begin at bit 21 like the standard
   18768  * format.
   18769  *
   18770  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
   18771  * secondary opcode for such VSX instructions.
   18772  *
   18773 */
   18774 
   18775 
   18776 struct vsx_insn {
   18777    UInt opcode;
   18778    const HChar * name;
   18779 };
   18780 
   18781 //  ATTENTION:  Keep this array sorted on the opcocde!!!
   18782 static struct vsx_insn vsx_all[] = {
   18783       { 0x0, "xsaddsp" },
   18784       { 0x4, "xsmaddasp" },
   18785       { 0x8, "xxsldwi" },
   18786       { 0x14, "xsrsqrtesp" },
   18787       { 0x16, "xssqrtsp" },
   18788       { 0x18, "xxsel" },
   18789       { 0x20, "xssubsp" },
   18790       { 0x24, "xsmaddmsp" },
   18791       { 0x28, "xxpermdi" },
   18792       { 0x34, "xsresp" },
   18793       { 0x40, "xsmulsp" },
   18794       { 0x44, "xsmsubasp" },
   18795       { 0x48, "xxmrghw" },
   18796       { 0x60, "xsdivsp" },
   18797       { 0x64, "xsmsubmsp" },
   18798       { 0x80, "xsadddp" },
   18799       { 0x84, "xsmaddadp" },
   18800       { 0x8c, "xscmpudp" },
   18801       { 0x90, "xscvdpuxws" },
   18802       { 0x92, "xsrdpi" },
   18803       { 0x94, "xsrsqrtedp" },
   18804       { 0x96, "xssqrtdp" },
   18805       { 0xa0, "xssubdp" },
   18806       { 0xa4, "xsmaddmdp" },
   18807       { 0xac, "xscmpodp" },
   18808       { 0xb0, "xscvdpsxws" },
   18809       { 0xb2, "xsrdpiz" },
   18810       { 0xb4, "xsredp" },
   18811       { 0xc0, "xsmuldp" },
   18812       { 0xc4, "xsmsubadp" },
   18813       { 0xc8, "xxmrglw" },
   18814       { 0xd2, "xsrdpip" },
   18815       { 0xd4, "xstsqrtdp" },
   18816       { 0xd6, "xsrdpic" },
   18817       { 0xe0, "xsdivdp" },
   18818       { 0xe4, "xsmsubmdp" },
   18819       { 0xf2, "xsrdpim" },
   18820       { 0xf4, "xstdivdp" },
   18821       { 0x100, "xvaddsp" },
   18822       { 0x104, "xvmaddasp" },
   18823       { 0x10c, "xvcmpeqsp" },
   18824       { 0x110, "xvcvspuxws" },
   18825       { 0x112, "xvrspi" },
   18826       { 0x114, "xvrsqrtesp" },
   18827       { 0x116, "xvsqrtsp" },
   18828       { 0x120, "xvsubsp" },
   18829       { 0x124, "xvmaddmsp" },
   18830       { 0x12c, "xvcmpgtsp" },
   18831       { 0x130, "xvcvspsxws" },
   18832       { 0x132, "xvrspiz" },
   18833       { 0x134, "xvresp" },
   18834       { 0x140, "xvmulsp" },
   18835       { 0x144, "xvmsubasp" },
   18836       { 0x148, "xxspltw" },
   18837       { 0x14c, "xvcmpgesp" },
   18838       { 0x150, "xvcvuxwsp" },
   18839       { 0x152, "xvrspip" },
   18840       { 0x154, "xvtsqrtsp" },
   18841       { 0x156, "xvrspic" },
   18842       { 0x160, "xvdivsp" },
   18843       { 0x164, "xvmsubmsp" },
   18844       { 0x170, "xvcvsxwsp" },
   18845       { 0x172, "xvrspim" },
   18846       { 0x174, "xvtdivsp" },
   18847       { 0x180, "xvadddp" },
   18848       { 0x184, "xvmaddadp" },
   18849       { 0x18c, "xvcmpeqdp" },
   18850       { 0x190, "xvcvdpuxws" },
   18851       { 0x192, "xvrdpi" },
   18852       { 0x194, "xvrsqrtedp" },
   18853       { 0x196, "xvsqrtdp" },
   18854       { 0x1a0, "xvsubdp" },
   18855       { 0x1a4, "xvmaddmdp" },
   18856       { 0x1ac, "xvcmpgtdp" },
   18857       { 0x1b0, "xvcvdpsxws" },
   18858       { 0x1b2, "xvrdpiz" },
   18859       { 0x1b4, "xvredp" },
   18860       { 0x1c0, "xvmuldp" },
   18861       { 0x1c4, "xvmsubadp" },
   18862       { 0x1cc, "xvcmpgedp" },
   18863       { 0x1d0, "xvcvuxwdp" },
   18864       { 0x1d2, "xvrdpip" },
   18865       { 0x1d4, "xvtsqrtdp" },
   18866       { 0x1d6, "xvrdpic" },
   18867       { 0x1e0, "xvdivdp" },
   18868       { 0x1e4, "xvmsubmdp" },
   18869       { 0x1f0, "xvcvsxwdp" },
   18870       { 0x1f2, "xvrdpim" },
   18871       { 0x1f4, "xvtdivdp" },
   18872       { 0x204, "xsnmaddasp" },
   18873       { 0x208, "xxland" },
   18874       { 0x212, "xscvdpsp" },
   18875       { 0x216, "xscvdpspn" },
   18876       { 0x224, "xsnmaddmsp" },
   18877       { 0x228, "xxlandc" },
   18878       { 0x232, "xxrsp" },
   18879       { 0x244, "xsnmsubasp" },
   18880       { 0x248, "xxlor" },
   18881       { 0x250, "xscvuxdsp" },
   18882       { 0x264, "xsnmsubmsp" },
   18883       { 0x268, "xxlxor" },
   18884       { 0x270, "xscvsxdsp" },
   18885       { 0x280, "xsmaxdp" },
   18886       { 0x284, "xsnmaddadp" },
   18887       { 0x288, "xxlnor" },
   18888       { 0x290, "xscvdpuxds" },
   18889       { 0x292, "xscvspdp" },
   18890       { 0x296, "xscvspdpn" },
   18891       { 0x2a0, "xsmindp" },
   18892       { 0x2a4, "xsnmaddmdp" },
   18893       { 0x2a8, "xxlorc" },
   18894       { 0x2b0, "xscvdpsxds" },
   18895       { 0x2b2, "xsabsdp" },
   18896       { 0x2c0, "xscpsgndp" },
   18897       { 0x2c4, "xsnmsubadp" },
   18898       { 0x2c8, "xxlnand" },
   18899       { 0x2d0, "xscvuxddp" },
   18900       { 0x2d2, "xsnabsdp" },
   18901       { 0x2e4, "xsnmsubmdp" },
   18902       { 0x2e8, "xxleqv" },
   18903       { 0x2f0, "xscvsxddp" },
   18904       { 0x2f2, "xsnegdp" },
   18905       { 0x300, "xvmaxsp" },
   18906       { 0x304, "xvnmaddasp" },
   18907       { 0x30c, "xvcmpeqsp." },
   18908       { 0x310, "xvcvspuxds" },
   18909       { 0x312, "xvcvdpsp" },
   18910       { 0x320, "xvminsp" },
   18911       { 0x324, "xvnmaddmsp" },
   18912       { 0x32c, "xvcmpgtsp." },
   18913       { 0x330, "xvcvspsxds" },
   18914       { 0x332, "xvabssp" },
   18915       { 0x340, "xvcpsgnsp" },
   18916       { 0x344, "xvnmsubasp" },
   18917       { 0x34c, "xvcmpgesp." },
   18918       { 0x350, "xvcvuxdsp" },
   18919       { 0x352, "xvnabssp" },
   18920       { 0x364, "xvnmsubmsp" },
   18921       { 0x370, "xvcvsxdsp" },
   18922       { 0x372, "xvnegsp" },
   18923       { 0x380, "xvmaxdp" },
   18924       { 0x384, "xvnmaddadp" },
   18925       { 0x38c, "xvcmpeqdp." },
   18926       { 0x390, "xvcvdpuxds" },
   18927       { 0x392, "xvcvspdp" },
   18928       { 0x3a0, "xvmindp" },
   18929       { 0x3a4, "xvnmaddmdp" },
   18930       { 0x3ac, "xvcmpgtdp." },
   18931       { 0x3b0, "xvcvdpsxds" },
   18932       { 0x3b2, "xvabsdp" },
   18933       { 0x3c0, "xvcpsgndp" },
   18934       { 0x3c4, "xvnmsubadp" },
   18935       { 0x3cc, "xvcmpgedp." },
   18936       { 0x3d0, "xvcvuxddp" },
   18937       { 0x3d2, "xvnabsdp" },
   18938       { 0x3e4, "xvnmsubmdp" },
   18939       { 0x3f0, "xvcvsxddp" },
   18940       { 0x3f2, "xvnegdp" }
   18941 };
   18942 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
   18943 
   18944 
   18945 // ATTENTION: This search function assumes vsx_all array is sorted.
   18946 static Int findVSXextOpCode(UInt opcode)
   18947 {
   18948    Int low, mid, high;
   18949    low = 0;
   18950    high = VSX_ALL_LEN - 1;
   18951    while (low <= high) {
   18952       mid = (low + high)/2;
   18953       if (opcode < vsx_all[mid].opcode)
   18954          high = mid - 1;
   18955       else if (opcode > vsx_all[mid].opcode)
   18956          low = mid + 1;
   18957       else
   18958          return mid;
   18959    }
   18960    return -1;
   18961 }
   18962 
   18963 
   18964 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
   18965  * passed, and we then try to match it up with one of the VSX forms
   18966  * below.
   18967  */
   18968 static UInt get_VSX60_opc2(UInt opc2_full)
   18969 {
   18970 #define XX2_MASK 0x000003FE
   18971 #define XX3_1_MASK 0x000003FC
   18972 #define XX3_2_MASK 0x000001FC
   18973 #define XX3_3_MASK 0x0000007C
   18974 #define XX4_MASK 0x00000018
   18975    Int ret;
   18976    UInt vsxExtOpcode = 0;
   18977 
   18978    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
   18979       vsxExtOpcode = vsx_all[ret].opcode;
   18980    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
   18981       vsxExtOpcode = vsx_all[ret].opcode;
   18982    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
   18983       vsxExtOpcode = vsx_all[ret].opcode;
   18984    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
   18985       vsxExtOpcode = vsx_all[ret].opcode;
   18986    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
   18987       vsxExtOpcode = vsx_all[ret].opcode;
   18988 
   18989    return vsxExtOpcode;
   18990 }
   18991 
   18992 /*------------------------------------------------------------*/
   18993 /*--- Disassemble a single instruction                     ---*/
   18994 /*------------------------------------------------------------*/
   18995 
   18996 /* Disassemble a single instruction into IR.  The instruction
   18997    is located in host memory at &guest_code[delta]. */
   18998 
   18999 static
   19000 DisResult disInstr_PPC_WRK (
   19001              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
   19002              Bool         resteerCisOk,
   19003              void*        callback_opaque,
   19004              Long         delta64,
   19005              const VexArchInfo* archinfo,
   19006              const VexAbiInfo*  abiinfo,
   19007              Bool         sigill_diag
   19008           )
   19009 {
   19010    UChar     opc1;
   19011    UInt      opc2;
   19012    DisResult dres;
   19013    UInt      theInstr;
   19014    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
   19015    Bool      allow_F  = False;
   19016    Bool      allow_V  = False;
   19017    Bool      allow_FX = False;
   19018    Bool      allow_GX = False;
   19019    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
   19020    Bool      allow_DFP = False;
   19021    Bool      allow_isa_2_07 = False;
   19022    UInt      hwcaps = archinfo->hwcaps;
   19023    Long      delta;
   19024 
   19025    /* What insn variants are we supporting today? */
   19026    if (mode64) {
   19027       allow_F  = True;
   19028       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
   19029       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
   19030       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
   19031       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
   19032       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
   19033       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
   19034    } else {
   19035       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
   19036       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
   19037       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
   19038       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
   19039       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
   19040       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
   19041       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
   19042    }
   19043 
   19044    /* The running delta */
   19045    delta = (Long)mkSzAddr(ty, (ULong)delta64);
   19046 
   19047    /* Set result defaults. */
   19048    dres.whatNext    = Dis_Continue;
   19049    dres.len         = 0;
   19050    dres.continueAt  = 0;
   19051    dres.jk_StopHere = Ijk_INVALID;
   19052 
   19053    /* At least this is simple on PPC32: insns are all 4 bytes long, and
   19054       4-aligned.  So just fish the whole thing out of memory right now
   19055       and have done. */
   19056    theInstr = getUIntPPCendianly( &guest_code[delta] );
   19057 
   19058    if (0) vex_printf("insn: 0x%x\n", theInstr);
   19059 
   19060    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
   19061 
   19062    /* Spot "Special" instructions (see comment at top of file). */
   19063    {
   19064       const UChar* code = guest_code + delta;
   19065       /* Spot the 16-byte preamble:
   19066          32-bit mode:
   19067             5400183E  rlwinm 0,0,3,0,31
   19068             5400683E  rlwinm 0,0,13,0,31
   19069             5400E83E  rlwinm 0,0,29,0,31
   19070             5400983E  rlwinm 0,0,19,0,31
   19071          64-bit mode:
   19072             78001800  rotldi 0,0,3
   19073             78006800  rotldi 0,0,13
   19074             7800E802  rotldi 0,0,61
   19075             78009802  rotldi 0,0,51
   19076       */
   19077       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
   19078       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
   19079       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
   19080       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
   19081       Bool is_special_preamble = False;
   19082       if (getUIntPPCendianly(code+ 0) == word1 &&
   19083           getUIntPPCendianly(code+ 4) == word2 &&
   19084           getUIntPPCendianly(code+ 8) == word3 &&
   19085           getUIntPPCendianly(code+12) == word4) {
   19086          is_special_preamble = True;
   19087       } else if (! mode64 &&
   19088                  getUIntPPCendianly(code+ 0) == 0x54001800 &&
   19089                  getUIntPPCendianly(code+ 4) == 0x54006800 &&
   19090                  getUIntPPCendianly(code+ 8) == 0x5400E800 &&
   19091                  getUIntPPCendianly(code+12) == 0x54009800) {
   19092          static Bool reported = False;
   19093          if (!reported) {
   19094             vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
   19095             vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
   19096             reported = True;
   19097          }
   19098          is_special_preamble = True;
   19099       }
   19100       if (is_special_preamble) {
   19101          /* Got a "Special" instruction preamble.  Which one is it? */
   19102          if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
   19103             /* %R3 = client_request ( %R4 ) */
   19104             DIP("r3 = client_request ( %%r4 )\n");
   19105             delta += 20;
   19106             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   19107             dres.jk_StopHere = Ijk_ClientReq;
   19108             dres.whatNext    = Dis_StopHere;
   19109             goto decode_success;
   19110          }
   19111          else
   19112          if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
   19113             /* %R3 = guest_NRADDR */
   19114             DIP("r3 = guest_NRADDR\n");
   19115             delta += 20;
   19116             dres.len = 20;
   19117             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
   19118             goto decode_success;
   19119          }
   19120          else
   19121          if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
   19122             delta += 20;
   19123             if (host_endness == VexEndnessLE) {
   19124                 /*  branch-and-link-to-noredir %R12 */
   19125                 DIP("branch-and-link-to-noredir r12\n");
   19126                 putGST( PPC_GST_LR,
   19127                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   19128                 putGST( PPC_GST_CIA, getIReg(12));
   19129             } else {
   19130                 /*  branch-and-link-to-noredir %R11 */
   19131                 DIP("branch-and-link-to-noredir r11\n");
   19132                 putGST( PPC_GST_LR,
   19133                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
   19134                 putGST( PPC_GST_CIA, getIReg(11));
   19135             }
   19136             dres.jk_StopHere = Ijk_NoRedir;
   19137             dres.whatNext    = Dis_StopHere;
   19138             goto decode_success;
   19139          }
   19140          else
   19141          if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
   19142             /* %R3 = guest_NRADDR_GPR2 */
   19143             DIP("r3 = guest_NRADDR_GPR2\n");
   19144             delta += 20;
   19145             dres.len = 20;
   19146             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
   19147             goto decode_success;
   19148          }
   19149          else
   19150          if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
   19151             DIP("IR injection\n");
   19152             if (host_endness == VexEndnessBE)
   19153                vex_inject_ir(irsb, Iend_BE);
   19154             else
   19155                vex_inject_ir(irsb, Iend_LE);
   19156 
   19157             delta += 20;
   19158             dres.len = 20;
   19159 
   19160             // Invalidate the current insn. The reason is that the IRop we're
   19161             // injecting here can change. In which case the translation has to
   19162             // be redone. For ease of handling, we simply invalidate all the
   19163             // time.
   19164 
   19165             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
   19166             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
   19167 
   19168             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
   19169             dres.whatNext    = Dis_StopHere;
   19170             dres.jk_StopHere = Ijk_InvalICache;
   19171             goto decode_success;
   19172          }
   19173          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   19174             can print the insn following the Special-insn preamble. */
   19175          theInstr = getUIntPPCendianly(code+16);
   19176          opc1     = ifieldOPC(theInstr);
   19177          opc2     = ifieldOPClo10(theInstr);
   19178          goto decode_failure;
   19179          /*NOTREACHED*/
   19180       }
   19181    }
   19182 
   19183    opc1 = ifieldOPC(theInstr);
   19184    opc2 = ifieldOPClo10(theInstr);
   19185 
   19186    // Note: all 'reserved' bits must be cleared, else invalid
   19187    switch (opc1) {
   19188 
   19189    /* Integer Arithmetic Instructions */
   19190    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
   19191    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
   19192       if (dis_int_arith( theInstr )) goto decode_success;
   19193       goto decode_failure;
   19194 
   19195    /* Integer Compare Instructions */
   19196    case 0x0B: case 0x0A: // cmpi, cmpli
   19197       if (dis_int_cmp( theInstr )) goto decode_success;
   19198       goto decode_failure;
   19199 
   19200    /* Integer Logical Instructions */
   19201    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
   19202    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
   19203       if (dis_int_logic( theInstr )) goto decode_success;
   19204       goto decode_failure;
   19205 
   19206    /* Integer Rotate Instructions */
   19207    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
   19208       if (dis_int_rot( theInstr )) goto decode_success;
   19209       goto decode_failure;
   19210 
   19211    /* 64bit Integer Rotate Instructions */
   19212    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
   19213       if (!mode64) goto decode_failure;
   19214       if (dis_int_rot( theInstr )) goto decode_success;
   19215       goto decode_failure;
   19216 
   19217    /* Integer Load Instructions */
   19218    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
   19219    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
   19220    case 0x20: case 0x21:            // lwz,  lwzu
   19221       if (dis_int_load( theInstr )) goto decode_success;
   19222       goto decode_failure;
   19223 
   19224    /* Integer Store Instructions */
   19225    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
   19226    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
   19227       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19228       goto decode_failure;
   19229 
   19230    /* Integer Load and Store Multiple Instructions */
   19231    case 0x2E: case 0x2F: // lmw, stmw
   19232       if (dis_int_ldst_mult( theInstr )) goto decode_success;
   19233       goto decode_failure;
   19234 
   19235    /* Branch Instructions */
   19236    case 0x12: case 0x10: // b, bc
   19237       if (dis_branch(theInstr, abiinfo, &dres,
   19238                                resteerOkFn, callback_opaque))
   19239          goto decode_success;
   19240       goto decode_failure;
   19241 
   19242    /* System Linkage Instructions */
   19243    case 0x11: // sc
   19244       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
   19245       goto decode_failure;
   19246 
   19247    /* Trap Instructions */
   19248    case 0x02:    // tdi
   19249       if (!mode64) goto decode_failure;
   19250       if (dis_trapi(theInstr, &dres)) goto decode_success;
   19251       goto decode_failure;
   19252 
   19253    case 0x03:   // twi
   19254       if (dis_trapi(theInstr, &dres)) goto decode_success;
   19255       goto decode_failure;
   19256 
   19257    /* Floating Point Load Instructions */
   19258    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
   19259    case 0x33:                       // lfdu
   19260       if (!allow_F) goto decode_noF;
   19261       if (dis_fp_load( theInstr )) goto decode_success;
   19262       goto decode_failure;
   19263 
   19264    /* Floating Point Store Instructions */
   19265    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
   19266    case 0x37:                       // stfdux
   19267       if (!allow_F) goto decode_noF;
   19268       if (dis_fp_store( theInstr )) goto decode_success;
   19269       goto decode_failure;
   19270 
   19271       /* Floating Point Load Double Pair Instructions */
   19272    case 0x39: case 0x3D:
   19273       if (!allow_F) goto decode_noF;
   19274       if (dis_fp_pair( theInstr )) goto decode_success;
   19275       goto decode_failure;
   19276 
   19277    /* 128-bit Integer Load */
   19278    case 0x38:  // lq
   19279       if (dis_int_load( theInstr )) goto decode_success;
   19280       goto decode_failure;
   19281 
   19282    /* 64bit Integer Loads */
   19283    case 0x3A:  // ld, ldu, lwa
   19284       if (!mode64) goto decode_failure;
   19285       if (dis_int_load( theInstr )) goto decode_success;
   19286       goto decode_failure;
   19287 
   19288    case 0x3B:
   19289       if (!allow_F) goto decode_noF;
   19290       opc2 = ifieldOPClo10(theInstr);
   19291 
   19292       switch (opc2) {
   19293          case 0x2:    // dadd - DFP Add
   19294          case 0x202:  // dsub - DFP Subtract
   19295          case 0x22:   // dmul - DFP Mult
   19296          case 0x222:  // ddiv - DFP Divide
   19297             if (!allow_DFP) goto decode_noDFP;
   19298             if (dis_dfp_arith( theInstr ))
   19299                goto decode_success;
   19300          case 0x82:   // dcmpo, DFP comparison ordered instruction
   19301          case 0x282:  // dcmpu, DFP comparison unordered instruction
   19302             if (!allow_DFP) goto decode_noDFP;
   19303             if (dis_dfp_compare( theInstr ) )
   19304                goto decode_success;
   19305             goto decode_failure;
   19306          case 0x102: // dctdp  - DFP convert to DFP long
   19307          case 0x302: // drsp   - DFP round to dfp short
   19308          case 0x122: // dctfix - DFP convert to fixed
   19309             if (!allow_DFP) goto decode_noDFP;
   19310             if (dis_dfp_fmt_conv( theInstr ))
   19311                goto decode_success;
   19312             goto decode_failure;
   19313          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
   19314             if (!allow_VX)
   19315                goto decode_failure;
   19316             if (!allow_DFP) goto decode_noDFP;
   19317             if (dis_dfp_fmt_conv( theInstr ))
   19318                goto decode_success;
   19319             goto decode_failure;
   19320          case 0x2A2: // dtstsf - DFP number of significant digits
   19321             if (!allow_DFP) goto decode_noDFP;
   19322             if (dis_dfp_significant_digits(theInstr))
   19323                goto decode_success;
   19324             goto decode_failure;
   19325          case 0x142: // ddedpd   DFP Decode DPD to BCD
   19326          case 0x342: // denbcd   DFP Encode BCD to DPD
   19327             if (!allow_DFP) goto decode_noDFP;
   19328             if (dis_dfp_bcd(theInstr))
   19329                goto decode_success;
   19330             goto decode_failure;
   19331          case 0x162:  // dxex - Extract exponent
   19332          case 0x362:  // diex - Insert exponent
   19333             if (!allow_DFP) goto decode_noDFP;
   19334             if (dis_dfp_extract_insert( theInstr ) )
   19335                goto decode_success;
   19336             goto decode_failure;
   19337          case 0x3CE: // fcfidus (implemented as native insn)
   19338             if (!allow_VX)
   19339                goto decode_noVX;
   19340             if (dis_fp_round( theInstr ))
   19341                goto decode_success;
   19342             goto decode_failure;
   19343          case 0x34E: // fcfids
   19344             if (dis_fp_round( theInstr ))
   19345                goto decode_success;
   19346             goto decode_failure;
   19347       }
   19348 
   19349       opc2 = ifieldOPClo9( theInstr );
   19350       switch (opc2) {
   19351       case 0x42: // dscli, DFP shift left
   19352       case 0x62: // dscri, DFP shift right
   19353          if (!allow_DFP) goto decode_noDFP;
   19354          if (dis_dfp_shift( theInstr ))
   19355             goto decode_success;
   19356          goto decode_failure;
   19357       case 0xc2:  // dtstdc, DFP test data class
   19358       case 0xe2:  // dtstdg, DFP test data group
   19359          if (!allow_DFP) goto decode_noDFP;
   19360          if (dis_dfp_class_test( theInstr ))
   19361             goto decode_success;
   19362          goto decode_failure;
   19363       }
   19364 
   19365       opc2 = ifieldOPClo8( theInstr );
   19366       switch (opc2) {
   19367       case 0x3:   // dqua  - DFP Quantize
   19368       case 0x23:  // drrnd - DFP Reround
   19369       case 0x43:  // dquai - DFP Quantize immediate
   19370          if (!allow_DFP) goto decode_noDFP;
   19371          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
   19372             goto decode_success;
   19373          goto decode_failure;
   19374       case 0xA2: // dtstex - DFP Test exponent
   19375          if (!allow_DFP) goto decode_noDFP;
   19376          if (dis_dfp_exponent_test( theInstr ) )
   19377             goto decode_success;
   19378          goto decode_failure;
   19379       case 0x63: // drintx - Round to an integer value
   19380       case 0xE3: // drintn - Round to an integer value
   19381          if (!allow_DFP) goto decode_noDFP;
   19382          if (dis_dfp_round( theInstr ) ) {
   19383             goto decode_success;
   19384          }
   19385          goto decode_failure;
   19386       default:
   19387          break;  /* fall through to next opc2 check */
   19388       }
   19389 
   19390       opc2 = IFIELD(theInstr, 1, 5);
   19391       switch (opc2) {
   19392       /* Floating Point Arith Instructions */
   19393       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
   19394       case 0x19:                       // fmuls
   19395          if (dis_fp_arith(theInstr)) goto decode_success;
   19396          goto decode_failure;
   19397       case 0x16:                       // fsqrts
   19398          if (!allow_FX) goto decode_noFX;
   19399          if (dis_fp_arith(theInstr)) goto decode_success;
   19400          goto decode_failure;
   19401       case 0x18:                       // fres
   19402          if (!allow_GX) goto decode_noGX;
   19403          if (dis_fp_arith(theInstr)) goto decode_success;
   19404          goto decode_failure;
   19405 
   19406       /* Floating Point Mult-Add Instructions */
   19407       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
   19408       case 0x1F:                       // fnmadds
   19409          if (dis_fp_multadd(theInstr)) goto decode_success;
   19410          goto decode_failure;
   19411 
   19412       case 0x1A:                       // frsqrtes
   19413          if (!allow_GX) goto decode_noGX;
   19414          if (dis_fp_arith(theInstr)) goto decode_success;
   19415          goto decode_failure;
   19416 
   19417       default:
   19418          goto decode_failure;
   19419       }
   19420       break;
   19421 
   19422    case 0x3C: // VSX instructions (except load/store)
   19423    {
   19424       // All of these VSX instructions use some VMX facilities, so
   19425       // if allow_V is not set, we'll skip trying to decode.
   19426       if (!allow_V) goto decode_noVX;
   19427 
   19428       UInt vsxOpc2 = get_VSX60_opc2(opc2);
   19429       /* The vsxOpc2 returned is the "normalized" value, representing the
   19430        * instructions secondary opcode as taken from the standard secondary
   19431        * opcode field [21:30] (IBM notatition), even if the actual field
   19432        * is non-standard.  These normalized values are given in the opcode
   19433        * appendices of the ISA 2.06 document.
   19434        */
   19435 
   19436       switch (vsxOpc2) {
   19437          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
   19438          case 0x018: case 0x148: // xxsel, xxspltw
   19439             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
   19440             goto decode_failure;
   19441          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
   19442          case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
   19443          case 0x2C8: case 0x2E8: // xxlnand, xxleqv
   19444             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
   19445             goto decode_failure;
   19446          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
   19447          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
   19448          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
   19449          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
   19450          case 0x034: case 0x014: // xsresp, xsrsqrtesp
   19451          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
   19452          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
   19453          case 0x092: case 0x232: // xsrdpi, xsrsp
   19454             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
   19455             goto decode_failure;
   19456          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
   19457             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
   19458             goto decode_failure;
   19459          case 0x0:   case 0x020: // xsaddsp, xssubsp
   19460          case 0x080:             // xsadddp
   19461          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
   19462          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
   19463          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
   19464          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
   19465          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
   19466          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
   19467          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
   19468          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
   19469          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
   19470          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
   19471          case 0x0A0:             // xssubdp
   19472          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
   19473          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
   19474             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
   19475             goto decode_failure;
   19476          case 0x180: // xvadddp
   19477          case 0x1E0: // xvdivdp
   19478          case 0x1C0: // xvmuldp
   19479          case 0x1A0: // xvsubdp
   19480          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
   19481          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
   19482          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
   19483          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
   19484          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
   19485          case 0x196: // xvsqrtdp
   19486             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
   19487             goto decode_failure;
   19488          case 0x100: // xvaddsp
   19489          case 0x160: // xvdivsp
   19490          case 0x140: // xvmulsp
   19491          case 0x120: // xvsubsp
   19492          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
   19493          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
   19494          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
   19495          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
   19496          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
   19497          case 0x116: // xvsqrtsp
   19498             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
   19499             goto decode_failure;
   19500 
   19501          case 0x250:             // xscvuxdsp
   19502          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
   19503          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
   19504          case 0x090: // xscvdpuxws
   19505             // The above VSX conversion instructions employ some ISA 2.06
   19506             // floating point conversion instructions under the covers,
   19507             // so if allow_VX (which means "supports ISA 2.06") is not set,
   19508             // we'll skip the decode.
   19509             if (!allow_VX) goto decode_noVX;
   19510             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   19511             goto decode_failure;
   19512 
   19513          case 0x2B0: // xscvdpsxds
   19514          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
   19515          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
   19516          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
   19517          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
   19518          case 0x292: case 0x296: // xscvspdp, xscvspdpn
   19519          case 0x312: // xvcvdpsp
   19520          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
   19521          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
   19522          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
   19523          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
   19524          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
   19525          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
   19526             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
   19527             goto decode_failure;
   19528 
   19529          case 0x18C: case 0x38C: // xvcmpeqdp[.]
   19530          case 0x10C: case 0x30C: // xvcmpeqsp[.]
   19531          case 0x14C: case 0x34C: // xvcmpgesp[.]
   19532          case 0x12C: case 0x32C: // xvcmpgtsp[.]
   19533          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
   19534          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
   19535              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
   19536              goto decode_failure;
   19537 
   19538          case 0x134:  // xvresp
   19539          case 0x1B4:  // xvredp
   19540          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
   19541          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
   19542          case 0x300: case 0x320: // xvmaxsp, xvminsp
   19543          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
   19544          case 0x3B2: case 0x332: // xvabsdp, xvabssp
   19545          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
   19546          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
   19547          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
   19548          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
   19549          case 0x112: case 0x156: // xvrspi, xvrspic
   19550          case 0x172: case 0x152: // xvrspim, xvrspip
   19551          case 0x132: // xvrspiz
   19552             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
   19553             goto decode_failure;
   19554 
   19555          default:
   19556             goto decode_failure;
   19557       }
   19558       break;
   19559    }
   19560 
   19561    /* 64bit Integer Stores */
   19562    case 0x3E:  // std, stdu, stq
   19563       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19564       goto decode_failure;
   19565 
   19566    case 0x3F:
   19567       if (!allow_F) goto decode_noF;
   19568       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
   19569          so we can simply fall through the first switch statement */
   19570 
   19571       opc2 = IFIELD(theInstr, 1, 5);
   19572       switch (opc2) {
   19573       /* Floating Point Arith Instructions */
   19574       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
   19575       case 0x19:                       // fmul
   19576          if (dis_fp_arith(theInstr)) goto decode_success;
   19577          goto decode_failure;
   19578       case 0x16:                       // fsqrt
   19579          if (!allow_FX) goto decode_noFX;
   19580          if (dis_fp_arith(theInstr)) goto decode_success;
   19581          goto decode_failure;
   19582       case 0x17: case 0x1A:            // fsel, frsqrte
   19583          if (!allow_GX) goto decode_noGX;
   19584          if (dis_fp_arith(theInstr)) goto decode_success;
   19585          goto decode_failure;
   19586 
   19587       /* Floating Point Mult-Add Instructions */
   19588       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
   19589       case 0x1F:                       // fnmadd
   19590          if (dis_fp_multadd(theInstr)) goto decode_success;
   19591          goto decode_failure;
   19592 
   19593       case 0x18:                       // fre
   19594          if (!allow_GX) goto decode_noGX;
   19595          if (dis_fp_arith(theInstr)) goto decode_success;
   19596          goto decode_failure;
   19597 
   19598       default:
   19599          break; // Fall through
   19600       }
   19601 
   19602       opc2 = IFIELD(theInstr, 1, 10);
   19603       switch (opc2) {
   19604       /* 128-bit DFP instructions */
   19605       case 0x2:    // daddq - DFP Add
   19606       case 0x202:  // dsubq - DFP Subtract
   19607       case 0x22:   // dmulq - DFP Mult
   19608       case 0x222:  // ddivq - DFP Divide
   19609          if (!allow_DFP) goto decode_noDFP;
   19610          if (dis_dfp_arithq( theInstr ))
   19611             goto decode_success;
   19612          goto decode_failure;
   19613       case 0x162:  // dxexq - DFP Extract exponent
   19614       case 0x362:  // diexq - DFP Insert exponent
   19615          if (!allow_DFP) goto decode_noDFP;
   19616          if (dis_dfp_extract_insertq( theInstr ))
   19617             goto decode_success;
   19618          goto decode_failure;
   19619 
   19620       case 0x82:   // dcmpoq, DFP comparison ordered instruction
   19621       case 0x282:  // dcmpuq, DFP comparison unordered instruction
   19622          if (!allow_DFP) goto decode_noDFP;
   19623          if (dis_dfp_compare( theInstr ) )
   19624             goto decode_success;
   19625          goto decode_failure;
   19626 
   19627       case 0x102: // dctqpq  - DFP convert to DFP extended
   19628       case 0x302: // drdpq   - DFP round to dfp Long
   19629       case 0x122: // dctfixq - DFP convert to fixed quad
   19630       case 0x322: // dcffixq - DFP convert from fixed quad
   19631          if (!allow_DFP) goto decode_noDFP;
   19632          if (dis_dfp_fmt_convq( theInstr ))
   19633             goto decode_success;
   19634          goto decode_failure;
   19635 
   19636       case 0x2A2: // dtstsfq - DFP number of significant digits
   19637          if (!allow_DFP) goto decode_noDFP;
   19638          if (dis_dfp_significant_digits(theInstr))
   19639             goto decode_success;
   19640          goto decode_failure;
   19641 
   19642       case 0x142: // ddedpdq   DFP Decode DPD to BCD
   19643       case 0x342: // denbcdq   DFP Encode BCD to DPD
   19644          if (!allow_DFP) goto decode_noDFP;
   19645          if (dis_dfp_bcdq(theInstr))
   19646             goto decode_success;
   19647          goto decode_failure;
   19648 
   19649       /* Floating Point Compare Instructions */
   19650       case 0x000: // fcmpu
   19651       case 0x020: // fcmpo
   19652          if (dis_fp_cmp(theInstr)) goto decode_success;
   19653          goto decode_failure;
   19654 
   19655       case 0x080: // ftdiv
   19656       case 0x0A0: // ftsqrt
   19657          if (dis_fp_tests(theInstr)) goto decode_success;
   19658          goto decode_failure;
   19659 
   19660       /* Floating Point Rounding/Conversion Instructions */
   19661       case 0x00C: // frsp
   19662       case 0x00E: // fctiw
   19663       case 0x00F: // fctiwz
   19664       case 0x32E: // fctid
   19665       case 0x32F: // fctidz
   19666       case 0x34E: // fcfid
   19667          if (dis_fp_round(theInstr)) goto decode_success;
   19668          goto decode_failure;
   19669       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
   19670       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
   19671          if (!allow_VX) goto decode_noVX;
   19672          if (dis_fp_round(theInstr)) goto decode_success;
   19673          goto decode_failure;
   19674 
   19675       /* Power6 rounding stuff */
   19676       case 0x1E8: // frim
   19677       case 0x1C8: // frip
   19678       case 0x188: // frin
   19679       case 0x1A8: // friz
   19680          /* A hack to check for P6 capability . . . */
   19681          if ((allow_F && allow_V && allow_FX && allow_GX) &&
   19682              (dis_fp_round(theInstr)))
   19683             goto decode_success;
   19684          goto decode_failure;
   19685 
   19686       /* Floating Point Move Instructions */
   19687       case 0x008: // fcpsgn
   19688       case 0x028: // fneg
   19689       case 0x048: // fmr
   19690       case 0x088: // fnabs
   19691       case 0x108: // fabs
   19692          if (dis_fp_move( theInstr )) goto decode_success;
   19693          goto decode_failure;
   19694 
   19695       case 0x3c6: case 0x346:          // fmrgew, fmrgow
   19696          if (dis_fp_merge( theInstr )) goto decode_success;
   19697          goto decode_failure;
   19698 
   19699       /* Floating Point Status/Control Register Instructions */
   19700       case 0x026: // mtfsb1
   19701       case 0x040: // mcrfs
   19702       case 0x046: // mtfsb0
   19703       case 0x086: // mtfsfi
   19704       case 0x247: // mffs
   19705       case 0x2C7: // mtfsf
   19706          // Some of the above instructions need to know more about the
   19707          // ISA level supported by the host.
   19708          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
   19709          goto decode_failure;
   19710 
   19711       default:
   19712          break; // Fall through...
   19713       }
   19714 
   19715       opc2 = ifieldOPClo9( theInstr );
   19716       switch (opc2) {
   19717       case 0x42: // dscli, DFP shift left
   19718       case 0x62: // dscri, DFP shift right
   19719          if (!allow_DFP) goto decode_noDFP;
   19720          if (dis_dfp_shiftq( theInstr ))
   19721             goto decode_success;
   19722          goto decode_failure;
   19723       case 0xc2:  // dtstdc, DFP test data class
   19724       case 0xe2:  // dtstdg, DFP test data group
   19725          if (!allow_DFP) goto decode_noDFP;
   19726          if (dis_dfp_class_test( theInstr ))
   19727             goto decode_success;
   19728          goto decode_failure;
   19729       default:
   19730          break;
   19731       }
   19732 
   19733       opc2 = ifieldOPClo8( theInstr );
   19734       switch (opc2) {
   19735       case 0x3:   // dquaq  - DFP Quantize Quad
   19736       case 0x23:  // drrndq - DFP Reround Quad
   19737       case 0x43:  // dquaiq - DFP Quantize immediate Quad
   19738          if (!allow_DFP) goto decode_noDFP;
   19739          if (dis_dfp_quantize_sig_rrndq( theInstr ))
   19740             goto decode_success;
   19741          goto decode_failure;
   19742       case 0xA2: // dtstexq - DFP Test exponent Quad
   19743          if (!allow_DFP) goto decode_noDFP;
   19744          if (dis_dfp_exponent_test( theInstr ) )
   19745             goto decode_success;
   19746          goto decode_failure;
   19747       case 0x63:  // drintxq - DFP Round to an integer value
   19748       case 0xE3:  // drintnq - DFP Round to an integer value
   19749          if (!allow_DFP) goto decode_noDFP;
   19750          if (dis_dfp_roundq( theInstr ))
   19751             goto decode_success;
   19752          goto decode_failure;
   19753 
   19754       default:
   19755          goto decode_failure;
   19756       }
   19757       break;
   19758 
   19759    case 0x13:
   19760       switch (opc2) {
   19761 
   19762       /* Condition Register Logical Instructions */
   19763       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
   19764       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
   19765       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
   19766          if (dis_cond_logic( theInstr )) goto decode_success;
   19767          goto decode_failure;
   19768 
   19769       /* Branch Instructions */
   19770       case 0x210: case 0x010: // bcctr, bclr
   19771          if (dis_branch(theInstr, abiinfo, &dres,
   19772                                   resteerOkFn, callback_opaque))
   19773             goto decode_success;
   19774          goto decode_failure;
   19775 
   19776       /* Memory Synchronization Instructions */
   19777       case 0x096: // isync
   19778          if (dis_memsync( theInstr )) goto decode_success;
   19779          goto decode_failure;
   19780 
   19781       default:
   19782          goto decode_failure;
   19783       }
   19784       break;
   19785 
   19786 
   19787    case 0x1F:
   19788 
   19789       /* For arith instns, bit10 is the OE flag (overflow enable) */
   19790 
   19791       opc2 = IFIELD(theInstr, 1, 9);
   19792       switch (opc2) {
   19793       /* Integer Arithmetic Instructions */
   19794       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
   19795       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
   19796       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
   19797       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
   19798       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
   19799       case 0x0C8: // subfze
   19800          if (dis_int_arith( theInstr )) goto decode_success;
   19801          goto decode_failure;
   19802 
   19803       case 0x18B: // divweu (implemented as native insn)
   19804       case 0x1AB: // divwe (implemented as native insn)
   19805          if (!allow_VX) goto decode_noVX;
   19806          if (dis_int_arith( theInstr )) goto decode_success;
   19807          goto decode_failure;
   19808 
   19809       /* 64bit Integer Arithmetic */
   19810       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
   19811       case 0x1C9: case 0x1E9: // divdu, divd
   19812          if (!mode64) goto decode_failure;
   19813          if (dis_int_arith( theInstr )) goto decode_success;
   19814          goto decode_failure;
   19815 
   19816       case 0x1A9: //  divde (implemented as native insn)
   19817       case 0x189: //  divdeuo (implemented as native insn)
   19818          if (!allow_VX) goto decode_noVX;
   19819          if (!mode64) goto decode_failure;
   19820          if (dis_int_arith( theInstr )) goto decode_success;
   19821          goto decode_failure;
   19822 
   19823       case 0x1FC:                         // cmpb
   19824          if (dis_int_logic( theInstr )) goto decode_success;
   19825          goto decode_failure;
   19826 
   19827       default:
   19828          break;  // Fall through...
   19829       }
   19830 
   19831       /* All remaining opcodes use full 10 bits. */
   19832 
   19833       opc2 = IFIELD(theInstr, 1, 10);
   19834       switch (opc2) {
   19835       /* Integer Compare Instructions  */
   19836       case 0x000: case 0x020: // cmp, cmpl
   19837          if (dis_int_cmp( theInstr )) goto decode_success;
   19838          goto decode_failure;
   19839 
   19840       /* Integer Logical Instructions */
   19841       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
   19842       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
   19843       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
   19844       case 0x19C: case 0x13C:             // orc,  xor
   19845       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
   19846          if (dis_int_logic( theInstr )) goto decode_success;
   19847          goto decode_failure;
   19848 
   19849       case 0x28E: case 0x2AE:             // tbegin., tend.
   19850       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
   19851       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
   19852       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
   19853       if (dis_transactional_memory( theInstr,
   19854                                     getUIntPPCendianly( &guest_code[delta + 4]),
   19855                                     abiinfo, &dres,
   19856                                     resteerOkFn, callback_opaque))
   19857             goto decode_success;
   19858          goto decode_failure;
   19859 
   19860       /* 64bit Integer Logical Instructions */
   19861       case 0x3DA: case 0x03A: // extsw, cntlzd
   19862          if (!mode64) goto decode_failure;
   19863          if (dis_int_logic( theInstr )) goto decode_success;
   19864          goto decode_failure;
   19865 
   19866          /* 64bit Integer Parity Instructions */
   19867       case 0xba: // prtyd
   19868          if (!mode64) goto decode_failure;
   19869          if (dis_int_parity( theInstr )) goto decode_success;
   19870          goto decode_failure;
   19871 
   19872       case 0x9a: // prtyw
   19873          if (dis_int_parity( theInstr )) goto decode_success;
   19874          goto decode_failure;
   19875 
   19876       /* Integer Shift Instructions */
   19877       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
   19878       case 0x218:                         // srw
   19879          if (dis_int_shift( theInstr )) goto decode_success;
   19880          goto decode_failure;
   19881 
   19882       /* 64bit Integer Shift Instructions */
   19883       case 0x01B: case 0x31A: // sld, srad
   19884       case 0x33A: case 0x33B: // sradi
   19885       case 0x21B:             // srd
   19886          if (!mode64) goto decode_failure;
   19887          if (dis_int_shift( theInstr )) goto decode_success;
   19888          goto decode_failure;
   19889 
   19890       /* Integer Load Instructions */
   19891       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
   19892       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
   19893       case 0x017: case 0x037:             // lwzx,  lwzux
   19894          if (dis_int_load( theInstr )) goto decode_success;
   19895          goto decode_failure;
   19896 
   19897       /* 64bit Integer Load Instructions */
   19898       case 0x035: case 0x015:             // ldux,  ldx
   19899       case 0x175: case 0x155:             // lwaux, lwax
   19900          if (!mode64) goto decode_failure;
   19901          if (dis_int_load( theInstr )) goto decode_success;
   19902          goto decode_failure;
   19903 
   19904       /* Integer Store Instructions */
   19905       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
   19906       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
   19907          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19908          goto decode_failure;
   19909 
   19910       /* 64bit Integer Store Instructions */
   19911       case 0x0B5: case 0x095: // stdux, stdx
   19912          if (!mode64) goto decode_failure;
   19913          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
   19914          goto decode_failure;
   19915 
   19916       /* Integer Load and Store with Byte Reverse Instructions */
   19917       case 0x214: case 0x294: // ldbrx, stdbrx
   19918          if (!mode64) goto decode_failure;
   19919          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19920          goto decode_failure;
   19921 
   19922       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
   19923       case 0x396:                            // sthbrx
   19924          if (dis_int_ldst_rev( theInstr )) goto decode_success;
   19925          goto decode_failure;
   19926 
   19927       /* Integer Load and Store String Instructions */
   19928       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
   19929       case 0x295: {                       // stswx
   19930          Bool stopHere = False;
   19931          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
   19932          if (!ok) goto decode_failure;
   19933          if (stopHere) {
   19934             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
   19935             dres.jk_StopHere = Ijk_Boring;
   19936             dres.whatNext    = Dis_StopHere;
   19937          }
   19938          goto decode_success;
   19939       }
   19940 
   19941       /* Memory Synchronization Instructions */
   19942       case 0x034: case 0x074:             // lbarx, lharx
   19943       case 0x2B6: case 0x2D6:             // stbcx, sthcx
   19944          if (!allow_isa_2_07) goto decode_noP8;
   19945          if (dis_memsync( theInstr )) goto decode_success;
   19946          goto decode_failure;
   19947 
   19948       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
   19949       case 0x256:                         // sync
   19950          if (dis_memsync( theInstr )) goto decode_success;
   19951          goto decode_failure;
   19952 
   19953       /* 64bit Memory Synchronization Instructions */
   19954       case 0x054: case 0x0D6: // ldarx, stdcx.
   19955          if (!mode64) goto decode_failure;
   19956          if (dis_memsync( theInstr )) goto decode_success;
   19957          goto decode_failure;
   19958 
   19959       case 0x114: case 0x0B6: // lqarx, stqcx.
   19960          if (dis_memsync( theInstr )) goto decode_success;
   19961          goto decode_failure;
   19962 
   19963       /* Processor Control Instructions */
   19964       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
   19965       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
   19966       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
   19967       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
   19968       case 0x220:                         // mcrxrt
   19969          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
   19970          goto decode_failure;
   19971 
   19972       /* Cache Management Instructions */
   19973       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
   19974       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
   19975       case 0x3D6:                         // icbi
   19976          if (dis_cache_manage( theInstr, &dres, archinfo ))
   19977             goto decode_success;
   19978          goto decode_failure;
   19979 
   19980 //zz       /* External Control Instructions */
   19981 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
   19982 //zz          DIP("external control op => not implemented\n");
   19983 //zz          goto decode_failure;
   19984 
   19985       /* Trap Instructions */
   19986       case 0x004:             // tw
   19987          if (dis_trap(theInstr, &dres)) goto decode_success;
   19988          goto decode_failure;
   19989 
   19990       case 0x044:             // td
   19991          if (!mode64) goto decode_failure;
   19992          if (dis_trap(theInstr, &dres)) goto decode_success;
   19993          goto decode_failure;
   19994 
   19995       /* Floating Point Load Instructions */
   19996       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
   19997       case 0x277:                         // lfdux
   19998          if (!allow_F) goto decode_noF;
   19999          if (dis_fp_load( theInstr )) goto decode_success;
   20000          goto decode_failure;
   20001 
   20002       /* Floating Point Store Instructions */
   20003       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
   20004       case 0x2F7:                         // stfdu, stfiwx
   20005          if (!allow_F) goto decode_noF;
   20006          if (dis_fp_store( theInstr )) goto decode_success;
   20007          goto decode_failure;
   20008       case 0x3D7:                         // stfiwx
   20009          if (!allow_F) goto decode_noF;
   20010          if (!allow_GX) goto decode_noGX;
   20011          if (dis_fp_store( theInstr )) goto decode_success;
   20012          goto decode_failure;
   20013 
   20014          /* Floating Point Double Pair Indexed Instructions */
   20015       case 0x317: // lfdpx (Power6)
   20016       case 0x397: // stfdpx (Power6)
   20017          if (!allow_F) goto decode_noF;
   20018          if (dis_fp_pair(theInstr)) goto decode_success;
   20019          goto decode_failure;
   20020 
   20021       case 0x357:                         // lfiwax
   20022          if (!allow_F) goto decode_noF;
   20023          if (dis_fp_load( theInstr )) goto decode_success;
   20024          goto decode_failure;
   20025 
   20026       case 0x377:                         // lfiwzx
   20027          if (!allow_F) goto decode_noF;
   20028          if (dis_fp_load( theInstr )) goto decode_success;
   20029          goto decode_failure;
   20030 
   20031       /* AltiVec instructions */
   20032 
   20033       /* AV Cache Control - Data streams */
   20034       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
   20035          if (!allow_V) goto decode_noV;
   20036          if (dis_av_datastream( theInstr )) goto decode_success;
   20037          goto decode_failure;
   20038 
   20039       /* AV Load */
   20040       case 0x006: case 0x026:             // lvsl, lvsr
   20041       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
   20042       case 0x067: case 0x167:             // lvx, lvxl
   20043          if (!allow_V) goto decode_noV;
   20044          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
   20045          goto decode_failure;
   20046 
   20047       /* AV Store */
   20048       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
   20049       case 0x0E7: case 0x1E7:             // stvx, stvxl
   20050          if (!allow_V) goto decode_noV;
   20051          if (dis_av_store( theInstr )) goto decode_success;
   20052          goto decode_failure;
   20053 
   20054       /* VSX Load */
   20055       case 0x00C: // lxsiwzx
   20056       case 0x04C: // lxsiwax
   20057       case 0x20C: // lxsspx
   20058       case 0x24C: // lxsdx
   20059       case 0x34C: // lxvd2x
   20060       case 0x14C: // lxvdsx
   20061       case 0x30C: // lxvw4x
   20062         // All of these VSX load instructions use some VMX facilities, so
   20063         // if allow_V is not set, we'll skip trying to decode.
   20064         if (!allow_V) goto decode_noV;
   20065 
   20066 	if (dis_vx_load( theInstr )) goto decode_success;
   20067           goto decode_failure;
   20068 
   20069       /* VSX Store */
   20070       case 0x08C: // stxsiwx
   20071       case 0x28C: // stxsspx
   20072       case 0x2CC: // stxsdx
   20073       case 0x3CC: // stxvd2x
   20074       case 0x38C: // stxvw4x
   20075         // All of these VSX store instructions use some VMX facilities, so
   20076         // if allow_V is not set, we'll skip trying to decode.
   20077         if (!allow_V) goto decode_noV;
   20078 
   20079 	if (dis_vx_store( theInstr )) goto decode_success;
   20080     	  goto decode_failure;
   20081 
   20082       /* Miscellaneous ISA 2.06 instructions */
   20083       case 0x1FA: // popcntd
   20084       case 0x17A: // popcntw
   20085       case 0x7A:  // popcntb
   20086 	  if (dis_int_logic( theInstr )) goto decode_success;
   20087     	  goto decode_failure;
   20088 
   20089       case 0x0FC: // bpermd
   20090          if (!mode64) goto decode_failure;
   20091          if (dis_int_logic( theInstr )) goto decode_success;
   20092          goto decode_failure;
   20093 
   20094       default:
   20095          /* Deal with some other cases that we would otherwise have
   20096             punted on. */
   20097          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
   20098          /* only decode this insn when reserved bit 0 (31 in IBM's
   20099             notation) is zero */
   20100          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
   20101             UInt rT = ifieldRegDS( theInstr );
   20102             UInt rA = ifieldRegA( theInstr );
   20103             UInt rB = ifieldRegB( theInstr );
   20104             UInt bi = ifieldRegC( theInstr );
   20105             putIReg(
   20106                rT,
   20107                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
   20108                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
   20109                                    : getIReg(rA),
   20110                            getIReg(rB))
   20111 
   20112             );
   20113             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
   20114             goto decode_success;
   20115          }
   20116          goto decode_failure;
   20117       }
   20118       break;
   20119 
   20120 
   20121    case 0x04:
   20122       /* AltiVec instructions */
   20123 
   20124       opc2 = IFIELD(theInstr, 0, 6);
   20125       switch (opc2) {
   20126       /* AV Mult-Add, Mult-Sum */
   20127       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
   20128       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
   20129       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
   20130          if (!allow_V) goto decode_noV;
   20131          if (dis_av_multarith( theInstr )) goto decode_success;
   20132          goto decode_failure;
   20133 
   20134       /* AV Permutations */
   20135       case 0x2A:                       // vsel
   20136       case 0x2B:                       // vperm
   20137       case 0x2C:                       // vsldoi
   20138          if (!allow_V) goto decode_noV;
   20139          if (dis_av_permute( theInstr )) goto decode_success;
   20140          goto decode_failure;
   20141 
   20142       case 0x2D:                       // vpermxor
   20143          if (!allow_isa_2_07) goto decode_noP8;
   20144          if (dis_av_permute( theInstr )) goto decode_success;
   20145          goto decode_failure;
   20146 
   20147       /* AV Floating Point Mult-Add/Sub */
   20148       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
   20149          if (!allow_V) goto decode_noV;
   20150          if (dis_av_fp_arith( theInstr )) goto decode_success;
   20151          goto decode_failure;
   20152 
   20153       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
   20154       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
   20155          if (!allow_V) goto decode_noV;
   20156          if (dis_av_quad( theInstr)) goto decode_success;
   20157          goto decode_failure;
   20158 
   20159       default:
   20160          break;  // Fall through...
   20161       }
   20162 
   20163       opc2 = IFIELD(theInstr, 0, 9);
   20164       switch (opc2) {
   20165       /* BCD arithmetic */
   20166       case 0x1: case 0x41:             // bcdadd, bcdsub
   20167          if (!allow_isa_2_07) goto decode_noP8;
   20168          if (dis_av_bcd( theInstr )) goto decode_success;
   20169          goto decode_failure;
   20170 
   20171       default:
   20172          break;  // Fall through...
   20173       }
   20174 
   20175       opc2 = IFIELD(theInstr, 0, 11);
   20176       switch (opc2) {
   20177       /* AV Arithmetic */
   20178       case 0x180:                         // vaddcuw
   20179       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
   20180       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
   20181       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
   20182       case 0x580:                         // vsubcuw
   20183       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
   20184       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
   20185       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
   20186       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
   20187       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
   20188       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
   20189       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
   20190       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
   20191       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
   20192       case 0x008: case 0x048:             // vmuloub, vmulouh
   20193       case 0x108: case 0x148:             // vmulosb, vmulosh
   20194       case 0x208: case 0x248:             // vmuleub, vmuleuh
   20195       case 0x308: case 0x348:             // vmulesb, vmulesh
   20196       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
   20197       case 0x688: case 0x788:             // vsum2sws, vsumsws
   20198          if (!allow_V) goto decode_noV;
   20199          if (dis_av_arith( theInstr )) goto decode_success;
   20200          goto decode_failure;
   20201 
   20202       case 0x088: case 0x089:             // vmulouw, vmuluwm
   20203       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
   20204       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
   20205       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
   20206       case 0x4C0:                         // vsubudm
   20207          if (!allow_isa_2_07) goto decode_noP8;
   20208          if (dis_av_arith( theInstr )) goto decode_success;
   20209          goto decode_failure;
   20210 
   20211       /* AV Polynomial Vector Multiply Add */
   20212       case 0x408: case 0x448:            // vpmsumb, vpmsumd
   20213       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
   20214          if (!allow_isa_2_07) goto decode_noP8;
   20215          if (dis_av_polymultarith( theInstr )) goto decode_success;
   20216          goto decode_failure;
   20217 
   20218       /* AV Rotate, Shift */
   20219       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
   20220       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
   20221       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
   20222       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
   20223       case 0x1C4: case 0x2C4:             // vsl, vsr
   20224       case 0x40C: case 0x44C:             // vslo, vsro
   20225          if (!allow_V) goto decode_noV;
   20226          if (dis_av_shift( theInstr )) goto decode_success;
   20227          goto decode_failure;
   20228 
   20229       case 0x0C4:                         // vrld
   20230       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
   20231           if (!allow_isa_2_07) goto decode_noP8;
   20232           if (dis_av_shift( theInstr )) goto decode_success;
   20233           goto decode_failure;
   20234 
   20235       /* AV Logic */
   20236       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
   20237       case 0x4C4: case 0x504:             // vxor, vnor
   20238          if (!allow_V) goto decode_noV;
   20239          if (dis_av_logic( theInstr )) goto decode_success;
   20240          goto decode_failure;
   20241 
   20242       case 0x544:                         // vorc
   20243       case 0x584: case 0x684:             // vnand, veqv
   20244          if (!allow_isa_2_07) goto decode_noP8;
   20245          if (dis_av_logic( theInstr )) goto decode_success;
   20246          goto decode_failure;
   20247 
   20248       /* AV Processor Control */
   20249       case 0x604: case 0x644:             // mfvscr, mtvscr
   20250          if (!allow_V) goto decode_noV;
   20251          if (dis_av_procctl( theInstr )) goto decode_success;
   20252          goto decode_failure;
   20253 
   20254       /* AV Floating Point Arithmetic */
   20255       case 0x00A: case 0x04A:             // vaddfp, vsubfp
   20256       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
   20257       case 0x1CA:                         // vlogefp
   20258       case 0x40A: case 0x44A:             // vmaxfp, vminfp
   20259          if (!allow_V) goto decode_noV;
   20260          if (dis_av_fp_arith( theInstr )) goto decode_success;
   20261          goto decode_failure;
   20262 
   20263       /* AV Floating Point Round/Convert */
   20264       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
   20265       case 0x2CA:                         // vrfim
   20266       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
   20267       case 0x3CA:                         // vctsxs
   20268          if (!allow_V) goto decode_noV;
   20269          if (dis_av_fp_convert( theInstr )) goto decode_success;
   20270          goto decode_failure;
   20271 
   20272       /* AV Merge, Splat */
   20273       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
   20274       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
   20275       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
   20276       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
   20277          if (!allow_V) goto decode_noV;
   20278          if (dis_av_permute( theInstr )) goto decode_success;
   20279          goto decode_failure;
   20280 
   20281       case 0x68C: case 0x78C:             // vmrgow, vmrgew
   20282           if (!allow_isa_2_07) goto decode_noP8;
   20283           if (dis_av_permute( theInstr )) goto decode_success;
   20284           goto decode_failure;
   20285 
   20286       /* AV Pack, Unpack */
   20287       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
   20288       case 0x0CE:                         // vpkuwus
   20289       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
   20290       case 0x1CE:                         // vpkswss
   20291       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
   20292       case 0x2CE:                         // vupklsh
   20293       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
   20294           if (!allow_V) goto decode_noV;
   20295           if (dis_av_pack( theInstr )) goto decode_success;
   20296           goto decode_failure;
   20297 
   20298       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
   20299       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
   20300          if (!allow_isa_2_07) goto decode_noP8;
   20301          if (dis_av_pack( theInstr )) goto decode_success;
   20302          goto decode_failure;
   20303 
   20304       case 0x508: case 0x509:             // vcipher, vcipherlast
   20305       case 0x548: case 0x549:             // vncipher, vncipherlast
   20306       case 0x5C8:                         // vsbox
   20307          if (!allow_isa_2_07) goto decode_noP8;
   20308          if (dis_av_cipher( theInstr )) goto decode_success;
   20309          goto decode_failure;
   20310 
   20311       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
   20312          if (!allow_isa_2_07) goto decode_noP8;
   20313          if (dis_av_hash( theInstr )) goto decode_success;
   20314          goto decode_failure;
   20315 
   20316       case 0x702: case 0x742:             // vclzb, vclzh
   20317       case 0x782: case 0x7c2:             // vclzw, vclzd
   20318          if (!allow_isa_2_07) goto decode_noP8;
   20319          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20320          goto decode_failure;
   20321 
   20322       case 0x703: case 0x743:             // vpopcntb, vpopcnth
   20323       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
   20324          if (!allow_isa_2_07) goto decode_noP8;
   20325          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20326          goto decode_failure;
   20327 
   20328       case 0x50c:                         // vgbbd
   20329          if (!allow_isa_2_07) goto decode_noP8;
   20330          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
   20331          goto decode_failure;
   20332 
   20333       case 0x140: case 0x100:             // vaddcuq, vadduqm
   20334       case 0x540: case 0x500:             // vsubcuq, vsubuqm
   20335       case 0x54C:                         // vbpermq
   20336          if (!allow_V) goto decode_noV;
   20337          if (dis_av_quad( theInstr)) goto decode_success;
   20338          goto decode_failure;
   20339 
   20340       default:
   20341          break;  // Fall through...
   20342       }
   20343 
   20344       opc2 = IFIELD(theInstr, 0, 10);
   20345       switch (opc2) {
   20346 
   20347       /* AV Compare */
   20348       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
   20349       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
   20350       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
   20351          if (!allow_V) goto decode_noV;
   20352          if (dis_av_cmp( theInstr )) goto decode_success;
   20353          goto decode_failure;
   20354 
   20355       case 0x0C7:                         // vcmpequd
   20356       case 0x2C7:                         // vcmpgtud
   20357       case 0x3C7:                         // vcmpgtsd
   20358           if (!allow_isa_2_07) goto decode_noP8;
   20359           if (dis_av_cmp( theInstr )) goto decode_success;
   20360           goto decode_failure;
   20361 
   20362       /* AV Floating Point Compare */
   20363       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
   20364       case 0x3C6:                         // vcmpbfp
   20365          if (!allow_V) goto decode_noV;
   20366          if (dis_av_fp_cmp( theInstr )) goto decode_success;
   20367          goto decode_failure;
   20368 
   20369       default:
   20370          goto decode_failure;
   20371       }
   20372       break;
   20373 
   20374    default:
   20375       goto decode_failure;
   20376 
   20377    decode_noF:
   20378       vassert(!allow_F);
   20379       vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
   20380 		 "can't be handled by Valgrind on this host.  This instruction\n"
   20381 		 "requires a host that supports Floating Point instructions.\n",
   20382 		 theInstr);
   20383       goto not_supported;
   20384    decode_noV:
   20385       vassert(!allow_V);
   20386       vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
   20387 		 "that can't be handled by Valgrind.  If this instruction is an\n"
   20388 		 "Altivec instruction, Valgrind must be run on a host that supports"
   20389 		 "AltiVec instructions.  If the application was compiled for e500, then\n"
   20390 		 "unfortunately Valgrind does not yet support e500 instructions.\n",
   20391 		 theInstr);
   20392       goto not_supported;
   20393    decode_noVX:
   20394       vassert(!allow_VX);
   20395       vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
   20396 		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
   20397 		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
   20398 		 theInstr);
   20399       goto not_supported;
   20400    decode_noFX:
   20401       vassert(!allow_FX);
   20402       vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
   20403 		 "that can't be handled by Valgrind on this host. This instruction\n"
   20404 		 "requires a host that supports the General Purpose-Optional instructions.\n",
   20405 		 theInstr);
   20406       goto not_supported;
   20407    decode_noGX:
   20408       vassert(!allow_GX);
   20409       vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
   20410 		 "that can't be handled by Valgrind on this host. This instruction\n"
   20411 		 "requires a host that supports the Graphic-Optional instructions.\n",
   20412 		 theInstr);
   20413       goto not_supported;
   20414    decode_noDFP:
   20415       vassert(!allow_DFP);
   20416       vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
   20417 		 "that can't be handled by Valgrind on this host.  This instruction\n"
   20418 		 "requires a host that supports DFP instructions.\n",
   20419 		 theInstr);
   20420       goto not_supported;
   20421    decode_noP8:
   20422       vassert(!allow_isa_2_07);
   20423       vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
   20424 		 "by Valgrind on this host.  This instruction requires a host that\n"
   20425 		 "supports Power 8 instructions.\n",
   20426 		 theInstr);
   20427       goto not_supported;
   20428 
   20429 
   20430    decode_failure:
   20431    /* All decode failures end up here. */
   20432    opc2 = (theInstr) & 0x7FF;
   20433    if (sigill_diag) {
   20434       vex_printf("disInstr(ppc): unhandled instruction: "
   20435                  "0x%x\n", theInstr);
   20436       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
   20437                  opc1, opc1, opc2, opc2);
   20438    }
   20439 
   20440    not_supported:
   20441    /* Tell the dispatcher that this insn cannot be decoded, and so has
   20442       not been executed, and (is currently) the next to be executed.
   20443       CIA should be up-to-date since it made so at the start of each
   20444       insn, but nevertheless be paranoid and update it again right
   20445       now. */
   20446    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
   20447    dres.len         = 0;
   20448    dres.whatNext    = Dis_StopHere;
   20449    dres.jk_StopHere = Ijk_NoDecode;
   20450    dres.continueAt  = 0;
   20451    return dres;
   20452    } /* switch (opc) for the main (primary) opcode switch. */
   20453 
   20454   decode_success:
   20455    /* All decode successes end up here. */
   20456    switch (dres.whatNext) {
   20457       case Dis_Continue:
   20458          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
   20459          break;
   20460       case Dis_ResteerU:
   20461       case Dis_ResteerC:
   20462          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
   20463          break;
   20464       case Dis_StopHere:
   20465          break;
   20466       default:
   20467          vassert(0);
   20468    }
   20469    DIP("\n");
   20470 
   20471    if (dres.len == 0) {
   20472       dres.len = 4;
   20473    } else {
   20474       vassert(dres.len == 20);
   20475    }
   20476    return dres;
   20477 }
   20478 
   20479 #undef DIP
   20480 #undef DIS
   20481 
   20482 
   20483 /*------------------------------------------------------------*/
   20484 /*--- Top-level fn                                         ---*/
   20485 /*------------------------------------------------------------*/
   20486 
   20487 /* Disassemble a single instruction into IR.  The instruction
   20488    is located in host memory at &guest_code[delta]. */
   20489 
   20490 DisResult disInstr_PPC ( IRSB*        irsb_IN,
   20491                          Bool         (*resteerOkFn) ( void*, Addr ),
   20492                          Bool         resteerCisOk,
   20493                          void*        callback_opaque,
   20494                          const UChar* guest_code_IN,
   20495                          Long         delta,
   20496                          Addr         guest_IP,
   20497                          VexArch      guest_arch,
   20498                          const VexArchInfo* archinfo,
   20499                          const VexAbiInfo*  abiinfo,
   20500                          VexEndness   host_endness_IN,
   20501                          Bool         sigill_diag_IN )
   20502 {
   20503    IRType     ty;
   20504    DisResult  dres;
   20505    UInt       mask32, mask64;
   20506    UInt hwcaps_guest = archinfo->hwcaps;
   20507 
   20508    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
   20509 
   20510    /* global -- ick */
   20511    mode64 = guest_arch == VexArchPPC64;
   20512    ty = mode64 ? Ity_I64 : Ity_I32;
   20513    if (!mode64 && (host_endness_IN == VexEndnessLE)) {
   20514       vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
   20515       dres.len         = 0;
   20516       dres.whatNext    = Dis_StopHere;
   20517       dres.jk_StopHere = Ijk_NoDecode;
   20518       dres.continueAt   = 0;
   20519       return dres;
   20520    }
   20521 
   20522    /* do some sanity checks */
   20523    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   20524             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   20525             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
   20526 
   20527    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   20528             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
   20529             | VEX_HWCAPS_PPC64_ISA2_07;
   20530 
   20531    if (mode64) {
   20532       vassert((hwcaps_guest & mask32) == 0);
   20533    } else {
   20534       vassert((hwcaps_guest & mask64) == 0);
   20535    }
   20536 
   20537    /* Set globals (see top of this file) */
   20538    guest_code           = guest_code_IN;
   20539    irsb                 = irsb_IN;
   20540    host_endness         = host_endness_IN;
   20541 
   20542    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
   20543    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
   20544 
   20545    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
   20546                              delta, archinfo, abiinfo, sigill_diag_IN);
   20547 
   20548    return dres;
   20549 }
   20550 
   20551 
   20552 /*------------------------------------------------------------*/
   20553 /*--- Unused stuff                                         ---*/
   20554 /*------------------------------------------------------------*/
   20555 
   20556 ///* A potentially more memcheck-friendly implementation of Clz32, with
   20557 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
   20558 //
   20559 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
   20560 //{
   20561 //   /* Welcome ... to SSA R Us. */
   20562 //   IRTemp n1  = newTemp(Ity_I32);
   20563 //   IRTemp n2  = newTemp(Ity_I32);
   20564 //   IRTemp n3  = newTemp(Ity_I32);
   20565 //   IRTemp n4  = newTemp(Ity_I32);
   20566 //   IRTemp n5  = newTemp(Ity_I32);
   20567 //   IRTemp n6  = newTemp(Ity_I32);
   20568 //   IRTemp n7  = newTemp(Ity_I32);
   20569 //   IRTemp n8  = newTemp(Ity_I32);
   20570 //   IRTemp n9  = newTemp(Ity_I32);
   20571 //   IRTemp n10 = newTemp(Ity_I32);
   20572 //   IRTemp n11 = newTemp(Ity_I32);
   20573 //   IRTemp n12 = newTemp(Ity_I32);
   20574 //
   20575 //   /* First, propagate the most significant 1-bit into all lower
   20576 //      positions in the word. */
   20577 //   /* unsigned int clz ( unsigned int n )
   20578 //      {
   20579 //         n |= (n >> 1);
   20580 //         n |= (n >> 2);
   20581 //         n |= (n >> 4);
   20582 //         n |= (n >> 8);
   20583 //         n |= (n >> 16);
   20584 //         return bitcount(~n);
   20585 //      }
   20586 //   */
   20587 //   assign(n1, mkexpr(arg));
   20588 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
   20589 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
   20590 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
   20591 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
   20592 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
   20593 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
   20594 //      a word of the form 1---10---0, then do a population-count idiom
   20595 //      (to count the 1s, which is the number of leading zeroes, or 32
   20596 //      if the original word was 0. */
   20597 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
   20598 //
   20599 //   /* unsigned int bitcount ( unsigned int n )
   20600 //      {
   20601 //         n = n - ((n >> 1) & 0x55555555);
   20602 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   20603 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
   20604 //         n = n + (n >> 8);
   20605 //         n = (n + (n >> 16)) & 0x3F;
   20606 //         return n;
   20607 //      }
   20608 //   */
   20609 //   assign(n8,
   20610 //          binop(Iop_Sub32,
   20611 //                mkexpr(n7),
   20612 //                binop(Iop_And32,
   20613 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
   20614 //                      mkU32(0x55555555))));
   20615 //   assign(n9,
   20616 //          binop(Iop_Add32,
   20617 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
   20618 //                binop(Iop_And32,
   20619 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
   20620 //                      mkU32(0x33333333))));
   20621 //   assign(n10,
   20622 //          binop(Iop_And32,
   20623 //                binop(Iop_Add32,
   20624 //                      mkexpr(n9),
   20625 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
   20626 //                mkU32(0x0F0F0F0F)));
   20627 //   assign(n11,
   20628 //          binop(Iop_Add32,
   20629 //                mkexpr(n10),
   20630 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
   20631 //   assign(n12,
   20632 //          binop(Iop_Add32,
   20633 //                mkexpr(n11),
   20634 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
   20635 //   return
   20636 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
   20637 //}
   20638 
   20639 /*--------------------------------------------------------------------*/
   20640 /*--- end                                         guest_ppc_toIR.c ---*/
   20641 /*--------------------------------------------------------------------*/
   20642